新手村中打满级大BOSS 2025-07-05 15:22 采纳率: 0%
浏览 12
已结题

433无线收发,同步码检测问题(有偿解决,100块)


 
#include "stm32f0xx.h"
#include <stdio.h>
#include "main.h"
#include "stm32f0xx_rcc.h"
#include "delay.h"
#include "stm32f0xx_exti.h"  // EXTI外设头文件
#include "stm32f0xx_syscfg.h" // SYSCFG头文件(EXTI滤波需要)
 
// 硬件配置
#define DATA_PIN     GPIO_Pin_15  //B  15
#define DATA_PORT    GPIOB
 
// 示波器测量
#define LEAD_CODE_HIGH_US   400   
#define LEAD_CODE_LOW_US    14000 
 
#define BIT_HIGH_US         1450   
#define BIT_LOW_US          500   
 
// 同步头容差
#define TOLERANCE_MIN 0.9f
#define TOLERANCE_MAX 1.1f
 
 
// 定义数据解码状态枚举
typedef enum {
      START,
    LEAD_CODE_H,     
    LEAD_CODE_L, 
    HIGH_BIT, 
    LOW_BIT,    
    COMPARE,    
} Decode_State_t;
 
// 全局变量和缓冲区
volatile uint32_t Bit_Count = 0;                 // 接收数据位计数
volatile uint32_t Received_Data = 0;             // 接收到的数据
volatile Decode_State_t RF_Decode_State = START; // 数据解码状态
volatile uint8_t Frame_Ready = 0;                // 帧接收完成标志
uint32_t stored_pairing_id = 0;                 // 存储配对成功的ID
uint8_t collected_digits[3] = {0};              // 收集的数字(百、十、个)
uint8_t digit_count = 0;                        // 已收集的数字个数
uint32_t last_time = 0;                         // 上次脉冲时间
uint8_t bit_val = 0;                            // 收集的值
 
static uint32_t last_received_id = 0;
static uint8_t last_received_key = 0xB;         // 配对模式的按键值
 
uint32_t H_duration=0;  //高电平脉冲宽度
uint32_t L_duration=0;  //低电平脉冲宽度
 
 
// 定时器初始化,微秒
void TIM_TimeBase_Init(void) {
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    
    TIM_TimeBaseInitTypeDef TIM_InitStruct;
    TIM_InitStruct.TIM_Prescaler = (SystemCoreClock / 1000000) - 1; // 1MHz频率
    TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    
    TIM_InitStruct.TIM_Period = 0xFFFF;
    TIM_TimeBaseInit(TIM3, &TIM_InitStruct);
    
    TIM_Cmd(TIM3, ENABLE);
}
 
// 初始化接收
void RF_RX_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    // 使能时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//这个必须要开启,被卡主了
    
    // 配置DO引脚为输入
    GPIO_InitStruct.GPIO_Pin = DATA_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DATA_PORT, &GPIO_InitStruct);
    
      SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource15);
    
    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_InitStruct.EXTI_Line = EXTI_Line15;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//触发 CPU 的中断处理流程
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //双边沿触发
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);
    
 
    // 配置中断优先级
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = EXTI4_15_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority =0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
    // 初始化定时器
    TIM_TimeBase_Init();
}
 
 
//接收到的数据
void print_received_data(uint32_t data, uint32_t bit_count) {
    char bin_str[25] = {0};
    // 提取24位数据,bit23(MSB)到bit0(LSB)
    for (int i = 0; i < 24; i++) {
        uint32_t mask = 1UL << (23 - i);
        bin_str[i] = (data & mask) ? '1' : '0';
    }
    printf("Bit[%d]: %s\n", bit_count, bin_str);
}                        
 
 
// 轮询接收函数
void Poll_RF_Receiver(uint16_t current_state) {
    uint32_t current_time = TIM_GetCounter(TIM3);
      uint32_t duration;
    if (current_time < last_time) {
 
        duration = 0xFFFF - last_time + current_time + 1;
    } else {
        duration = current_time - last_time;
    }
    last_time = current_time;
        
 
    switch (RF_Decode_State) {
        case START:
            if (current_state == 1) {
                RF_Decode_State = LEAD_CODE_H;
            }
            break;
 
        case LEAD_CODE_H:
            if (current_state == 0) {
    
                if (duration >= (LEAD_CODE_HIGH_US * TOLERANCE_MIN) && duration <= (LEAD_CODE_HIGH_US * TOLERANCE_MAX)) {
printf("Dur1=%d\n",duration);        
                    RF_Decode_State = LEAD_CODE_L;
                } else {
                    RF_Decode_State = START;
                }
            }
            break;
 
        case LEAD_CODE_L:
            if (current_state == 1) {
printf("Dur2=%d\n",duration);                            
                if (duration >= (LEAD_CODE_LOW_US * TOLERANCE_MIN) && duration <= (LEAD_CODE_LOW_US * TOLERANCE_MAX)) {
printf("Dur3=%d\n",duration);        
                    Received_Data = 0;
                    Bit_Count = 0;
                    RF_Decode_State = HIGH_BIT;
                } else {
                    RF_Decode_State = LEAD_CODE_H;
                }
            }
            break;
 
        case HIGH_BIT:
                        
            if (current_state == 0) {     
                                        H_duration = duration;
                                        RF_Decode_State = LOW_BIT;
 
            }
            break;
 
        case LOW_BIT:
                        
            if (current_state == 1) { 
                                        L_duration = duration;
                                        RF_Decode_State = COMPARE;
 
            }
            break;
 
                case COMPARE: {
 
                        const uint32_t diff = (H_duration > L_duration) 
                                ? (H_duration - L_duration)
                                : (L_duration - H_duration);
                        
                        if(diff > 50) { 
                                bit_val = (H_duration > L_duration) ? 1 : 0;
                                
                                // LSB优先接收 (与后续打印一致)
                                Received_Data = (bit_val << (23 - Bit_Count)) | Received_Data;
                                Bit_Count++;
                                
                                if(Bit_Count >= 24) {
                                        Frame_Ready = 1;
                                    print_received_data(Received_Data,Bit_Count);
                                        RF_Decode_State = START;
                                } else {
                                        RF_Decode_State = HIGH_BIT;
                                }
                        } else {
                                // 微小差异不重置状态机,继续接收
                                RF_Decode_State = HIGH_BIT;
                        }
                        break;
                }
    }
}
 
 
void EXTI4_15_IRQHandler(void) {
    
    static int irq_count = 0;
    
    if (EXTI_GetITStatus(EXTI_Line15) != RESET) {
    uint8_t current = GPIO_ReadInputDataBit(DATA_PORT, DATA_PIN);
    Poll_RF_Receiver(current);        
        EXTI_ClearITPendingBit(EXTI_Line15);  // 清除中断标志
 
    }
}
 

上述程序为,轮询接收RF信号的解码曼彻斯特编码的状态机,解码433无线通信
,程序运行后,日志如下

Dur1=439
Dur2=1448
Dur1=424
Dur2=1096
Dur1=432
Dur2=1561
Dur1=440
Dur2=1293
Dur1=360
Dur2=1216
Dur1=413
Dur2=1290
Dur1=382
Dur2=717
Dur1=383
Dur2=1119
Dur1=409
Dur2=1117
Dur1=436
Dur2=1634
Dur1=383
Dur2=1032
Dur1=388
Dur2=1128
Dur1=413
Dur2=939
Dur1=434
Dur2=581
Dur1=439
Dur2=1407
Dur1=433
Dur2=1113
Dur1=429
Dur2=921
Dur1=408
Dur2=913

img

红色为发射的波形,白色为接收的波形。同步码的高电平400可以收到,但是低电平的14000,确一直无法检测到,导致无法解码,使用的单片机为stm32f030,48Mhz,请教一下是什么原因

  • 写回答

6条回答 默认 最新

  • 阿里嘎多学长 2025-07-05 15:22
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    问题解答

    433MHz无线收发同步码检测问题

    您的问题是关于433MHz无线收发的同步码检测问题,使用STM32F0微控制器编写C语言代码。

    从您的代码中,我可以看到您已经包含了必要的头文件和宏定义。下面是一些可能有助于解决问题的建议:

    1. 检测同步码的方法:您可以使用 timer 模块来检测同步码的出现。例如,您可以使用 timer 的溢出事件来检测同步码的出现。
    2. 433MHz无线收发的同步码检测算法:您可以使用一些常见的同步码检测算法,例如 Manchester 编码、NRZ-I 编码等。
    3. 代码实现:以下是一个简单的示例代码,使用 timer 模块来检测同步码的出现:
    void detect_sync_code(void) {
        // 配置 timer 模块
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        TIM2_PSC = 100; // 设置 timer 的分频率
        TIM2_ARR = 999; // 设置 timer 的溢出值
    
        // 配置 timer 的溢出事件
        NVIC_EnableIRQ(TIM2_IRQn);
        TIM2_IRQHandler();
    
        // 检测同步码
        while (1) {
            if (TIM2->SR & TIM_SR_UIF) {
                // 检测到同步码
                // 处理同步码的逻辑
            }
        }
    }
    

    这个示例代码只是一个简单的示例,实际实现中可能需要根据您的具体需求进行修改。

    如果您需要更多帮助,请提供更多的代码和详细的描述。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月5日
  • 修改了问题 7月5日
  • 创建了问题 7月5日