蓝桥杯备赛题解(小蜜蜂)(二)

必备基础技能训练15 项

【基础08】外部中断的基本操作

新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:

1、将CT107D 上J5 处跳帽接到2~3 引脚,使S4 和S5 按键一端接地,S4 按键的另一端接到单片机的P32/INT0 引脚,S5 按键的另一端接到单片机的P33/INT1 引脚。

2、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。

3、控制L1 指示灯循环闪烁。

4、将P32/INT0 引脚定义成外部中断,下降沿触发,使能相关中断控制位。即按下S5按键就会产生一个外部中断触发信号,进入外部中断服务函数。

5、在外部中断服务函数中,点亮L8 指示灯,延时片刻后,熄灭。

image-20230328225146398

实现代码:

#include "reg51.h"

sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚

sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;

void Delay(unsigned int t);     // 延迟函数
void HC138Init(unsigned int n); // 74HC138初始化
void InterruptInit(void);       // 外部中断初始化

// 08外部中断的基本操作
void main(void)
{
    HC138Init(4);    // 初始化74HC138
    InterruptInit(); // 初始化外部中断
    while (1) {
        // LED1循环闪烁
        L1 = 0;
        Delay(1000);
        L1 = 1;
        Delay(1000);
    }
}

void Delay(unsigned int t) // 延迟函数
{
    unsigned char i, j;
    while (t > 0) {
        i = 2;
        do {
            while (--j)
                ;
        } while (--i);
        t--;
    }
}

void HC138Init(unsigned int n) // 74HC138初始化
{
    P2 = 0x00; // P2口输出0
    if (n == 4) {
        HC138_C = 1;
        HC138_B = 0; // 设置74HC138为 100  4
        HC138_A = 0;
    } else if (n == 5) {
        HC138_C = 1; // 设置74HC138为 101  5
        HC138_B = 0;
        HC138_A = 1;
    } else if (n == 6) {
        HC138_C = 1; // 设置74HC138为 110  6
        HC138_B = 1;
        HC138_A = 0;
    } else if (n == 7) {
        HC138_C = 1; // 设置74HC138为 111  7
        HC138_B = 1;
        HC138_A = 1;
    }
}

void InterruptInit(void) // 外部中断初始化
{
    IT0 = 1; // 设置外部中断0为下降沿触发
    EX0 = 1; // 开启外部中断0
    EA  = 1; // 开启总中断
}

void Interrupt0(void) interrupt 0 // 外部中断0服务程序
{
    L8 = 0;
    Delay(2000);
    L8 = 1;
}

【基础09】定时器实现秒闪功能

新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:

1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。

2、利用定时/计数器T0 的模式1 实现50ms 的间隔定时。

3、在50ms 间隔定时的基础上,每隔1 秒L1 指示灯闪烁一次,即L1 指示灯循环点亮
0.5 秒,熄灭0.5 秒。

4、每隔10 秒L8 指示灯闪烁1 次,即L1 指示灯循环点亮5 秒,熄灭5 秒。

通过STC-ISP生成中断初始化函数

再在其中开启中断:ET0、EA、PT0

实现代码:

#include "REG51.H"

sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚

sbit L1 = P0^0;
sbit L8 = P0^7;

void HC138Init(unsigned int n); // 74HC138初始化
void Timer0_Init(void);         // 定时器0初始化
void main()
{
    HC138Init(4);  // 初始化74HC138
    Timer0_Init(); // 初始化定时器0
    while (1) {
    }
}

void HC138Init(unsigned int n) // 74HC138初始化
{
    P2 = 0x00; // P2口输出0
    if (n == 4) {
        HC138_C = 1;
        HC138_B = 0; // 设置74HC138为 100  4
        HC138_A = 0;
    } else if (n == 5) {
        HC138_C = 1; // 设置74HC138为 101  5
        HC138_B = 0;
        HC138_A = 1;
    } else if (n == 6) {
        HC138_C = 1; // 设置74HC138为 110  6
        HC138_B = 1;
        HC138_A = 0;
    } else if (n == 7) {
        HC138_C = 1; // 设置74HC138为 111  7
        HC138_B = 1;
        HC138_A = 1;
    }
}

void Timer0_Init(void) // 50毫秒@12.000MHz
{
    TMOD &= 0xF0; // 设置定时器模式
    TMOD |= 0x01; // 设置定时器模式
    TL0 = 0xB0;   // 设置定时初始值
    TH0 = 0x3C;   // 设置定时初始值
    TF0 = 0;      // 清除TF0标志
    TR0 = 1;      // 定时器0开始计时

    ET0 = 1; // 允许定时器0中断
    EA  = 1; // 开总中断
    PT0 = 0; // 定时器0为低优先级中断
}

void Timer0_Routine() interrupt 1// 定时器0中断服务程序
{
    unsigned char i;
    TL0 = 0xB0; // 设置定时初始值
    TH0 = 0x3C; // 设置定时初始值

    i++;
    if (i % 10 == 0) // 500ms
    {
        L1 = ~L1;
    }

    if (i == 100) // 5s
    {
        i  = 0;
        L8 = ~L8;
    }
}

【基础10】定时器实现秒表功能

新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,利用定时器T0、数码管和2 个独立按键,设计并实现一个秒表,具有启动、暂停和清零功能。

1、秒表的显示格式:分-秒-0.05 秒(即50ms)

  • 如8 分26 秒900 毫秒,显示为:08-26-18

2、独立按键S4 定义为:启动/暂停,即第1 次按下启动秒表,再次按下暂停秒表。

3、独立按键S5 定义为:清零。

4、按键均为按下有效。

注意一下临界条件判断

实现代码:

#include <REG51.H>

sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚

sbit Key1 = P3^0; // 按键1
sbit Key2 = P3^1; // 按键2
sbit Key3 = P3^2; // 按键3
sbit Key4 = P3^3; // 按键4

unsigned char code Duanma[18] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x80, 0xc6, 0xc0, 0x86, 0x8e, 0xbf, 0x7f};

void Delay(unsigned int t);                            // 延迟函数
void HC138Init(unsigned int n);                        // 74HC138初始化
void LED_Shu(unsigned int location, unsigned int num); // 数码管显示函数
void Display();                                        // LED显示
void Timer0_Init(void);                                // 定时器0初始化

unsigned int min = 0, sec = 0, ssec = 0; // 分,秒,毫秒
unsigned int flag1 = 0, flag2 = 0;

// 10定时器实现秒表功能
void main()
{
    Timer0_Init();
    while (1) {
        if (Key1 == 0) {
            Delay(20);while (Key1 == 0);Delay(20);// 去抖

            flag1 = !flag1;// 按下一次开始,再按一次暂停
        }
        if (Key2 == 0 && flag2 == 0) {
            Delay(20);while (Key2 == 0);Delay(20);// 去抖

            flag2 = !flag2;
        }
        Display();
    }
}

void Delay(unsigned int t) // 延迟函数
{
    unsigned char i, j;
    while (t > 0) {
        i = 2;
        do {
            while (--j)
                ;
        } while (--i);
        t--;
    }
}

void HC138Init(unsigned int n) // 74HC138初始化
{
    if (n == 4) {
        HC138_C = 1;
        HC138_B = 0; // 设置74HC138为 100  4
        HC138_A = 0;
    } else if (n == 5) {
        HC138_C = 1; // 设置74HC138为 101  5
        HC138_B = 0;
        HC138_A = 1;
    } else if (n == 6) {
        HC138_C = 1; // 设置74HC138为 110  6
        HC138_B = 1;
        HC138_A = 0;
    } else if (n == 7) {
        HC138_C = 1; // 设置74HC138为 111  7
        HC138_B = 1;
        HC138_A = 1;
    }
}

void LED_Shu(unsigned int location, unsigned int num) // 数码管显示函数
{
    HC138Init(6); // 位选
    P0 = 0x01 << location;
    HC138Init(7); // 段选
    P0 = Duanma[num];
    // 消影
    Delay(1);
    P0 = 0xFF;
}

void Display() // LED显示
{
    LED_Shu(0, min / 10);
    Delay(1);
    LED_Shu(1, min % 10);
    Delay(1);
    LED_Shu(2, 16);

    LED_Shu(3, sec / 10);
    Delay(1);
    LED_Shu(4, sec % 10);
    Delay(1);
    LED_Shu(5, 16);

    LED_Shu(6, ssec / 10);
    Delay(1);
    LED_Shu(7, ssec % 10);
    Delay(1);
}

void Timer0_Init(void) // 50毫秒@12.000MHz
{
    TMOD &= 0xF0; // 设置定时器模式
    TMOD |= 0x01; // 设置定时器模式
    TL0 = 0xB0;   // 设置定时初始值
    TH0 = 0x3C;   // 设置定时初始值
    TF0 = 0;      // 清除TF0标志
    TR0 = 1;      // 定时器0开始计时

    ET0 = 1; // 允许定时器0中断
    EA  = 1; // 开总中断
    PT0 = 0; // 定时器0为低优先级中断
}

void Timer0_Routine() interrupt 1 // 定时器0中断服务程序
{
    TL0 = 0xB0; // 设置定时初始值
    TH0 = 0x3C; // 设置定时初始值

    if (flag1 == 1 && flag2 == 0) {
        ssec++;
        if (ssec == 20) {
            ssec = 0;
            sec++;
        }
        if (sec >= 60) {
            sec = 0;
            min++;
        }
        if (min >= 60) {
            min = 0;
        }
    }
    if (flag2 == 1) {
        min = 0, sec = 0, ssec = 0;
    }
}

【基础11】利用PWM 控制灯光亮度

新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,利用PWM 脉宽信号实现独立按键S7 对L1 指示灯亮度变化的控制:

1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。

2、PWM 脉宽信号的频率为100Hz。

3、L1 指示灯有4 种亮度,分别是:完全熄灭、10%的亮度、50%的亮度和90%的亮度。

4、按下S7 按键,循环切换L1 指示灯的四种亮度模式,如下图所示:

image-20230328133736650

实现代码:

#include "REG51.H"

sbit HC138_A = P2^5; // 74HC138的A引脚
sbit HC138_B = P2^6; // 74HC138的B引脚
sbit HC138_C = P2^7; // 74HC138的C引脚

sbit Key1 = P3^0; // 按键1
sbit L1   = P0^0; // LED1

void Timer0_Init(void);     // 定时器0初始化函数
void HC138Init();           // 74HC138初始化函数
void Delay(unsigned int t); // 延迟函数

unsigned int PWM_flag = 0;
unsigned int flag     = 0;

void main(void)
{
    HC138Init();
    Timer0_Init();

    while (1) {
        if (Key1 == 0) {
            Delay(20);while (Key1 == 0);Delay(20);

            if (flag == 0) {
                EA = 1; // 开总中断
                PWM_flag = 10;
                flag = 1;
            } else if (flag == 1) {
                PWM_flag = 50;
                flag = 2;
            } else if (flag == 2) {
                PWM_flag = 90;
                flag = 3;
            } else if (flag == 3) {
                PWM_flag = 0;
                EA = 0; // 开总中断
                L1 = 1;
            }
        }
    }
}

void Delay(unsigned int t) // 延迟函数
{
    unsigned char i, j;
    while (t > 0) {
        i = 2;
        do {
            while (--j)
                ;
        } while (--i);
        t--;
    }
}
void Timer0_Init(void) // 100微秒@12.000MHz
{
    TMOD &= 0xF0; // 设置定时器模式
    TMOD |= 0x01; // 设置定时器模式
    TL0 = 0xB0;   // 设置定时初始值
    TH0 = 0x3C;   // 设置定时初始值
    TF0 = 0;      // 清除TF0标志
    TR0 = 1;      // 定时器0开始计时

    ET0 = 1; // 允许定时器0中断
    PT0 = 0; // 定时器0为低优先级中断
}

void HC138Init() // 74HC138初始化函数
{
    P2 = 0x00; // P2口输出0

    HC138_A = 0;
    HC138_B = 0;
    HC138_C = 1;
}

void Timer0_Routine() interrupt 1 // 定时器0中断服务程序
{
    unsigned char count;

    TL0 = 0xB0; // 设置定时初始值
    TH0 = 0x3C; // 设置定时初始值

    count++;

    if (count == PWM_flag) {
        L1 = 1;
    } else if (count == 100) {
        L1 = 0;
        count = 0;
    }
}

【基础12】串行接口的基本操作

新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:

1、初始化串口为模式1,即8 位UART 模式,波特率9600,允许接收。

2、数据发送采用查询方式,数据接收采用中断方式。

3、系统上电初始化之后,单片机向上位机发送两个字节:0x5a 和0xa5(串口助手以十六进制HEX 发送和显示)。

4、串口每成功接收到一个字节后,在该字节基础上加1,然后通过串口发送回上位机。

5、注意89C52 单片机和IAP15F2K61S2 单片机串口应用的差别,使用9600 波特率时,晶振时钟选择11.0592MHz。

image-20230331223135943

实现代码:

#include "reg51.h"

sfr AUXR = 0x8e; // IAP15F2K61S新增配置
unsigned char Date;

void UART_Init();                  // 串口初始化函数
void Send_Data(unsigned char dat); // 发送数据

// 12串行接口的基本操作
void main(void)
{
    UART_Init();
    Send_Data(0X5A);
    Send_Data(0XA5);
    while (1) {
    }
}

void UART_Init() // 串口初始化函数
{
    // STC-ISP 波特率设置模块
    //  11.0592MHz 9600bps 串口1 8位数据 定时器1(8位自动重载) 12T

    TMOD &= 0x0F; // 清除定时器1模式位
    TMOD |= 0x20; // 设定定时器1为8位自动重装方式
    TL1 = 0xFD;   // 设定定时初值
    TH1 = 0xFD;   // 设定定时器重装值
    ET1 = 0;      // 禁止定时器1中断
    TR1 = 1;      // 启动定时器1
    EA  = 1;      // 开总中断
    PT1 = 0;      // 定时器1为低优先级中断
    ES  = 1;      // 串口中断允许

    SCON = 0x50; // 8位数据,可变波特率

    AUXR = 0x00;
}
void UART_Routine(void) interrupt 4 // 串口中断函数,接受数据
{
    if (RI == 1) {
        Date = SBUF;
        Send_Data(Date + 1);
        RI = 0;
    }
}

void Send_Data(unsigned char dat) // 发送数据
{
    SBUF = dat;
    while (TI == 0);
    TI = 0;
}

【基础13】串行接口的进阶应用

新建工程,以I/O 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:

1、初始化串口为模式1,即8 位UART 模式,波特率9600,允许接收。

2、数据发送采用查询方式,数据接收采用中断方式。

3、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯,通过串口向上位机发送字符串:“Welcome to XMF system!”,回车换行。

4、上位机通过串口发送单字节命令,控制单片机的8 个LED 灯开关,单片机响应正确的控制命令后,完成相应的灯光操作。

5、上位机通过串口发送单字节命令,读取单片机运行信息,单片机响应正确的读取命令后,向上位机返回指定的信息。

6、上位机与单片机的通信规约如下表:

image-20230328133857154

实现代码:

#include "reg51.h"

sfr AUXR = 0x8e; // IAP15F2K61S新增配置

sbit HC138_A = P2 ^ 5; // 74HC138的A引脚
sbit HC138_B = P2 ^ 6; // 74HC138的B引脚
sbit HC138_C = P2 ^ 7; // 74HC138的C引脚

void UART_Init(void);                   // 初始化串口
void UART_SentByte(unsigned char dat);  // 串口发送一个字节
void UART_SentDate(unsigned char *str); // 串口发送字符串
void HC138_Init(void);                  // 初始化74HC138

unsigned char Data = 0x00; // 接收到的数据

// 13串行接口的进阶应用
void main(void)
{
    UART_Init();  // 初始化串口
    HC138_Init(); // 初始化74HC138
    UART_SentDate("Welcome to XMF system!\r\n");
    while (1) {
        if (Data != 0x00) {
            switch (Data & 0xf0) {
                // 模式判断
                case 0xa0: // 控制L1~L4灯
                    P0 = 0xff;
                    P0 = P0 & (~Data | 0xf0);
                    Data = 0x00;
                    break;
                case 0xb0: // 控制L5~L8灯
                    P0 = 0xff;
                    P0 = P0 & ((~Data << 4) | 0x0f);
                    Data = 0x00;
                    break;
                case 0xc0: // 返回状态
                    UART_SentDate("The System is Running...\r\n");
                    Data = 0x00;
                    break;
            }
        }
    }
}

void UART_Init(void) // 初始化串口
{
    PCON &= 0x7F; // 波特率不倍速
    SCON = 0x50;  // 8位数据,可变波特率
    TMOD &= 0x0F; // 清除定时器1模式位
    TMOD |= 0x20; // 设定定时器1为8位自动重装方式

    TL1 = 0xFD; // 设定定时初值
    TH1 = 0xFD; // 设定定时器重装值
    ET1 = 0;    // 禁止定时器1中断
    TR1 = 1;    // 启动定时器1
    EA  = 1;    // 使能总中断
    PT1 = 0;    // 定时器1为低优先级中断
    ES  = 1;    // 使能串口中断

    AUXR = 0x00;
}
void UART_Routine(void) interrupt 4 // 串口中断函数,接受数据
{
    if (RI == 1) {
        Data = SBUF; // 读取数据
        RI   = 0;
    }
}
void UART_SentByte(unsigned char dat) // 串口发送一个字节
{
    SBUF = dat;
    while (!TI);
    TI = 0;
}
void UART_SentDate(unsigned char *str)
{
    while (*str != '\0')
        UART_SentByte(*str++);
}
void HC138_Init(void)
{
    HC138_C = 1; // 设置74HC138为 100  4
    HC138_B = 0;
    HC138_A = 0;
}


【基础14】存储器映射扩展技术应用

新建工程,以MM 模式编写代码,在CT107D 单片机综合训练平台上,实现以下功能:

1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。

2、循环实现以下功能:

  • 首先,点亮指示灯低4 位,关闭高4 位,延时片刻;
  • 接着,点亮指示灯的高4 位,关闭低4 位,延时片刻;
  • 然后,关闭所有指示灯。
  • 接着,依次逐个点亮数码管的所有段码,每次只点亮一个数码管。

3、外部扩展资源的地址映射关系:

  • LED 指示灯---- 0x8000;
  • 蜂鸣器与继电器----0xa000;
  • 数码管位选----0xc000;
  • 数码管段码----0xe000

4、关于CT107D 存储器映射扩展MM 编程模式的设计提示:CT107D 平台的J13 要将1-2 脚短接,选择MM 模式。
程序中引入头文件“absacc.h”,通过XBYTE 关键字来直接操作扩展资源。

存储器映射扩展方式要占用单片机的P3.6 引脚。

IO扩展:

#include "reg51.h"

void Delay(unsigned int t);        // 延迟函数
void Select_HC573(unsigned int i); // 选择HC573

// 14存储器映射扩展技术应用(IO扩展)
void main(void)
{
    unsigned int i;
    while (1) {
        Select_HC573(4);
        P0 = 0xf0;
        Delay(1000);
        P0 = 0x0f;
        Delay(1000);
        P0 = 0xff;

        for (i = 0; i < 8; i++) {
            Select_HC573(6);
            P0 = 0x01 << i;
            Select_HC573(7);
            P0 = 0x00;
            Delay(1000);
        }
        P0 = 0xff;
        Delay(1000);
    }
}

void Delay(unsigned int t) // 延迟函数
{
    unsigned char i, j;
    while (t > 0) {
        i = 2;
        do {
            while (--j)
                ;
        } while (--i);
        t--;
    }
}

void Select_HC573(unsigned int i) // 选择HC573
{
    switch (i) {
        case 4:
            P2 = (P2 & 0X1f) | 0x80;
            break;
        case 5:
            P2 = (P2 & 0X1f) | 0xa0;
            break;
        case 6:
            P2 = (P2 & 0X1f) | 0xc0;
            break;
        case 7:
            P2 = (P2 & 0X1f) | 0xe0;
            break;
    }
}


存储器扩展:

#include "reg51.h"
#include "absacc.h"

void Delay(unsigned int t); // 延迟函数

voidmain(void)
{
    unsigned int i;
    while (1) {
        XBYTE[0x8000] = 0xf0;
        XBYTE[0x8000] = 0xf0;
        Delay(1000);
        XBYTE[0x8000] = 0x0f;
        Delay(1000);
        XBYTE[0x8000] = 0xff;

        for (i = 0; i < 8; i++) {
            XBYTE[0xc000] = 0x01 << i;
            XBYTE[0xe000] = 0x00;
            Delay(1000);
        }
        XBYTE[0xe000] = 0xff;
        Delay(1000);
    }
}

void Delay(unsigned int t) // 延迟函数
{
    unsigned char i, j;
    while (t > 0) {
        i = 2;
        do {
            while (--j)
                ;
        } while (--i);
        t--;
    }
}

【基础15】工厂灯光控制系统

新建工程,分别以I/O 模式和MM 模式编写代码,在CT107D 单片机综合训练平台上,实现灯光的本地操作和远程控制,并通过串口远程读取系统的运行时间,模拟实现工厂灯光控制系统。具体功能要求如下:

1、系统上电后,关闭蜂鸣器,关闭继电器,关闭8 个LED 灯。

2、首先检测LED 指示灯,从L1 到L8 依次逐个点亮,再依次逐个熄灭;然后检测数码管,从左到右依次点亮数码管的所有段码,再依次从左到右熄灭。

3、系统从上电开始显示系统运行时间,从00 时00 分00 秒开始,显示格式:

image-20230328134034643

4、8 个LED 指示灯分为2 组:L1、L2、L3 和L4 为远程控制组,L7 和L8 为本地控制组。远程控制组的指LED 示灯由上位机通过串口发送命令控制开关,本地控制组的LED 指示灯由独立按键控制开关。按键松开有效,S5 按键控制L7 指示灯,S4 按键控制L8 指示灯。

5、串口工作在模式1,即8 位UART 模式,波特率为9600(使用9600 波特率时,晶振时钟选择11.0592MHz。如果是其他频率的系统时钟,需要降低波特率,可选择用2400,否则串口通信可能出现乱码,无法正常收发数据)。

6、上位机通过串口控制下位机的L1 到L4 指示灯和读取系统运行时间。

7、上位机和单片机的串口通信规约如下表:

image-20230328134045274

控制命令为一个字节,高4 位为命令类型,低4 位为执行参数。控制灯光开关命令中,低4 位每1 位控制一个LED 灯的开关,无返回值。读取运行时间命令中,低4 位保留,各位为0,返回3 个字节的时间数据,用16 进制的BCD 码表示,先发时,再发分,后发秒。如果系统运行的时间为12 时24 分16 秒,收到读取时间命令字后,返回:0x12 0x24 0x16。

#include <REGX52.H>

sfr AUXR = 0x8e; // IAP15F2K61S新增配置

unsigned char code Duanma[18] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x80, 0xc6, 0xc0, 0x86, 0x8e, 0xbf, 0x7f};

sbit Key1 = P3^0; // 按键1
sbit Key2 = P3^1; // 按键2
		
sbit L7   = P0^6; // LED1
sbit L8   = P0^7; // LED1
	
void Delay(unsigned int t); // 延迟函数
void Select_HC138(unsigned int n); // 初始化74HC138
void LED_Shu(unsigned int location, unsigned int num); // 数码管显示函数
void Show_Time(void);//数码管显示时间
void Time0_Init(void);//定时器初始化
void UART_Init(void);//初始化串口
void check();//设备判断
void Check_Key(void);//判断按键
void UART_SendByte(unsigned char dat);//发送字节
void Check_Data(void);//判断串口数据	
	
unsigned char hour=0,min=0,sec=0;
unsigned int flag = 0;
unsigned char Data = 0x00; // 接收到的数据	

	
void main(){
	Time0_Init();
	UART_Init();
	while(1){
		if(flag == 0)//第一次运行,设备检验
		{
			check();
			flag = 1;
		}
		Show_Time();//数码管显示时间
		Check_Key();//判断按键
		Check_Data();//判断串口数据
	}
}

void Delay(unsigned int t)		//延迟函数
{
	
	unsigned char i, j;
	while(t){
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		t--;
	}
}

void Select_HC138(unsigned int n)
{
	
	switch(n){
		case 4:
			P2 = (P2 & 0x1f) | 0x80;		//Y4输出0,选择LED控制
			break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;		//Y5输出0,选择蜂鸣器和继电器控制
			break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;		//Y6输出0,选择数码管位选
			break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;		//Y7输出0,选择数码管段码
			break;
		case 0:
			P2 = (P2 & 0x1f) | 0x00;		//所有锁存器不选择
			break;
	}
}

void LED_Shu(unsigned int location, unsigned int num)
{
	Select_HC138(6);
	P0 = 0x01 << location;
	Select_HC138(7);
	P0 = Duanma[num];
	
	//消影
	Delay(1);
    P0 = 0xFF;
}

void Show_Time()//数码管显示时间
{
	LED_Shu(0, hour / 10);
    Delay(1);
    LED_Shu(1, hour % 10);
    Delay(1);
    LED_Shu(2, 16);

    LED_Shu(3, min / 10);
    Delay(1);
    LED_Shu(4, min % 10);
    Delay(1);
    LED_Shu(5, 16);

    LED_Shu(6, sec / 10);
    Delay(1);
    LED_Shu(7, sec % 10);
    Delay(1);
}

void Time0_Init(void)//50毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
    TL0 = 0xB0; // 设置定时初始值
    TH0 = 0x3C; // 设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0 = 1; // 允许定时器0中断
    EA  = 1; // 开总中断
    PT0 = 0; // 定时器0为低优先级中断
}

void check()//设备判断
{
	unsigned int i;
	Select_HC138(4);
	for(i = 0; i < 8; i++)
	{
		P0 = 0xff << i;
		Delay(500);
	}
	
	for(i = 0; i <= 8; i++)
	{
		P0 = ~(0xff << i);
		Delay(500);
	}
	
	for(i = 0; i<8; i++)
	{
		Select_HC138(6);
		P0 = 0x01 << i;
		Select_HC138(7);
		P0 = 0x00;
		Delay(500);
	}
	for(i = 0; i<8; i++)
	{
		Select_HC138(6);
		P0 = ~(0x01 << i);
		Select_HC138(7);
		P0 = 0xFF;
		Delay(500);
	}
}

void Check_Key(void)
{
	if(Key1 == 0)
	{
		Show_Time();
		while(Key1 == 0) 
			Show_Time();
		Select_HC138(4);
		L8 = ~L8;		
	}
	if(Key2 == 0)
	{
		Show_Time();
		while(Key2 == 0) 
			Show_Time();
		Select_HC138(4);
		L7 = ~L7;	
	}
}

void UART_Init(void)		//9600bps@11.0592MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	
	ES = 1;
	AUXR = 0x00;
}

void UART_SendByte(unsigned char dat)
{
	SBUF = dat;
    while (!TI);
    TI = 0;
}

void Check_Data(void)
{
	if(Data != 0x00)
	{
		switch(Data & 0xf0){
			case 0xa0:									//远程灯光控制命令
				Select_HC138(4);
                P0 = 0xff;
				P0 = P0 & (~Data | 0xf0);
				Select_HC138(0);
				Data = 0x00;
			break;
			
			case 0xb0:									//读取现场系统运行时间命令
				UART_SendByte((hour / 10 << 4) | (hour % 10));
				UART_SendByte((min / 10 << 4) | (min % 10));
				UART_SendByte((sec / 10 << 4) | (sec % 10));
				Data = 0x00;
			break;
		}
	}
}




void Time0_Run(void) interrupt 1
{
	unsigned char i;
    TL0 = 0xB0; // 设置定时初始值
    TH0 = 0x3C; // 设置定时初始值
	
	i++;
	if(i == 20)//1s
	{
		sec++;
		i = 0;
		if(sec == 60){
			min++;
			sec = 0;
			if(min == 60){
				hour++;
				min = 0;
				if(hour == 24)
					hour = 0;
			}
		}
	}
}

void UART_Run(void) interrupt 4
{
	if (RI == 1) {
        Data = SBUF;
        RI = 0;
    }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值