蓝桥杯第9届省赛:pwm调节led的接口(结尾有总代码文件及最终效果视频)

学习内容

写blog对个人的作用:将繁琐的知识碎片经过 思考->概括->总结 整合为较为完整独立的知识节点,复习时可快速体会其知识内核,方便建立知识体系。 ——YLAD

pwm驱动不同状态的led

1. pwm接口

周期为16ms,占空比根据ADC采集旋钮电阻分压得到led_level参数;
api参数:led_var指定让8个里面的哪些点亮(1:亮;0:灭),如:0x81就是将L1与L8同时用此pwm波驱动;

/*
原理:
	pwm波图解:-表示1ms时间段,|表示根据led_level设置的占空比(题目要求平分4个等级)
	如下是led_pwm_time在定时器中自增的时间标志(最大到16ms),|划分了4个等级(占空比)
		
		led_pwm_time:----|----|----|----|(16ms)
		
参数:
	led_pwm_time:中断中设置的pwm时间线0-16ms无限循环
	led_level:通过ad旋钮调节占空比
	
api重点1:hc4设置需要的位时用到的是|与&,不会影响到其他位,因此要记得将其他位熄灭,具体操作只在改变led显示状态时执行1次就行,因此将熄灭操作放在void taskled();函数中即可
*/
void pwm_led(u8 led_var,u8 led_pwm_time,u8 led_level)//led_var指定让8个里面的哪些点亮,如:0x81就是将L1与L8同时用此pwm波驱动
{
		if(led_pwm_time<led_level*4)//level=1时,led_level*4=4ms,即上图中的一个|
		{//亮hc4&=0xfe;
			select(Y0);hc4&=~led_var;P0=hc4;select(Y4);//据题目要求,等级越低,led越暗
		}else{//灭hc4|=0x01;
			select(Y0);hc4|=led_var;P0=hc4;select(Y4);
		}
}

2.LED处理函数

重点:每个时间间隔后(改变led显示状态)都要将数码管全部熄灭,熄灭操作如下:select(Y0);hc4=0xff;P0=hc4;select(Y4);

void taskled()//多间隔时间标志
{
	if(led_on==1)
	{
		//自定义时间间隔如500ms执行一次
		if(led_mod_int>=led_int[led_mod])//==在改变间隔时间时容易出错
		{
			led_mod_int=0;//该led模式下的间隔时间标志
			
			select(Y0);hc4=0xff;P0=hc4;select(Y4);//!!!!加这一句很重要,因为每次要改变led_var值后,要保证,hc4里面的数据消除之前的数据;!!!!
		
			if(led_mod==0)
			{
				led_var=0x01<<led_mod_i;//led_var经过实验必须定义,将其传至hc4
				led_mod_i++;if(led_mod_i==8)led_mod_i=0;//led移动
			}else if(led_mod==1)
			{
				led_var=0x80>>led_mod_i;
				led_mod_i++;if(led_mod_i==8)led_mod_i=0;
			}else if(led_mod==2)
			{
				led_var=led_34[led_mod_i_34];
				led_mod_i_34++;if(led_mod_i_34==4)led_mod_i_34=0;
			}else if(led_mod==3)
			{
				led_var=led_34[led_mod_i_34];
				led_mod_i_34--;if(led_mod_i_34==255)led_mod_i_34=3;
			}
			
			
		}
	}
}

3.中断处理函数

调用pwm接口+taskled处理函数

/*全局变量总概览*/

//当前led的模式与该模式下的时间间隔参数
u8 led_mod=0;//通过按键切换led显示模式
u16 led_int[4];//四个模式的间隔,可通过按键设置间隔大小
u16 led_mod_int=0;//哎!!又忘了是16位

//pwm接口要用到的参数
u8 led_var;//pwm的接口,向pwm传输端口信息;在taskled()函数中根据模式进行改变;
u8 led_pwm_time=0;//该参数在中断中循环自增;
u8 led_level=1;//pwm频率为50hz,即在20ms内根据led_level调占空比;

//taskled任务要用到的具体led移动方式的参数
bit led_on=0;//通过按键决定taskled是否运行
u8 led_mod_i=0;//模式1,2的led移位标志
u8 led_mod_i_34=0;//模式3,4的led移位标志
u8 led_34[4]={0x81,0x42,0x24,0x18};/*模式3,4,led端口值,
	/10000001/ /01000010/ /00100100/ /00011000/  (1:亮)
	*/

void Timer1_Isr(void) interrupt 3
{
	//led处理及标志位设置,如:模式1下时间间隔为400ms(即:led_mod=0;400=led_int[0])\
	执行完成taskled()后向外部传出led_var,之后**pwm接口函数**使用led_var变量进行led的显示;
	taskled();//400ms执行一次led状态的改变(led_var参数的改变)
	if(led_mod_int<led_int[led_mod])led_mod_int++;
	
	//pwm处理函数必要参数
	pwm_led(led_var);
	led_pwm_time++;
	if(led_pwm_time>=16)led_pwm_time=0;//pwm周期为20ms
}

总结:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值