完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
废话不多,直接切入正题,根据需要自行选择标题内容
红外原理性的东西,就不在这进行介绍了,不懂的可自行百度,会百度也是一种学习能力。 直接介绍红外的两部分,发射和接收。也就是发射机与接收器这两部分属于硬件的设计需要考虑的范围,如果只是单纯的想写好代码,那么就请略过本小节,直接吃透NEC通讯协议。但为了更多人考虑,还是需要介绍一下的。 发射机 通常是个带纽扣电池的手持装置。现在很多低功耗芯片用于红外发射的原因就是可以很灵活的使用,在没有遥控按钮操作时,发射机几乎不会消耗电量,当有按钮操作时会马上唤醒相应红外命令。而通常市面上的发射机都基本采用陶瓷晶振,通过对外红LED控制电流范围来实现控制距离的远近。当然对于这如何进行选择最优解还是需要根据实际情况来判断。 一个简单的晶体三极管放大电路就可以驱动红外LED。 接收器 重点为调制频率和区域可行性。 红外信号由接收器的检波二极管接收,信号通过放大和限幅处理,使信号有稳定的脉冲电平。 不用担心不懂此处的电路部分,因为厂家已经集成到一个接收模块中,此处可作为了解。 NEC通讯协议 这是***重点***内容 特征: 8bit地址码,8bit命令码 完整发射两次地址码和命令码 脉冲时间长短调制方式 38KHz载波频率 位时间1.12ms和2.25ms NEC协议根据脉冲时间长短解码,每个脉冲为560us长的38KHz载波。逻辑“1”脉冲时间为2.25ms 逻辑“0”脉冲时间为1.12ms 0.56ms的低电平,1.68ms的高电平脉冲 为 1 0.56ms的低电平,0.56ms的高电平脉冲 为 0 完整的协议波形图如下 协议规定低位首先发送。每次发送信息首先是9ms的低电平脉冲,接着是4.5ms的高电平,然后就是地址码和命令码。地址码和命令码发送两次,第二次发送的是反码,用于验证接收信息的准确性。因为每位都发送一次它的反码,所以总体的发送时间是恒定的。 当然,也会有人一直按着一个按键不放,注意,一串信息只能发送一次。如果一直按着同一按键不放,发送的则是以110ms为中期的重复码。 Demo编写 先说明下思维,这种方式为计算脉冲高电平时间来判断是否为逻辑1或0. 通过采用接收器所在GPIO管脚映射到外部事件中断线上,下降沿触发中断 当然还有各种不同的写法,比如通过定时器做的,个人认为芯片外设是少而珍贵的,如果能用数学思维来解决问题是比较好,把外设留给更重要的事件使用。 具体的电器属性配置还需根据自身情况来设定 这是STM32F030芯片,根据公司的产品的电路图所写 切不可直接 ctrl+c+v EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource6); EXTI_InitStruct.EXTI_Line=EXTI_Line6; EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; EXTI_InitStruct.EXTI_LineCmd=ENABLE; EXTI_Init(&EXTI_InitStruct); NVIC_InitStruct.NVIC_IRQChannel=EXTI4_15_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority=2; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct); 计算高电平时间,有关函数中的延时,会出有关延时的各种写法的文章。此处的延时为精准的20us,不同的芯片所对应的晶振也会不同,导致延时时间不同,需要根据自身情况判断 u8 IR_High_time(void) { u8 t=0; while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)==1) { t++; delay_us(2); if(t>=250) { return t; //超时溢出 } } return t; } 解码函数,不严谨的地方在于,在中断中进行了处理,切记不可在中断中处理复杂的事情,另外一个处理版本,不可公布出来。 u8 time=0,ok=0,data,Num=0; while(1) { if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)==1) { time=IR_High_time(); if(time>=250) { break; } if(time>=200&&time<250) { ok=1; } else if(time>=60&&time<90) { data=1; } else if(time>=10&&time<50) { data=0; } if(ok==1) { IR_Recive_data<<=1; IR_Recive_data+=data; if(Num>=32) { IR_Recive_flag=1; break; } } Num++; } } 最后还有两个全局变量用于判读和接收 u32 IR_Recive_data; u8 IR_Recive_flag; 主函数部分,就只展示最简单的通过串口输出已解码的字符 while ( 1 ) { if(IR_Recive_flag==1) { IR_Recive_flag=0; printf("Recive_data: %xrn",(u16)IR_Recive_data); } } |
|
|
|
只有小组成员才能发言,加入小组>>
3137 浏览 9 评论
2833 浏览 16 评论
3344 浏览 1 评论
8719 浏览 16 评论
3940 浏览 18 评论
9550浏览 3评论
890浏览 3评论
462浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
460浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2181浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-22 11:20 , Processed in 0.954953 second(s), Total 79, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191