一、功能需求
使用定时器中断,实现数码管显示数值的递减
时间范围:10~0
递减步长:1000ms
二、数码管驱动原理
数码管显示的工作原理,其实不难,只要了解数码管的结构是由8个小的LED组成的。如下图所示,每一个数码(带1个小数点)管,都由8个led组成一个8字行,通过控制这些小灯的ON/OFF,就能组合成0-9各个数字。
而显示什么数字,其对应的8个灯管on/off的输出次序,就是编码表,如下图所示
硬件是使用两个HC595驱动的两组数码管,其电路连接如图所示(源自官方资料)。
8位数码管由两片HC595芯片驱动,一片HC595芯片负责接收串行数据输入,作为位选数据用于驱动单个数码管进行显示。高八位数据串行输入到另一片HC595芯片,作为片选数据。当数据传输完毕后,在RCLK引脚上给予不小于2us的上升沿,按照数据的内容点亮某一位数码管。
三、软件原理
硬件连接上使用3个GPIO口作为输出,1个数据位输出,2个为时钟输出(因为时钟和锁存输出时钟)。供电使用开发板上的3v3,共5根线其接法如下图
由于要求定时从10减到0,这里我采用定时器去更新数码管的显示内容,定时1s,num自减,定时器配置如下:
保存后编译无误。接着开始写代码封装 8个数码管的驱动显示函数,先看码表的定义:
uint8_t LED_0F[] = {// 0 1 2 3 4 5 6 7 8 9 A b C d E F - 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf,0xff }; // 全局变量 uint8_t LED[8]={0,1,17,17,17,17,17,17}; //用于LED的8位显示缓存 void LED8_Display (void) { uint8_t *led_table; // 查表指针 uint8_t i; //显示第1位 led_table = LED_0F + LED[0]; i = *led_table; LED_OUT(i); LED_OUT(0x01); RCLK_RESET; RCLK_SET; //显示第2位 led_table = LED_0F + LED[1]; i = *led_table; LED_OUT(i); LED_OUT(0x02); RCLK_RESET; RCLK_SET; //显示第3位 led_table = LED_0F + LED[2]; i = *led_table; LED_OUT(i); LED_OUT(0x04); RCLK_RESET; RCLK_SET; //显示第4位 led_table = LED_0F + LED[3]; i = *led_table; LED_OUT(i); LED_OUT(0x08); RCLK_RESET; RCLK_SET; //显示第5位 led_table = LED_0F + LED[4]; i = *led_table; LED_OUT(i); LED_OUT(0x10); RCLK_RESET; RCLK_SET; //显示第6位 led_table = LED_0F + LED[5]; i = *led_table; LED_OUT(i); LED_OUT(0x20); RCLK_RESET; RCLK_SET; //显示第7位 led_table = LED_0F + LED[6]; i = *led_table; LED_OUT(i); LED_OUT(0x40); RCLK_RESET; RCLK_SET; //显示第8位 led_table = LED_0F + LED[7]; i = *led_table; LED_OUT(i); LED_OUT(0x80); RCLK_RESET; RCLK_SET; } void LED_OUT(uint8_t X) { uint8_t i; for(i=8;i>=1;i--) { if (X&0x80) { DIO_SET; } else { DIO_RESET; } X<<=1; SCLK_RESET; SCLK_SET; } }
主函数如下:
#include "ti_msp_dl_config.h" #include "HC595.h" #include "Delay.h" int8_t num=10; int main(void) { SYSCFG_DL_init(); NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); DL_TimerG_startCounter(TIMER_0_INST); while (1) { LED8_Display (); } } //定时实现10到0递减 void TIMER_0_INST_IRQHandler(void) { num--; if(num<0)num=10; LED[1]=num/10; LED[0]=num%10; if(LED[1]==0)LED[1]=17; DL_GPIO_togglePins(GPIO_LED_PORT,GPIO_LED_LED1_PIN); }
为了减小数码管闪烁,这里我把数码管显示放在主函数的while(1)循环中,以高刷新率去显示。定时器中断函数中,每到达1s定时,num自减,这样就实现了数码管从10减到0的效果。
四、下载验证
下载测试没有问题,b站视频如下: