STM32 HAL 库接收 NEC 协议代码详解

由于 NEC 协议的数据格式比较简单,可以直接使用 STM32 的外部中断来接收信号。以下是一个基于 STM32 HAL 库的 NEC 协议接收代码示例。

1. 定义常量和变量

首先,需要定义一些 NEC 协议相关的常量和变量:

#define NEC_START_HIGH 9000 // NEC 协议起始码高电平时间(μs)
#define NEC_START_LOW 4500 // NEC 协议起始码低电平时间(μs)
#define NEC_BIT_HIGH 560 // NEC 协议数据位高电平时间(μs)
#define NEC_BIT_LOW_0 560 // NEC 协议数据位 0 低电平时间(μs)
#define NEC_BIT_LOW_1 1690 // NEC 协议数据位 1 低电平时间(μs)
#define NEC_REPEAT 110000 // NEC 协议重复码时间(μs)

volatile uint32_t nec_data = 0; // 存储接收到的数据
volatile uint8_t nec_bit_count = 0; // 记录已接收的数据位数
volatile uint32_t nec_last_time = 0; // 上一次中断时间

2. 外部中断回调函数

接下来是外部中断回调函数,用于接收 NEC 协议信号:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    uint32_t time = HAL_GetTick() - nec_last_time; // 计算距离上一次中断的时间
    nec_last_time = HAL_GetTick(); // 更新上一次中断时间

    if (time > NEC_REPEAT) { // 如果是重复码
        nec_data = 0xFFFFFFFF; // 存储为全 1
        nec_bit_count = 0; // 重置数据位数
        return;
    }

    if (nec_bit_count == 0) { // 如果是起始码的第一个高电平
        if (time >= NEC_START_HIGH - NEC_BIT_HIGH && time <= NEC_START_HIGH + NEC_BIT_HIGH) {
            // 如果高电平时间在 NEC_START_HIGH 的范围内,则开始接收数据
            nec_bit_count = 1;
        }
        return;
    }

    if (nec_bit_count <= 32) { // 如果正在接收数据位
        if (time >= NEC_BIT_HIGH - NEC_BIT_HIGH / 2 && time <= NEC_BIT_HIGH + NEC_BIT_HIGH / 2) {
            // 如果高电平时间在 NEC_BIT_HIGH 的范围内,则接收到了一个 1
            nec_data |= 1 << (nec_bit_count - 1); // 存储数据
            nec_bit_count++; // 数据位数加 1
        } else if (time >= NEC_BIT_LOW_0 - NEC_BIT_LOW_0 / 2 && time <= NEC_BIT_LOW_0 + NEC_BIT_LOW_0 / 2) {
            // 如果低电平时间在 NEC_BIT_LOW_0 的范围内,则接收到了一个 0
            nec_bit_count++; // 数据位数加 1
        } else if (time >= NEC_BIT_LOW_1 - NEC_BIT_LOW_1 / 2 && time <= NEC_BIT_LOW_1 + NEC_BIT_LOW_1 / 2) {
            // 如果低电平时间在 NEC_BIT_LOW_1 的范围内,则接收到了一个 1
            nec_data |= 1 << (nec_bit_count - 1); // 存储数据
            nec_bit_count++; // 数据位数加 1
        } else { // 如果低电平时间不在 NEC_BIT_LOW_0 和 NEC_BIT_LOW_1 的范围内,则数据错误
            nec_bit_count = 0; // 重置数据位数
        }
    }

    if (nec_bit_count > 32) { // 如果已经接收完所有数据位
        nec_bit_count = 0; // 重置数据位数
    }
}

3. 主函数初始化

最后,可以在主函数中使用上述代码来接收 NEC 协议信号:

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    // 初始化 GPIO 和外部中断
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

    while (1) {
        if (nec_data != 0xFFFFFFFF) { // 如果接收到了有效数据
            // 处理接收到的数据
            nec_data = 0xFFFFFFFF; // 重置为全 1,等待下一次接收
        }
    }
}

总结

该代码示例展示了如何使用 STM32 HAL 库接收 NEC 协议信号。通过定义必要的常量和变量,并在外部中断回调函数中处理接收到的数据,即可实现 NEC 协议数据的接收。在主函数中,需要初始化 GPIO 和外部中断,并循环检测接收到的数据。


原文地址: https://www.cveoy.top/t/topic/mOp0 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录