• C51项目 - 可调万年历


    一、实验目的

    使用51单片机作为主控芯片,制作可调万年历

    二、实验仪器

    主控芯片 STC89C52
    时钟芯片 DS1302
    温度传感器 DS18B20
    1602液晶 LCD12864
    任意红外遥控器
    晶振 11.0952M x1,32.768K x1
    电阻、电容若干(详见实验原理图)

    三、实验效果预览

    1.显示效果

    1602液晶屏显示:

    年/月/日 星期
    时:分:秒 AM/PM 温度


    图1 1602液晶屏显示效果

    2.调节效果

    红外遥控器任意按键进入调节模式请添加图片描述
    图2 调节模式显示效果

    调节模式被选中的数值下方出现光标,按 < 键和 > 键移动光标,按 + 键和 - 键改变光标选中数值,按 = 键退出调节模式(键值需要自行设置)。
    请添加图片描述
    图3 调节模式中将星期四改变为星期五

    四、实验原理

    LCD12864液晶屏VO端接电位器R21,调节R21,使液晶对比度最佳。
    在这里插入图片描述
    图4 可调万年历实验原理图

    五、单片机代码

    1.头文件包含

    #include 
    #include 
    
    • 1
    • 2

    2.类型定义

    定义字节型变量BYTE和字变量WORD

    typedef unsigned char BYTE;
    typedef unsigned short WORD;
    
    • 1
    • 2

    3.时钟模块

    sbit TSCLK = P1 ^ 0;	// 时钟线
    sbit TIO = P1 ^ 1;		// 数据线
    sbit TEN = P1 ^ 2;		// 使能端
    // 读一字节
    BYTE DS1302_read_byte(BYTE _Cmd)
    {
        BYTE i;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = _Cmd & 0x01;
            TSCLK = 1;
            _Cmd >>= 1;
        }
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            _Cmd >>= 1;
            if (TIO)
                _Cmd |= 0x80;
            TSCLK = 1;
        }
        return _Cmd;
    }
    // 写一字节
    void DS1302_write_byte(BYTE _Cmd, BYTE _Dat)
    {
        BYTE i;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = _Cmd & 0x01;
            TSCLK = 1;
            _Cmd >>= 1;
        }
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = _Dat & 0x01;
            TSCLK = 1;
            _Dat >>= 1;
        }
    }
    // 时钟突发突发模式读
    void clock_brust_read(BYTE *_Buf)
    {
        BYTE i, j = 0xbf;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = j & 0x01;
            TSCLK = 1;
            j >>= 1;
        }
        for (i = 0; i < 7; i++)
            for (j = 0; j < 8; j++) {
                TSCLK = 0;
                _Buf[i] >>= 1;
                if (TIO)
                    _Buf[i] |= 0x80;
                TSCLK = 1;
            }
    }
    // 时钟突发突发模式写
    void clock_brust_write(const BYTE *_Buf)
    {
        BYTE i, j = 0xbe, k;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = j & 0x01;
            TSCLK = 1;
            j >>= 1;
        }
        for (i = 0; i < 7; i++) {
            k = _Buf[i];
            for (j = 0; j < 8; j++) {
                TSCLK = 0;
                TIO = k & 0x01;
                TSCLK = 1;
                k >>= 1;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    4. 液晶显示模块

    #define LCD_DATA P0		// 液晶数据线
    sbit LCD_RS = P3 ^ 5; 	// 数据/命令选择端
    sbit LCD_WR = P3 ^ 6; 	// 读/写选择端
    sbit LCD_EN = P3 ^ 4; 	// 使能端
    // 读状态
    BYTE LCD_read_state()
    {
        BYTE state;
        LCD_RS = 0;
        LCD_WR = 1;
        LCD_EN = 1;
        state = LCD_DATA;
        LCD_EN = 0;
        return state;
    }
    // 写指令
    void LCD_write_cmd(BYTE _Cmd)
    {
        LCD_EN = 0;
        LCD_EN = 1;
        LCD_RS = 0;
        LCD_WR = 0;
        LCD_DATA = _Cmd;
        LCD_EN = 0;
    }
    // 读数据
    BYTE LCD_read_data()
    {
        BYTE i;
        LCD_RS = 1;
        LCD_WR = 1;
        LCD_EN = 1;
        i = LCD_DATA;
        LCD_EN = 0;
        return i;
    }
    // 写数据
    void LCD_write_data(BYTE _Dat)
    {
        LCD_EN = 0;
        LCD_EN = 1;
        LCD_RS = 1;
        LCD_WR = 0;
        LCD_DATA = _Dat;
        LCD_EN = 0;
    }
    // 等待写指令
    void LCD_wait_cmd(BYTE _Cmd)
    {
        while (LCD_read_state() & 0x80)
            ;
        LCD_write_cmd(_Cmd);
    }
    // 等待写数据
    void LCD_wait_write_data(BYTE _Dat)
    {
        while (LCD_read_state() & 0x80)
            ;
        LCD_write_data(_Dat);
    }
    // 等待读数据
    BYTE LCD_wait_read_data()
    {
        while (LCD_read_state() & 0x80)
            ;
        return LCD_read_data();
    }
    // 写入字符串
    void LCD_write_string(const char *_Str)
    {
        BYTE i = 0;
        while (_Str[i])
            LCD_wait_write_data(_Str[i++]);
    }
    #define _LCD_CLS 0x01 // 显示清屏
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    5.温度传感器模块

    sbit DS18B20 = P2 ^ 2;	// 温度传感器1-wire线
    // 1-wire初始化时序
    void init_DS18B20()
    {
        do {
            DS18B20 = 1;
            _nop_();
            DS18B20 = 0;
            timer0_delay(65074); // delay 499.45 us
            DS18B20 = 1;
            timer0_delay(65500); // delay 37.95 us
        } while (DS18B20);
        timer0_delay(65404); // delay 141.95 us
        DS18B20 = 1;
        _nop_();
    }
    // 1-wire写时序
    void write_byte_1wire(BYTE _Dat)
    {
        BYTE i;
        for (i = 0; i < 8; i++) {
            DS18B20 = 0;
            _nop_();
            DS18B20 = _Dat & 0x01 ? 1 : 0;
            timer0_delay(65464); // delay 76.95 us
            DS18B20 = 1;
            _nop_();
            _Dat >>= 1;
        }
    }
    // 1-wire读时序
    BYTE read_byte_1wire()
    {
        BYTE dat = 0, i;
        for (i = 0; i < 8; i++) {
            dat >>= 1;
            DS18B20 = 0;
            _nop_(); // 产生读时序
            DS18B20 = 1;
            _nop_(); // 释放总线
            if (DS18B20)
                dat |= 0x80;
            timer0_delay(65464); // delay 76.95 us
        }
        return dat;
    }
    // ROM指令
    #define _SEARCH_ROM 0xf0 // 搜索 ROM 指令
    #define _READ_ROM   0x33 // 读取 ROM 指令
    #define _MATH_ROM   0x55 // 匹配 ROM 指令
    #define _SIKP_ROM   0xcc // 忽略 ROM 指令
    #define _ALARM_ROM  0xec // 报警搜索指令
    // DS18B20功能指令
    #define _CONVERT_T         0x44 // 温度转换指令
    #define _WRITE_SCRATCHPAD  0x4e // 写暂存器指令
    #define _READ_SCRATCHPAD   0xbe // 读暂存器指令
    #define _COPY_SCRATCHPAD   0x48 // 拷贝暂存器指令
    #define _RECALL_E2         0xb8 // 召回 EEPROM 指令
    #define _READ_POWER_SUPPLY 0xb4 // 读电源模式指令
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    6. 红外通讯模块

    BYTE IRtime;    // 红外高低电平持续时间
    BYTE IRcord[2]; // 8位地址+8位数据
    bit IRdone = 0; // 数据接收完成标志位
    // 定时器1中断 - 每中断一次需要256个机器周期
    void timer1() interrupt 3
    {
        IRtime++; // _MACHINE_CYCLE*256=277.76 μs
    }
    // 外部中断0
    void int0() interrupt 0
    {
        static BYTE i;            // 32次数据计数
        static bit startflag = 0; // 开始储存脉宽标志位
        static BYTE IRdata[4];    // 数据接收缓冲区
        BYTE j;
        if (startflag) {
            if (IRtime >= 32 && IRtime < 53) { // 起始码判定 8.8ms~14ms
                i = 0;
                IRtime = 0;
                return;
            }
            j = (i++) >> 3;
            IRdata[j] >>= 1;
            if (IRtime > 5) // 数据0=高电平560μs+低电平560μs=1120μs
                IRdata[j] |= 0x80;
            IRtime = 0;    // 计数清零
            if (i == 32) { // 如果已经存入了32次脉宽
                i = 0;     // 数据计数清零准备下次存入
                if (IRdata[0] == ~IRdata[1] && IRdata[2] == ~IRdata[3]) {
                    IRdone = 1; // 32位数据接收完成
                    IRcord[0] = IRdata[0];
                    IRcord[1] = IRdata[2];
                }
            }
        } else {
            IRtime = 0;
            startflag = 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    7.开机初始化

    /* 开机初始化 */
    void init()
    {
        // 初始化时钟模块
        DS1302_write_byte(0x8e, 0x80); // 开写保护
        // 初始化LCD1802液晶
        delay_ms(15);
        LCD_write_cmd(0x38);
        delay_ms(5);
        LCD_write_cmd(0x38);
        delay_ms(5);
        LCD_write_cmd(0x38);
        LCD_wait_cmd(0x38);     // 显示模式设置
        LCD_wait_cmd(0x0c);     // 开显示 不显示光标 光标不闪烁
        LCD_wait_cmd(_LCD_CLS); // 显示清屏
        /* 红外通讯初始化 - 使用定时器1 */
        TMOD = (TMOD & 0x0f) | 0x20;
        TH1 = 0;
        TL1 = 0;
        TR1 = 1;
        EA = 1;  // 开总中断
        ET1 = 1; // 开定时器1中断
        EX0 = 1; // 开外部中断0
        IT0 = 1; // 设置外部中断0边沿触发
        TR1 = 1; // 启动定时器0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    8.特殊功能函数

    /* 转换函数 */
    // 组合BCD码转换函数
    BYTE to_BCD(BYTE _Dat)
    {
        return ((_Dat / 10) << 4) | _Dat % 10;
    }
    // 非组合BCD码 ---> 可显示字符ASCII
    BYTE to_hex(BYTE _Dat)
    {
        _Dat += _Dat < 10 ? '0' : '7';
        return _Dat;
    }
    
    // 返回是否是闰年
    bit is_leap(WORD _Year)
    {
        return _Year % 4 == 0 && _Year % 100 != 0 || _Year % 400 == 0;
    }
    
    /* 延时函数 */
    // 低精度毫秒级延时
    void delay_ms(WORD _Ms)
    {
        BYTE x;
        while (_Ms--)
            for (x = 144; x > 0; x--)
                ;
    }
    // 定时器0延时
    void timer0_delay(WORD _Th)
    {
        TMOD = (TMOD & 0xf0) | 0x01;
        TH0 = _Th >> 8;
        TL0 = _Th & 0xff;
        TR0 = 1;
        while (TF0 == 0)
            ;
        TF0 = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    9.代码段常量

    // 星期的英文缩写
    char code weekday[7][3] = {
        "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
    // 一个月有几天(平年)
    BYTE code monthday[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    • 1
    • 2
    • 3
    • 4
    • 5

    10.完整代码

    #include 
    #include 
    
    /* typedef */
    typedef unsigned char BYTE;
    typedef unsigned short WORD;
    
    /* cast */
    BYTE to_BCD(BYTE _Dat)
    {
        return ((_Dat / 10) << 4) | _Dat % 10;
    }
    BYTE to_hex(BYTE _Dat)
    {
        _Dat += _Dat < 10 ? '0' : '7';
        return _Dat;
    }
    
    char code weekday[7][3] = {
        "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
    BYTE code monthday[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    bit is_leap(WORD _Year)
    {
        return _Year % 4 == 0 && _Year % 100 != 0 || _Year % 400 == 0;
    }
    
    /* 时钟模块 */
    sbit TSCLK = P1 ^ 0;
    sbit TIO = P1 ^ 1;
    sbit TEN = P1 ^ 2;
    // 读一字节
    BYTE DS1302_read_byte(BYTE _Cmd)
    {
        BYTE i;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = _Cmd & 0x01;
            TSCLK = 1;
            _Cmd >>= 1;
        }
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            _Cmd >>= 1;
            if (TIO)
                _Cmd |= 0x80;
            TSCLK = 1;
        }
        return _Cmd;
    }
    // 写一字节
    void DS1302_write_byte(BYTE _Cmd, BYTE _Dat)
    {
        BYTE i;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = _Cmd & 0x01;
            TSCLK = 1;
            _Cmd >>= 1;
        }
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = _Dat & 0x01;
            TSCLK = 1;
            _Dat >>= 1;
        }
    }
    // 时钟突发突发模式读
    void clock_brust_read(BYTE *_Buf)
    {
        BYTE i, j = 0xbf;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = j & 0x01;
            TSCLK = 1;
            j >>= 1;
        }
        for (i = 0; i < 7; i++)
            for (j = 0; j < 8; j++) {
                TSCLK = 0;
                _Buf[i] >>= 1;
                if (TIO)
                    _Buf[i] |= 0x80;
                TSCLK = 1;
            }
    }
    // 时钟突发突发模式写
    void clock_brust_write(const BYTE *_Buf)
    {
        BYTE i, j = 0xbe, k;
        TEN = 0;
        TSCLK = 0;
        TEN = 1;
        for (i = 0; i < 8; i++) {
            TSCLK = 0;
            TIO = j & 0x01;
            TSCLK = 1;
            j >>= 1;
        }
        for (i = 0; i < 7; i++) {
            k = _Buf[i];
            for (j = 0; j < 8; j++) {
                TSCLK = 0;
                TIO = k & 0x01;
                TSCLK = 1;
                k >>= 1;
            }
        }
    }
    
    /* 延时 */
    // 低精度毫秒级延时
    void delay_ms(WORD _Ms)
    {
        BYTE x;
        while (_Ms--)
            for (x = 144; x > 0; x--)
                ;
    }
    // 定时器0延时
    void timer0_delay(WORD _Th)
    {
        TMOD = (TMOD & 0xf0) | 0x01;
        TH0 = _Th >> 8;
        TL0 = _Th & 0xff;
        TR0 = 1;
        while (TF0 == 0)
            ;
        TF0 = 0;
    }
    
    /* LCD1802液晶 */
    #define LCD_DATA P0
    sbit LCD_RS = P3 ^ 5; // 数据/命令选择端
    sbit LCD_WR = P3 ^ 6; // 读/写选择端
    sbit LCD_EN = P3 ^ 4; // 使能端
    // 读状态
    BYTE LCD_read_state()
    {
        BYTE state;
        LCD_RS = 0;
        LCD_WR = 1;
        LCD_EN = 1;
        state = LCD_DATA;
        LCD_EN = 0;
        return state;
    }
    // 写指令
    void LCD_write_cmd(BYTE _Cmd)
    {
        LCD_EN = 0;
        LCD_EN = 1;
        LCD_RS = 0;
        LCD_WR = 0;
        LCD_DATA = _Cmd;
        LCD_EN = 0;
    }
    // 读数据
    BYTE LCD_read_data()
    {
        BYTE i;
        LCD_RS = 1;
        LCD_WR = 1;
        LCD_EN = 1;
        i = LCD_DATA;
        LCD_EN = 0;
        return i;
    }
    // 写数据
    void LCD_write_data(BYTE _Dat)
    {
        LCD_EN = 0;
        LCD_EN = 1;
        LCD_RS = 1;
        LCD_WR = 0;
        LCD_DATA = _Dat;
        LCD_EN = 0;
    }
    // 等待写指令
    void LCD_wait_cmd(BYTE _Cmd)
    {
        while (LCD_read_state() & 0x80)
            ;
        LCD_write_cmd(_Cmd);
    }
    // 等待写数据
    void LCD_wait_write_data(BYTE _Dat)
    {
        while (LCD_read_state() & 0x80)
            ;
        LCD_write_data(_Dat);
    }
    // 等待读数据
    BYTE LCD_wait_read_data()
    {
        while (LCD_read_state() & 0x80)
            ;
        return LCD_read_data();
    }
    // 写入字符串
    void LCD_write_string(const char *_Str)
    {
        BYTE i = 0;
        while (_Str[i])
            LCD_wait_write_data(_Str[i++]);
    }
    #define _LCD_CLS 0x01 // 显示清屏
    
    /* 1-wire总线 */
    sbit DS18B20 = P2 ^ 2;
    // 1-wire初始化时序
    void init_DS18B20()
    {
        do {
            DS18B20 = 1;
            _nop_();
            DS18B20 = 0;
            timer0_delay(65074); // delay 499.45 us
            DS18B20 = 1;
            timer0_delay(65500); // delay 37.95 us
        } while (DS18B20);
        timer0_delay(65404); // delay 141.95 us
        DS18B20 = 1;
        _nop_();
    }
    // 1-wire写时序
    void write_byte_1wire(BYTE _Dat)
    {
        BYTE i;
        for (i = 0; i < 8; i++) {
            DS18B20 = 0;
            _nop_();
            DS18B20 = _Dat & 0x01 ? 1 : 0;
            timer0_delay(65464); // delay 76.95 us
            DS18B20 = 1;
            _nop_();
            _Dat >>= 1;
        }
    }
    // 1-wire读时序
    BYTE read_byte_1wire()
    {
        BYTE dat = 0, i;
        for (i = 0; i < 8; i++) {
            dat >>= 1;
            DS18B20 = 0;
            _nop_(); // 产生读时序
            DS18B20 = 1;
            _nop_(); // 释放总线
            if (DS18B20)
                dat |= 0x80;
            timer0_delay(65464); // delay 76.95 us
        }
        return dat;
    }
    // ROM指令
    #define _SEARCH_ROM 0xf0 // 搜索 ROM 指令
    #define _READ_ROM   0x33 // 读取 ROM 指令
    #define _MATH_ROM   0x55 // 匹配 ROM 指令
    #define _SIKP_ROM   0xcc // 忽略 ROM 指令
    #define _ALARM_ROM  0xec // 报警搜索指令
    // DS18B20功能指令
    #define _CONVERT_T         0x44 // 温度转换指令
    #define _WRITE_SCRATCHPAD  0x4e // 写暂存器指令
    #define _READ_SCRATCHPAD   0xbe // 读暂存器指令
    #define _COPY_SCRATCHPAD   0x48 // 拷贝暂存器指令
    #define _RECALL_E2         0xb8 // 召回 EEPROM 指令
    #define _READ_POWER_SUPPLY 0xb4 // 读电源模式指令
    
    /* 红外通讯 */
    BYTE IRtime;    // 红外高低电平持续时间
    BYTE IRcord[2]; // 8位地址+8位数据
    bit IRdone = 0; // 数据接收完成标志位
    // 定时器1中断 - 每中断一次需要256个机器周期
    void timer1() interrupt 3
    {
        IRtime++; // _MACHINE_CYCLE*256=277.76 μs
    }
    // 外部中断0
    void int0() interrupt 0
    {
        static BYTE i;            // 32次数据计数
        static bit startflag = 0; // 开始储存脉宽标志位
        static BYTE IRdata[4];    // 数据接收缓冲区
        BYTE j;
        if (startflag) {
            if (IRtime >= 32 && IRtime < 53) { // 起始码判定 8.8ms~14ms
                i = 0;
                IRtime = 0;
                return;
            }
            j = (i++) >> 3;
            IRdata[j] >>= 1;
            if (IRtime > 5) // 数据0=高电平560μs+低电平560μs=1120μs
                IRdata[j] |= 0x80;
            IRtime = 0;    // 计数清零
            if (i == 32) { // 如果已经存入了32次脉宽
                i = 0;     // 数据计数清零准备下次存入
                if (IRdata[0] == ~IRdata[1] && IRdata[2] == ~IRdata[3]) {
                    IRdone = 1; // 32位数据接收完成
                    IRcord[0] = IRdata[0];
                    IRcord[1] = IRdata[2];
                }
            }
        } else {
            IRtime = 0;
            startflag = 1;
        }
    }
    
    /* 开机初始化 */
    void init()
    {
        /* 初始化数码管 */
        NIXIE_TUBE = 0x00;
        DU = 1;
        DU = 0;
        WE = 0;
        // 初始化时钟模块
        DS1302_write_byte(0x8e, 0x80); // 开写保护
        // 初始化LCD1802液晶
        delay_ms(15);
        LCD_write_cmd(0x38);
        delay_ms(5);
        LCD_write_cmd(0x38);
        delay_ms(5);
        LCD_write_cmd(0x38);
        LCD_wait_cmd(0x38);     // 显示模式设置
        LCD_wait_cmd(0x0c);     // 开显示 不显示光标 光标不闪烁
        LCD_wait_cmd(_LCD_CLS); // 显示清屏
        /* 红外通讯初始化 - 使用定时器1 */
        TMOD = (TMOD & 0x0f) | 0x20;
        TH1 = 0;
        TL1 = 0;
        TR1 = 1;
        EA = 1;  // 开总中断
        ET1 = 1; // 开定时器1中断
        EX0 = 1; // 开外部中断0
        IT0 = 1; // 设置外部中断0边沿触发
        TR1 = 1; // 启动定时器0
    }
    
    void main()
    {
        BYTE i, j, k;
        BYTE buf[7] = {0, 2, 13, 17, 11, 4, 22};
        char line1[17] = "2022/03/11 Wed:3";
        char line2[17] = "21:40:00 PM 37C";
        WORD temp;
        bit IRflag = 0;
        BYTE cursor = 0x00;
        for (i = 0; i < 7; i++)
            buf[i] = to_BCD(buf[i]);
        init();
        DS1302_write_byte(0x8e, 0x00); // 关写保护
        clock_brust_write(buf);
        DS1302_write_byte(0x8e, 0x80); // 开写保护
        while (1) {
            clock_brust_read(buf);
            /* update line1 */
            line1[2] = '0' + (buf[6] >> 4);
            line1[3] = '0' + (buf[6] & 0x0f);
            line1[5] = '0' + (buf[4] >> 4);
            line1[6] = '0' + (buf[4] & 0x0f);
            line1[8] = '0' + (buf[3] >> 4);
            line1[9] = '0' + (buf[3] & 0x0f);
            buf[5]--;
            line1[11] = weekday[buf[5]][0];
            line1[12] = weekday[buf[5]][1];
            line1[13] = weekday[buf[5]][2];
            buf[5]++;
            line1[15] = '0' + buf[5];
            /* update line2 */
            line2[0] = '0' + (buf[2] >> 4);
            line2[1] = '0' + (buf[2] & 0x0f);
            line2[3] = '0' + (buf[1] >> 4);
            line2[4] = '0' + (buf[1] & 0x0f);
            line2[6] = '0' + (buf[0] >> 4);
            line2[7] = '0' + (buf[0] & 0x0f);
            line2[9] = buf[2] >= 0x12 ? 'P' : 'A';
            /* update temperature */
            init_DS18B20();
            write_byte_1wire(_SIKP_ROM);
            write_byte_1wire(_CONVERT_T);
            init_DS18B20();
            write_byte_1wire(_SIKP_ROM);
            write_byte_1wire(_READ_SCRATCHPAD);
            temp = read_byte_1wire();
            temp |= read_byte_1wire() << 8;
            temp >>= 4;
            line2[12] = '0' + temp / 10;
            line2[13] = '0' + temp % 10;
            /* display */
            LCD_wait_cmd(0x80);
            LCD_write_string(line1);
            LCD_write_cmd(0xc0);
            LCD_write_string(line2);
            /* IR receive */
            if (IRdone) {
                if (IRcord[0] == 0x00) {
                    if (IRflag == 0)
                        IRflag = 1;
                    else
                        switch (IRcord[1]) {
                            case 0x44: // PREV
                                switch (cursor) {
                                    case 0x05:
                                    case 0x08:
                                    case 0x43:
                                    case 0x46:
                                        cursor -= 2;
                                        break;
                                    case 0x0f:
                                        cursor = 0x09;
                                        break;
                                    case 0x40:
                                        cursor = 0x0f;
                                        break;
                                    case 0x00:
                                        cursor = 0x47;
                                        break;
                                    default:
                                        cursor--;
                                }
                                break;
                            case 0x40: // NEXT
                                switch (cursor) {
                                    case 0x03:
                                    case 0x06:
                                    case 0x41:
                                    case 0x44:
                                        cursor += 2;
                                        break;
                                    case 0x09:
                                        cursor = 0x0f;
                                        break;
                                    case 0x0f:
                                        cursor = 0x40;
                                        break;
                                    case 0x47:
                                        cursor = 0x00;
                                        break;
                                    default:
                                        cursor++;
                                }
                                break;
                            case 0x07: // VOL-
                            case 0x15: // VOL+
                                j = IRcord[1] == 0x15 ? 0x01 : 0x09;
                                switch (cursor) {
                                    case 0x00:
                                    case 0x01:
                                        line1[cursor] = (line1[cursor] - '0' + j) % 10 + '0';
                                        LCD_wait_cmd(0x80 | cursor);
                                        LCD_wait_write_data(line1[cursor]);
                                        break;
                                    case 0x02:
                                    case 0x03:
                                        DS1302_write_byte(0x8e, 0x00); // 关写保护
                                        i = DS1302_read_byte(0x8d);
                                        i += j << ((0x03 - cursor) << 2);
                                        i = (((i >> 4) % 10) << 4) | ((i & 0x0f) % 10);
                                        DS1302_write_byte(0x8c, i);
                                        DS1302_write_byte(0x8e, 0x80); // 开写保护
                                        break;
                                    case 0x05:
                                    case 0x06:
                                        DS1302_write_byte(0x8e, 0x00); // 关写保护
                                        i = DS1302_read_byte(0x89);
                                        if (cursor == 0x05) {
                                            if (i >> 4)
                                                i &= 0x0f;
                                            else {
                                                i |= 0x10;
                                                if (i > 0x12)
                                                    i &= 0x0f;
                                            }
                                        } else {
                                            k = i & 0x0f;
                                            i &= 0xf0;
                                            if (i && j == 0x09)
                                                j = 0x02;
                                            k = (k + j) % (i ? 3 : 10);
                                            i |= k;
                                        }
                                        DS1302_write_byte(0x88, i);
                                        DS1302_write_byte(0x8e, 0x80); // 开写保护
                                        break;
                                    case 0x08:
                                    case 0x09:
                                        i = buf[3]; // 日
                                        buf[4] = (buf[4] >> 4) * 10 + (buf[4] & 0x0f);
                                        buf[3] = monthday[buf[4] - 1];
                                        if (buf[4] == 2 && is_leap((WORD)(line1[0] - '0') * 1000 + (WORD)(line1[1] - '0') * 100 + (WORD)buf[6]))
                                            buf[3]++;
                                        if (cursor == 0x08) {
                                            buf[0] = buf[3] / 10; // mod
                                            if ((i & 0x0f) <= buf[3] % 10)
                                                buf[0]++;
                                            if (j == 0x09)
                                                j = buf[0] - 1;
                                            k = i >> 4;
                                            i &= 0x0f;
                                            k = (k + j) % buf[0];
                                            i |= k << 4;
                                        } else {
                                            buf[0] = 10; // mod;
                                            if ((i >> 4) == buf[3] / 10)
                                                buf[0] = buf[3] % 10;
                                            if (buf[0]) {
                                                if (j == 0x09)
                                                    j = buf[0] - 1;
                                                k = i & 0x0f;
                                                i &= 0xf0;
                                                k = (k + j) % buf[0];
                                                i |= k;
                                            }
                                        }
                                        DS1302_write_byte(0x8e, 0x00); // 关写保护
                                        DS1302_write_byte(0x86, i);
                                        DS1302_write_byte(0x8e, 0x80); // 开写保护
                                        break;
                                    case 0x0f:
                                        i = buf[5];
                                        if (j == 0x09)
                                            j = 0x06;
                                        i = (i - 1 + j) % 7 + 1;
                                        DS1302_write_byte(0x8e, 0x00); // 关写保护
                                        DS1302_write_byte(0x8a, i);
                                        DS1302_write_byte(0x8e, 0x80); // 开写保护
                                        break;
                                    case 0x40:
                                    case 0x41:
                                        i = buf[2];
                                        if (cursor == 0x40) {
                                            buf[0] = 2; // mod
                                            if ((i & 0x0f) < 4)
                                                buf[0]++;
                                            if (j == 0x09)
                                                j = buf[0] - 1;
                                            k = i >> 4;
                                            i &= 0x0f;
                                            k = (k + j) % buf[0];
                                            i |= k << 4;
                                        } else {
                                            buf[0] = i >> 4 < 2 ? 10 : 4; // mod
                                            if (j == 0x09)
                                                j = buf[0] - 1;
                                            k = i & 0x0f;
                                            i &= 0xf0;
                                            k = (k + j) % buf[0];
                                            i |= k;
                                        }
                                        DS1302_write_byte(0x8e, 0x00); // 关写保护
                                        DS1302_write_byte(0x84, i);
                                        DS1302_write_byte(0x8e, 0x80); // 开写保护
                                        break;
                                    case 0x43:
                                    case 0x44:
                                    case 0x46:
                                    case 0x47:
                                        i = buf[cursor <= 0x44 ? 1 : 0];
                                        if (cursor == 0x43 || cursor == 0x46) {
                                            if (j == 0x09)
                                                j = 0x05;
                                            k = i >> 4;
                                            i &= 0x0f;
                                            k = (k + j) % 0x06;
                                            i |= k << 4;
                                        } else {
                                            k = i & 0x0f;
                                            i &= 0xf0;
                                            k = (k + j) % 10;
                                            i |= k;
                                        }
                                        DS1302_write_byte(0x8e, 0x00); // 关写保护
                                        DS1302_write_byte(cursor <= 0x44 ? 0x82 : 0x80, i);
                                        DS1302_write_byte(0x8e, 0x80); // 开写保护
                                        break;
                                }
                                break;
                            case 0x09: // EQ
                                IRflag = 0;
                                LCD_wait_cmd(0x0c);
                                break;
                        }
                }
                IRdone = 0;
            }
            /* IR display */
            if (IRflag) {
                LCD_wait_cmd(0x80 | cursor);
                LCD_wait_cmd(0x0e);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
  • 相关阅读:
    企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
    RMAN-08137 主库无法删除归档文件
    RabbitMQ 的延时队列和镜像队列原理与实战
    ISIS—ISIS邻居建立&影响ISIS邻居建立的因素有哪些—03
    在 LangChain 尝试了 N 种可能后,我发现了分块的奥义!
    夯实算法-跳跃游戏
    Jmeter(五):json提取器元件及jsonpath介绍,响应断言元件
    线上展厅的作用 广州商迪
    Win11系统设置闪退的解决方案
    假期AI新闻热点:亚运会Al技术亮点;微软GPT-4V论文精读;Perplexity推出pplx-api;DALL-E 3多渠道测评 | ShowMeAI日报
  • 原文地址:https://blog.csdn.net/m0_55464171/article/details/127923751