3203.21红外遥控实验ALIENTKEMiniSTM3开发板给使用者配备了标准的红外接收头和一个很小巧的红外遥控器。本节将向大家介绍,如何在ALIENTEKMiniSTM32开发板上实现红外遥控器的控制。本节分为如下几个部分:3.21.1红外遥控简介3.21.2硬件设计3.21.3软件设计3.21.4下载与测试3213.21.1红外遥控简介红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。由于红外线遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力,所以,在设计红外线遥控器时,不必要像无线电遥控器那样,每套(发射器和接收器)要有不同的遥控频率或编码(否则,就会隔墙控制或干扰邻居的家用电器),所以同类产品的红外线遥控器,可以有相同的遥控频率或编码,而不会出现遥控信号“串门”的情况。这对于大批量生产以及在家用电器上普及红外线遥控提供了极大的方面。由于红外线为不可见光,因此对环境影响很小,再由红外光波动波长远小于无线电波的波长,所以红外线遥控不会影响其他家用电器,也不会影响临近的无线电设备。红外遥控的编码目前广泛使用的是:NECProtocol的PWM(脉冲宽度调制)和PhilipsRC-5Protocol的PPM(脉冲位置调制)。我们配套的遥控器使用的是NEC协议,其特征如下:1、8位地址和8位指令长度;2、地址和命令2次传输(确保可靠性)3、PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”;4、载波频率为38Khz;5、位时间为1.125ms或2.25ms;NEC码的位定义:一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms(560us脉冲+560us低电平)。而遥控接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,我们在接收头端收到的信号为:逻辑1应该是560us低+1680us高,逻辑0应该是560us低+560us高。NEC遥控指令的数据格式为:同步码头、地址码、地址反码、控制码、控制反码。同步码由一个9ms的低电平和一个4.5ms的高电平组成,地址码、地址反码、控制码、控制反码均是8位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性(可用于校验)。我们遥控器的按键2按下时,从红外接收头端收到的波形如下:图3.21.1.1按键2所对应的红外波形从图中可以看到,其地址码为0,控制码为168。可以看到在100ms之后,我们还受到了几个脉冲,这是NEC码规定的连发码(由9ms低电平+2.5m高电平+0.56ms低电平+97.94ms高电平组成),如果在一帧数据发送完毕之后,按键仍然没有放开,则发射重复码,即连发码,可以通过统计连发码的次数来标记按键按下的长短/次数。3223.21.2硬件设计本实验采用中断解码(也可以采用输入捕获解码),本节实验功能简介:开机在LCD上显示一些信息之后,即进入等待红外触发,如过接收到正确的红外信号,则解码,并在LCD上显示键值和所代表的意义,以及按键次数等信息。同样我们也是用LED0来指示程序正在运行。所要用到的硬件资源如下:1)STM32F103RBT6。2)DS0(外部LED0)。3)TFTLCD液晶模块。4)红外接收头。5)红外遥控器。前面三部分,在之前的实例已经介绍过了,遥控器属于外部器件,遥控接收头在板子上,与MCU的连接原理图如下:图3.21.2.1红外遥控接收头与STM32的连接电路图红外遥控接收头与STM32的PA1通过跳线帽连接,这个在硬件上要连接上,否则PA1将得不到信号,我们采用中断解码,PA1对应的中断为中断1,所以在程序设计的时候,我们只要开启中断1,然后在中断里执行解码就可以了。开发板配套的红外遥控器外观如下:图3.21.2.2红外遥控器3233.21.3软件设计打开上一节的工程,首先在HARDWARE文件夹下新建一个REMOTE的文件夹。然后新建一个remote.c和remote.h的文件保存在REMOTE文件夹下,并将这个文件夹加入头文件包含路径。打开remote.c文件,输入如下代码:#includeremote.h#includedelay.h//MiniSTM32开发板//红外遥控接收驱动函数//正点原子@ALIENTEK//2010/6/17u32Remote_Odr=0;//命令暂存处u8Remote_Cnt=0;//按键次数,此次按下键的次数u8Remote_Rdy=0;//红外接收到数据//初始化红外接收引脚的设置//开启中断,并映射voidRemote_Init(void){RCC-APB2ENR|=12;//PA时钟使能GPIOA-CRL&=0XFFFFFF0F;GPIOA-CRL|=0X00000080;//PA1输入GPIOA-ODR|=11;//PA.1上拉Ex_NVIC_Config(GPIO_A,1,FTIR);//将line1映射到PA.1,下降沿触发.MY_NVIC_Init(2,1,EXTI1_IRQChannel,2);}//检测脉冲宽度//昀长脉宽为5ms//返回值:x,代表脉宽为x*20us(x=1~250);u8Pulse_Width_Check(void){u8t=0;while(RDATA){t++;delay_us(20);if(t==250)returnt;//超时溢出}returnt;}//处理红外接收/*-------------------------协议--------------------------324开始拉低9ms,接着是一个4.5ms的高脉冲,通知器件开始传送数据了接着是发送4个8位二进制码,第一二个是遥控识别码(REMOTE_ID),第一个为正码(0),第二个为反码(255),接着两个数据是键值,第一个为正码第二个为反码.发送完后40ms,遥控再发送一个9ms低,2ms高的脉冲,表示按键的次数,出现一次则证明只按下了一次,如果出现多次,则可以认为是持续按下该键.---------------------------------------------------------*///外部中断服务程序voidEXTI1_IRQHandler(void){u8res=0;u8OK=0;u8RODATA=0;while(1){if(RDATA)//有高脉冲出现{res=Pulse_Width_Check();//获得此次高脉冲宽度if(res==250)break;//非有用信号if(res=200&&res250)OK=1;//获得前导位(4.5ms)elseif(res=85&&res200)//按键次数加一(2ms){Remote_Rdy=1;//接受到数据Remote_Cnt++;//按键次数增加break;}elseif(res=50&&res85)RODATA=1;//1.5mselseif(res=10&&res50)RODATA=0;//500usif(OK){Remote_Odr=1;Remote_Odr+=RODATA;Remote_Cnt=0;//按键次数清零}}}EXTI-PR=11;//清除中断标志位}//处理红外键盘//返回相应的键值u8Remote_Process(void){u8t1,t2;325t1=Remote_Odr24;//红外解码t2=(Remote_Odr16)&0xff;Remote_Rdy=0;//清除标记if(t1==(u8)~t2&&t1==REMOTE_ID)//检验遥控识别码(ID){t1=Remote_Odr8;t2=Remote_Odr;if(t1==(u8)~t2)returnt1;//处理键值}return0;}该部分代码比较简单,主要是通过中断解码,解码程序是按照前面介绍的NEC码来解的,在这里我们就不再多说了。保存remote.c,然后把该文件加入HARDWARE组下。接下来打开remote.h在该文件里面加入如下代码:#ifndef__RED_H#define__RED_H#includesys.h//MiniSTM32开发板//红外遥控接收驱动函数//正点原子@ALIENTEK//2010/6/17#defineRDATAPAin(1)//红外数据输入脚//红外遥控识别码(ID),每款遥控器的该值基本都不一样,但也有一样的.//我们选用的遥控器识别码为0#defineREMOTE_ID0externu8Remote_Cnt;//按键次数,此次按下键的次数externu8Remote_Rdy;//红外接收到数据externu32Remote_Odr;//命令暂存处voidRemote_Init(void);//红外传感器接收头引脚初始化u8Remote_Process(void);//红外接收到数据处理u8Pulse_Width_Check(void);//检查脉宽#endif这里的REMOTE_ID就是我们开发板配套的遥控器的识别码,对于其他遥控器可能不一样,只要修改这个为你所使用的遥控器的一致就可以了。其他是一些函数的声明,我们保存此部分代码,然后在test.c里面修改主函数如下:intmain(void){u8key;u8t;Stm32_Clock_Init(9);//系统时钟设置delay_init(72);//延时初始化uart_init(72,9600);//串口1初始化326LCD_Init();//初始化液晶LED_Init();//LED初始化Remote_Init();//初始化红外接收POINT_COLOR=RED;//设置字体为红色LCD_ShowString(60,50,MiniSTM32);LCD_ShowString(60,70,REMOTETEST);LCD_ShowString(60,90,ATOM@ALIENTEK);LCD_ShowString(60,110,2010/6/17);LCD_ShowString(30,130,KEYVAL:);LCD_ShowString(130,130,KEYCNT:);LCD_ShowString(30,150,SYMBOL:);while(1){if(Remote_Rdy){key=Remote_Process();LCD_ShowNum(86,130,key,3,16);//显示键值LCD_ShowNum(186,130,Remote_Cnt,3,16);//显示按键次数switch(key){case0:LCD_ShowString(86,150,ERROR);break;case162:LCD_ShowString(86,150,POWER);break;case98:LCD_ShowString(86,150,VOL+);break;case2:LCD_ShowString(86,150,VOL-);break;case226:LCD_ShowString(86,150,CH+);break;case194:LCD_ShowString(86,150,CH-);break;case34:LCD_ShowString(86,150,RECALL);break;327case56:LCD_ShowString(86,150,0);break;case224:LCD_ShowString(86,150,1);break;case168:LCD_ShowString(86,150,2);break;case144:LCD_ShowString(86,150,3);break;case104:LCD_ShowString(86,150,4);break;case152:LCD_ShowString(86,150,5);bre