#申请原创#
一、引脚中断的使用步骤
之前测试的DS1307日历模块有秒信号输出功能,可以利用其输出的秒信号触发中断,实现单片机中秒计数和控制LED闪烁,取代之前用定时器进行秒计数,同时准备实验的红外遥控接收也打算使用中断来处理,实现及时响应,因此本次重点进行了引脚中断处理的实验。
DS1307日历模块输出的是1Hz方波,因为触发方式可以为下降沿,也可以为上升沿,我的设置如下:
红外接收实验用的是从机顶盒拆下来的VS838接收头,其典型指标如下:
从上图可以看出应该设置为下降沿触发:
引脚参数配置好以后,直接生成代码,可以在intrrupt_manager.c文件中看到中断处理过程:
具体的中断处理函数在pin_manager.c文件中,我们可以在此写入代码:
秒信号中断的代码很简单,只是对second变量增1,代码如下:
/**
IOCAF5 Interrupt Service Routine
*/
void IOCAF5_ISR(void) {
// Add custom IOCAF5 code DS1307_SQ秒信号中断
second++;
// Call the interrupt handler for the callback registered at runtime
if(IOCAF5_InterruptHandler)
{
IOCAF5_InterruptHandler();
}
IOCAFbits.IOCAF5 = 0;
}
二、红外遥控信号接收
常用的红外遥控信号是由起始码及32bit数据构成,其中包含两组(各8位)的用户码和两组(各8位)的数据组成的,两组用户码可以是相同的,后8位也可以是前8位的反码,两组数据码则后一组是前一组的反码,具体可以参见前面第二幅图片。其时序图如下:
不过我在测试中遇到一款万能电视机遥控器,其起始码之后仅有16bit 数据,即用户码和数据各8位,没有校验用的反码,其时序图如下:
通过分析,其起始码也不是常用的9ms低电平+4.5ms的高电平,而是各为3ms左右的低电平+高电平,这就成为了我识别这两种红外遥控器的标志。
这款遥控器的另一个特点是按下按键会同时发出5组相同的数据,两组间隔约24ms,这个特点就需要在识别代码中处理,可以通过延时忽略掉重复的数据,也可以在完成识别之后设立标志,在处理结束后取消标志,在标志取消之前就不识别收到的数据。下图为实际抓取的时序图:
在测试某机顶盒红外遥控器的时候,发现其发送完一次数据之后,还会跟一个起始码(如下图所示),好在这个起始码的高电平时间没有4.5ms,仅有约2.2ms,这也成了识别处理的标志:
下面是我识别测试中使用的代码,这个代码是我独自写的,可以算是成原创了:
//红外线遥控器解码,识别的数据存放在全局变量IR[4]中,其中IR[0]和IR[1]存放用户码,IR[2]和IR[3]存放数据
void IR_Handier(void)
{
uint8_t i,j,dat = 0;
uint8_t times;
if(IRok>0)
return; //前一数据未处理,不解释新的信息
Led1_SetLow(); //测试用
times = 200;
while((0==IR_GetValue())&&(times>0)){ //等待高电平信号(9ms或3ms)
DELAY_microseconds(100);
times--;
Led1_Toggle();
}
Led1_SetHigh();
if(times > 150){ //按万能遥控器8+8位解码(200-22=178)
times = 50;
while((IR_GetValue()>0)&&(times>0)){//等待高电平起始码信号结束(4.5sm)
DELAY_microseconds(100);
Led1_Toggle();
times--;
}
Led1_SetLow();
for(j=0; j<2; j++){
for(i=0; i<8; i++){
times = 10;
while((0==IR_GetValue())&&(times>0)){//等待0.5ms的数据低电平信号结束
DELAY_microseconds(100);
times--;
}
Led1_SetHigh();
dat >>= 1;
times = 30;
while((IR_GetValue()>0)&&(times>0)){//等待数据高电平信号结束(计算高电平时间1.5/2.5ms)
DELAY_microseconds(100);
times--;
Led1_Toggle();
}
Led1_SetLow();
if(times<15)
dat |= 0x80; //高电平times=30-19;低电平times=30-11
}
IR[j] = dat;
dat = 0;
}
IR[2] = IR[1];
IR[1] = 222; //随意设置的标志
IR[3] = 222;
}
else{ //按标准遥控器9+4.5位解码(200-70=130)
times = 50;
while((IR_GetValue()>0)&&(times>0)){//等待高电平起始码信号结束(50-34=17)
DELAY_microseconds(100);
times--;
Led1_Toggle();
}
if(times>20) //处理末尾的结束信号(50-18=32)
return;
Led1_SetLow();
for(j=0; j<4; j++){
Led1_SetHigh();
for(i=0; i<8; i++){
Led1_SetLow();
times = 10;
while((0==IR_GetValue())&&(times>0)){//等待0.56ms的数据低电平信号结束
DELAY_microseconds(100);
times--;
}
Led1_SetHigh();
dat >>= 1;
times = 20;
while((IR_GetValue()>0)&&(times>0)){
DELAY_microseconds(100);//520+620us(520~1140us)
times--;
Led1_Toggle();
}
Led1_SetLow();
if(times<10)
dat |= 0x80; //高电平:times=12;低电平:times=20
}
IR[j] = dat;
dat = 0;
Led1_SetLow();
}
}
IRok++; //置红外信号标志
}
红外遥控的实际使用代码尚未编写,本次测试仅仅是将收到的用户码和键值显示在LCD屏幕上,下面是测试过程的照片“
这是显示效果,因光线太强,屏幕有点不清晰:
|