在物联网产品的开发过程中经常需要基于无线的简单交互通讯,红外通讯比较适合近距离低速的
交换数据场景,红外协议比较多,比如NEC,RC5,NRC17等。
NEC红外协议,GPIO口的输出时序,
1.逻辑0为脉冲时间560us低电平+560us高电平,1.12ms周期 ,逻辑1为脉冲时间560us低电平+1690us高电平, 2.25ms周期。
2.命令格式 9ms低电平引导码+4.5ms高电平结果码+地址码+地址反码+命令码+命令反码 (经测试必须32BIT(4个字节))+560us低电平作为结束,经测试接收管自动反向,注意这四个字节为(A,~A,B,~B)。
3.占空比1/4到1/3载波为38KHZ的PWM。
4.命令格式的电平反向形式。
使用GD32F4XX串口3作为红外编解码通讯接口,
USART3_RX接收BC7120A的红外解码数据,波特率9600。
USART3_TX作为普通IO输出因引脚与外部38KHZ振荡电路通过与门输出调制脉冲到红外发射管。
delay.c软件延时
#ifndef __DELAY_H__
#define __DELAY_H__
#include "gd32f4xx.h"
#define delay_us Delay_US
#define delay_ms Delay_MS
#define HAL_Delay Delay_MS
void Delay_US(uint32_t time);
void Delay_MS(uint32_t time);
#endif
#include "delay.h"
#define CURRENT_CPU_FREQ (SystemCoreClock / 1000000)
void Delay_US(uint32_t time)
{
while(time--)
{
#if (CURRENT_CPU_FREQ == 120)
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
#elif (CURRENT_CPU_FREQ == 168)
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
#elif (CURRENT_CPU_FREQ == 200)
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
#else
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
#endif
}
}
void Delay_MS(uint32_t time)
{
Delay_US(time * 11000);
}
timer1.c定时器硬件延时
#ifndef __TIMER1_H__
#define __TIMER1_H__
#include "gd32f4xx.h"
#include "it_config.h"
void Timer_Init(void);
void Timer_Dly_Wait(uint32_t time);
#endif
#include "timer1.h"
#define TIMx TIMER0
#define RCU_TIMx_CLK RCU_TIMER0
#define TIMx_IRQn TIMER0_UP_TIMER9_IRQn
#define TIMx_IRQHandler TIMER0_UP_TIMER9_IRQHandler
/**100us时基*/
static __IO uint32_t timer1_100us_cnt = 0;
void Timer_Init(void)
{
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMx_CLK);
timer_deinit(TIMx);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER1 configuration 配置出来中断为100us 168MHZ下*/
timer_initpara.prescaler = 168 - 1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 100;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
nvic_irq_enable(TIMx_IRQn, TIMER1_NVIC_PREEMPTIONPRIORITY, TIMER1_NVIC_SUBPRIORITY);
timer_init(TIMx, &timer_initpara);
timer_interrupt_enable(TIMx, TIMER_INT_UP);
timer_enable(TIMx);
}
/**
* @brief This function handles TIMER1 interrupt request.
* @param None
* @retval None
*/
void TIMx_IRQHandler(void)
{
if(SET == timer_interrupt_flag_get(TIMx, TIMER_INT_FLAG_UP)){
/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(TIMx, TIMER_INT_FLAG_UP);
timer1_100us_cnt++;
}
}
//定时器防止uint32_t溢出延时函数
void Timer_Dly_Wait(uint32_t time)
{
uint32_t cur_cnt = timer1_100us_cnt;
if(cur_cnt + time <= 0xFFFFFFFF)
{
while(timer1_100us_cnt - cur_cnt < time);
}
else
{
while(timer1_100us_cnt < 0xFFFFFFFF);
time = time - (0xFFFFFFFF - cur_cnt);
while(1 + timer1_100us_cnt < time);
}
}
infrared.c红外软编码硬解码实现
#ifndef __INFRARED_H__
#define __INFRARED_H__
#include <string.h>
#include "cmsis_os.h"
#include "gd32f4xx.h"
#include "config.h"
#include "comtypes.h"
#include "delay.h"
#include "timer1.h"
#include "raygunled.h"
#include "mode.h"
#define IR_TX_FUNC
#define IR_RX_FUNC
void IR_Init(void);
void IR_Send(uint8_t*buf, uint8_t len);
#endif
#include "infrared.h"
#define USART2_DATA_ADDRESS ((uint32_t)&USART_DATA(USART2))
#define USART3_DR_ADDR USART2_DATA_ADDRESS
#define USARTx USART2
#define RCU_GPIO_CLK RCU_GPIOC
#define RCU_USARTx_CLK RCU_USART2
#define USART_GPIO_AF GPIO_AF_7
#define USARTx_TX_GPIO_PORT GPIOC
#define USARTx_TX_PIN GPIO_PIN_10
#define USARTx_RX_GPIO_PORT GPIOC
#define USARTx_RX_PIN GPIO_PIN_11
#define DMAx DMA0
#define RCU_DMAx_CLK RCU_DMA0
#define USARTx_TX_DMA_CHANNEL DMA_CH3
#define USARTx_RX_DMA_CHANNEL DMA_CH1
#define USARTx_DMA_SUBPERI4 DMA_SUBPERI4
#define USARTx_IRQn USART2_IRQn
#define USARTx_IRQHandler USART2_IRQHandler
#define USART3_RECV_BUFF_LEN (3)
#define TX_PIN_SET gpio_bit_set(USARTx_TX_GPIO_PORT,USARTx_TX_PIN)
#define TX_PIN_RESET gpio_bit_reset(USARTx_TX_GPIO_PORT,USARTx_TX_PIN)
#define IR_TX(x) ((x) ? TX_PIN_SET : TX_PIN_RESET)
static dma_single_data_parameter_struct dma_init_struct;
//DMA接收缓冲区
static __IO uint8_t usart3_recv_buf[USART3_RECV_BUFF_LEN];
__IO BOOLEAN is_be_shooted = FALSE;
__IO int shooted_bullet = 0;
#ifdef IR_TX_FUNC
static __INLINE void IR_DELAY(uint8_t tm)
{
uint8_t tmp;
tmp = tm / 10;
if(tmp)
{
osDelay(tmp);
}
tmp = tm % 10;
if(tmp)
{
Timer_Dly_Wait(tmp);
}
}
#endif
void IR_Init(void)
{
rcu_periph_clock_enable(RCU_GPIO_CLK);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USARTx_CLK);
/* connect port to USARTx_Tx */
//gpio_af_set(USARTx_TX_GPIO_PORT, USART_GPIO_AF, USARTx_TX_PIN);
/* connect port to USARTx_Rx */
gpio_af_set(USARTx_RX_GPIO_PORT, USART_GPIO_AF, USARTx_RX_PIN);
/* configure USART Tx push-pull */
gpio_mode_set(USARTx_TX_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP,USARTx_TX_PIN);
gpio_output_options_set(USARTx_TX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,USARTx_TX_PIN);
gpio_bit_set(USARTx_TX_GPIO_PORT,USARTx_TX_PIN);
/* configure USART Rx as alternate function push-pull */
gpio_mode_set(USARTx_RX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP,USARTx_RX_PIN);
gpio_output_options_set(USARTx_RX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,USARTx_RX_PIN);
/* USART configure */
usart_deinit(USARTx);
//注意该波特率
usart_baudrate_set(USARTx, 9600U);
usart_word_length_set(USARTx, USART_WL_8BIT);
usart_stop_bit_set(USARTx, USART_STB_1BIT);
usart_parity_config(USARTx, USART_PM_NONE);
usart_hardware_flow_rts_config(USARTx, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USARTx, USART_CTS_DISABLE);
usart_receive_config(USARTx, USART_RECEIVE_ENABLE);
//usart_transmit_config(USARTx, USART_TRANSMIT_ENABLE);
///
/* enable DMA1 */
rcu_periph_clock_enable(RCU_DMAx_CLK);
dma_deinit(DMAx, USARTx_RX_DMA_CHANNEL);
dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
dma_init_struct.memory0_addr = (uint32_t)usart3_recv_buf;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
dma_init_struct.number = USART3_RECV_BUFF_LEN;
dma_init_struct.periph_addr = USART3_DR_ADDR;
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_single_data_mode_init(DMAx, USARTx_RX_DMA_CHANNEL, &dma_init_struct);
/* configure DMA mode */
dma_circulation_enable(DMAx, USARTx_RX_DMA_CHANNEL);
dma_channel_subperipheral_select(DMAx, USARTx_RX_DMA_CHANNEL, USARTx_DMA_SUBPERI4);
nvic_irq_enable(USARTx_IRQn, USART3_NVIC_PREEMPTIONPRIORITY, USART3_NVIC_SUBPRIORITY);
usart_dma_receive_config(USARTx, USART_DENR_ENABLE);
dma_channel_enable(DMAx, USARTx_RX_DMA_CHANNEL);
usart_interrupt_enable(USARTx,USART_INT_IDLE);
usart_enable(USARTx);
}
//NEC协议软编码
void IR_Send(uint8_t*buf, uint8_t len)
{
#ifdef IR_TX_FUNC
uint8_t i = 0;
uint8_t j = 0;
uint8_t tmp = 0;
//发送9ms引导码 低电平
IR_TX(0);
IR_DELAY(90);
//发送4.5ms结果码 高电平
IR_TX(1);
IR_DELAY(45);
IR_TX(0);
for(i=0;i < len;i++)
{
tmp = buf;
//数据从低位向高位发送
for(j=0;j < 8;j++)
{
//发送逻辑1
if(tmp & 0x01)
{
IR_TX(0);
IR_DELAY(5);
Delay_US(60);
//共计560us 低电平
IR_TX(1);
IR_DELAY(16);
Delay_US(90);
IR_TX(0);
//共计1.690ms 高电平
}
//发送逻辑0
else
{
IR_TX(0);
IR_DELAY(5);
Delay_US(60);
//共计560us 低电平
IR_TX(1);
IR_DELAY(5);
Delay_US(60);
IR_TX(0);
//共计560us 高电平
}
tmp >>= 1;
}
}
//最后发送一个结束560us低电平,实验得到非常重要
IR_TX(0);
IR_DELAY(5);
Delay_US(60);
//波形两端拉高
IR_TX(1);
#endif
}
//串口3DMA空闲中断处理函数,用于接收BC7120A硬解码的红外数据。
void USARTx_IRQHandler(void)
{
uint16_t tmp;
dma_channel_disable(DMAx, USARTx_RX_DMA_CHANNEL);
usart_interrupt_flag_clear(USARTx,USART_INT_FLAG_IDLE);
usart_data_receive(USARTx);
if(USART3_RECV_BUFF_LEN != dma_transfer_number_get(DMAx,USARTx_RX_DMA_CHANNEL)) goto USART3_IRQEND;
tmp = usart3_recv_buf[0];
if(usart3_recv_buf[1] != (uint8_t)~tmp) goto USART3_IRQEND;
usart3_recv_buf[2] ^= (uint8_t)(tmp * 5);
if(!Is_Raygunled_Hurt(usart3_recv_buf[2],&tmp)) goto USART3_IRQEND;
shooted_bullet = tmp;
is_be_shooted = TRUE;
USART3_IRQEND:
dma_deinit(DMAx, USARTx_RX_DMA_CHANNEL);
dma_single_data_mode_init(DMAx, USARTx_RX_DMA_CHANNEL, &dma_init_struct);
dma_circulation_enable(DMAx, USARTx_RX_DMA_CHANNEL);
dma_channel_subperipheral_select(DMAx, USARTx_RX_DMA_CHANNEL, USARTx_DMA_SUBPERI4);
dma_channel_enable(DMAx, USARTx_RX_DMA_CHANNEL);
}
————————————————
版权声明:本文为CSDN博主「麦德泽特」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44470384/article/details/131310202
|
|