当前位置:   article > 正文

STM32实战项目-数码管_stm32数码管

stm32数码管

程序实现功能:

1、上电后,数码管间隔50ms计数;

2、触摸按键1调节数码管亮度,8个等级;


目录

1、硬件电路

 1.1数码管

1.2TIM1620 驱动电路

 二、技术讲解

2.1概述 

2.2特性

2.3引脚说明

 3.指令说明及配置

3.1显示模式命令设置 

 3.2写数据地址模式

 3.3显示控制命令设置

 3.4显示寄存器地址

3.5数码管显示驱动 

 4.软件编程

4.1串口高低电平配置 

 4.2数码管译码配置

 4.3写入函数

4.4初始化TIM1620函数

 4.5数码管显示函数

 4.6运行函数

 4.7回调函数-按键控制亮度


 


1、硬件电路

 1.1数码管

 

1.2TIM1620 驱动电路

 

 二、技术讲解

2.1概述 

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

2.2特性

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

2.3引脚说明

TIM1620需要通过引脚CLK、DIN、STB 控制串行数据传输,所以优先配置好GPIO串口,具体配置如下图所示:

 3.指令说明及配置

3.1显示模式命令设置 

该指令用来设置选择段和位的个数(4~6 位,8~10 段) 。当该指令被执行时,显示被强制关闭。 在显示模式不变时,显存内的数据不会被改变,显示控制命令控制显示开关。如下图所示:


 为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

  1. /显示模式
  2. typedef enum
  3. {
  4. Disp_Mode_GRID4_SEG10 = 0x00,
  5. Disp_Mode_GRID5_SEG9 = 0x01,
  6. Disp_Mode_GRID6_SEG8 = 0x02,
  7. } Disp_Mode_t;

 3.2写数据地址模式

该指令用来设置数据写和读,B1和B0位不允许设置01或11。具体如下图所示:


  为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

  1. //写数据模式
  2. typedef enum
  3. {
  4. Write_Data_Addr_Fix = 0x44,
  5. Write_Data_Addr_Auto_Add = 0x40,
  6. } Write_Data_Addr_Mode_t;

 3.3显示控制命令设置

该指令用来设置显示的开关以及显示亮度调节。共有8级辉度可供选择进行调节。如下图所示:


 为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

  1. //灰度等级
  2. typedef enum
  3. {
  4. Brightness_level_0 = 0x80,
  5. Brightness_level_1 = 0x88,
  6. Brightness_level_2 = 0x89,
  7. Brightness_level_3 = 0x8A,
  8. Brightness_level_4 = 0x8B,
  9. Brightness_level_5 = 0x8C,
  10. Brightness_level_6 = 0x8D,
  11. Brightness_level_7 = 0x8E,
  12. Brightness_level_8 = 0x8F,
  13. } Brightness_level_t;

 3.4显示寄存器地址

该寄存器存储通过串行接口接收从外部器件传送到TM1620的数据,最多有效地址从00H-0BH共12字节单元,
分别与芯片SEG和GRID管脚对应,具体分配如下图:写LED显示数据的时候,按照显示地址从低位到高位,数据字节从低位到高位操作
 

 

 为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

  1. //显示寄存器地址
  2. typedef enum
  3. {
  4. Disp_SFR_Addr_Num = (uint8_t)12,
  5. Disp_SFR_Addr_00H = 0xC0,
  6. Disp_SFR_Addr_01H = 0xC1,
  7. Disp_SFR_Addr_02H = 0xC2,
  8. Disp_SFR_Addr_03H = 0xC3,
  9. Disp_SFR_Addr_04H = 0xC4,
  10. Disp_SFR_Addr_05H = 0xC5,
  11. Disp_SFR_Addr_06H = 0xC6,
  12. Disp_SFR_Addr_07H = 0xC7,
  13. Disp_SFR_Addr_08H = 0xC8,
  14. Disp_SFR_Addr_09H = 0xC9,
  15. Disp_SFR_Addr_0AH = 0xCA,
  16. Disp_SFR_Addr_0BH = 0xCB,
  17. } Disp_SFR_Addr_t;

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

3.5数码管显示驱动 

关于小数点是否启动,也将其封装起来,代码如下:

  1. typedef enum
  2. {
  3. Disp_DP_OFF = 0x01,
  4. Disp_DP_ON = 0x02,
  5. } Disp_DP_Status_t;

 4.软件编程

4.1串口高低电平配置 

为了方便串口数据传输,我们使用宏定义 将串口的读写重新定义,具体代码如下:

  1. //TM1620穿行通讯口
  2. #define SET_STB HAL_GPIO_WritePin(TM1620_STB_GPIO_Port,TM1620_STB_Pin,GPIO_PIN_SET)
  3. #define CLR_STB HAL_GPIO_WritePin(TM1620_STB_GPIO_Port,TM1620_STB_Pin,GPIO_PIN_RESET)
  4. #define SET_DIN HAL_GPIO_WritePin(TM1620_DIN_GPIO_Port,TM1620_DIN_Pin,GPIO_PIN_SET)
  5. #define CLR_DIN HAL_GPIO_WritePin(TM1620_DIN_GPIO_Port,TM1620_DIN_Pin,GPIO_PIN_RESET)
  6. #define SET_CLK HAL_GPIO_WritePin(TM1620_CLK_GPIO_Port,TM1620_CLK_Pin,GPIO_PIN_SET)
  7. #define CLR_CLK HAL_GPIO_WritePin(TM1620_CLK_GPIO_Port,TM1620_CLK_Pin,GPIO_PIN_RESET)

 4.2数码管译码配置

没有单独配置小数点,函数内部需要小数点的话,单独加上即可。

uint8_t Disp_Decode[16]    = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};  //数码管译码 0 - 9

 4.3写入函数

 

 根据时序图写函数,首先在传输八位数据之前,需要将STB置零拉低,因为是使用库函数,有一定的延时,所不用额外加延时函数,开始一个一个bit传的时候也需要拉低CLK,拉高CLK,用每个bit位与1&从而确定每个bit是高低电平,发出信号。具体代码如下:

  1. static void TM1620_Write_Byte(uint8_t dat)
  2. {
  3. uint8_t i = 0;
  4. //参考数据手册时序图
  5. CLR_STB;
  6. for(i=0;i<8;i++)
  7. {
  8. CLR_CLK;
  9. //准备数据位
  10. if((dat & BIT0) == BIT0) //BIT0为宏定义值为0x01
  11. SET_DIN;
  12. else
  13. CLR_DIN;
  14. dat = dat >> 1; //移位,准备下一个bit
  15. //时钟上升沿发送下一个数据
  16. SET_CLK;
  17. __nop();
  18. }
  19. }

4.4初始化TIM1620函数

芯片显示寄存器在上电瞬间其内部保存的值可能是随机不确定的,此时客户直接发送开屏命令,将有可能出现显示乱码 ,所以要进行清零操作,因为芯片内部有配置可以自动地址增加,具体如下图示:

具体配置代码如下:

  1. static void TM1620_Init()
  2. {
  3. uint8_t i = 0;
  4. //设置显示模式
  5. TM1620_Write_Byte(Disp_Mode_GRID6_SEG8);
  6. SET_STB;
  7. //地址自动增加
  8. TM1620_Write_Byte(Write_Data_Addr_Auto_Add);
  9. SET_STB;
  10. //清除显示寄存器
  11. TM1620_Write_Byte(Disp_SFR_Addr_00H); //设置首地址
  12. for(i=0;i<Disp_SFR_Addr_Num;i++)
  13. TM1620_Write_Byte(0x00);
  14. SET_STB;
  15. //显示
  16. TM1620_Write_Byte(Display.Brightness);
  17. SET_STB;
  18. }

 4.5数码管显示函数

数码管是一个个显示的,不需要自动增加地址,需要固定地址,如下图所示:

 

具体配置代码如下; 

  1. static void Disp(Disp_NUM_t Disp_NUM,uint8_t Dat,Disp_DP_Status_t Disp_DP_Status)
  2. {
  3. //参数范围检查
  4. if(Dat > 0x0F)
  5. {
  6. System.Assert_Failed();
  7. }
  8. //设置显示模式
  9. TM1620_Write_Byte(Disp_Mode_GRID6_SEG8);
  10. SET_STB;
  11. //地址固定
  12. TM1620_Write_Byte(Write_Data_Addr_Fix);
  13. SET_STB;
  14. //写地址
  15. TM1620_Write_Byte(Disp_NUM);
  16. //写数据
  17. if(Disp_DP_Status == Disp_DP_ON)
  18. TM1620_Write_Byte(Disp_Decode[Dat] + 0x80);
  19. else
  20. TM1620_Write_Byte(Disp_Decode[Dat]);
  21. SET_STB;
  22. //显示
  23. TM1620_Write_Byte(Display.Brightness);
  24. SET_STB;
  25. }

 4.6运行函数

  1. static void Run()
  2. {
  3. static uint32_t Cnt = 0;
  4. //数码管显示计数值
  5. Display.Disp(Disp_NUM_1,Cnt%10, Disp_DP_OFF); //个位
  6. Display.Disp(Disp_NUM_2,Cnt/10%10, Disp_DP_OFF); //十位
  7. Display.Disp(Disp_NUM_3,Cnt/100%10, Disp_DP_OFF); //百位
  8. Display.Disp(Disp_NUM_4,Cnt/1000%10, Disp_DP_OFF); //千位
  9. Display.Disp(Disp_NUM_5,Cnt/10000%10,Disp_DP_OFF); //万位
  10. Display.Disp(Disp_NUM_6,Cnt/100000, Disp_DP_OFF); //十万位
  11. //更新计数值
  12. if(++Cnt > 999999)
  13. Cnt = 0;
  14. //延时50ms
  15. HAL_Delay(50);
  16. }

 4.7回调函数-按键控制亮度

  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  2. {
  3. if(GPIO_Pin == KEY1_Pin)
  4. {
  5. LED.LED_Flip(LED2);
  6. switch(Display.Brightness)
  7. {
  8. case Brightness_level_1: Display.Brightness = Brightness_level_2; break;
  9. case Brightness_level_2: Display.Brightness = Brightness_level_3; break;
  10. case Brightness_level_3: Display.Brightness = Brightness_level_4; break;
  11. case Brightness_level_4: Display.Brightness = Brightness_level_5; break;
  12. case Brightness_level_5: Display.Brightness = Brightness_level_6; break;
  13. case Brightness_level_6: Display.Brightness = Brightness_level_7; break;
  14. case Brightness_level_7: Display.Brightness = Brightness_level_8; break;
  15. case Brightness_level_8: Display.Brightness = Brightness_level_1; break;
  16. default: Display.Brightness = Brightness_level_3;
  17. }
  18. }
  19. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/752250
推荐阅读
相关标签
  

闽ICP备14008679号