目录
前言
主程序 做到蓝桥杯第九届彩灯,我被沉默。。。。。
1.什么是PWM? 小蜜蜂老师讲解
2.恭喜你,陷入了疯狂
- 用PCF8951的AD转换来控制灯的亮度调节
- 按键来控制流水灯的间隔和流水灯模式
3.老八下饭,后庭开花
- AD转化是模拟值到数值。
- 模拟值是电压,数值就仅仅是数。
- 数值不能改变亮度,而是数值表示的PWM占空比 ,实现亮度调节
4.可能一切的可能 ,是不可能
- 亮度调节(PWM)需要中断;
- 流转间隔同样需要中断;
- 谁的优先级高???
本着十八年当灯泡的经历,点亮灯后才能调节亮度。
流转间隔的中断大于亮度调节(PWM)中断;
LED熄灭后,亮度调节同样失效。
5.万事具备,东风不来,北风啸啸
PCF8951NUM();返回的值是 1、2、3、4
PWM_duty=PCF8951NUM();
一、主程序
//定时器1,1ms.
void Timer1Init(void)
{
AUXR &= 0xBF;
TMOD &= 0x0F;
TL1 = 0x18;
TH1 = 0xFC;
TF1 = 0;
TR1 = 1;
EA=1; ET1=1;
}
//定时器1设置,模式控制LED灯亮度和流转间隔
void time_1() interrupt 3{
LED_t++;
//控制流转间隔
if(LED_t>=LED_gap){ LED_t=0; //到达间隔
if(LED_flag) {LED_flag=0;} //上一个LED灯熄灭
else{num++; LED_flag=1;} //下一个LED点亮,num指的是第几位LED
}
//控制亮度
if(LED_flag) { PWM_t++; //ledflag=1;表示LED是亮的
if(PWM_t==PWM_duty) led=0xff; //PWM_t到达高电平LED熄灭
if(PWM_t==5) { PWM_t=0; //PWM_t==5,高电平结束,回到低电平,LED亮。
switch(led_mode) //选择LED流转模式
{
case 1:if(num>=8)num=0;led=LED1[num];break;//led1
case 2:if(num>=8)num=0;led=LED2[num];break;//led2
case 3:if(num>=4)num=0;led=LED3[num];break;//led3
case 4:if(num>=4)num=0;led=LED4[num];break;//led4
//LED每流转一次mum加1;点亮下一个LED
}
}
}
else led=0xff;
//不满足 if(LED_flag) LED熄灭
}
二、流水灯流转
1.通过数组来实现不同LED流转模式
2.数组的内容,是P0的值
3.LED[0]=0xfe, 1111 1110 表示L1亮,LED灯熄灭
uchar LED1[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //模式1
uchar LED2[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //模式2
uchar LED3[4]={0x7e,0xbd,0xdb,0xe7}; //模式3
uchar LED4[4]={0xe7,0xdb,0xbd,0x7e}; //模式4
三、流水灯亮度调节
通过PCF8591,AD转换值控制LED的亮度
uchar PCF8591NUM()
{
uchar Val;
EA = 0;
IIC_Start(); //IIC启动
IIC_SendByte(0x90); //IIC选择地址,并发送写指令
IIC_WaitAck(); //等待IIC应答
IIC_SendByte(0x03); //选择模拟量输入通道
IIC_WaitAck();
IIC_Stop(); //IIC停止,接下来开始读取数据
IIC_Start(); //IIC启动
IIC_SendByte(0x91); //IIC选择地址,并发送读指令
IIC_WaitAck(); //IIC等待应答
Val = IIC_RecByte(); //接收PCF8591数据,最大值255
IIC_SendAck(1); //发送非应答位
IIC_Stop();
EA = 1;
if(Val<80)
Val = 1;
else if(Val<120)
Val = 2; // 80<=val<120
else if(V<180)
Val = 3; // 120<=val<180
else
Val = 4; // 180<=val<255
/*根据所得ad值返回四种不同的数据给PWM*/
return Val;
}