单片机学习笔记之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&0x80)//上次有数据被接收到了
{	
RmtSta&=~0X10;						//取消上升沿已经被捕获标记
if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
if((RmtSta&0X0F)<14)RmtSta++;
else
{
RmtSta&=~(1<<7);//清空引导标识
RmtSta&=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&0X10)					//完成一次高电平捕获 
{
if(RmtSta&0X80)//接收到了引导码
{
if(Dval>300&&Dval<800)			//560为标准值,560us
{
RmtRec<<=1;	//左移一位.
RmtRec|=0;	//接收到0	   
}else if(Dval>1400&&Dval<1800)	//1680为标准值,1680us
{
RmtRec<<=1;	//左移一位.
RmtRec|=1;	//接收到1
}else if(Dval>2200&&Dval<2600)	//得到按键键值增加的信息 2500为标准值2.5ms
{
RmtCnt++; 		//按键次数增加1次
RmtSta&=0XF0;	//清空计时器		
}
}else if(Dval>4200&&Dval<4700)		//4500为标准值4.5ms
{
RmtSta|=1<<7;	//标记成功接收到了引导码
RmtCnt=0;		//清除按键次数计数器
}						 
}
RmtSta&=~(1<<4);
}				 		     	    					   
}
TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);  //清除中断标志位 
}
//处理红外键盘
//返回值:
//	 0,没有任何按键按下
//其他,按下的按键键值.
u8 Remote_Scan(void)
{        
u8 sta=0;       
u8 t1,t2;  
if(RmtSta&(1<<6))//得到一个按键的所有信息了
{ 
t1=RmtRec>>24;			//得到地址码
t2=(RmtRec>>16)&0xff;	//得到地址反码 
if((t1==(u8)~t2)&&t1==REMOTE_ID)//检验遥控识别码(ID)及地址 
{ 
t1=RmtRec>>8;
t2=RmtRec; 	
if(t1==(u8)~t2)sta=t1;//键值正确	 
}   
if((sta==0)||((RmtSta&0X80)==0))//按键数据错误/遥控已经没有按下了
{
RmtSta&=~(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条评论

关于作者

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

发表评论

博客作者

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

标签云

博客统计

  • 3,065 点击次数
召唤伊斯特瓦尔