红外遥控接口电路
STM32单片机红外遥控程序源代码
#include "sys.h"
#define LED_RED PBout(12) //红色发光二极管控制管脚初始化PB12
#define LED_GREEN PBout(13) //绿色发光二极管控制管脚初始化PB13
#define LED_YELLOW PBout(14) //黄色发光二极管控制管脚初始化PB14
#define LED_BLUE PBout(15) //蓝色发光二极管控制管脚初始化PB15
#define BEEP PBout(5) //蜂鸣器端口定义PB5
#define RDATA PAin(1) //红外数据输入脚
//红外遥控识别码(ID),每款遥控器的该值基本都不一样,但也有一样的
//我们选用的遥控器识别码为0
#define REMOTE_ID 0
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数
void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);
void Led_Init(void); //发光二极管控制管脚初始化
void Red_Led_Light(void); //点亮红色发光二极管
void Green_Led_Light(void); //点亮绿色发光二极管
void Yellow_Led_Light(void); //点亮黄色发光二极管
void Blue_Led_Light(void); //点亮蓝色发光二极管
void Red_Led_Goout(void); //熄灭红色发光二极管
void Green_Led_Goout(void); //熄灭绿色发光二极管
void Yellow_Led_Goout(void); //熄灭黄色发光二极管
void Blue_Led_Goout(void); //熄灭蓝色发光二极管
void Beep_Init(void);
void Beep_Tweet(void);
void Beep_Silent(void);
extern u8 Remote_Cnt; //按键次数,此次按下键的次数
extern u8 Remote_Rdy; //红外接收到数据
extern u32 Remote_Odr; //命令暂存处
u32 Remote_Odr=0; //命令暂存处
u8 Remote_Cnt=0; //按键次数,此次按下键的次数
u8 Remote_Rdy=0; //红外接收到数据
void Remote_Init(void); //红外传感器接收头引脚初始化
u8 Remote_Process(void); //红外接收到数据处理
u8 Pulse_Width_Check(void); //检查脉宽
extern u8 USART_RX_BUF[64]; //接收缓冲,最大63个字节.末字节为换行符
extern u8 USART_RX_STA; //接收状态标记
//如果想串口中断接收,请不要注释以下宏定义
//#define EN_USART1_RX //使能串口1接收
void uart_init(u32 pclk2,u32 bound);
/*************************************************************
开发板上电后,用红外遥控器对着开发板上的红外接收头。
按下遥控器上的按键0,开发板通过串口(程序下载的串口)发送数值0;
按下遥控器上的按键1,开发板通过串口(程序下载的串口)发送数值1;
按下遥控器上的按键2,开发板通过串口(程序下载的串口)发送数值2;
按下遥控器上的按键3,开发板通过串口(程序下载的串口)发送数值3;
按下遥控器上的按键4,开发板通过串口(程序下载的串口)发送数值4;
按下遥控器上的按键5,开发板通过串口(程序下载的串口)发送数值5;
按下遥控器上的按键6,开发板通过串口(程序下载的串口)发送数值6;
按下遥控器上的按键7,开发板通过串口(程序下载的串口)发送数值7;
按下遥控器上的按键8,开发板通过串口(程序下载的串口)发送数值8;
按下遥控器上的按键9,开发板通过串口(程序下载的串口)发送数值9;
串口助手设置:波特率9600 数据位:8 停止位:1 HEX显示
*************************************************************/
void delay_init(u8 SYSCLK)
{
SysTick->CTRL&=0xfffffffb; //bit2清空,选择外部时钟 HCLK/8
fac_us=SYSCLK/8;
fac_ms=(u16)fac_us*1000;
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL=0x01 ; //开始倒数
do{temp=SysTick->CTRL;}
while(temp&0x01&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL=0x01 ; //开始倒数
do{temp=SysTick->CTRL;}
while(temp&0x01&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void Led_Init(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB接口时钟
GPIOB->CRH&=0XFFF0FFFF;
GPIOB->CRH|=0X00030000; //PB12推挽输出
GPIOB->ODR|=1<<12; //PB12输出高电平
GPIOB->CRH&=0XFF0FFFFF;
GPIOB->CRH|=0X00300000; //PB13推挽输出
GPIOB->ODR|=1<<13; //PB13输出高电平
GPIOB->CRH&=0XF0FFFFFF;
GPIOB->CRH|=0X03000000; //PB14推挽输出
GPIOB->ODR|=1<<14; //PB14输出高电平
GPIOB->CRH&=0X0FFFFFFF;
GPIOB->CRH|=0X30000000; //PB15推挽输出
GPIOB->ODR|=1<<15; //PB15输出高电平
}
void Red_Led_Light(void){LED_RED=0;}
void Red_Led_Goout(void){LED_RED=1;}
voidGreen_Led_Light(void){LED_GREEN=0;}
voidGreen_Led_Goout(void){LED_GREEN=1;}
void Yellow_Led_Light(void){LED_YELLOW=0;}
voidYellow_Led_Goout(void){LED_YELLOW=1;}
void Blue_Led_Light(void){LED_BLUE=0;}
void Blue_Led_Goout(void){LED_BLUE=1;}
void Beep_Init(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0XFF0FFFFF;
GPIOB->CRL|=0X00300000; //PB5推挽输出
GPIOB->ODR|=1<<5; //PB5输出高
}
void Beep_Tweet(void){BEEP=0;}
void Beep_Silent(void){BEEP=1;}
void Remote_Init(void)
{
RCC->APB2ENR|=1<<2; //PA时钟使能
GPIOA->CRL&=0XFFFFFF0F;
GPIOA->CRL|=0X00000080; //PA1输入
GPIOA->ODR|=1<<1; //PA.1上拉
Ex_NVIC_Config(GPIO_A,1,FTIR); //将line1映射到PA.1,下降沿触发.
MY_NVIC_Init(2,1,EXTI1_IRQChannel,2);
}
u8 Pulse_Width_Check(void)
{
u8 t=0;
while(RDATA)
{t++;delay_us(20);if(t==250)return t;} //超时溢出
return t;
}
void EXTI1_IRQHandler(void)
{
u8 res=0;u8 OK=0;u8 RODATA=0;
while(1)
{
if(RDATA) //有高脉冲出现
{
res=Pulse_Width_Check(); //获得此次高脉冲宽度
if(res==250)break; //非有用信号
if(res>=200&&res<250)OK=1; //获得前导位(4.5ms)
else if(res>=85&&res<200) //按键次数加一(2ms)
{
Remote_Rdy=1; //接受到数据
Remote_Cnt++; //按键次数增加
break;
}
else if(res>=50&&res<85)RODATA=1;//1.5ms
else if(res>=10&&res<50)RODATA=0;//500us
if(OK)
{
Remote_Odr<<=1;
Remote_Odr+=RODATA;
Remote_Cnt=0; //按键次数清零
}
}
}
EXTI->PR=1<<1; //清除中断标志位
}
u8 Remote_Process(void)
{
u8 t1,t2;
t1=Remote_Odr>>24; //得到地址码
t2=(Remote_Odr>>16)&0xff; //得到地址反码
Remote_Rdy=0; //清除标记
if(t1==(u8)~t2&&t1==REMOTE_ID) //检验遥控识别码(ID)及地址
{
t1=Remote_Odr>>8;
t2=Remote_Odr;
if(t1==(u8)~t2)return t1; //处理键值
}
return 0;
}
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16); //得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
RCC->APB2ENR|=1<<14; //使能串口时钟
GPIOA->CRH&=0XFFFFF00F;
GPIOA->CRH|=0X000008B0; //IO状态设置
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14); //停止复位
//波特率设置
USART1->BRR=mantissa; //波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位.
#ifdef EN_USART1_RX //如果使能了接收
//使能接收中断
USART1->CR1|=1<<8; //PE中断使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQChannel,2); //组2,最低优先级
#endif
}
int main(void)
{
u8 key;u8 t;
Stm32_Clock_Init(9); //时钟初始化
delay_init(72); //延时
uart_init(72,9600); //串口初始化
Led_Init(); //发光二极管控制管脚初始化
Remote_Init(); //红外遥控控制初始化
Beep_Init(); //蜂鸣器控制管脚初始化
while(1)
{
if(Remote_Rdy) //如果接收到红外遥控信号
{
key = Remote_Process(); //获取按键值
Beep_Tweet(); //蜂鸣器响
delay_ms(50); //延迟一段时间
Beep_Silent(); //蜂鸣器不响
switch(key) //判断键值
{
case 0x68: //如果键值是0x68
{USART1->DR=0x00;while((USART1->SR&0X40)==0);}break;//通过串口发送0x00
case 0x30: //如果键值是0x30
{USART1->DR=0x01;while((USART1->SR&0X40)==0);}break;//通过串口发送0x01
case 0x18: //如果键值是0x18
{USART1->DR=0x02;while((USART1->SR&0X40)==0);}break;//通过串口发送0x02
case 0x7A: //如果键值是0x7A
{USART1->DR=0x03;while((USART1->SR&0X40)==0);}break;//通过串口发送0x03
case 0x10: //如果键值是0x10
{USART1->DR=0x04;while((USART1->SR&0X40)==0);}break;//通过串口发送0x04
case 0x38: //如果键值是0x38
{USART1->DR=0x05;while((USART1->SR&0X40)==0);}break;//通过串口发送0x05
case 0x5A: //如果键值是0x5A
{USART1->DR=0x06;while((USART1->SR&0X40)==0);}break;//通过串口发送0x06
case 0x42: //如果键值是0x42
{USART1->DR=0x07;while((USART1->SR&0X40)==0);}break;//通过串口发送0x07
case 0x4A: //如果键值是0x4A
{USART1->DR=0x08;while((USART1->SR&0X40)==0);}break;//通过串口发送0x08
case 0x52: //如果键值是0x52
{USART1->DR=0x09;while((USART1->SR&0X40)==0);}break;//通过串口发送0x09
}
}
else{delay_ms(2);}
t++;
if(t==200)
{t=0;LED_RED = !LED_RED;}
}
}
void USART1_IRQHandler(void)
{
u8 res;
if(USART1->SR&(1<<5)) //接收到数据
{
res=USART1->DR;
if((USART_RX_STA&0x80)==0) //接收未完成
{
if(USART_RX_STA&0x40) //接收到了0x0d
{
if(res!=0x0a)USART_RX_STA=0; //接收错误,重新开始
else USART_RX_STA|=0x80; //接收完成了
}
else //还没收到0X0D
{
if(res==0x0d)USART_RX_STA|=0x40;
else
{
USART_RX_BUF[USART_RX_STA&0X3F]=res;
USART_RX_STA++;
if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}