项目概述
使用定时器中断实现数码管数值的递减
功能分析
功能一:数码管驱动成功,并显示需要的内容.
功能二:定时器中断处理
下面简单介绍一下数码管的驱动原理,课程一中我们已经成功驱动了RGB三色LED.
这里我们可以把数码管看成是一个"七色LED"
数码管每个笔画("段")由一个LED进行控制点亮或熄灭.
课程提供的数码管是"八段"的,带有小数点,测量温读的时候可以通过"浮点数"的形式展示温度测量值.
数码管内部LED会挑选一段连接在一起,这样就形成了所谓的"共阴""共阳"
共阴极数码管:公共端接低电平,相应段选信号接高电平即可点亮LED
共阳极数码管:公共端接搞电平,相应段选信号接低电平即可点亮LED
上图是段码表
如果显示1,点亮bc就可以
如果显示3,点亮abcdg就可以
依此类推,其他的数字也是同样的道理.
结合原理图,开发板上的单片机虽然引脚超过8个,但最对只能驱动一个数码管,我们这里的数码管是两个四位的数码管,最少需要8个片选引脚+8个段选引脚
如果直接连接单片机GPIO,多少有点大财小用了.
这里就得提到日常项目中经常使用的IO扩展芯片-->74HC595
上图是有关该芯片的一些基本信息,它可以将串行信号并行输出,并支持级联.
这就意味着,如果对速度要求不高,只需少量IO引脚就可以扩展出任意数量(8的倍数)的IO
上图是芯片的驱动原理(时序图),数码管模块原理图如下所示:
可以看出595芯片部分控制引脚并未引出,只提供了三个控制引脚.
硬件接线如上图所示
下面接到了代码环节了,
首先配置sysconfig,生成基础配置代码
上图是定时器配置(这些参数可以手动调整,如果有问题,会报错提示的,希望大家多动手修改修改,报错也没有太大问题)
本人在测试过程中发现数码管显示的数值一直保持在"10",后来发现是中断没有配置,大家一定注意
GPIO配置
详细代码
#include "ti_msp_dl_config.h"
#define HC595_PORT (GPIO_HC595_PORT)
#define HC595_DIO_PIN (GPIO_HC595_HC595_DIO_PIN)
#define HC595_SCLK_PIN (GPIO_HC595_HC595_SCLK_PIN)
#define HC595_RCLK_PIN (GPIO_HC595_HC595_RCLK_PIN)
uint8_t Disp_DX[ 16 ]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //段显
uint8_t Disp_PX[ 8 ]={1,2,3,4,5,6,7,8}; //片选
#define HC595_DAT(x) ((x)?(DL_GPIO_setPins(HC595_PORT, HC595_DIO_PIN)) : (DL_GPIO_clearPins(HC595_PORT, HC595_DIO_PIN)))
#define HC595_CLK(x) ((x)?(DL_GPIO_setPins(HC595_PORT, HC595_SCLK_PIN)) : (DL_GPIO_clearPins(HC595_PORT, HC595_SCLK_PIN)))
#define HC595_RCK(x) ((x)?(DL_GPIO_setPins(HC595_PORT, HC595_RCLK_PIN)) : (DL_GPIO_clearPins(HC595_PORT, HC595_RCLK_PIN)))
uint8_t TimerCnt = 0, TmpVal = 10;
/* 开启数码管输出 */
void Display_Out()
{
HC595_RCK(0);
delay_cycles(100);
HC595_RCK(1);
delay_cycles(100);
}
/* 串行数据写入 */
void HC595_WriteData(uint8_t data)
{
uint8_t i;
for(i = 0; i < 8; i++)
{
if(data&0x80)
{
HC595_DAT(1);
}
else
{
HC595_DAT(0);
}
data <<=1;
delay_cycles(100);
HC595_CLK(0);
delay_cycles(100);
HC595_CLK(1);
delay_cycles(100);
}
}
/* 按位点亮数码管 */
void HC595_SEND_DATA(uint8_t disp_num, uint8_t disp_bit)
{
HC595_WriteData(disp_num);
HC595_WriteData(1<<disp_bit);
Display_Out();
}
void Disp_Data(uint16_t dataShow)
{
uint16_t tempShow;
uint8_t num_s,num_g;
tempShow = dataShow;
num_s = tempShow/10%10;
num_g = tempShow%10;
/* 数字小于十,十位数字不显示 */
if (num_s) {
HC595_SEND_DATA(Disp_DX[num_s],1);
}
HC595_SEND_DATA(Disp_DX[num_g],0);
}
void TIMER_0_INST_IRQHandler(void)
{
switch(DL_Timer_getPendingInterrupt(TIMER_0_INST)){
case DL_TIMER_IIDX_ZERO:
TimerCnt ++;
if(TimerCnt >= 100)
{
TimerCnt = 0;
TmpVal --;
if(TmpVal == 0)
{
TmpVal = 10;
}
}
break;
default:
break;
}
}
int main(void)
{
/* Power on GPIO, initialize pins as digital outputs */
SYSCFG_DL_init();
NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);
while (1) {
Disp_Data(TmpVal);
}
}
成果展示
数字10
数字9
数字8
数字7
数字6
数字5
数字4
数字3
数字2
数字1