完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
这里没有解析红外的函数,毕竟考虑到学习的红外有几种协议(如:NEC)。同时代码存在一些问题(有部分遥控是学习不了的(如:空调、DVD))。
红外数据接收:定时器捕获红外信号(还有一个是通过外部中断的,这里不列出) 红外数据发射:使用PWM输出 下面直接上代码 remote.c /*remote.c*/ #include “remote.h” #include “delay.h” #include “usart.h” /** 发射:PA7-TIM3-CH2 接收:PC8-TIM8-CH3 TIM8: 下面代码中捕获中断和定时中断分开,不在同一中断函数,所以需要配置两次中断优先级(应该可以合在一起配置) */ /** * @name void Remote_Init(void) * @description 红外遥控初始化 设置IO以及定时器8的输入捕获 * Infrared remote initializer sets IO and timer 8 input capture * @notice */ void Remote_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE); //使能PORTB时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE); //TIM8 时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //PC8 输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_SetBits(GPIOC,GPIO_Pin_8); //初始化GPIOC.8 TIM_TimeBaseStructure.TIM_Period = 9999; //设定计数器自动重装值 最大10ms溢出 TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //预分频器,1M的计数频率,1us加1. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; // 选择输入端 IC4映射到TI4上 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频 TIM_ICInitStructure.TIM_ICFilter = 0x03; //IC4F=0011 配置输入滤波器 8个定时器时钟周期滤波 TIM_ICInit(TIM8, &TIM_ICInitStructure); //初始化定时器输入捕获通道 TIM_Cmd(TIM8,ENABLE ); //使能定时器4 NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn; //TIM8TIM8捕获比较中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 TIM_ITConfig( TIM8,TIM_IT_CC3,ENABLE); //允许更新中断 ,允许CC4IE捕获中断 NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 TIM_ITConfig( TIM8,TIM_IT_Update,ENABLE); //允许更新中断 ,允许CC4IE捕获中断 } /** * @name void TIM3_PWM_Init(u16 arr,u16 psc) * @description 初始化定时器3的设置,将定时器3用于PWM调制,PWM输出口为 PA.7 * @param arr -- u16,定时器重装值 psc -- u16,定时器分频值 * @return * @notice PWM频率 = 72M/((arr+1)*(psc+1)),这里用作红外发射的载波,需要生成38kHz的方波,故取arr = 1895,psc = 0。 */ void TIM3_PWM_Init(u16 arr,u16 psc) { /* 初始化结构体定义 */ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定时器基本设置 TIM_OCInitTypeDef TIM_OCInitStructure; //定时器比较输出配置 /* 使能相应端口的时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器2时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设时钟 /* GPIOA.7初始化 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; // TIM3 CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // PA.7 复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_7); /* TIM3 初始化*/ TIM_TimeBaseInitStructure.TIM_Period = arr; //下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseInitStructure.TIM_Prescaler = psc; //作为TIMx时钟频率除数的预分频值 TIM_TimeBaseInitStructure.TIM_ClockDivision = 0; //时钟分割:TDTS = Tck_tim TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); /* 定时器TIM3 Ch2 PWM模式初始化 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM PWM1 TIM_OCMode_PWM1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = (arr+1)/3; //占空比1:3 (arr+1)/10 3 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OCPolarity_High TIM_OC2Init(TIM3, &TIM_OCInitStructure); /* 使能TIM3在CCR1上的预装载寄存器 */ TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); } u8 RmtSta=0; //红外学习上升或下降标志位 u16 Dval; //上升沿、下降沿的计数器的值 u8 RmtCnt=0; //定时器红外学习计数超时标志位 u8 PulseTabCnt=0; //上升沿下降沿计数器的值 u16 PulseTab[MAX_PULSE_LEN]={0}; //红外学习存储数据 u8 Flag_LearnState = 0; //红外学习标志位 /** *@name void TIM8_UP_IRQHandler(void) *@brief TIM8的定时计数中断函数 * The timing count interrupt function of TIM8 *@note */ void TIM8_UP_IRQHandler(void) { if(TIM_GetITStatus(TIM8,TIM_IT_Update)!=RESET) { if(RmtCnt++》50) { RmtCnt = 0; if(RmtSta) { RmtSta = 0; Flag_LearnState = 1; } } } TIM_ClearITPendingBit(TIM8,TIM_IT_Update); } /** *@name void TIM8_CC_IRQHandler(void) *@brief 捕获红外载波的高低电平宽度,记录到数组PulseTab * Capture the high and low level width of the infrared carrier and record it to the array PulseTab *@note */ void TIM8_CC_IRQHandler(void) { if(TIM_GetITStatus(TIM8,TIM_IT_CC3)!=RESET) //获取上升沿或下降沿状态 { if(RDATA) //上升沿捕获 { Dval=TIM_GetCapture3(TIM8); //读取CCR4也可以清CC4IF标志位 TIM_OC3PolarityConfig(TIM8,TIM_ICPolarity_Falling); //CC4P=1 设置为下降沿捕获 TIM_SetCounter(TIM8,0); //清空定时器值 if(RmtSta&0X01) { PulseTab[PulseTabCnt++] = Dval; RmtSta = 0x10; } else { RmtSta = 0X10; //标记上升沿已经被捕获 } } else //下降沿捕获 { Dval=TIM_GetCapture3(TIM8); //读取CCR4也可以清CC4IF标志位 TIM_OC3PolarityConfig(TIM8,TIM_ICPolarity_Rising); //CC4P=0 设置为上升沿捕获 TIM_SetCounter(TIM8,0); //清空定时器值 if(RmtSta&0X10) //完成一次高电平捕获 { PulseTab[PulseTabCnt++] = Dval; RmtSta = 0x01; } else { RmtSta = 0x01; } } } TIM_ClearITPendingBit(TIM8,TIM_IT_CC3); } /** *@name void Infrared_Send_IR1(u16 *irdata,u32 irlen) *@description 红外信号发射函数 *@param irdata -- u16,红外数据 irlen -- u32,红外数据长度 *@return *@notice */ void Infrared_Send(u16 *irdata,u32 irlen) { u32 i; //用于下面的for循环 for(i=0; i《irlen && irdata[i]!=0xffff; i++) //循环,从i=0开始,当i《irlen 并且 irdata[i] != 0xffff 时成立,当其中一个不成立,退出循环 { if(i%2 == 0) //偶数的下标的数组成员延时拉高电平 { TIM_Cmd(TIM3,ENABLE); delay_us(irdata[i]); TIM_Cmd(TIM3,DISABLE); GPIO_SetBits(GPIOA,GPIO_Pin_7); } else { GPIO_SetBits(GPIOA,GPIO_Pin_7); delay_us(irdata[i]); } } delay_us(555); GPIO_ResetBits(GPIOA,GPIO_Pin_7); return ; } remote.h /*remote.h*/ #ifndef __RED_H #define __RED_H #include “sys.h” #define RDATA PCin(8) //红外数据输入脚 //红外遥控识别码(ID),每款遥控器的该值基本都不一样,但也有一样的。 //我们选用的遥控器识别码为0 #define REMOTE_ID 0 #define MAX_PULSE_LEN 400 //500 300 extern u8 RmtCnt; //按键按下的次数 extern u16 PulseTab[MAX_PULSE_LEN]; extern u8 Flag_LearnState ; extern u8 PulseTabCnt;//上升沿下降沿计数器的值 void Remote_Init(void); //红外传感器接收头引脚初始化 void TIM3_PWM_Init(u16 arr,u16 psc); void Infrared_Send(u16 *irdata,u32 irlen); #endif main.c /*main.c*/ #include “delay.h” #include “sys.h” #include “usart.h” #include “remote.h” #include “string.h” /** *@name int main(void) *@brief *@retval return 0 *@note */ int main(void) { delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 Remote_Init(); //红外接收初始化 TIM3_PWM_Init(1895,0); //tim3 pwm initialize printf(“init okrn”); while(1) { if(Flag_LearnState) { printf(“%srn”,(char *)PulseTab); Infrared_Send(PulseTab,PulseTabCnt); PulseTabCnt = 0; Flag_LearnState=0; memset((void *)PulseTab,0,MAX_PULSE_LEN); } } } 最后 实验现象: 本实验开机之后,即进入等待红外触发,如过接收到正确的红外信号,则500ms后自动从红外发射棒发射红外,同时通过串口1,将接受的红外信号以16进制打印出来。 注意事项: 1,可以用最小开发板调试,红外接收头和发射棒可以外接。 2,当使用的接收或发射引脚不一样是,注意将定时器修改。 3,本实验为万能学习红外遥控器,属于半成品,未做存储处理,需要储存需使用芯片的flash或外接eeprom。 |
|
|
|
只有小组成员才能发言,加入小组>>
4331个成员聚集在这个小组
加入小组3285 浏览 0 评论
航顺(HK)联合电子发烧友推出“近距离体验高性能Cortex-M3,免费申请价值288元评估板
4232 浏览 1 评论
4236 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-20 12:29 , Processed in 0.669480 second(s), Total 75, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号