• STC15单片机-数码管显示PCB板温度(TM1620驱动芯片使用介绍)


    数码管显示PCB板温度、TM1620使用介绍

    数码管驱动方式

    单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间
    专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可,如TM1620、TM1640

    TM1620

    TM1620是一种LED(发光二极管显示器)驱动控制专用IC,内部集成有MCU数字接口、数据锁存器、LED驱动等电路。多用于数码管或LED显示设备。

    工作温度:-0.5V ~ +7.0V

    特性说明
    1. 采用CMOS工艺
    2. 显示模式(8 段×6 位~10段×4位)
    3. 辉度调节电路(8 级占空比可调)
    4. 串行接口(CLK,STB,DIN)
    5. 振荡方式:内置RC振荡
    6. 内置上电复位电路
    7. 内置数据锁存电路
    8. 内置针对LED反偏漏电导致暗亮问题优化电路
    9. 抗干扰能力强
    10. 封装形式:SOP20
    管脚定义

    在这里插入图片描述

    管脚功能
    符号管脚名称管脚号说明
    DIN数据输入18在时钟上升沿输入串行数据,从低位开始。
    CLK时钟输入19在上升沿读取串行数据,下降沿输出数据。
    STB片选输入20在下降沿初始化串行接口,随后等待接收指令。STB为低后的第一个字节作为指令,当处理指令时,当前其它处理被终止。当STB为高时,CLK 被忽略。
    SGE1 ~SGE8输出(段)2 ~ 9段输出,P管开漏输出
    GRID1 ~ GRID4输出(位)16 ~ 17 、13 ~ 14位输出,N管开漏输出
    SEG13/GRID6 ~ SEG14/GRID5输出(段/位)10 ~ 11段/位复用输出,只能选段或位输出
    VDD逻辑电源1接电源正
    GND逻辑地12、15接系统地
    硬件设计电路

    DIG1、DIG2连接到了TM1620的位选引脚,分别是GRID1和GRID2,因为数码管就两个,就靠这两个位来进行控制

    SEG1 ~ SEG8是段选,就是控制 A ~ DP 8个段哪一个段亮,8个位组成一个字节

    STB、CLK、DIN是TM1620接收STC15单片机控制信号的,通过厂商定义的串行协议进行通信

    在这里插入图片描述

    串行通信

    在进行通行前,要先将STB拉低,开启数据传输,CLK在低电平时,可以往DIN上放数据,当CLK在高电平时,TM1620就读取DIN上的数据,数据传输是从低位开始,一位一位地传,最高位结束

    在这里插入图片描述

    /*
    * @name   TM1620_Write_Byte
    * @brief  TM1620写入一个字节
    * @param  dat:待写入数据
    * @retval None   
    */
    static void TM1620_Write_Byte(uint8_t dat)
    {
        uint8_t i = 0;
        STB = 0;
        Public.Delay_ms(1);
        for(i=0;i<8;i++)
        {
            //CLK为低电平时往DIN上放数据
             CLK = 0;
    		DIN = 0x01 & (dat>>i);	//先取出最低位进行发送,然后dat右移,把最低位移出去,再取补上地低位进行发送
            _nop_();    //延时1us
            
            //CLK为高电平时TM1620读取DIN上的数据
            CLK = 1;
            _nop_();    //延时1us
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    通信命令

    通过上面写好的TM1620_Write_Byte()函数,就可以往TM1620写入数据了,那TM1620怎么识别STC15传输过来的数据是要干嘛的呢?

    厂商对TM1620也做了设置,来识别传输过来的数据的目的

    在这里插入图片描述

    简单理解:调用TM1620_Write_Byte()函数往TM1620写入一个字节数据,共8位,而TM1620就是根据最高的两位B7、B6来区别为不同的指令,如上表所示,4种不同的指令分别表示了不同的命令,而这命令的说明也是只有高手才能一眼看出是什么作用的,新手想弄懂还得花点时间

    显示模式命令

    在这里插入图片描述

    B7、B6都为0的命令就是显示模式命令,这两位是固定的了,该模式下B5 ~ B2是没用的位,所以就剩下B1、B0来控制,是用来设置TM1620要控制多少位和多少段的,有4位10段,这说明有4个数码管,一个数码管里面有10个段要控制,用函数往TM1620写入0x00就表示设置显示模式为4位10段;

    本次实验用的到是6位8段,但实战板数码管只有两个,就是由上面硬件电路图中的DIG1和DIG2位控制,其他的DIG位选引脚不接,8段就是SEG1 ~ SEG8段选全用上,写入0x02就是设置为6位8段

    数据命令设置

    在这里插入图片描述

    B7为0,B6为1就是数据命令模式,B5和B4没有用到,靠B3 ~ B0来设置为不同的数据命令;

    主要是地址增加模式设置,数据模式设置没用到,测试模式是厂商内部测试用的,做实验也没用到

    自动地址增加:后面会介绍到显示寄存器,就是往显示寄存器写入一个地址初值,然后写入数据(要显示的段),每次写入一个字节数据后,地址指针会从初值自动加一,跳到下一个地址,可以不用再设置地址,直接写入数据;就只设置一次地址,可以连续写数据;

    固定地址:先写入地址,再写入数据,写下一个数据前,要先再写入一个地址,就每次写数据前都要先写地址

    显示控制命令

    在这里插入图片描述

    这个命令比较简单,就是用来设置数码管显示的亮度,B7为1,B6为0,B5和B4没用,用剩余位进行选择控制

    亮度调整是用了PWM,是TM1620内部自动发出的PWM波,只要写入不同的命令就能控制输出不同的占空比,这不需要额外的控制线

    注意B3是控制显示开关的,要数码管亮起来,B3必须为1,也就是设置脉冲宽度的命令中,B3都是1,如设置脉冲宽度为1/16,那写入的命令就是0x88;让数码管不亮,则B3位清0,写入的命令就是0x80

    显示寄存器地址

    我觉得在看地址命令设置之前,要先看懂显示寄存器地址的说明,所以先把显示寄存器地址解释一下

    在这里插入图片描述

    对这个显示寄存器的简单理解就是:数码管的位选,选择哪一个数码管亮起

    GRID1 ~ GRID6 共6个位选引脚,一个位选引脚控制一个数码管;那数码管有可能接到GRID1,也有可能接到GRID6,当然也可以6个数码管分别接完6个GRID引脚,那想指定某一个数码管亮起来该怎么设置?这就要通过往TM1620写入上表中的地址数据来进行选择某一位选引脚

    先看表右边的位选,再水平着向左看,HL(低四位)和HU(高四位)是对段选SEG来说的,和位选GRID的地址设置没关系,先不用管。

    GRID1对应的地址是01和00,也就是说可以往TM1620写入0x01或者0x00来选择是GRID1这个位选引脚,那为什么两个地址都是选择这个位选引脚呢?因为地址00对应了SEG1 ~ SEG8这8个段选,地址01对应了SEG13和SEG14这两个段选(表的上半部分),因为TM1620是可以控制9段或者10段的,所以复用了SEG13和SEG14这两个段选引脚;但本次实验中的数码管是8段的,分别接到了SEG1 ~ SEG8,而位选引脚接到了GRID1,所以位选就是GRID1,再根据段选,GRID1的地址就设置为0x00,没有用到SEG13和SEG14,所以不用管0x01;其他位选引脚同理

    而图片开头的文字说明说12个字节单元也能理解了,就6个位选,每个位选对应两种不同的地址,6 * 2 = 12,所以是12个字节单元

    这就相当于一步把位选和段选都确定了,因为确定位选引脚后,那也要确定段选引脚吧,段选选好后,后续再写入数据控制哪几个段亮起,就可以显示数字了

    地址命令设置

    在这里插入图片描述

    经过上面的显示寄存器地址解释,就可以理解这个地址命令设置是什么东西了;上面的位选地址00和01等的地址怎么来,就是在这里进行设置的

    B7、B6固定都为1,B3 ~ B0不同的组合就表示不同的地址,这些地址在程序中最好先用宏定义写好,在后面想设置位选和段选时,就直接把这些地址写入到TM1620就行了;可以说这些地址就是为了设置显示寄存器而准备的


    前面介绍的都是一些命令或地址,TM1620收到了这些命令会做出相应的设置,把这些命令都通过TM1620_Write_Byte()函数发送给TM1620即可,数码管就会亮起;那具体怎么个发送法呢,厂商也给出了通信的图示,如下面介绍到的


    数据传输(地址自动增加模式)

    在这里插入图片描述

    按照厂商给的这个数据传输图,首先在STB为低电平时,才开始往DIN上发送命令,每一步命令是设置什么的图上有说明,注意每次传输完一个命令后,STB要拉高,下次发送命令时要先再次拉低再发送命令;在发送段选数据的时候STB就不用再拉高了

    注意:TM1620的数据手册上有这样一句话:芯片显示寄存器在上电瞬间其内部保存的值可能是随机不确定的,此时客户直接发送开屏命令,将有可能出现显示乱码。所以我司建议客户对显示寄存器进行一次上电清零操作,即上电后向12位显存地址(00H-0BH)中全部写入数据0x00

    清零操作就可以设置为地址自动增加模式,然后写入位选初始地址是0x00,从GRID1开始,然后用循环不断写入段选数据0x00,进行清零操作,后续代码中有这一步

    数据传输(固定地址模式)

    在这里插入图片描述

    固定地址模式就是每次写入段选数据前都要先确定位选,而且写完段选数据后STB要拉高,写下一个位选地址时STB要再次拉低

    程序

    文件结构

    在这里插入图片描述

    main.c ->主函数文件,包含main函数等;

    Public.c ->公共函数文件,包含Delay延时函数等;

    Sys_init ->系统初始化函数,包含GPIO初始化函数等;

    ADC.c ->ADC初始化,采集ADC值等;

    NTC.c ->NTC外设函数,包含查表,获取环境温度等;

    TM1620.c ->驱动IC初始化,协议,温度显示等函数;

    实验现象

    每间隔 500ms 通过ADC获取一次PCB板温度,数码管显示PCB板温度,数码管亮度会自动变化。

    TM1620.h

    主要是定义4种不同命令的枚举类型,将所有的十六进制的命令都写成能看懂的名称,不然在c文件里发送0x00根本不知道是什么命令,还得去看手册

    #ifndef __TM1620_H_
    #define __TM1620_H_
    
    //显示模式枚举类型
    typedef enum
    {
        Disp_Mode_GRID4_SEG10 = 0x00,       //4位10段
        Disp_Mode_GRID5_SEG9  = 0x01,       //5位9段
        Disp_Mode_GRID6_SEG8  = 0x02        //6位8段
    }Disp_Mode_t;
    
    //写数据地址模式枚举类型
    typedef enum
    {
        Write_Data_Addr_Auto_Add = 0x40,    //自动地址增加
        Write_Data_Addr_Fix      = 0x44     //固定地址
    }Write_Data_Addr_Mode_t;
    
    //辉度等级枚举类型
    typedef enum
    {
        Brightness_level_0  =   0x80,       //显示关
        Brightness_level_1  =   0x88,       //脉冲宽度为1/16
        Brightness_level_2  =   0x89,       //脉冲宽度为2/16
        Brightness_level_3  =   0x8A,       //脉冲宽度为4/16
        Brightness_level_4  =   0x8B,       //脉冲宽度为10/16
        Brightness_level_5  =   0x8C,       //脉冲宽度为11/16
        Brightness_level_6  =   0x8D,       //脉冲宽度为12/16
        Brightness_level_7  =   0x8E,       //脉冲宽度为13/16
        Brightness_level_8  =   0x8F,       //脉冲宽度为14/16
    }Brightness_level_t;
    
    //显示寄存器地址枚举类型    —>    位选GRID的地址
    typedef enum
    {
        Disp_SFR_Addr_Num   =   (uint8_t)12,
    
        Disp_SFR_Addr_00H   =   0xC0, 
        Disp_SFR_Addr_01H   =   0xC1,
        Disp_SFR_Addr_02H   =   0xC2,
        Disp_SFR_Addr_03H   =   0xC3,
        Disp_SFR_Addr_04H   =   0xC4,
        Disp_SFR_Addr_05H   =   0xC5,
        Disp_SFR_Addr_06H   =   0xC6,
        Disp_SFR_Addr_07H   =   0xC7,
        Disp_SFR_Addr_08H   =   0xC8,
        Disp_SFR_Addr_09H   =   0xC9,
        Disp_SFR_Addr_0AH   =   0xCA,
        Disp_SFR_Addr_0BH   =   0xCB,
    }Disp_SFR_Addr_t;
    
    //定义结构体类型
    typedef struct
    {
        Brightness_level_t  Brightness;	//辉度变量
        void (*TM1620_Init)();          //TM1620初始化
        void (*Disp_Tempareture)();     //数码管显示温度
    }TM1620_t;
    
    /* extern variables-----------------------------------------------------------*/
    extern TM1620_t idata TM1620;
    /* extern function prototypes-------------------------------------------------*/ 
    
    #endif
    /********************************************************
      End Of File
    ********************************************************/
    
    • 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
    TM1620.c

    实现三个函数,第一个是TM162通过串行通行发送一个字节的函数,要注意STB拉低后要适当延时,不然数据通信会出错;

    第二个函数是TM1620的初始化,先设置为地址自动增加,然后循环写入0x00清零显示寄存器,然后再设置为固定地址模式,给左右两个数码管初始化为全亮;

    第三个函数是读取温度值并显示,把浮点型的温度值先转为整型,再分别取出十位和个位,分别显示在左边和右边的数码管上

    注意:TM1620_Write_Byte()函数只是在TM1620.c文件里使用,并不提供给外部使用,所以不用声明函数指针指向该函数

    /* Includes ------------------------------------------------------------------*/
    #include 
    
    /* Private define-------------------------------------------------------------*/
    #define DIN     P24
    #define CLK     P25
    #define STB     P26
    
    //左右两个数码管显示寄存器地址宏定义
    #define Disp_Position_Left      Disp_SFR_Addr_00H
    #define Disp_Position_Right     Disp_SFR_Addr_02H
    /* Private variables----------------------------------------------------------*/
    uint8_t Disp_SEG[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};   //数码管显示0 ~ 9
    
    static void TM1620_Write_Byte(uint8_t );
    static void TM1620_Init();
    static void Disp_Tempareture();
    /* Public variables-----------------------------------------------------------*/
    TM1620_t idata TM1620 = 
    {
        Brightness_level_3,
        TM1620_Init,
        Disp_Tempareture
    };
    /* Private function prototypes------------------------------------------------*/
    
    /*
    * @name   TM1620_Write_Byte
    * @brief  TM1620写入一个字节
    * @param  dat:待写入数据
    * @retval None   
    */
    static void TM1620_Write_Byte(uint8_t dat)
    {
        uint8_t i = 0;
        STB = 0;
        Public.Delay_ms(1);	//需要加延时等待,不然数码管显示会出异常
        for(i=0;i<8;i++)
        {
            //CLK为低电平时往DIN上放数据
            CLK = 0;
    		DIN = 0x01 & (dat>>i);  //先取出最低位进行发送,然后dat右移,把最低位移出去,再取补上地低位进行发送
            _nop_();    //延时1us
            
            //CLK为高电平时TM1620读取DIN上的数据
            CLK = 1;
            _nop_();    //延时1us
        }
    }
    
    /*
    * @name   TM1620_Init
    * @brief  TM1620初始化
    * @param  None
    * @retval None   
    */
    static void TM1620_Init()
    {
        uint8_t i = 0;
        //设置显示模式:6位8段
        TM1620_Write_Byte(Disp_Mode_GRID6_SEG8);
        STB = 1;
    
        //设置地址模式:自动地址增加
        TM1620_Write_Byte(Write_Data_Addr_Auto_Add);
        STB = 1;
    
        //清除显示寄存器,厂商要求
        TM1620_Write_Byte(Disp_SFR_Addr_00H);
        for(i=0;i<Disp_SFR_Addr_Num;i++)
        {
            TM1620_Write_Byte(0x00);
        }
        STB = 1;
    
        //显示默认辉度:level3
        TM1620_Write_Byte(TM1620.Brightness);
        STB = 1;
    
        //设置显示模式:6位8段
        TM1620_Write_Byte(Disp_Mode_GRID6_SEG8);
        STB = 1;
    
        //设置地址模式:固定地址
        TM1620_Write_Byte(Write_Data_Addr_Fix);
        STB = 1;
    
        //写显示寄存器
        //先设置位选,设置为左边的数码管,再写入段选的数据0xFF,数码管8个段全亮
        TM1620_Write_Byte(Disp_Position_Left);
        TM1620_Write_Byte(0xFF);
        STB = 1;
    	//然后设置位选为右边的数码管,同样写入段选数据0xFF,8个段全亮
        TM1620_Write_Byte(Disp_Position_Right);
        TM1620_Write_Byte(0xFF);
        STB = 1;
    
        //显示辉度
        TM1620_Write_Byte(TM1620.Brightness);
        STB = 1;
    }
    
    /*
    * @name   Disp_Tempareture
    * @brief  数码管显示温度
    * @param  None
    * @retval None   
    */
    static void Disp_Tempareture()
    {
        uint8_t temp = 0;
        
        //因为获取到的温度是浮点型,而数码管只有两位,不够显示,所以要转为无符号整型数据
        temp = (uint8_t)NTC.fTemperature;
    
        TM1620_Write_Byte(Disp_Position_Left);  //选择左边的数码管
        TM1620_Write_Byte(Disp_SEG[temp/10]);   //取出温度值的十位作为下标去找段码表对应的段选数据
        STB = 1;
    
        TM1620_Write_Byte(Disp_Position_Right); //选择右边的数码管
        TM1620_Write_Byte(Disp_SEG[temp%10]);   //取出温度值的个位作为下标去找段码表对应的段选数据
        STB = 1;
        
        //显示辉度
        TM1620_Write_Byte(TM1620.Brightness);
        STB = 1;
    }
    /********************************************************
      End Of File
    ********************************************************/
    
    • 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
    main.c

    主函数中先预编译串口打印初始化信息,然后while循环内不断获取温度值,再调用TM1620的Disp_Tempareture()函数来在数码管上显示两位温度值;

    用switch语句来切换数码管的辉度,数码管的亮度就会一节一节地从暗到亮

    /*
    * @name   main
    * @brief  主函数
    * @param  void	
    * @retval int      
    */
    int main(void)
    {
    	//系统初始化
    	Hradware.Sys_Init();
    
    	//串口1发送初始化信息
    	#ifdef Monitor_Run_Code
    		printf("Initialization completed,system startup!\r\n\r\n");
    	#endif
    	
    	//系统主循环
    	while(1)
    	{
    		NTC.Get_Temperature_Value();
    		Public.Delay_ms(500);
    
    		//数码管显示温度
    		TM1620.Disp_Tempareture();
    		//调整亮度
    		switch (TM1620.Brightness)
    		{
    			case Brightness_level_1:TM1620.Brightness = Brightness_level_2;break;
    			case Brightness_level_2:TM1620.Brightness = Brightness_level_3;break;
    			case Brightness_level_3:TM1620.Brightness = Brightness_level_4;break;
    			case Brightness_level_4:TM1620.Brightness = Brightness_level_5;break;
    			case Brightness_level_5:TM1620.Brightness = Brightness_level_6;break;
    			case Brightness_level_6:TM1620.Brightness = Brightness_level_7;break;
    			case Brightness_level_7:TM1620.Brightness = Brightness_level_8;break;
    			case Brightness_level_8:TM1620.Brightness = Brightness_level_1;break;
    			default:TM1620.Brightness = Brightness_level_1;break;
    		}
    		Public.Delay_ms(500);
    	}
    }
    /********************************************************
      End Of File
    ********************************************************/
    
    • 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
    出现问题

    如果定义函数指针指向TM1620_Write_Byte()函数,那在TM1620初始化和显示温度的函数中全都用TM1620.TM1620_Write_Byte()的形式来调用该函数往TM1620写数据的话,烧录后数码管是没有亮的;

    但只要把任意一个TM1620.TM1620_Write_Byte()改为TM1620_Write_Byte(),即本来通过函数指针调用的,改为直接用函数名调用,烧录后数码管居然是可以亮的;或者全部改为直接用函数名也是可以亮

    找了几个小时也没发现问题出在哪,这种现象也是第一次遇见,按理说通过函数指针调用和直接用函数名调用是没有区别的,但为什么在这个实验中就出现问题,而且还只要改其中任意一个就行,改了之后数码管就显示了,说明两种调用方式都可以用,混着用也行,说明代码逻辑是没有问题的

    另外我把教程的代码也全改为了用函数指针调用,也是不亮的,网上也没查到这个问题,只能留着以后再看看有什么解决办法了

    TM1620.h

    //定义结构体类型
    typedef struct
    {
        Brightness_level_t Brightness;
        
        void (*TM1620_Write_Byte)(uint8_t);	//指向TM1620初始化函数的函数指针
        void (*TM1620_Init)();
        void (*Disp_Tempareture)();
    }TM1620_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    TM1620.c

    TM1620_t idata TM1620 = 
    {
        Brightness_level_3,
    
        TM1620_Write_Byte,		
        TM1620_Init,
        Disp_Tempareture
    };
    
    //函数指针调用方式,全部使用这种调用方式,则数码管不亮
    TM1620.TM1620_Write_Byte();
        
    //函数名调用方式,只要有一个函数名调用方式,则数码管能亮
    TM1620_Write_Byte();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    看教程时注意的点

    驱动数码管也可以用三极管,但这样就需要单片机不断的进行扫描才能显示,使用专用的IC,如TM1620,就能实现自动扫描并显示

    项目的TM1620显示模式命令设置是6位8段

    根据TM1620的手册将寄存器的值进行定义封装,32的库就类似这样,不用每次使用时都要去看手册配寄存器

    TM1620也相当于一个小MCU,也有自己的寄存器,STC15MCU通过串行协议与TM1620进行通信,对TM1620内部寄存器进行配置,让TM1620自动工作

    当写很多地址时,选用地址增加模式,当写一两个地址时,选用固定地址模式

    TM1620写入字节函数是内部函数,不需要被其他函数调用,所以不用写在结构体里

    单片机引脚P24、P25、P26设置为开漏输出,因为这是给一个信号,不是进行驱动,如果要驱动的话,就要设置为推挽输出,输出信号控制的话,开漏和准双向口都可以

    显示寄存器地址:GRID是位选,SEG是段选,根据硬件电路,第一个数码管接到了GRID1上,并且用到了SEG1 ~ SEG8,并没有用到SEG13和SEG14,所以GRID1的地址就是00H,GRID2同理

    GRID位选最多是6个,每一个位选可以选择SEG1 ~SEG8 或者SEG13 ~SEG14两种段选,该两种段选所对应的GRID位选寄存器的地址又是不同的,两种段选不能一起使用,所以便有6 x 2 = 12个位选的地址

    TM1620会根据写入数据的首两位判断为不同的命令

  • 相关阅读:
    JVM 配置参数 -D,-X,-XX 的区别
    Java面向对象(基础)-- 类的成员之三:构造器(Constructor)
    【数据结构与算法】树、二叉树的概念及结构(详解)
    科技的成就(五十二)
    36、Flink 的 Formats 之Parquet 和 Orc Format
    获取了文心一言的内测及与其ChatGPT、GPT-4 对比结果
    2023年华数杯数学建模A题隔热材料的结构优化控制研究解题全过程文档及程序
    一款好用的内存清理工具
    二叉树中查找后继节点问题
    day17正则表达式作业
  • 原文地址:https://blog.csdn.net/weixin_46251230/article/details/126682119