一. 简介
最近在做项目的过程中,由于使用的是核心板,没有按键,尝试通过串口进行数据发送,进行控制,但是太麻烦了。于是想到了通过红外遥控进行控制。经济又实惠,还可以隔空远程操作,且只有一个数据线,YYDS。
欢迎关注 微信公众号 FPGA之旅 获取更多,所用资料将会第一时间发布在上面。
二. 红外遥控数据传输协议
不做过多的理论知识的简介,主要是为了教大家怎么使用。传输过程如下
空闲态 为 高电平
引导码 : 9ms的低电平 和 4.5ms的高电平
数据码: 数据码包括四个部分依次是用户码、用户反码、键码和键码反码,每个8位,共32位,560us的低电平加560us的高电平表示数据0,560us的低电平加1.68ms的高电平表示数据1
停止位:可以忽略,软件中可以不用管
依次按照对应的时间来检测就可以。
本次设计通过外部IO中断来进行红外数据的读取,低电平触发(空闲为高电平)。
三. 程序设计
定义好相关变量,RCC和GPIO
//红外遥控控制 #define InfraredGPIOPort GPIOB #define InfraredGPIOPin GPIO_Pin_0 #define InfraredRCC_APB RCC_APB2Periph_GPIOB
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); }
开启中断
中断控制线可以根据自己的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寄存器 }
电平持续时间计数
这里主要是对电平的出现时间进行一个计数
//计算低电平的持续时间 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; }
编写中断控制函数
通过数据的参数过程进行判断,就可以了。持续时间需要在一个范围内,可以自己测试后设置。
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); } }
公众号:FPGA之旅