一、功能需求
使用定时器中断,实现数码管显示数值的递减
时间范围: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站视频如下:


我要赚赏金
