一. 简介
最近在做项目的过程中,由于使用的是核心板,没有按键,尝试通过串口进行数据发送,进行控制,但是太麻烦了。于是想到了通过红外遥控进行控制。经济又实惠,还可以隔空远程操作,且只有一个数据线,YYDS。
二. 红外遥控数据传输协议
不做过多的理论知识的简介,主要是为了教大家怎么使用。传输过程如下
1.空闲态 为 高电平
2.引导码 : 9ms的低电平 和 4.5ms的高电平
3.数据码: 数据码包括四个部分依次是用户码、用户反码、键码和键码反码,每个8位,共32位,560us的低电平加560us的高电平表示数据0,560us的低电平加1.68ms的高电平表示数据1
4.停止位:可以忽略,软件中可以不用管
依次按照对应的时间来检测就可以。
本次设计通过外部IO中断来进行红外数据的读取,低电平触发(空闲为高电平)。
三. 程序设计
1.定义好相关变量,RCC和GPIO
- //红外遥控控制
- #define InfraredGPIOPort GPIOB
- #define InfraredGPIOPin GPIO_Pin_0
- #define InfraredRCC_APB RCC_APB2Periph_GPIOB
复制代码
2.GPIO初始化
- void InfraredGPIOInit(void)//GPIO口初始化
- {
- GPIO_InitTypeDef GPIOInitStruct;
- RCC_APB2PeriphClockCmd(InfraredRCC_APB | RCC_APB2Periph_AFIO ,ENABLE); //开启时钟 RCC_APB2Periph_AFIO
- GPIOInitStruct.GPIO_Pin = InfraredGPIOPin;
- GPIOInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_Init(InfraredGPIOPort,&GPIOInitStruct);
- }
复制代码
3.开启中断
中断控制线可以根据自己的Pin来确定,如果是GPIO_Pin_8,那么这里就是EXTI_Line8.
- void InfraredEXTIInit(void)//中断初始化
- {
- EXTI_InitTypeDef EXTI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;//定义中断结构体变量
- //中断配置
- EXTI_ClearITPendingBit(EXTI_Line0);
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
- EXTI_InitStructure.EXTI_Line = EXTI_Line0;
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
-
- NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//EXTI0中断通道
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority =1; //子优先级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
复制代码
4.电平持续时间计数
这里主要是对电平的出现时间进行一个计数
- //计算低电平的持续时间
- uint16_t InfraredRecvLowTime(void)
- {
- uint16_t time = 0;
- while(GPIO_ReadInputDataBit(InfraredGPIOPort,GPIO_Pin_0) == 0)
- {
- if(time >= 500)
- break;
- time +=1;
- delay_us(17);
- }
- return time;
- }
- //计算高电平的持续时间
- uint16_t InfraredRecvHighTime(void)
- {
- uint16_t time = 0;
- while(GPIO_ReadInputDataBit(InfraredGPIOPort,GPIO_Pin_0) == 1)
- {
- if(time >= 250)
- break;
- time +=1;
- delay_us(17);
- }
- return time;
- }
复制代码
5.编写中断控制函数
通过数据的参数过程进行判断,就可以了。持续时间需要在一个范围内,可以自己测试后设置。
- uint8_t InfraredDataRecv() //获取红外遥控数据
- {
- uint16_t time;
- uint8_t i,j;
- uint8_t data[4] = {0};
- //获取引导码
- time = InfraredRecvLowTime();
- if(time < 400 || time >= 500)
- return 0x00;
- time = InfraredRecvHighTime();
- if(time < 150 || time > 250)
- return 0x00;
- //获取数据
- for(i = 0; i < 4 ; i++)
- {
- for(j = 0 ; j < 8 ;j ++)
- {
- time = InfraredRecvLowTime();
- if(time < 20 || time > 35)
- return 0x00;
- time = InfraredRecvHighTime(); //通过高电平的时间长短来判断数据0,1
- if(time < 35) //数据0
- {
- data<i> <<= 1;
- data<i> |=0x0;
- }
- else
- {
- data<i> <<= 1;
- data<i> |= 0x1;
- }
- }
- }
- return data[2];
- }
- void EXTI0_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line0) != RESET)
- {
- uint8_t data;
- data = InfraredDataRecv();
- if(data == InfraredLeft)
- KEYState = KEYLEFT;
- else if(data == InfraredRight)
- KEYState = KEYRIGHT;
- else if(data == InfraredUp)
- KEYState = KEYUP;
- else if(data == InfraredDown)
- KEYState = KEYDOWN;
- else if(data == InfraredReturn)
- KEYState = KEYRETURN;
- delay_ms(10);
- /*清除标志位 */
- EXTI_ClearITPendingBit(EXTI_Line0);
- }
- }
- </i></i></i></i>
复制代码
|