自己写了一个通过遥控器输入数据输出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);
}
}
}
Leave A Comment