STM32——红外接收和红外发射
这里没有解析红外的函数,毕竟考虑到学习的红外有几种协议(如:NEC).同时代码存在一些问题(有部分遥控是学习不了的(如:空调、DVD)).
红外数据接收:定时器捕获红外信号(还有一个是通过外部中断的,这里不列出)
红外数据发射:使用PWM输出
下面直接上代码
remote.c
/*remote.c*/
#include "remote.h"
#include "delay.h"
#include "usart.h"/**
发射:PA7-TIM3-CH2
接收:PC8-TIM8-CH3TIM8:
下面代码中捕获中断和定时中断分开,不在同一中断函数,所以需要配置两次中断优先级(应该可以合在一起配置)
*//*** @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.8TIM_TimeBaseStructure.TIM_Period = 9999; //设定计数器自动重装值 最大10ms溢出 TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //预分频器,1M的计数频率,1us加1. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMxTIM_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 ); //使能定时器4NVIC_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 CH2GPIO_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_timTIM_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_PWM1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_Pulse = (arr+1)/3; //占空比1:3 (arr+1)/10 3TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OCPolarity_HighTIM_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 300extern 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); //串口初始化为115200Remote_Init(); //红外接收初始化 TIM3_PWM_Init(1895,0); //tim3 pwm initializeprintf("init ok\r\n");while(1){if(Flag_LearnState){printf("%s\r\n",(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.
STM32——红外接收和红外发射相关推荐
- thinkphp6 接收不到数据_单片机红外接收与红外发射
1. 红外接收1.1 说明1.2 NEC协议1.3 关于红外接收的波形1.4 解码1.4 红外对射思考2. 红外发射2.1 红外发射管参数2.2 红外发射电路搭建2.3 程序设计2.5 实验结果2.4 ...
- Arduino 红外模块 红外接收 红外发射
需要用到IRremote库文件 红外遥控按键16进制编码,使用时添加前缀 0X 红外接收 .源代码 //***************** //红外接收模块测试 //***************** ...
- 基于STM32的万能红外遥控器
本博客介绍一种基于STM32的可学习和存储已有红外发射设备的万能红外遥控器的设计思路. 一.首先需要了解设计一款这功能的遥控器需要什么硬件设备支持. 1.3.3V,5V电源模块,用作给系统模块供电和单 ...
- 红外遥控实现回充原理红外发射与调制信号
遥控红外通信原理 在实际的通信领域,发出来的信号一般有较宽的频谱,而且都是在比较低的频率段分布大量的能量,所以称之为基带信号,这种信号是不适合直接在信道中传输的.为便于传输.提高抗干扰能力和有效的利用 ...
- 浅谈38K红外发射接受编码(非常好)
若不允许转载,请联系我删除. 之前做接触过一次红外遥控器,现在有空想用简单的话来聊一聊,下面有错误的地方欢迎改正指出: 1:红外的概念不聊,那是一种物理存在.以下聊38K红外发射接收,主要讲可编程的红 ...
- 【扫盲贴】浅谈38K红外发射接受编码(非常好)
呃,最初的原文好像已经消失了,,,我担心以后会看不到,转载一下,如不允许转载请站内短信通知我,,谢谢! 之前做接触过一次红外遥控器,现在有空想用简单的话来聊一聊,下面有错误的地方欢迎改正指出: 1:红 ...
- ESP32实现红外遥控 红外发射与接收实现原理
文章目录 一,原理 1.1 概括 1.2,时钟 1.3,认识 item 1.4,发射/接收器 1.5 电路原理图 1.5.1,发射电路 1.5.2 ,接收电路 二,红外发射 2.1 整体的思路 2.2 ...
- Arduino红外发射实验
相关资料链接 链接:https://pan.baidu.com/s/1eE0rkaSJsKJMU_RUorS5OA 提取码:3ujh 1.1 介绍: 传感器主要由红外发射管等组成,它是可将电能直接转换 ...
- 浅谈38K红外发射接收编码
浅谈38K红外发射接收编码 https://blog.csdn.net/gmdjmawy/article/details/47129989 http://blog.sina.com.cn/s/blog ...
- s8050三极管经典电路_曝光一个产品级的红外发射电路
作者:瑞生,来源:科技老顽童微信公众号:芯片之家(ID:chiphome-dy今天给大家一个产品级的红外发射电路.为什么说是产品级的?因为这个电路我已经在各类产品上见过多次!很多小伙伴学电子有一个误区 ...
最新文章
- 判断一个序列是不是堆的方法
- vue router html,vue-router.html
- Python中的异常(Exception)处理
- 算法分析股票类型的相关题型
- 6 redhat 查看rtc时间_Linux EasyStack-Redhat安装Docker
- java换水_java-交流灌水之谁是水王?
- ISP DSP的不同
- 25个学习要点帮助你从java菜鸟成为Java高手
- db2离线备份_DB2高危操作LOAD命令风险详解
- 怎样用代码方式退出IOS程序
- 最好用的五大服装进销存管理软件,强推第一个
- 关于查询FileNet PE中用户Inbox信息
- pytho_抓取下载音乐歌曲
- 逻辑回归实现文本分类
- 赵小楼《天道》《遥远的救世主》深度解析(144)问题本身就是答案。需要强调的东西不是本来的那个东西。
- 安卓 解析软件包时出现问题
- ROB 第一篇 DFS BFS (寻迹算法)
- 《2019全国互联网行业程序员就业报告》出炉,程序员平均月薪为1.8W
- 加州大学计算机硕士,加州大学伯克利分校cs专业
- 王童:知行合一 · 当大数据遇到生物学 | 优秀毕业生专访
热门文章
- Speedoffice(word)怎么撤回上一步的操作
- linux硬盘异响,完美解决Ubuntu Linux关机异响[SATA硬盘]
- word技巧-分节符和连续页码,页眉页脚加线
- python主页面_使用Wagtail CMS使用Python检测父页面和子页面...
- steam无法连接至计算机,无法连接至steam网络怎么办 无法连接至steam网络解决方法【图文】...
- java浅_浅谈Java浅层复制和深层复制
- python环境下skimage处理高通道tif图片(10通道)
- android studio umake,Android Studio中NDK开发傻瓜教程(CMake)
- WebRTC 概念介绍--一篇读懂source、track、sink、mediastream
- 解决谷歌disabled状态下操作问题