什么?RMB1.6 ! 8H4K32TL-40MHz-LQFP48/32, QFN48/32 16个触摸按键,硬件自动刷新驱动32个8段LED数码管,或16个米字形数码管 80mA大电流硬件LED数码管自动刷新驱动器居然可以8位亮度256种组合? 怎么实现的!!!




因为我要用电位器调米字数码管的亮度,但是8H4K64TL只支持3位亮度,调起来一级一级的蹦看起来很明显,一点也不丝滑,想了很多办法都不能很优雅的解决这个问题,后来过了几天灵机一动就解决了,在此我把这个方法命名为8H4K64TL的“硬3软5”80mA大电流硬件LED驱动器亮度调节方法,不废话了,具体看程序,无关代码已删除,关键代码都写了备注。
程序: unsigned char SEG_Bri; //8bit亮度,范围0~251 void PWM_Func(void) { SEG_Bri=(unsigned char)((pow((float)Filter_Value,2.2F))/351204.0F); //Gamma校正,输入Filter_Value,范围0~4095,输出SEG_Bri,范围0~251 } void SEG_Func(unsigned char temp) //输入temp,范围0~8,对应亮度0%、12.5%、25%、37.5%、50%、62.5%、75%、87.5%、100% { if(temp>8) //无效数据限幅 { temp=8; } if(temp) //大于0亮 { LEDCTRL=7-(temp-1)|0x90; //计算LEDCTRL COMEN=0x1F; //开COM SEGENL=0xFF; //开SEG SEGENH=0x3F; //开SEG } else //否则灭 { COMEN=0x00; //关COM SEGENL=0x00; //关SEG(不关低亮度有鬼影,仅在硬件亮度频繁在0和1之间切换时有) SEGENH=0x00; //关SEG(不关低亮度有鬼影,仅在硬件亮度频繁在0和1之间切换时有) LEDCTRL=0x97; //无法关闭,只能设置为最低亮度 } COM0_DA_L=(unsigned char)SEG_Buf[SEG_Addr]; COM0_DA_H=(unsigned char)(SEG_Buf[SEG_Addr]>>8)&0x3F; COM1_DA_L=(unsigned char)SEG_Buf[SEG_Addr+1]; COM1_DA_H=(unsigned char)(SEG_Buf[SEG_Addr+1]>>8)&0x3F; COM2_DA_L=(unsigned char)SEG_Buf[SEG_Addr+2]; COM2_DA_H=(unsigned char)(SEG_Buf[SEG_Addr+2]>>8)&0x3F; COM3_DA_L=(unsigned char)SEG_Buf[SEG_Addr+3]; COM3_DA_H=(unsigned char)(SEG_Buf[SEG_Addr+3]>>8)&0x3F; COM4_DA_L=(unsigned char)(SEG_Buf[SEG_Addr]>>15)&0x01; COM4_DA_H=0x00; } void Init(void) { P_SW2|=EAXFR; //PxMx在这里设置一下,硬件LED驱动器相关IO设置成推挽 P2DR=0x00; AUXR=0x55; //设置定时器0为12T模式,设置定时器1为1T模式,使能定时器2,设置定时器2为1T模式,选择定时器2作为波特率发生器 TMOD=0x01; //设置定时器0为16位不自动重载模式,设置定时器1为16位自动重载模式 TM2PS=0x00; //设置定时器2分频器 TL1=(0x10000-6400); //设置定时器1初始值(6400)频率同步,160*8*5=6400 TH1=(0x10000-6400)>>8; //设置定时器1初始值(6400)频率同步,160*8*5=6400 TF1=0; //清除TF1中断标志位 TR1=1; //打开定时器1 ET1=1; //启用定时器1中断 COMEN=0x1F; //使用的COM SEGENL=0xFF; //使用的SEG SEGENH=0x3F; //使用的SEG LEDCTRL=0x90; //默认最大亮度 LEDCKS=0x00; //最高频率不分频 EA=1; COM0_DA_L=0x00; COM0_DA_H=0x00; COM1_DA_L=0x00; COM1_DA_H=0x00; COM2_DA_L=0x00; COM2_DA_H=0x00; COM3_DA_L=0x00; COM3_DA_H=0x00; COM4_DA_L=0x00; COM4_DA_H=0x00; } void main(void) { Init(); while(1) { PWM_Func(); } } void Timer1_Isr(void) interrupt 3 { static unsigned char temp,temph,templ; if(SEG_Bri>0&&SEG_Bri<=4) //1、2、3都按4处理,否则极低亮度闪烁明显,因为硬件LED驱动器运行到哪里不知道,也没有中断,频率不能绝对同步 { SEG_Bri=4; } temph=SEG_Bri/28; //因为硬件量化级数是0~8共9级,9的倍数在8位之内最大值为252,所以SEG_Bri为0~251,软件量化级数为252/9=28,temph为MSB,给硬件,范围0~8 templ=SEG_Bri%28; //因为硬件量化级数是0~8共9级,9的倍数在8位之内最大值为252,所以SEG_Bri为0~251,软件量化级数为252/9=28,templ为LSB,给软件,范围0~27 if(templ<=temp) //和模拟电路PWM类似,temp为上升锯齿波,templ为固定值,二者比较即可形成PWM,如果等于也按本级亮度处理,不然最高亮度temph溢出 { SEG_Func(temph); //硬件为本级亮度 } else { SEG_Func(temph+1); //硬件为下一级亮度 } temp++; //计数器扫描,范围0~27 if(temp==28) //溢出 { temp=0; //清零 } }
让你愉快的去编程的小工具



被折叠的 条评论
为什么被折叠?



