单片机编程的习题,,

1.已知晶振是11.0592MHz,要求串口工作在方式1,波特率为4800,分别完成以下题目:
1)编写程序让串口每秒向外发送一次数据0x55,延时程序直接调用delay();
2)编写程序让串口每秒向外发送一次数据0x55,延时程序使用T0硬件产生;
3)每次外部中断0时通过串口发送外部中断0产生的中断次数;
4)编写程序当串口接收到数据后把接收到的数据通过串口在发送出去,同时把接收到的数据取反后送给P2口。
2.已知4位8段共阴极数码管的数据口连接了P1口,位选口连接了P2口,当输出低电平时该位被选中,上电后数码管显示数据0000-5000循环显示,时间间隔2秒,编写程序每次外部中断1时数码管显示重新由0000开始进行循环显示。(要求延时2秒程序由T1定时器实现,单片机晶振为6MHZ,动态显示延时10ms调用 “delay10ms()”子程序。)

  1. P1口连接共阴极8段数码管,上电后数码管0-9循环显示,中间间隔1秒,编写程序第一次外部中断0时数码管全灭(送0xAA)1秒,第二次中断时数码管全亮(送0X55)1秒,每次外部中断0时以此循环。延时程序直接调用delay()。
  2. P1.0、P1.1、P1.2分别连接了红、黄、绿三个LED灯,低电平亮,编写交通灯程序红灯亮30秒后绿灯亮25秒,然后黄灯再亮3秒,以此循环,要求延时程序通过调用延时1S子程序“delay1s()”程序实现。(
  3. 已知void Show_R(uchar r1,uchar r2)函数功能为控制16个LED亮灭,其中参数r1控制低8位LED亮,r2控制高8位LED亮,高电平亮,低电平灭,编写程序使得16个LED流水灯循环点亮,中间延时程序直接调用delay()子程序。
  4. P1.0-P1.3连接了4个开关,闭合为0,断开为1,P1.4-P1.7连接了4个LED,低电平亮,编写程序用开关控制相应的LED亮灭。开关闭合时灯亮,断开时灯灭。
  5. 已知6位8段共阴极数码管的数据口连接了P1口,位选口连接了P2口,当输出低电平时该位被选中,编写程序第一次外部中断0时显示123456,第二次外部中断时显示自己学号后6位,以此循环。
  6. P1.0连接了一个按钮,按下为低电平,P1.1连接了指示灯,低电平亮,编写程序,第一次按动按钮时指示灯亮,第二次按动按钮时指示灯灭,第三次按动时再亮......以此循环。
  7. 已知P1口接了8个LED,高电平灭,低电平亮,编写流水灯程序,时间间隔1S。(延时1S子程序直接调用“Delay1000ms()”)。
  8. 已知void Show_R(uchar r1,uchar r2)函数功能为控制16个LED亮灭,其中参数r1控制低8位LED亮,r2控制高8位LED亮,编写程序使16位LED灯输出循环加1数据,中间延时程序直接调用delay()子程序。

已知晶振是11.0592MHz,波特率为4800,要求串口工作在方式1。
编写程序让串口每秒向外发送一次数据0x55,延时程序直接调用delay():

#include <reg52.h>

void delay()
{
    int i, j;
    for(i = 0; i < 1000; i++)
        for(j = 0; j < 1000; j++);
}

void main()
{
    while(1)
    {
        SBUF = 0x55;
        while(!TI);
        TI = 0;
        delay();
    }
}

编写程序让串口每秒向外发送一次数据0x55,延时程序使用定时器产生:

#include <reg52.h>

void timer_init()
{
    TMOD = 0x01;
    TH0 = (65536 - 11.0592 * 1000 / 12) / 256;
    TL0 = (65536 - 11.0592 * 1000 / 12) % 256;
    ET0 = 1;
    TR0 = 1;
}

void timer0() interrupt 1
{
    TH0 = (65536 - 11.0592 * 1000 / 12) / 256;
    TL0 = (65536 - 11.0592 * 1000 / 12) % 256;
    SBUF = 0x55;
    while(!TI);
    TI = 0;
}

void main()
{
    timer_init();
    while(1);
}

每次外部中断0时通过串口发送外部中断0产生的中断次数:

#include <reg52.h>

unsigned char count = 0;

void ext0() interrupt 0
{
    count++;
    SBUF = count;
    while(!TI);
    TI = 0;
}

void main()
{
    EA = 1;
    EX0 = 1;
    IT0 = 1;
    while(1);
}

编写程序当串口接收到数据后把接收到的数据通过串口再发送出去,同时把接收到的数据取反后送给P2口:

#include <reg52.h>
#include <intrins.h>

sbit P2 = 0xA0;

void Uart_Init()
{
    SCON = 0x50; //设置串口工作方式1,波特率4800
    TMOD = 0x20; //设置T1为8位自动重装模式
    TH1 = 0xFD; //设置波特率
    TL1 = 0xFD;
    TR1 = 1; //启动T1
    ES = 1; //打开串口中断开关
}

void Uart_Send(unsigned char dat)
{
    SBUF = dat; //数据发送到SBUF缓冲区
    while (!TI); //等待发送完毕
    TI = 0; //清空发送标志位
}

void Uart_ISR() interrupt 4 //串口中断
{
    if (RI) //接收到数据
    {
        RI = 0; //清除接收标志位
        unsigned char dat = SBUF; //读取接收到的数据
        Uart_Send(dat); //发送接收到的数据
        P2 = ~dat; //取反后送给P2口
    }
}

void main()
{
    Uart_Init(); //初始化串口
    while (1); //程序不停止
}

2.已知4位8段共阴极数码管的数据口连接了P1口,位选口连接了P2口,当输出低电平时该位被选中,上电后数码管显示数据0000-5000循环显示,时间间隔2秒,编写程序每次外部中断1时数码管显示重新由0000开始进行循环显示。
(要求延时2秒程序由T1定时器实现,单片机晶振为6MHZ,动态显示延时10ms调用“delay10ms()”子程序。)

#include <reg52.h>

unsigned char i;

void delay(void) {
    unsigned int j;
    for (j = 0; j < 60000; j++);
}

void delay10ms(void) {
    unsigned int j;
    for (j = 0; j < 600; j++);
}

void display(unsigned char num) {
    P1 = num;
    P2 = 0x01;
    delay10ms();
    P2 = 0x02;
    delay10ms();
    P2 = 0x04;
    delay10ms();
    P2 = 0x08;
    delay10ms();
}

void timer1_init(void) {
    TMOD = 0x10;
    TH1 = 0xFD;
    TL1 = 0xFD;
    TR1 = 1;
    EA = 1;
    ET1 = 1;
}

void timer1_int(void) interrupt 3 {
    i++;
    display(i % 10);
    if (i == 50) {
        i = 0;
    }
}

void main(void) {
    timer1_init();
    while (1) {
    }
}

1.P1口连接共阴极8段数码管,上电后数码管0·
9循环显示,中间间隔1秒,编写程序第一次外部中断0时数码管全灭(送0xAA)1秒,第二次中断时数码管全亮(送0X55)1秒,每次外部中断0时以此循环。延时程序直接调用
delay()。

#include <reg52.h>

unsigned char i, flag = 0;

void delay(void) {
    unsigned int j;
    for (j = 0; j < 60000; j++);
}

void display(unsigned char num) {
    P1 = num;
    P2 = 0x01;
    delay();
    P2 = 0x02;
    delay();
    P2 = 0x04;
    delay();
    P2 = 0x08;
    delay();
}

void external_int0(void) interrupt 0 {
    if (flag == 0) {
        display(0xAA);
        flag = 1;
    } else {
        display(0x55);
        flag = 0;
    }
}

void main(void) {
    EA = 1;
    EX0 = 1;
    while (1) {
    }
}

P1.0、P1.1、P1.2分别连接了红、黄、绿三
个LED灯,低电平亮,编写交通灯程序红灯亮30秒后绿灯亮25秒,然后黄灯再亮3秒,以此循环,要求延时程序通过调用延时1S子程
序“delay1s()”程序实现。

#include <reg51.h>

void delay1s()
{
    unsigned int i, j;
    for (i = 0; i < 1000; i++)
        for (j = 0; j < 125; j++);
}

void main()
{
    while (1)
    {
        P1 = 0x01; // red LED on
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();

        P1 = 0x04; // green LED on
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();
        delay1s();

        P1 = 0x02; // yellow LED on
        delay1s();
        delay1s();
        delay1s();
    }
}

3.已知void Show_R(uchar r1,uchar r2)函数功能
为控制16个LED亮灭,其中参数r1控制低8位
LED亮,r2控制高8位LED亮,高电平亮,低
电平灭,编写程序使得16个LED流水灯循环点
亮,中间延时程序直接调用delay()子程序。

#include<reg51.h>

void Show_R(uchar r1, uchar r2) {
  // Code to control the LED lights based on the value of r1 and r2
}

void delay() {
  // Code to implement the delay
}

void main() {
  uchar i;
  while(1) {
    for(i=0; i<=255; i++) {
      Show_R(i, 255-i);
      delay();
    }
  }
}

这段代码实现了16个LED流水灯的循环点亮,在主程序中,使用for循环枚举i的值从0到255,每次循环都调用Show_R(i, 255-i)函数,第一个参数控制低8位LED亮,第二个参数控制高8位LED灭。最后调用delay()函数实现延时。
4.P1.0-P1.3连接了4个开关,闭合为0,断开为
1,P1.4-P1.7连接了4个LED,低电平亮,编写程序用开关控制相应的LED亮灭。开关闭合时灯亮,断开时灯灭。

#include<reg52.h>
void main()
{
    while(1)
    {
        P1 = 0xff; // 先设定所有LED灯为灭
        if(P1 & 0x01 == 0x00) 
            P1 &= 0xef;  // 开关1闭合,LED1亮
        if(P1 & 0x02 == 0x00) 
            P1 &= 0xdf;  // 开关2闭合,LED2亮
        if(P1 & 0x04 == 0x00) 
            P1 &= 0xbf;  // 开关3闭合,LED3亮
        if(P1 & 0x08 == 0x00) 
            P1 &= 0x7f;  // 开关4闭合,LED4亮
    }
}

5.已知6位8段共阴极数码管的数据口连接了P1
口,位选口连接了P2口,当输出低电平时该位被选中,编写程序第一次外部中断0时显示123456,第二次外部中断时显示自己学号后6位,以此循环。

#include <reg52.h>

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar num[12]={1,2,3,4,5,6,7,8,9,0,7,8};
uchar flag=0;

void delay(unsigned int t)
{
    while(t--);
}

void display(uchar data)
{
    P1=data;
    P2=0xfe;
    delay(500);
    P2=0xff;
}

void INT0() interrupt 0
{
    flag++;
    if(flag>1) flag=0;
}

void main()
{
    EA=1;
    IT0=1;
    while(1)
    {
        if(flag==0)
        {
            for(int i=0;i<6;i++)
            {
                display(table[num[i]]);
                delay(1000);
            }
        }
        else
        {
            for(int i=6;i<12;i++)
            {
                display(table[num[i]]);
                delay(1000);
            }
        }
    }
}

6.P1.0连接了一个按钮,按下为低电平,P1.1
连接了指示灯,低电平亮,编写程序,第一次按动按钮时指示灯亮,第二次按动按钮时指示灯灭,第三次按动时再亮……以此循环。

#include<reg51.h>

sbit button = P1^0;  // 定义按钮对应的引脚
sbit led = P1^1;  // 定义指示灯对应的引脚

unsigned char flag = 0;  // 定义循环标识变量

void main() {
    while(1) {
        if (button == 0) {  // 当按钮按下时
            delay(10);  // 延时10ms,去抖动
            if (button == 0) {  // 再次判断,确保按键按下
                flag ++;  // 标识变量自增
                while(!button);  // 等待按键抬起
            }
        }
        if (flag % 2 == 1) {  // 当标识变量为奇数时
            led = 0;  // 指示灯亮
        } else {  // 当标识变量为偶数时
            led = 1;  // 指示灯灭
        }
    }
}

注释:

sbit 是定义单片机的一个引脚的宏,可以简化对引脚的操作。
button 和 led 分别表示按钮和指示灯的引脚。
flag 用来记录按键被按下的次数,并用于控制指示灯的状态。
delay 函数是延时函数,用于去抖动。
while(1) 是一个无限循环,程序不断检测按键的状态。
while(!button) 是等待按键抬起的循环,只有当按键抬起时,程序才继续执行。
在每次检测按键时,都要先判断标识
7.已知P1口接了8个LED,高电平灭,低电平
亮,编写流水灯程序,时间间隔1S。(延时
1S子程序直接调用“Delay1000ms()”)。

#include<reg52.h> 
#define uchar unsigned char 
#define uint unsigned int 

sbit LED0=P1^0; 
sbit LED1=P1^1; 
sbit LED2=P1^2; 
sbit LED3=P1^3; 
sbit LED4=P1^4; 
sbit LED5=P1^5; 
sbit LED6=P1^6; 
sbit LED7=P1^7; 

void Delay1000ms(){ 
    uint i,j; 
    for(i=0;i<1000;i++) 
    for(j=0;j<120;j++); 
} 

void main(){ 
    while(1){ 
        LED0=0; 
        Delay1000ms(); 
        LED0=1; 
        LED1=0; 
        Delay1000ms(); 
        LED1=1; 
        LED2=0; 
        Delay1000ms(); 
        LED2=1; 
        LED3=0; 
        Delay1000ms(); 
        LED3=1; 
        LED4=0; 
        Delay1000ms(); 
        LED4=1; 
        LED5=0; 
        Delay1000ms(); 
        LED5=1; 
        LED6=0; 
        Delay1000ms(); 
        LED6=1; 
        LED7=0; 
        Delay1000ms(); 
        LED7=1; 
    } 
}

注释:

#include<reg52.h>:包含51单片机的头文件
sbit LED0=P1^0;:定义 LED0 为 P1.0 管脚
void Delay1000ms(){ ... }:定义延时函数,1000ms
while(1){ ... }:循环执行流水灯代码
LEDx=0/1:点亮/熄灭 LEDx
Delay1000ms():调用延时函数
8.已知void Show_R(uchar r1,uchar r2)函数功能
为控制16个LED亮灭,其中参数r1控制低8位LED亮,r2控制高8位LED亮,编写程序使16位LED灯输出循环加1数据,中间延时程序直接调用delay()子程序。

#include<reg52.h>
void delay();
void Show_R(uchar r1,uchar r2);
void main()
{
    uchar i;
    while(1)
    {
        for(i=0; i<256; i++)
        {
            Show_R(i,i);  // 函数调用,将i的值传入作为参数
            delay();      // 延时
        }
    }
}

void Show_R(uchar r1, uchar r2)
{
    P1 = ~r1;    // 控制低8位LED
    P2 = ~r2;    // 控制高8位LED
}

void delay()
{
    uchar i,j;
    for(i=0; i<100; i++)
        for(j=0; j<100; j++);
}

上述代码是在使用C语言实现16位LED灯输出循环加1数据的程序。在代码中,主函数中定义一个循环,在循环中调用Show_R函数,Show_R函数控制低8位LED和高8位LED的亮灭。在Show_R函数中,P1的值为r1的反码,P2的值为r2的反码,因为高电平为灭,低电平为亮。最后,程序调用delay函数延时一段时间,控制LED灯循环加1数据的速度。