前言
目标
2个独立按键,按下K1,数码管显示的数字加1
按下K2,数码管显示的数字减1
效果
https://www.bilibili.com/video/BV1aXo9YxEhY
原理
-
独立按键,用于控制数字的加减
-
把完整的数字,分成若干数位显示
-
构造一个函数
show_digit(pos,digit)
, 可以在指定位置(0<=pos<=7), 显示指定的数(0<=digit<=9) -
利用视觉暂留效应,快速遍历一个完整数字的所有位,可以做到“同时”显示多位数字
参考
-
4-2 动态数码管显示
-
独立按键控制LED数码管 https://www.cnblogs.com/luckydoog/p/18798811
遇到的问题
1. 超过3位就无法显示
原因是红色框起来的地方,一开始写成了 pos%=3
属于是笔误
2. 残影
原因:根据江科大51单片机的教程,残影问题来自于两次位选之间,段数据未清零,导致第二个位置显示了前一个位置的字符,留下了残影
解决方法:可以通过在两次位选之间,进行 清零 来解决
3. 无法显示 超过 65535 的数
这是由于一开始这里的 digit 只用了 unsigned int
类型
而我们的51单片机上的 unsigned int 只有 16 位,表示范围 是 0 - 65535
解决方法
用 unsigned long 来定义 digit 变量,表示范围是 0 到 232-1
完整代码
#include <REGX52.H>
#include <INTRINS.H>#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned longunsigned char led_data[]={0x3F, //"0"0x06, //"1"0x5B, //"2"0x4F, //"3"0x66, //"4"0x6D, //"5"0x7D, //"6"0x07, //"7"0x7F, //"8"0x6F, //"9"
};void Delay1ms() ;
void Delay(int t);
void show(ulong digit);
void show_digit(uchar pos, uchar digit);void main()
{ulong digit = 0;while(1){if(0 == P3_1){Delay(10);while(0 == P3_1){//nop}Delay(10); if(digit<99999999){digit++;}else{digit = 0;}}else if(0 == P3_0){Delay(10);while(0 == P3_0){//nop}Delay(10); if(digit>0){digit--;}else{digit = 99999999;}}show(digit);}
}void Delay1ms() //@11.0592MHz
{unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);
}void Delay(int t){int i = 0;for(i=0;i<t;i++){Delay1ms();}
}void show(ulong digit)
{unsigned char pos = 0;do{show_digit(pos,digit%10);digit/=10;pos++;}while(digit);
}void show_digit(uchar pos, uchar digit)
{static uchar pos_map[][3] = {{0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}};pos %= 8;P2_2 = pos_map[pos][2];P2_3 = pos_map[pos][1];P2_4 = pos_map[pos][0];digit %= 10;P0 = led_data[digit];Delay1ms();P0 = 0;//clear
}