单片机学习笔记之1——遥控器输入

///单片机学习笔记之1——遥控器输入

单片机学习笔记之1——遥控器输入

自己写了一个通过遥控器输入数据输出pwm波的代码,代码的算法实现还是比较简单的,不过因为我的编码能力太差了,还是费了不少功夫的。在写这个代码的时候我深刻的体会到了用库的魅力(简称偷懒,而且在下一个代码里用库把我坑惨了),通过库省去了我很多的编码时间和学习时间(所以我学到的东西比较少,现在还是很菜)。现在把代码加了注释分享一下:

//这是main函数的部分,比较简单,不做介绍了
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "sys.h"
#include "beep.h"
#include "key.h"
#include "lcd.h"
#include "remote.h"
#include "exti.h"

void _show_info(void);

extern double frequency,duty;

int main(void)
{
	int key_status,remote_status;
	delay_init(168);
	LED_Init();
	KEY_Init();
 	Remote_Init();	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	uart_init(115200);		
 	LCD_Init();   
	EXTIX_Init();
	POINT_COLOR=BLUE;  
	PWMMODE_84psc(frequency,duty); 	
	_show_info();
	while(1)
	{
		remote_status=Remote_Scan();
		if(remote_status)
		{
			if(remote_status==34)
			{
				duty+=5.0;
				if(duty>99)duty=99.9;
				PWMMODE_84psc(frequency,duty);
				_show_info();
				delay_ms(1000);
			}
			else if(remote_status==194)
			{
				duty-=5.0;
				if(duty>99)duty=99.9;
				PWMMODE_84psc(frequency,duty);
				_show_info();
				delay_ms(1000);
			}
			else if(remote_status==98)
			{
				frequency+=100.0;
				if(frequency>4999)frequency=5000.0;
				PWMMODE_84psc(frequency,duty);
				_show_info();
				delay_ms(1000);
			}
			else if(remote_status==168)
			{
				frequency-=100.0;
				if(frequency<499)frequency=500.0;
				PWMMODE_84psc(frequency,duty);
				_show_info();
				delay_ms(1000);
			}
			else if(remote_status==162)
			{
				_input_frequency();
			}
			else if(remote_status==226)
			{
				_input_duty();
			}
			else
			{
				delay_ms(50);
			}
			remote_status=Remote_Scan();
			remote_status=Remote_Scan();
		}
	}
}

void _show_info(void)
{
	LCD_Clear(WHITE);
	char prin1[100];
	char prin2[100];
	sprintf(prin1,"Frequency:%.2f KHz",frequency/1000);
	sprintf(prin2,"Duty:%.2f%%",duty);
	printf("Frequency:%.2f KHz  Duty:%.2f%% \r\n",frequency/1000,duty);
	LCD_ShowString(30,70,200,16,16,prin1);
 	LCD_ShowString(30,110,200,16,16,prin2);
	return;
}
//这是我直接调用的库来获取遥控器按键键值
u8 	RmtSta=0;	  	  
u16 Dval;		//下降沿时计数器的值
u32 RmtRec=0;	//红外接收到的数据	   		    
u8  RmtCnt=0;	//按键按下的次数	 
//定时器1溢出中断
void TIM1_UP_TIM10_IRQHandler(void)
{
 
  if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) //溢出中断
	{
		if(RmtSta&amp;0x80)//上次有数据被接收到了
		{	
			RmtSta&amp;=~0X10;						//取消上升沿已经被捕获标记
			if((RmtSta&amp;0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
			if((RmtSta&amp;0X0F)<14)RmtSta++;
			else
			{
				RmtSta&amp;=~(1<<7);//清空引导标识
				RmtSta&amp;=0XF0;	//清空计数器	
			}						 	   	
		}							    
	}
	TIM_ClearITPendingBit(TIM1,TIM_IT_Update);  //清除中断标志位 
} 
//定时器1输入捕获中断服务程序	 
void TIM1_CC_IRQHandler(void)
{ 		    	 
	if(TIM_GetITStatus(TIM1,TIM_IT_CC1)==SET) //处理捕获(CC1IE)中断
	{	  
		if(RDATA)//上升沿捕获
		{
			TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Falling);		//CC1P=1 设置为下降沿捕获
			TIM_SetCounter(TIM1,0);	   	//清空定时器值
			RmtSta|=0X10;					//标记上升沿已经被捕获
		}else //下降沿捕获
		{
			Dval=TIM_GetCapture1(TIM1);//读取CCR1也可以清CC1IF标志位
			TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Rising); //CC1P=0	设置为上升沿捕获
			if(RmtSta&amp;0X10)					//完成一次高电平捕获 
			{
 				if(RmtSta&amp;0X80)//接收到了引导码
				{
					
					if(Dval>300&amp;&amp;Dval<800)			//560为标准值,560us
					{
						RmtRec<<=1;	//左移一位.
						RmtRec|=0;	//接收到0	   
					}else if(Dval>1400&amp;&amp;Dval<1800)	//1680为标准值,1680us
					{
						RmtRec<<=1;	//左移一位.
						RmtRec|=1;	//接收到1
					}else if(Dval>2200&amp;&amp;Dval<2600)	//得到按键键值增加的信息 2500为标准值2.5ms
					{
						RmtCnt++; 		//按键次数增加1次
						RmtSta&amp;=0XF0;	//清空计时器		
					}
 				}else if(Dval>4200&amp;&amp;Dval<4700)		//4500为标准值4.5ms
				{
					RmtSta|=1<<7;	//标记成功接收到了引导码
					RmtCnt=0;		//清除按键次数计数器
				}						 
			}
			RmtSta&amp;=~(1<<4);
		}				 		     	    					   
	}
	TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);  //清除中断标志位 
}
//处理红外键盘
//返回值:
//	 0,没有任何按键按下
//其他,按下的按键键值.
u8 Remote_Scan(void)
{        
	u8 sta=0;       
    u8 t1,t2;  
	if(RmtSta&amp;(1<<6))//得到一个按键的所有信息了
	{ 
	    t1=RmtRec>>24;			//得到地址码
	    t2=(RmtRec>>16)&0xff;	//得到地址反码 
 	    if((t1==(u8)~t2)&amp;&amp;t1==REMOTE_ID)//检验遥控识别码(ID)及地址 
	    { 
	        t1=RmtRec>>8;
	        t2=RmtRec; 	
	        if(t1==(u8)~t2)sta=t1;//键值正确	 
		}   
		if((sta==0)||((RmtSta&amp;0X80)==0))//按键数据错误/遥控已经没有按下了
		{
		 	RmtSta&amp;=~(1<<6);//清除接收到有效按键标识
			RmtCnt=0;		//清除按键次数计数器
		}
	}  
    return sta;
}
//以下是对得到的键值进行处理的函数
//对于每种思路只注释了一次,希望阅读时理解了思路后自己再看看没有注释的地方尝试理解
void _input_frequency(void)
{
	char prin1[20]={0};//保存用于输出输入的数据的字符串,并全部初始化为0
	_Bool status=1;//保存当前输入状态为小数点前还是小数点后
	int current=0;//保存一个指向输出字符串当前修改位置的数
	double new_frequency=0.0;//保存输入的频率
	double position=1.0;//保存进入小数输入模式之后输入数据的位置
	int remote_status;//保存读取的键值
	LCD_ShowString(30,150,220,16,16,"Please enter new frequency!");//输出文字提示
	while(1)
	{
		remote_status=Remote_Scan();//读取键值
		if(remote_status)
		{
			if(remote_status==104)//若读取按键为1
			{
				if(status)//判断是否为小数输入状态
				{//若为整数输入状态
					new_frequency*=10;//将当前数据放大十倍
					new_frequency+=1;//个位增加当前输入的值
				}
				else
				{//若为小数输入状态
					position/=10.0;//将输入位置移至下一位小数
					new_frequency+=1*position;//给输入值加上当前位置的小数
				}
				prin1[current]='1';//将字符串当前位置改为输入的数
				current++;//将指向字符串的位置增加一位
			}
			else if(remote_status==152)//若读取键值为2,参考上方,下同
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=2;
				}
				else
				{
					position/=10.0;
					new_frequency+=2*position;
				}
				prin1[current]='2';
				current++;
			}
			else if(remote_status==176)
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=3;
				}
				else
				{
					position/=10.0;
					new_frequency+=3*position;
				}
				prin1[current]='3';
				current++;
			}
			else if(remote_status==48)
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=4;
				}
				else
				{
					position/=10.0;
					new_frequency+=4*position;
				}
				prin1[current]='4';
				current++;
			}
			else if(remote_status==24)
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=5;
				}
				else
				{
					position/=10.0;
					new_frequency+=5*position;
				}
				prin1[current]='5';
				current++;
			}
			else if(remote_status==122)
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=6;
				}
				else
				{
					position/=10.0;
					new_frequency+=6*position;
				}
				prin1[current]='6';
				current++;
			}
			else if(remote_status==16)
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=7;
				}
				else
				{
					position/=10.0;
					new_frequency+=7*position;
				}
				prin1[current]='7';
				current++;
			}
			else if(remote_status==56)
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=8;
				}
				else
				{
					position/=10.0;
					new_frequency+=8*position;
				}
				prin1[current]='8';
				current++;
			}
			else if(remote_status==90)
			{
				if(status)
				{
					new_frequency*=10;
					new_frequency+=9;
				}
				else
				{
					position/=10.0;
					new_frequency+=9*position;
				}
				prin1[current]='9';
				current++;
			}
			else if(remote_status==66)//若输入0,只需改变位置属性
			{
				if(status)
				{
					new_frequency*=10;
				}
				else
				{
					position/=10.0;
				}
				prin1[current]='0';
				current++;
			}
			else if(remote_status==224)//若输入小数点(这里用VOL+表示)
			{
				status=0;//将状态改为小数输入模式
				prin1[current]='.';//字符串中增加一个小数点
				current++;
			}
			else if(remote_status==2)//若输入确认(这里是播放键)
			{
				if(new_frequency<499 || new_frequency >5001)//判断输入是否合法(这里给出的合法范围为500到5000)
				{//若输入非法
					LCD_ShowString(30,230,200,16,16,"Input Error!");//显示输入错误
					delay_ms(2000);//延时显示
					_show_info();//重置屏幕
					break;//结束操作
				}
				else
				{//若输入合法
					frequency=new_frequency;//改变当前频率值
					PWMMODE_84psc(frequency,duty);//输出新的频率值
					_show_info();//重置屏幕并显示新的信息
					break;//结束操作
				}
			}
			else if(remote_status==82)//若输入退格
			{
				if(current==0)//判断当前是否有输入
				{
					continue;//如果没有,直接结束,等待下一次输入
				}
				//如果有输入
				if(status)//判断输入状态
				{//若为整数输入状态
					new_frequency=(int)(new_frequency/10);//去掉新输入的数
					current--;//字符串操作指向上次输入的那位
					prin1[current]=0;//将那位清空置0
				}
				else
				{//若为小数输入状态
					if(position>0.5)//判断小数输入情况
					{//如果上一次输入为小数点(即没有进行小数部分的输入)
						position=1.0;//重置小数输入位置(其实没必要)
						status=1;//将状态改为整数输入状态
						current--;//和上面一样输出字符串减一位
						prin1[current]=0;
					}
					else
					{//若已经进行过小数部分的输入
						new_frequency-=(prin1[current]-'0'+1)*position;//减掉最新输入的那位小数
						position*=10;//输入位置回到上一位
						current--;//和上面一样输出字符串减一位
						prin1[current]=0;
					}
				}
				_show_info();//重置屏幕
				LCD_ShowString(30,150,220,16,16,"Please enter new frequency!");//重新输出提示
			}
			LCD_ShowString(30,190,200,16,16,prin1);//输出退格后的输入数据
			delay_ms(1000);
			//和之前一样清空缓冲区
			remote_status=Remote_Scan();
			remote_status=Remote_Scan();
		}
		else//若没有接收到信号
		{
			delay_ms(50);//延时后再次接受
		}
	}
}

void _input_duty(void)//输入频率函数(这部分代码原理和之前基本一模一样,请自己体会)
{
	char prin1[20]={0};
	_Bool status=1;
	int current=0;
	double new_duty=0.0;
	double position=1.0;
	int remote_status;
	LCD_ShowString(30,150,220,16,16,"Please enter new duty!");
	while(1)
	{
		remote_status=Remote_Scan();
		if(remote_status)
		{
			if(remote_status==104)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=1;
				}
				else
				{
					position/=10.0;
					new_duty+=1*position;
				}
				prin1[current]='1';
				current++;
			}
			else if(remote_status==152)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=2;
				}
				else
				{
					position/=10.0;
					new_duty+=2*position;
				}
				prin1[current]='2';
				current++;
			}
			else if(remote_status==176)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=3;
				}
				else
				{
					position/=10.0;
					new_duty+=3*position;
				}
				prin1[current]='3';
				current++;
			}
			else if(remote_status==48)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=4;
				}
				else
				{
					position/=10.0;
					new_duty+=4*position;
				}
				prin1[current]='4';
				current++;
			}
			else if(remote_status==24)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=5;
				}
				else
				{
					position/=10.0;
					new_duty+=5*position;
				}
				prin1[current]='5';
				current++;
			}
			else if(remote_status==122)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=6;
				}
				else
				{
					position/=10.0;
					new_duty+=6*position;
				}
				prin1[current]='6';
				current++;
			}
			else if(remote_status==16)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=7;
				}
				else
				{
					position/=10.0;
					new_duty+=7*position;
				}
				prin1[current]='7';
				current++;
			}
			else if(remote_status==56)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=8;
				}
				else
				{
					position/=10.0;
					new_duty+=8*position;
				}
				prin1[current]='8';
				current++;
			}
			else if(remote_status==90)
			{
				if(status)
				{
					new_duty*=10;
					new_duty+=9;
				}
				else
				{
					position/=10.0;
					new_duty+=9*position;
				}
				prin1[current]='9';
				current++;
			}
			else if(remote_status==66)
			{
				if(status)
				{
					new_duty*=10;
				}
				else
				{
					position/=10.0;
				}
				prin1[current]='0';
				current++;
			}
			else if(remote_status==224)
			{
				status=0;
				prin1[current]='.';
				current++;
			}
			else if(remote_status==2)
			{
				if(new_duty<0 || new_duty >100)
				{
					LCD_ShowString(30,230,200,16,16,"Input Error!");
					delay_ms(2000);
					_show_info();
					break;
				}
				else
				{
					duty=new_duty;
					PWMMODE_84psc(frequency,duty);
					_show_info();
					break;
				}
			}
			else if(remote_status==82)
			{
				if(current==0)
				{
					continue;
				}
				if(status)
				{
					new_duty=(int)(new_duty/10);
					current--;
					prin1[current]=0;
				}
				else
				{
					if(position>0.9)
					{
						position=1.0;
						status=1;
						current--;
						prin1[current]=0;
					}
					else
					{
						current--;
						new_duty-=(prin1[current]-'0')*position;
						position*=10;
						prin1[current]=0;
					}
				}
				_show_info();
				LCD_ShowString(30,150,220,16,16,"Please enter new duty!");
			}
			LCD_ShowString(30,190,200,16,16,prin1);
			remote_status=Remote_Scan();
			delay_ms(1000);
			remote_status=Remote_Scan();
		}
		else
		{
			delay_ms(50);
		}
	}
	
}
发布者 | 2018-12-23T18:28:24+08:00 十一月 22nd, 2018|单片机, 学习笔记|0条评论

关于作者

一个想要变强的萌新 座右铭:坚强大概——并不是指的的结果,而是迈向某个目标的过程吧。

发表评论

博客作者

坚强大概——并不是指的的结果,而是迈向某个目标的过程吧。

标签云

博客统计

  • 2,164 点击次数
召唤伊斯特瓦尔