本文最后更新于45 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
数码管控制代码



考点
1.显示数字
以num = 1234为例:
SMG[4] = num/1000;
SMG[5] = num/100%10;
SMG[6] = num/10%10;
SMG[7] = num%10;
2.显示小数点
以显示adc采样电压,保留两位小数为例:
uint adc;
adc = (PCF8591_read(0x03)/51.0)*100;//因为定义的类型时unsigned int类型,保存不了小数,需要放大100倍
SMG[5] = adc/100%10;
SMG[6] = adc/10%10;
SMG[7] = adc%10;
dot[5] = 1;
3.显示特殊字符
最近几年比赛会提供A-F断码,需要自己写的断码有:-、P、n、H、U、L等,以P为例: 开发板上数码管为共阳极数码管,io口给低电平会点亮
写成二进制就是10001100;对应十六进制0x8c
4.多界面


多界面需要定义显示状态码,根据题目分为三个主界面,其中一个主界面分为三个子界面
所以定义一个state_display1,定义一个state_display2
5.数码管闪烁
有两种写法:1、用DS1302的秒控制(只能以秒为单位闪烁、并且题目使用了DS1302,否则0分),2、用定时器中断产生标志位:
//DS1302写法为例
SMG[0] = Time[2]/16;
SMG[1] = Time[2]%16;
SMG[2] = (Time[0]%2) ? 17 :16;//16为-的索引、17为熄灭索引
SMG[3] = Time[1]/16;
SMG[4] = Time[1]%16;
SMG[5] = (Time[0]%2) ? 17 :16;//16为-的索引、17为熄灭索引
SMG[6] = Time[0]/16;
SMG[7] = Time[0]%16;
//定时器中断标志为例
void timer1() interrupt 3
{
if(++count_1000ms == 1000)
{
count_1000ms = 0;
flag_flash ^= 1;
}
systick_ms++;
key_dly++;
display_dly++;
collect_dly++;
smg(SMG,dot,pos);
led(LED,pos);
if(++pos == 8) pos = 0;
}
SMG[0] = Time[2]/16;
SMG[1] = Time[2]%16;
SMG[2] = (flag_flash) ? 17 :16;//16为-的索引、17为熄灭索引
SMG[3] = Time[1]/16;
SMG[4] = Time[1]%16;
SMG[5] = (flag_flash) ? 17 :16;//16为-的索引、17为熄灭索引
SMG[6] = Time[0]/16;
SMG[7] = Time[0]%16;
6.高位熄灭
以频率测量为例:
SMG[0] = 17;
SMG[1] = 17;
SMG[2] = 17;
SMG[3] = (fre < 10000) ? 17 :fre/10000;
SMG[4] = (fre < 1000) ? 17 :fre/1000%10;
SMG[5] = (fre < 100) ? 17 :fre/100%10;
SMG[6] = (fre < 10) ? 17 :fre/10%10;
SMG[7] = fre%10;
7.负数显示
以第十四届国赛为例: 
char par = -100;//因为题目同时考到了负数显示及高位熄灭,只能按正负分类讨论,否则嵌套逻辑太复杂
if(par >= 0)//大于0需要高位熄灭
{
SMG[5] = (par < 100) ? 17 : par/100;
SMG[6] = (par < 10) ? 17 : par/10%10;
SMG[7] = par%10;
}
else if(par < 0)
{
SMG[5] = (par < -10) ? 16 : 17;//17为熄灭索引,16为-索引
SMG[6] = (par > -10) ? 16 : (-par)/10;
SMG[7] = (-par)%10;
}
8.单位切换
以第十三届国赛为例: 
//假设频率 为245HZ那么切换后为0.2KHZ,切换后发现数码管带小数的这位高位不熄灭
unsigned long fre; //显示六位,已经大于65535了,不能用uint
unsigned long fre_khz
if(mode_fre)//单位HZ
{
SMG[0] = 15; //F
SMG[1] = 17;
SMG[2] = (fre < 100000) ? 17 :fre/100000;
SMG[3] = (fre < 10000) ? 17 :fre/10000%10;
SMG[4] = (fre < 1000) ? 17 :fre/1000%10;
SMG[5] = (fre < 100) ? 17 :fre/100%10;
SMG[6] = (fre < 10) ? 17 :fre/10%10;
SMG[7] = fre%10;
dot[6] = 0;
}
else//单位KHZ
{
fre_khz = (fre/1000.0)*10;//保留几位小数就×10的几次方
SMG[0] = 15; //F
SMG[1] = 17;
SMG[2] = (fre_khz < 100000) ? 17 :fre/100000;
SMG[3] = (fre_khz < 10000) ? 17 :fre/10000%10;
SMG[4] = (fre_khz < 1000) ? 17 :fre/1000%10;
SMG[5] = (fre_khz < 100) ? 17 :fre/100%10;
SMG[6] = fre_khz/10%10; //高位不熄灭
SMG[7] = fre_khz%10;
dot[6] = 1;
}

简单分析一下会发现单位为m时只是最高位多了个0,并且小数点位置不变,所以单位为m时高位不熄灭
uchar distance;
if(mode_distance)//单位cm
{
SMG[0] = 10; //A
SMG[1] = 17;
SMG[2] = 17;
SMG[3] = 17;
SMG[4] = 17;
SMG[5] = (distance < 100) ? 17 :distance/100;
SMG[6] = (distance < 10) ? 17 :distance/10%10;
SMG[7] = distance%10;
dot[5] = 0;
}
else//单位m
{
SMG[0] = 10; //A
SMG[1] = 17;
SMG[2] = 17;
SMG[3] = 17;
SMG[4] = 17;
SMG[5] = distance/100;//带小数点高位不熄灭
SMG[6] = distance/10%10;
SMG[7] = distance%10;
dot[5] = 1;
}
十二届省赛第二场 
unsigned long fre; //七位已经大于65535了,不能用uint
unsigned long T;
if(mode_fre)//显示频率
{
SMG[0] = 15; //F
SMG[1] = (fre < 1000000) ? 17 :fre/1000000;;
SMG[2] = (fre < 100000) ? 17 :fre/100000%10;
SMG[3] = (fre < 10000) ? 17 :fre/10000%10;
SMG[4] = (fre < 1000) ? 17 :fre/1000%10;
SMG[5] = (fre < 100) ? 17 :fre/100%10;
SMG[6] = (fre < 10) ? 17 :fre/10%10;
SMG[7] = fre%10;
}
else//显示周期 T= 1/F,注意单位是us;要×10的6次
{
T=(1.0/fre) *1000000;//因为要保留小数所以1要变成1.0
SMG[0] = 18; //n
SMG[1] = (T < 1000000) ? 17 :T/1000000;;
SMG[2] = (T < 100000) ? 17 :T/100000%10;
SMG[3] = (T < 10000) ? 17 :T/10000%10;
SMG[4] = (T < 1000) ? 17 :T/1000%10;
SMG[5] = (T < 100) ? 17 :T/100%10;
SMG[6] = (T < 10) ? 17 :T/10%10;
SMG[7] = T%10;
}

