单片机学习笔记之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条评论

关于作者

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

发表评论

召唤伊斯特瓦尔