历史上的今天
返回首页

历史上的今天

今天是:2024年12月20日(星期五)

正在发生

2021年12月20日 | STM32红外串口接收

2021-12-20 来源:eefocus

1.NEC协议

现有的红外遥控包括两种方式: PWM(脉冲宽度调制)和PPM(脉冲位置调制)。

两种形式编码的代表分别为NEC 和 PHILIPS的RC-5、RC-6以及将来的RC-7。


PWM(脉冲宽度调制):以发射红外载波的占空比代表"0”和"1"。为了节省能量,一般情况下,发射红外载波的时间固定,通过改变不发射载波的时间来改变占空比。例如常用的电视遥控器,TOSHIBA的TC9012,其引导码为载波发射4. 5ms,不发射4.5ms,其"0"为载波发射0.56ms,不发射0.565ms,其"1"为载波发射0.56ms,不发射1.69ms。


PPM(脉冲位置调制)∶以发射载波的位置表示"0"和"1"。从发射载波到不发射载波为"0",从不发射载波到发射载波为"1"。其发射载波和不发射载波的时间相同,都为0.68ms,也就是每位的时间是固定的。


2.电路图:三条线,VCC 、GND、DATA

在这里插入图片描述

3.通信协议图,总共4*8=32位数据。

在这里插入图片描述

4.地址码,持续时间1690us为数据"1",持续时间560us为数据"0"。

他们低电平部分560us相同,可以省略判断,直接根据高电平持续时间来判断是数据0还是数据1。


通过测量不同的高电平持续时间,就能够知道当前的信号是引导码、比特0、比特1。

地址码
在这里插入图片描述

思路:


红外发射头发射红外,相当于按下按键,变为高电平。 红外发射头停止发射,相当于松开按键,变为高电平,默认的时候是高电平。

所以采用外部中断来触发。


5.代码


#include "stm32f4xx.h"

#include "stm32f4xx_gpio.h"

#include "stm32f4xx_rcc.h"

#include "stm32f4xx_usart.h"

#include "stdio.h"


static GPIO_InitTypeDef  GPIO_InitStructure;

static USART_InitTypeDef USART_InitStructure;

static NVIC_InitTypeDef NVIC_InitStructure;

static EXTI_InitTypeDef    EXTI_InitStructure;


static volatile uint8_t g_ir_data[4]={0};

static volatile uint32_t g_ir_event=0;



//重定义fputc函数 

int fputc(int ch, FILE *f)

{

USART_SendData(USART1,ch);

while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);  

return ch;

}   


void delay_us(uint32_t nus)

{

uint32_t temp;      

SysTick->LOAD =SystemCoreClock/8/1000000*nus; //时间加载    

SysTick->VAL  =0x00;        //清空计数器

SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能滴答定时器开始倒数  

do

{

temp=SysTick->CTRL;

}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达   

SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器

SysTick->VAL =0X00;        //清空计数器 

}


void delay_ms(uint16_t nms)

{     

uint32_t temp;    

SysTick->LOAD=SystemCoreClock/8/1000*nms; //时间加载(SysTick->LOAD为24bit)

SysTick->VAL =0x00;            //清空计数器

SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;    //能滴答定时器开始倒数 

do

{

temp=SysTick->CTRL;

}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达   

SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;    //关闭计数器

SysTick->VAL =0X00;        //清空计数器       




void USART1_Init(uint32_t baud)

{

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能USART1时钟

 

//串口1对应引脚复用映射

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1

GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1

//USART1端口配置

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10


//USART1 初始化设置

USART_InitStructure.USART_BaudRate = baud; //波特率设置

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式

USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位

USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

USART_Init(USART1, &USART_InitStructure); //初始化串口1

USART_Cmd(USART1, ENABLE);  //使能串口1 

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启相关中断


//Usart1 NVIC 配置

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3

NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

}



void ir_init(void)

{


/* GPIOA硬件时钟使能 */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

/* Enable SYSCFG clock ,使能系统配置时钟*/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);



/* 配置PA8引脚为输入模式  */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //第8根引脚

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入模式,能够检测外部电平状态

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //GPIO最大的速度为100MHz

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //不需要上下拉电阻

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Configure EXTI Line8 ,配置外部中断控制线8*/

EXTI_InitStructure.EXTI_Line = EXTI_Line8; //使能外部中断控制线8

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发,能够检测到红外信号的到达

EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断控制线使能,让它工作

EXTI_Init(&EXTI_InitStructure);

/* Connect EXTI Line8 to PA8 pin */

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource8);


/* Enable and set EXTI Line8 Interrupt to the lowest priority ,使能并设置外部中断控制线8中断,优先级是最低*/

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //外部中断控制线9_5触发中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; //抢占优先级为0xF

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; //响应优先级为0xF

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //允许外部中断控制线9_5触发中断

NVIC_Init(&NVIC_InitStructure);



}



int main(void)

LED_Init();


//系统定时器初始化,时钟源来自HCLK,且进行8分频,

//系统定时器时钟频率=168MHz/8=21MHz

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 

//设置中断优先级分组2

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

//串口1,波特率115200bps,开启接收中断

USART1_Init(115200);

ir_init();

while(1)

{


if(g_ir_event)

{

printf("ir data:%02X%02X%02X%02Xrn",g_ir_data[0],g_ir_data[1],g_ir_data[2],g_ir_data[3]);

g_ir_event=0;

}

}

}

//分析红外信号,总结出规律,通过测量不同的高电平持续时间,就能够知道当前的信号是引导码、比特0、比特1

uint8_t IR_PluseHighTime(void)

{

uint8_t t=0;

//高电平

while(PAin(8) == 1)

{

t++;

delay_us(20);

//超时溢出

if(t > 250)

return t;

}


return t;

}



void EXTI9_5_IRQHandler(void)

{

uint8_t t=0,ir_vaild=0,ir_bit=0;

uint32_t ir_data=0,ir_bit_cnt=0;

//检查当前外部中断控制线8是否触发中断

if(EXTI_GetITStatus(EXTI_Line8) != RESET)

{

//添加代码

while(1)

{

//若出现高电平,就进行测量

if(PAin(8)==1)

{

t = IR_PluseHighTime();

//当前信号是非法信号

if(t >=250)

break;

//判断当前信号是引导码

if(t>=200 && t<250) //4ms ~ 5ms

{

ir_vaild=1;

continue;

}

//收到bit1

else if(t>=60 && t<90) //1.2ms~1.8ms

{

ir_bit = 1;

}

//收到bit0

else if(t>=10 && t<50)  //0.2ms ~ 1 ms

{

ir_bit = 0;

}

//获取bit数据

if(ir_vaild)

{

ir_data|=ir_bit< }

ir_bit_cnt++;

if(ir_bit_cnt >=32)

{

g_ir_data[0] = (uint8_t)((ir_data>>24)&0xFF);

g_ir_data[1] = (uint8_t)((ir_data>>16)&0xFF);

g_ir_data[2] = (uint8_t)((ir_data>>8)&0xFF);

g_ir_data[3] = (uint8_t)(ir_data&0xFF);


//进行数据校验判断,检查当前接收到的红外数据是否正确

if(g_ir_data[0] == (0xFF - g_ir_data[1]))

{

if(g_ir_data[2] == (0xFF - g_ir_data[3]))

{

g_ir_event = 1;

}

}

break;


}

}

}

/* Clear the EXTI line 8 pending bit,清空中断标志位,就代表说我已经完成中断处理 */

EXTI_ClearITPendingBit(EXTI_Line8);

}

}


void USART1_IRQHandler(void)                //串口1中断服务程序

{

uint8_t d;


if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断

{

d = USART_ReceiveData(USART1);

推荐阅读

史海拾趣

Gamma Microelectronics ( APM )公司的发展小趣事

为了提高DSSC的转换效率和长期稳定性,G24i积极寻求技术合作。公司与离子液体供应商BASF公司签署了合作协议,共同开发性能更优的离子液体和电解液配方。此外,G24i还与国内外多家科研机构建立了紧密的合作关系,共同推进DSSC技术的研发和创新。这些合作不仅为G24i带来了先进的技术支持,也促进了整个DSSC行业的快速发展。

Akustica(Bosch)公司的发展小趣事

为了进一步满足市场需求,G24i在英国威尔士卡迪夫建成了世界上第一条25MW的大规模生产基于钛衬底的DSSC基地。这一基地的建成标志着G24i在DSSC领域实现了从研发到生产的全链条覆盖。大规模生产不仅降低了产品的制造成本,也提高了生产效率和质量稳定性。G24i通过不断优化生产流程和提升管理水平,确保了产品的市场竞争力。

General Diode Corp公司的发展小趣事
检查电源模块是否损坏,更换故障部件;检查电源输入电压是否稳定,确保在正常范围内。
Good Sky Electric Co Ltd公司的发展小趣事
在电气原理图中,互锁功能用于防止两个或多个接触器同时工作,以避免电路短路或设备损坏。例如,正反转按钮互锁就是防止电机在正转和反转之间突然切换,导致设备损坏。自锁功能则是指接触器在吸合后能够保持通电状态,即使按钮松开也不会立即断开电路,从而保证设备的持续运行。
ETA-USA公司的发展小趣事

ETA-USA公司起源于XXXX年,当时由几位电子工程领域的先驱者在美国密歇根州的Troy市创立了这家专注于电子技术和解决方案的公司。初创时期,ETA-USA面临着技术挑战、资金短缺和市场竞争激烈等多重困难。然而,通过不断创新和提供高质量的工程服务,公司逐渐在电子行业崭露头角,赢得了客户的信任。

Dean Technology公司的发展小趣事

Dean Technology公司起源于上世纪80年代,当时电子行业正经历着飞速的发展。创始人凭借其深厚的电子技术背景和敏锐的市场洞察力,决定进入高压二极管领域。他带领研发团队不断攻克技术难题,成功推出了一系列性能稳定、品质可靠的高压二极管产品,奠定了公司在行业中的技术领先地位。

问答坊 | AI 解惑

跪求FTDI的驱动D2xx和有过ft254开发经验的大侠!

最近小弟在用的板子上的usb用的是ft245am的usb芯片,但是插到电脑里识别不了,是不是没装驱动?所以想问问那位大哥有它的驱动,在此先谢过各位了…

查看全部问答>

关于通过无线局域网连接控制器的问题

有一台控制器设备,有LAN接口,IP地址是200.200.200.* 直接通过网线连接到电脑上,电脑的IP地址设为200.200.200.*,DNS是255.255.255.0网关设为192.168.1.1则可以连接到控制器,若把IP地址和网关设为其他的却不行,控制器软件只有一个IP地址,把IP ...…

查看全部问答>

高手请进:关于增强型单片机lpc932与pc的通信

麻烦高手看一下,我用的是增强型uart,pc发送一个“s”给单片机,单片机受到后会给pc发送一个response at 9600 baud 。不知程序是否有问题??? 程序如下: #include \"reg932.h\" #define uchar unsigned char uchar temp; char text[]= ...…

查看全部问答>

虚拟磁盘问题,可能是内存访问有问题

我修改了 FileDisk.c 这个虚拟磁盘源码,把它改成像还原精灵差不多。 功能:把对虚拟磁盘的写操作定向到另一个文件。 这样下次虚拟出来的磁盘就还是原来的。 程序设计:1、申请一块内存记录有过写操作的扇区号 2、对于写操作,写入另一临时文件 ...…

查看全部问答>

LM3S8962开发板自带的小游戏在哪可以下到程序啊?

LM3S8962开发板自带的小游戏在哪可以下到程序啊?…

查看全部问答>

帮实验室老是转让一些他项目剩余的芯片开发工具等

  芯片有:名称           数量 AT89C52        50       每片3元ATmega16L       11 ...…

查看全部问答>

冒死也要向大家推荐的两本书

[ 本帖最后由 37°男人 于 2011-2-8 14:22 编辑 ]…

查看全部问答>

未定义指令

                                 买的是北京微芯力科的开发板,付带了St公司的软件函数库,把这些函数库添加到应用程序文件,编译没问题,但仿真的 ...…

查看全部问答>

郭天祥超好的51书籍珍藏版快来收藏吧

郭天祥超好的51书籍珍藏版快来收藏吧 [ 本帖最后由 鑫海宝贝 于 2011-3-22 19:18 编辑 ]…

查看全部问答>

求一字模提取软件

今天在网上找了10几个, 没一个满意的, 其实我的要求非常简单, 自己能输入文字, 并能编辑此文字, 按行排或按列排, 可编辑分辨率, 可随意转换二进制码, 十六进制码, 共阴或共阳码!   以上要求8x8点阵字模提取软件, pctolcd2002, Zimo221软件等 ...…

查看全部问答>