一、数码管扫描的原理
- ①人的眼睛中的画面在0.02S(50Hz)左右,光源的闪烁频率高于50-60赫兹时,人眼通常无法察觉到光的闪烁;
- ②通过控制LED的亮灭透过模具贴纸从而控制数字和图案的亮灭;
文章来源地址https://www.toymoban.com/news/detail-825691.html
二、display.c的实现
1、void Display(void) 各模式界面定义数据
u8 CxSegData[]={0,0,0,0}; //显示Ram缓存区
//=============================================================================
//函数名称:Display
//输 入:无
//输 出:无
//功 能:界面菜单显示
//=============================================================================
void Display(void)
{
if(b_Display_Flag== 0) return; //更新显示
b_Display_Flag=0; //显示标志清0
switch(Mode)
{
case 0: //全灭显示界面
CxSegData[0]=0x00;
CxSegData[1]=0x00;
CxSegData[2]=0x00;
CxSegData[3]=0x00;
b_Fresh_Flag=1; //刷新显示Ram
break;
case 1: //全显显示界面
CxSegData[0]=0xff;
CxSegData[1]=0xff;
CxSegData[2]=0xff;
CxSegData[3]=0xff;
b_Fresh_Flag=1; //刷新显示Ram
break;
case 2: //自定义界面显示1
CxSegData[3]=Unb_Red;
CxSegData[3]=Unb_Inf;
CxSegData[3]=Unb_Twi; //不显示某一个点
b_Fresh_Flag=1; //刷新显示Ram
break;
case 3: //自定义界面显示2
CxSegData[3]=b_Red;
CxSegData[3]=b_Inf;
CxSegData[3]=b_Twi; //显示某一个点
b_Fresh_Flag=1; //刷新显示Ram
break;
case 4: //自定义界面显示2
LcdDisplay_8bit(LzLcdNum1,LedNumCoding[6]);
LcdDisplay_8bit(LzLcdNum2,LedNumCoding[6]); //数码管显示66
b_Fresh_Flag=1; //刷新显示Ram
break;
case 5: //自定义界面显示3
b_Fresh_Flag=1; //刷新显示Ram
break;
case 6: //自定义界面显示4
b_Fresh_Flag=1; //刷新显示Ram
break;
}
}
2、void BackupRamToDisRam(void)从缓存区刷新显示映射Ram
u8 CxSeg[]={0,0,0,0}; //显示Ram
//=============================================================================
//函数名称:BackupRamToDisRam
//输 入:无
//输 出:无
//功 能:更新显示RAM
//=============================================================================
void BackupRamToDisRam(void)
{
if(b_Fresh_Flag)
{
b_Fresh_Flag=0;
CxSeg[0]= CxSegData[0];
CxSeg[1]= CxSegData[1];
CxSeg[2]= CxSegData[2];
CxSeg[3]= CxSegData[3];
}
}
3、void FreshDisplay(void) 映射显示Ram到主控的IO口
sbit b_Com1 = P3^4; //C_0
sbit b_Com2 = P3^5; //C_1
sbit b_Com3 = P3^6; //C_2
sbit b_Com4 = P3^7; //C_3 COM口定义
sbit b_Seg1 = P1^4; //S1
sbit b_Seg2 = P1^2; //S2
sbit b_Seg3 = P1^1; //S3
sbit b_Seg4 = P1^0; //S4
sbit b_Seg5 = P0^3; //S5
sbit b_Seg6 = P0^2; //S6 SEG口定义
//=============================================================================
//函数名称:FreshDisplay
//输 入:无
//输 出:无
//功 能:LED全部刷新显示
//=============================================================================
void FreshDisplay(void)
{
static u8 disIndex=0;
P3 |=0xf0; //关闭所有屏幕显示
if(disIndex==PwmLevel) //PwmLevel= 5 100%亮度 =10 1/2亮度 =15 1/3亮度 =20 1/4亮度
disIndex=0; //20分频亮度
disIndex++;
b_Seg1 = CxSeg[0]&0x01;
b_Seg2 = CxSeg[0]&0x02;
b_Seg3 = CxSeg[0]&0x04;
b_Seg4 = CxSeg[0]&0x08;
b_Seg5 = CxSeg[0]&0x10;
b_Seg6 = CxSeg[0]&0x20;
switch(disIndex)
{
case 1:
b_Com1 = 0; //刷新第一个Com显示
break;
case 2:
b_Com2 = 0; //刷新第二个Com显示
break;
case 3:
b_Com3 = 0; //刷新第三个Com显示
break;
case 4:
b_Com4 = 0; //刷新第四个Com显示
break;
}
}
4、void LcdDisplay_8bit(void) 映射显示Ram到主控的IO口
#define b_Red CxSegData[3]|0x01
#define b_Inf CxSegData[3]|0x02
#define b_Twi CxSegData[3]|0x04
#define b_P1 CxSegData[2]|0x04
#define b_P2 CxSegData[2]|0x08
#define b_P3 CxSegData[2]|0x10
#define b_P4 CxSegData[2]|0x20 //对应一个点图案显示
#define Unb_Red CxSegData[3]&~0x01
#define Unb_Inf CxSegData[3]&~0x02
#define Unb_Twi CxSegData[3]&~0x04
#define Unb_P1 CxSegData[2]&~0x04
#define Unb_P2 CxSegData[2]&~0x08
#define Unb_P3 CxSegData[2]&~0x10
#define Unb_P4 CxSegData[2]&~0x20 //对应一个点图案不显示
u8 code LzLcdNum1[]={
COM1,SEG1, //A
COM1,SEG2, //B
COM1,SEG3, //C
COM1,SEG4, //D
COM1,SEG5, //E
COM1,SEG6, //F
COM3,SEG1, //G
0xff,0xff
};
u8 code LzLcdNum2[]={
COM2,SEG1, //A
COM2,SEG2, //B
COM2,SEG3, //C
COM2,SEG4, //D
COM2,SEG5, //E
COM2,SEG6, //F
COM3,SEG2, //G
0xff,0xff
};
unsigned char code LedNumCoding[]={
0x3F, //0 0 1 1 1 1 1 1 as 0 0
0x06, //0 0 0 0 0 1 1 0 as 1 1
0x5B, //0 1 0 1 1 0 1 1 as 2 2
0x4F, //0 1 0 0 1 1 1 1 as 3 3
0x66, //0 1 1 0 0 1 1 0 as 4 4
0x6D, //0 1 1 0 1 1 0 1 as 5 5
0x7D, //0 1 1 1 1 1 0 1 as 6 6
0x07, //0 0 0 0 0 1 1 1 as 7 7
0x7F, //0 1 1 1 1 1 1 1 as 8 8
0x6F, //0 1 1 0 1 1 1 1 as 9 9
0x00, //0 0 0 0 0 0 0 0 as "全灭" 10
0x40, //0 1 0 0 0 0 0 0 as "-" 11
0x76, //0 1 1 1 0 1 1 0 as "H" 12
0x38, //0 0 1 1 1 0 0 0 as "L" 13
0x50, //0 1 0 1 0 0 0 0 as "r" 14
0x39, //0 0 1 1 1 0 0 1 as “C” 15
0x37, //0 0 1 1 0 1 1 1 as “n” 16
0x77, //0 1 1 1 0 1 1 1 as “A” 17
0x71, //0 1 1 1 0 0 0 1 as “F” 18
0x7F}; //0 1 1 1 1 1 1 1 as 全显
//=============================================================================
//函数名称:LcdDisplay_8bit
//输 入:无
//输 出:无
//功 能:LED按位显示数据到CxSegData缓存区
//=============================================================================
void LcdDisplay_8bit(u8 *Table_Seg,u8 Value)
{
u8 i=0,j=0;
u8 Seg,Com;
Com=Table_Seg[i];
Seg=Table_Seg[i+1];
i+=2; //表的内容为一个seg一个com所以每移一次需要加2
for(;Com!=0xff;)
{
if((Value & 0x01)==1)
CxSegData[Com]=CxSegData[Com] | Seg;
else
CxSegData[Com]=CxSegData[Com] & ~Seg;
//CxSegData[Com] &= (Value & 0x01); //优化if else
Value=Value>>1;
Com=Table_Seg[i];
Seg=Table_Seg[i+1];
i+=2;
}
}
三、display.h的外部接口
extern bit b_Display_Flag; //更新显示
extern void Display(void); //各个界面模式显示
extern void BackupRamToDisRam(void);//更新缓冲区数据到映射Ram
extern void FreshDisplay(void); //显示Ram映射到硬件IO
四、显示功能的使用、Note
- 在主函数main的while循环里调用,等标志更新显示
void main(void)
{
//_nop_(); //自定义初始化和上电功能
/**************************************************************************************************/
while(1)
{
Display(); //显示数据更新
BackupRamToDisRam();//更新显示Ram数据
if(b_16Hz_Flag)
{
F_16HzTask(); //以频率16Hz进行的任务
}
if(b_2Hz_Flag)
{
F_2HzTask(); //以频率2Hz进行的任务
}
}
/***********************************************************************************/
}
- 在2~4kHz的定时器里面调用FreshDisplay() 映射到IO功能函数,频率偏低可能观察到有闪烁,可以调节PwmLevel 的大小从而调节亮度,降低功耗;
//=============================================================================
// Function:Time2中断
//=============================================================================
void TIM2_INT(void) interrupt 5 //4kHz 频率
{
TF2=0; //清理中断标志位
FreshDisplay(); //刷新LED数字显示
- 该框架可使用于LCD、数码管、LED显示,可以通过修改映射关系进而移植到其它项目上;
- 数码管显示难点是如何建立映射关系?如何将IO和显示Ram建立关系?如何控制每个LED的亮灭关系?如何显示数字和字母?
- 需要更新屏幕显示注意b_Display_Flag是否需要更新缓存区CxSegData的数据,需要更新缓存数据到硬件IO注意b_Fresh_Flag标志;
- 显示功能基本战项目的50%的代码量,模块化功能程序可以很好定位Bug的位置,缩短开发周期;
文章来源:https://www.toymoban.com/news/detail-825691.html
到了这里,关于数码管扫描显示-单片机通用模板的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!