蓝桥杯 模板Template Part6:数码管 定时器动态驱动
● 改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改
一、流程图
二、基本模板
头文件
//-----------------------------SEG-------数码管------------------------------------//
extern uchar puc_SEG_Buf[9]; //数码管段码缓冲数组
extern uchar puc_SEG_Code[8]; //数码管段码
extern uchar uc_SEG_Position; //数码管位选
extern uint ui_SEG_flag; //tim定时器,数码管扫描频率标志位
extern void SEG_Tran(uchar *puc_SEG_Buf,uchar *puc_SEG_Code); //动态数码段码示转换
extern void SEG_Disp(uchar *puc_SEG_Code,uchar uc_SEG_Position); //动态数码管显示
extern void SEG_Proc(void); //数码管处理函数
SEG.c
#include <STC15F2K60S2.h>
#include <stdio.h>
#include <intrins.h>
#include <main.h>
//------------------------------------数码管段码转换-------------------//
void SEG_Tran(uchar *puc_SEG_Buf,uchar *puc_SEG_Code)
{
uchar i;
uchar j=0;
uchar temp;
for(i=0;i<8;i++,j++)
{
switch(puc_SEG_Buf[j])
{
case '0': temp = 0xc0; break;
case '1': temp = 0xf9; break;
case '2': temp = 0xa4; break;
case '3': temp = 0xb0; break;
case '4': temp = 0x99; break;
case '5': temp = 0x92; break;
case '6': temp = 0x82; break;
case '7': temp = 0xf8; break;
case '8': temp = 0x80; break;
case '9': temp = 0x90; break;
case 'A': temp = 0x88; break;
case 'b': temp = 0x83; break;
case 'C': temp = 0xC6; break;
case 'd': temp = 0xA1; break;
case 'E': temp = 0x86; break;
case 'F': temp = 0x8E; break;
case 'H': temp = 0x89; break;
case 'L': temp = 0xC7; break;
case 'N': temp = 0xC8; break;
case 'P': temp = 0x8C; break;
case 'U': temp = 0xC1; break;
case '-': temp = 0xBF; break;
case ' ': temp = 0xFF; break;
default: temp = 0XFF;
}
if(puc_SEG_Buf[j+1] == '.') //小数点
{
temp = temp&0X7F;
j++;
}
puc_SEG_Code[i] = temp; // 数码管段码数组
}
}
//-----------------------------------------动态数码管显示---------------------//
void SEG_Disp(uchar *puc_SEG_Code,uchar uc_SEG_Position)
{
//消隐
P0 = 0xff;
P2 = P2 & 0x1f | 0xE0; //开数码管段选573
P2 &= 0x1f; //关573
//数码管位选
P0 = 1<<uc_SEG_Position; //开数码管位选573
P2 = P2 & 0x1f | 0xC0;
P2 &= 0x1f;
//数码管段选
P0 = puc_SEG_Code[uc_SEG_Position]; //开数码管段选573
P2 = P2 & 0x1f | 0xE0;
P2 &= 0x1f;
}
//-----------------------------------------数码管处理函数---------------//
void SEG_Proc(void) //数码管处理函数
{
if(ui_SEG_flag) return; //刷新频率
ui_SEG_flag = 1;
sprintf(puc_SEG_Buf,"%01c%02u",uc_Key_state,(uint)uc_Key_Value);
SEG_Tran(puc_SEG_Buf,puc_SEG_Code); //数码管段码转换
}
数码管处理函数
的调用
while(1)
{
Key_Proc(); //按键扫描与处理
SEG_Proc(); //数码管处理与显示
LED_Proc(); //LED处理与显示
}
数码管显示函数
的调用
//1ms定时器1的中断服务函数
void Timer1_ISR(void) interrupt 3
{
ul_ms++;
…………
SEG_Disp(puc_SEG_Code,uc_SEG_Position); //数码管显示
if(++uc_SEG_Position == 8) uc_SEG_Position = 0;
LED_Disp(uc_LED); //LED显示
}
修改记录:
2021.5.4:五四青年节,写下了第一条修改记录,
自作聪明的改编了官方例程的初始化代码,加上对消隐理解的不到位,最后导致数码管微亮(消隐没做好)。改进了动态数码管显示
函数,如下👇:
锁存器 的工作原理可以理解为数据透传
,数码管的点亮受 段选 和 位选 的控制,对于数码管来说 位选端 和 段选端 指的是 直接控制数码管引脚的端口,在蓝桥杯开发板上也就是573锁存器的输出引脚。 而P2 和 P0 是锁存器的控制引脚。
因此,消隐 是清空 段选端 的上一次数据,保证本次打开 位选 的时候不会 受到上次段选端数据的影响。
消隐 是清空 段选端 的上一次数据,并不是清空控制引脚P0的数据。
//-----------------------------------------动态数码管显示---------------------//
void SEG_Disp(uchar *puc_SEG_Code,uchar uc_SEG_Position)
{
//消隐
P0 = 0xff;
P2 = P2 & 0x1f | 0xE0; //开数码管段选573
P2 &= 0x1f; //关573
//数码管位选
P0 = 1<<uc_SEG_Position; //开数码管位选573
P2 = P2 & 0x1f | 0xC0;
P2 &= 0x1f;
//数码管段选
P0 = puc_SEG_Code[uc_SEG_Position]; //开数码管段选573
P2 = P2 & 0x1f | 0xE0;
P2 &= 0x1f;
}