GPIO模拟时序控制外设4——红外发射管

这篇具有很好参考价值的文章主要介绍了GPIO模拟时序控制外设4——红外发射管。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

上一篇介绍了使用GPIO模拟时序实现I2C协议的功能,本文继续使用GPIO模拟的方式来实现一个平时生活中常用的模块——红外发射管的驱动,红外在家电的应用中十分广泛,空调、电视、投影等都是通过红外遥控来实现的。

红外发射管简介

红外发射管实物就是下图中左边的红框内的器件,右侧的是红外接收管。
GPIO模拟时序控制外设4——红外发射管
大家拿到红外发射管后,第一反应可能就是这玩儿意和LED灯长得一模一样啊,其实,不光长得一样,其的工作原理也是一样,就是通过一定的规律给电平,点“亮”和熄灭红外发射管来产生红外光信号,这个红外光信号被接收管接受处理后,就会产生对应的电信号,然后用户接收和处理这个电信号用来控制不同的外设即可。只不过红外发射管的波长超过了我们肉眼可见的波段,我们平常事无法观察到的。如下图:我们肉眼可见的光波段就是380nm----760nm,而这个红外发射管的波长是940nm。
GPIO模拟时序控制外设4——红外发射管
GPIO模拟时序控制外设4——红外发射管
当然,如果实在是想看见点亮效果,也可以把周围的灯都关了,找一个比较黑的环境,用手机摄像头就可以看见红光。
GPIO模拟时序控制外设4——红外发射管

NEC协议

上面提到了,红外发射管用的是一种特殊的方式进行数据发送,具体的发送格式需要参考红外接收管的芯片手册以及使用到的具体通信协议了,这里接收管使用的是HS0038,通信协议是NEC。

HS0038

先来看看HS0038的手册是怎么描述的,如下图所示,可以知道,当接收到的输入红外光是一个频率为38khz,占空比为50%,持续时间为500us-700us的PWM波形时,HS0038的输出端就会产生一个低电平,而当输入的红外光不是此规格的信号时,HS0038就会输出一个高电平。
GPIO模拟时序控制外设4——红外发射管
来个实际波形分析一下:
如下图所示:D1是红外发射管发射出的光信号,D0是红外接收管根据输入信号产生的输出信号,可以看出,当D1的波形变成了PWM时,D0输出低电平,而D1输出不是PWM时,D0输出就是高电平。
GPIO模拟时序控制外设4——红外发射管

NEC 的逻辑“1”与逻辑“0”

为啥我上面一直说的HS0038的输出是高低电平而不是逻辑0和逻辑1呢?
还记得之前驱动WS2812B与DHT11的时候,他们的逻辑0与逻辑1并不是简单的对应高低电平,这里也是如此,NEC协议中的逻辑0与逻辑1也不是简单的高低电平,而是有不同时间段的高低电平组合而成,其中:
逻辑“0”是由560us的低电平加560us的高电平组成,
逻辑“1”是由560us的低电平加1690us的高电平组成,
再结合下面的这个逻辑分析仪的图大家就可以看懂了,注意最下面绿色的解码,第一段低电平与第一段高电平组成了第一个逻辑0,
第二段低电平与第二段高电平又组成了一个逻辑0,
而第三段的低电平与第三段高电平组成的是逻辑1,
GPIO模拟时序控制外设4——红外发射管
因为红外传输的工程中大部分设备都是支持NEC格式的,所以我们发射管端也要对应这个NEC码的时序做出调整,当需要输出逻辑1时,就要使用到下图的前半段时序,而输出逻辑“0”时,就需要使用到下图的后半段时序:
原文链接——http://t.csdn.cn/LoC2r
GPIO模拟时序控制外设4——红外发射管
整个数据传输动态过程可以看下面的动图:
单片机控制开关管按照逻辑“0”与逻辑“1”的时序来控制红外发射管的点亮与关闭,而红外接收管接收到红外发射管的信号后就会输出对应的高低电平信息,使用MCU进行捕获处理这部分信号就可以了。
GPIO模拟时序控制外设4——红外发射管

NEC的数据帧格式

再弄清楚了NEC协议的逻辑“0”与逻辑“1”后,就要知道其数据帧的具体格式了,为了进一步提高数据的稳定性,NEC码在传输的过程中对于数据帧也有着很高的要求,具体帧格式如下:
GPIO模拟时序控制外设4——红外发射管
需要注意一点,前面的数据通信都是高位在前,高位先发,此处的NEC是低位在前,低位先发。

同步码头(引导码/起始码)、地址码(遥控ID)、地址反码、控制码(键值)、控制反码。
同步码、地址码(遥控ID)、地址反码、控制码(键值)、控制反码
同步码由一个 9ms 的低电平和一个 4.5ms 的高电平组成
如果接收到同步,说明有红外数据进来

同步码 + 8位地址码+ 8位地址码反码+ 8位控制码 + 8位控制码反码
红外接收每一次接收到数据都是32位

实际的数据:

帧头 地址码 地址码反码 命令 命令反码
9ms 的低电平+ 4.5ms 的高电平 8位 8位 8位 8位
9ms 的低电平+ 4.5ms 的高电平 1011 0111 0100 1000 0110 0110 1001 1001

GPIO模拟时序控制外设4——红外发射管
除此之外还有一个连续发送的数据帧格式,这里就不做介绍了,有需要的自己去研究一下吧。

编程思路

搞清楚了红外发射管与接收管的通信过程以及其数据帧的格式后,接下来就可以开始编程了,本文先解决红外发射管的代码,接收管的使用留到下一篇介绍GPIO复用功能的时候再说。

1. GPIO管脚

首先第一步,二话不说,直接看原理图,找到GPIO是PB7,前面分析了,在发送红外光的时候,需要发送一段频率为38khz,占空比位50%,持续时间长度为560us的PWM,来使得红外接收管输出低电平,一般来说最好的解决方案就是使用定时器来产生PWM来实现低电平,当时间到了后再将GPIO口拉低不输出PWM即可实现
这里选择PB7管脚是可以作为定时器4的通道2来使用的,但是有一个问题,在实际使用过程中定时器4另有它用;所以没法了,只能使用GPIO模拟的办法来实现红外发射管的功能了,这里就需要模拟出一段PWM波形,当然是使用推挽模式配合延时来实现。
GPIO模拟时序控制外设4——红外发射管
对于PWM实现的方案,这里给大吉留几个链接,供大家参考。
STM32 NEC红外遥控器解码——
基于STM32f103c8t6的红外接收发送
除此之外还有几篇写的很好地博客也给大家贴在这
STM32入门开发: 制作红外线遥控器(智能居家-万能遥控器)
GPIO模拟时序控制外设4——红外发射管
GPIO初始化代码:

/************************************************
函数功能:红外发送控制码
函数名:Infrared_Send_Init
函数形参:None
函数返回值:
备注:  PB7
**************************************************/
void Infrared_Send_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;                       // 定义一个GPIO_InitTypeDef类型的变量
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   // 允许GPIOB时钟
	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;                  // GPIO_Pin_7
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;           // 通用推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;          // 50MHz速度
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	GPIO_ResetBits(GPIOB, GPIO_Pin_7);                      //PB7拉低
}

找到实现方案后,就该具体执行了,对于这类数据帧比较复杂的通信方式,在模拟其时序的时候一定记得从下往上来写,先搞定各个部分,然后再拼接起来组成一整个时序。
整个数据帧无非就是以下几个内容组成,
1.同步头,2.逻辑“0”与逻辑“1”;而且逻辑0与逻辑1还可以进一步细分为低电平和高电平,也就是一个PWM,一个非PWM。那么接下来就一个一个的实现。

2. 模拟同步头

由于接收管的同步头是9ms的低电平加上4.5ms的高电平,那么根据转换方式可以知道,发射管的同步头是9ms的38khz、50%占空比的PWM加上4.5ms的低电平。
GPIO模拟时序控制外设4——红外发射管
38khz的PWM,一个脉冲的时长为1/38 000=26.3us;
占空比50%,则输出高电平的时间:26.3/2=13.15us由于STM32F103C8T6的系统滴答延时最多支持到us级别,所以这里把小数点后的给省略,直接高低电平各自延时13us。
而9ms的PWM一共有9ms/26=346个。
于是代码就有了:

/************************************************
函数功能:红外发送同步头
函数名:NEC_IE_Start
函数形参:None
函数返回值:
备注:  
// ①引导码:载波发射9ms,不发射4.5ms
**************************************************/
//------------------------------------------------------------
void NEC_IE_Start(void)
{
	u16 i;
// 载波发射 9ms ≈ 26.3us * 346
	for(i=0;i<346;i++) 
	{
		PBout(7)=1;	// IE抬高,发射红外光
		Systick_Delay_us(13);	// 延时13us
		PBout(7)=0;;	// IE拉低,不发射红外光
		Systick_Delay_us(13);	// 延时13us
	}
	// 载波不发射 4.5ms ≈ 26.3us * 171
	for(i=0;i<171;i++)
	{
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(26);	// 延时26us
	}
}

3.发送逻辑“0”与逻辑“1”

逻辑“0”与逻辑“1”的共有部分是560us的PWM波形,不同之处在于后面的部分,
GPIO模拟时序控制外设4——红外发射管
先看逻辑“1”,除了560us的PWM,它还需要2.25ms-560us=1690us的低电平,PWM还是参考上面的思路,于是发送逻辑“1”的代码就有了:

/************************************************
函数功能:红外发送逻辑“1”
函数名:NEC_IE_Send_one
函数形参:None
函数返回值:
备注:  
// NEC协议数据"1" = 载波发射0.56ms + 载波不发射1.68ms
**************************************************/
//-------------------------------------------------
void NEC_IE_Send_one(void)
{
	u8 i;
	// 载波发射0.56ms ≈ 26.3us * 21
	//-------------------------------
	for(i=0;i<22;i++)
	{
		//26.3us(载波发射周期)占空比50%
		//------------------------------------
		PBout(7)=1;    // IE抬高,发射红外光
		Systick_Delay_us(13);	// 延时13us
		
		PBout(7)=0;  // IE拉低,不发射红外光
		Systick_Delay_us(13);	// 延时13us
		//------------------------------------
	}
	
	// 载波不发射1.69ms ≈ 26us * 65
	//--------------------------------
	for(i=0;i<65;i++)
	{
		//26us(载波不发射周期)
		//------------------------------------
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(26);	// 延时26us
	}
}

同样的逻辑“0”的思路也差不多,直接给出代码:


/************************************************
函数功能:红外发送逻辑“0”
函数名:NEC_IE_Send_zero
函数形参:None
函数返回值:
备注:  
// NEC协议数据"0"= 载波发射0.56ms + 载波不发射0.56ms
**************************************************/
//-------------------------------------------------
void NEC_IE_Send_zero(void)     
{
	u8 i;
	
	// 载波发射0.56ms ≈ 26.3us * 21
	//-------------------------------
	for(i=0;i<22;i++)
	{
        //26.3us(载波发射周期)
		//------------------------------------
		PBout(7)=1;	// IE抬高,发射红外光
		Systick_Delay_us(13);	// 延时13us                       
											
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(13);	// 延时13us
		//------------------------------------
	}

	
	// 载波不发射0.56ms ≈ 26.3us * 21
	//-------------------------------
	for(i=0;i<21;i++)
	{
        //26.3us(载波不发射周期)
		//------------------------------------
		PBout(7)=0;	// IE拉低,不发射红外光
		Systick_Delay_us(26);	// 延时26us
		//------------------------------------
	}
}

发送一个字节数据

搞定了逻辑“0”与逻辑“1”之后,下一步自然是封装一个可以一次发送8个位也就是一字节的函数。这里需要注意的是低位先发。
GPIO模拟时序控制外设4——红外发射管
于是代码如下:

/************************************************
函数功能:红外发送一个字节
函数名:NEC_IE_One_Data
函数形参:u8 IE_One_Data
函数返回值:
备注:  发送一个字节的数据,一次发8位,低位在前。
**************************************************/
//----------------------------------------------------------------------------------------------
void NEC_IE_One_Data(u8 IE_One_Data)
{
	u8 i;
	
	for(i=0;i<8;i++)
	{
		if( IE_One_Data & 0x01 )
			NEC_IE_Send_one();
		else
			NEC_IE_Send_zero();
			
		IE_One_Data>>=1;
	}
}

发送一帧数据

一帧数据格式在前面已经介绍了,这里根据帧格式配合上面的函数做一个组合就可以了。
代码如下:


/************************************************
函数功能:发送NEC 一帧数据
函数名:NEC_IE_code_message
函数形参:u8 IE_One_Data
函数返回值:
备注: 
// 将一帧数据调制为NEC协议规定的红外载波发射出去
// 一帧数据格式:低位在前,由低到高发送8位数据
// 这帧数据是:②8位用户码字节(8位) / ③8位用户码反码(8位) / ④8位数据码 / ⑤8位数据码的反码
**************************************************/
void NEC_IE_code_message(u8 user_code_8bit, u8 data_code_8bit)
{
	// ①引导码:载波发射9ms,不发射4.5ms
	NEC_IE_Start();
	//------------------------------------------------------------
	//------------------------------------------------------------
	// ②8位用户码	:8位数据
	NEC_IE_One_Data(user_code_8bit);
	
	// ③8位用户码的反码:8位数据
	NEC_IE_One_Data(~user_code_8bit);
	
	// ④8位数据码 :8位数据
	NEC_IE_One_Data(data_code_8bit);
	
	// ⑤8位数据码的反码:8位数据
	NEC_IE_One_Data(~data_code_8bit);
	//------------------------------------------------------------
	// ⑥结束码‘0’
	//--------------
	NEC_IE_Send_zero();
	//--------------
}

结束码

关于结束码,由于32位数据发送完毕后,不管最后一位的逻辑是0还是1,末尾都是PBout(7)=0; // IE拉低,不发射红外光;理论来说,这种情况不额外添加结束码是可行的;但是笔者尝试了一下,不再末尾加一个发送逻辑“0”的结束码的话,逻辑分析仪无法解析出数据,为了能够正常解析出数据还是在发送外32位数据后加上一句NEC_IE_Send_zero()。
需要注意,实际上的遥控器大部分是没有这个结束信号的。
GPIO模拟时序控制外设4——红外发射管
GPIO模拟时序控制外设4——红外发射管
GPIO模拟时序控制外设4——红外发射管

而对于连续码的时序,如下图,有兴趣的话可以自己尝试,调通后可以投食一下,我想白嫖。
GPIO模拟时序控制外设4——红外发射管
既然搞定了红外发送的基本用法,最大的想法自然是控制空调之类的设备了,但是需要注意,各个厂家的空调的协议不太一样,需要在上面代码的基础上进一步修改才行。
具体的介绍大家参考这些大佬的——
STM32入门开发: 制作红外线遥控器(智能居家-万能遥控器)
格力空调红外编码解析
STM32解析美的空调红外遥控器
格力空调红外编码
GPIO模拟时序控制外设4——红外发射管

现象

这里笔者还没去倒腾空调的编码,只是实现了简单的功能,最后捕捉到的实际波形和解析出来数据如下:
GPIO模拟时序控制外设4——红外发射管

总结

关于使用GPIO模拟时序驱动红外发射管的介绍就先记录到这,至于空调的控制,这个先鸽了,或者有做出来的可以踢我一下。文中如有不足欢迎批评指正。文章来源地址https://www.toymoban.com/news/detail-504819.html

到了这里,关于GPIO模拟时序控制外设4——红外发射管的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 硬件外设使用方法——GPIO

    经过与硬件群的小伙伴商量,决定直接找个板子讲实战了- -。 本部分内容为视频内容补充。外设基本使用方法+pyb(STM32)+machine(micropython通用。) GPIO是General Purpose Input/Output的缩写,意思是通用输入/输出。 它是一种可以通过软件控制的电子接口,可实现与其他硬件设备的连

    2024年02月10日
    浏览(25)
  • STM32外设GPIO(学习笔记)

    在编写stm32程序时,对寄存器进行操着需要知道每个外设的基地址,标准库的stm32f10x.h文件里也有各种外设的基地址。 比如GPIO:在定义输出数据寄存器地址GPIOA_ODR_Addr时,在GPIOA_BASE(GPIO端口A的基址地址)地址基础上偏移 在stm32f10x.h文件里面有定义GPIOA_BASE,是APB2PERIPH_BASE(

    2024年04月12日
    浏览(32)
  • STM32模拟SPI时序控制双路16位数模转换(16bit DAC)芯片DAC8552电压输出

    STM32部分芯片具有12位DAC输出能力,要实现16位及以上DAC输出需要外挂DAC转换ASIC。 DAC8552是双路16位DAC输出芯片,通过SPI三线总线进行配置控制输出。这里介绍通过GPIO管脚模拟时序进行控制的方式。 DAC8552支持2.7V~5.5V的供电,根据需要提供电源电压,对于STM32可能面对不同供电电

    2023年04月09日
    浏览(28)
  • 一眼就能看懂STM32的外设GPIO(通用输入输出)

    GPIO,简称通用输入输出,关键在于他是通用的。任何外设都可以用它,他的主要目的在于控制的IO,输出或由外部输入高低电平,与之对应的是AFIO的复用输入输出,当用到引脚的第二个功能的时候,就需要启用它; 你只需要记住他:他是控制引脚(IO口)的输入输出功能,高

    2024年02月04日
    浏览(29)
  • STM32萌新学习日志——用GPIO外设寄存器输出点亮LED对比库函数点亮LED——谈学习感悟

            本周学习STM32单片机,由于之前学过51单片机,为了便于切入,先学习了寄存器点亮LED灯的方法,整体思路与51单片机相似。在基本掌握后,尝试自己构建库函数雏形,过程比较困难,后面开始借鉴野火官方库函数。         这里其实建议大家在学会构建库函数后

    2024年03月17日
    浏览(80)
  • 【IMX6ULL驱动开发学习】09.Linux驱动之GPIO中断(附SR501人体红外感应驱动代码)

    Linux驱动的GPIO中断编程主要有以下几个步骤: 1、 通过GPIO号获取 软件中断号 (中断编程不需要设置GPIO输入输出,当然申请GPIO,设置输入也没问题) 参数 含义 gpio GPIO引脚编号 2、 注册 中断处理函数 ,设置中断 触发方式 (上升沿、下降沿等) 参数 含义 irq 软件中断号(通过

    2024年02月11日
    浏览(41)
  • Unity制作射击游戏案例01(控制角色+发射子弹+摄像机跟踪)

    //【业务逻辑】这个脚本用来1.控制物体移动旋转(WASD)、   2.发射子弹(空格键) //【程序逻辑2】 首先检测用户没有按下空格键 2.如果按下呢执行发射子弹函数    3.克隆子弹 4.让克隆的子弹往前跑 为子弹模板添加刚体,并且限制旋转 这个脚本需要挂在到摄像机,里面谈

    2024年02月06日
    浏览(42)
  • (红外遥控)STM32+红外模块控制格力空调

      其他红外介绍不多说了,下面介绍一下我使用stm32控制格力空调所遇到问题。    网上大部分对格力空调红外编码的介绍都是     起始码(S)+35位数据码+连接码(C)+32位数据码   0的电平宽度为:620us低电平+540us高电平, 1的电平宽度为:620us低电平+1620us高电平 起始码S电

    2024年01月22日
    浏览(25)
  • 使用GPIO来模拟UART

    最近在看一些秋招的笔试和面试题,刚好看到一个老哥的经验贴,他面试的时候被问到了如果芯片串口资源不够了该怎么办?其实可以用IO口来模拟串口,但我之前也没有具体用代码实现过,借此机会用32开发板上的两个IO口来实现串口的功能,实现开发板和串口调试助手两者

    2024年02月11日
    浏览(21)
  • 使用Harmony OS控制外设——输入输出

    本节课程主要介绍如何在HiSpark WiFi IoT套件上使用Hamony OS进行编程,以及如何使用GPIO输入输出功能。 Hi3861开发板第一个示例程序演示 熟悉使用DevEco Device Tool插件进行程序烧录 熟悉串口调试工具sscom的使用 官方文档中控制核心板上LED的 led_example.c 讲解及演示 源码路径: appli

    2023年04月20日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包