125K RFID解码

  曼彻斯特编码能够把数据速率对应的时钟信息嵌入到消息中,便于接收端恢复时钟。此外,曼彻斯特编码还有一个额外优点:其平均直流(DC)电平始终为 50%。这对解调器电路设计以及调制后发射射频(RF)频谱的管理都有积极意义。这意味着在一些调制方式中(例如调幅 AM),若输出功率是消息信号的函数,则平均功率保持恒定,不随编码后的数据流变化。

  曼彻斯特编码规定:在每个数据比特帧的中点,消息信号一定会发生一次跳变。至于在比特边界处是否跳变,则取决于前一个比特帧的状态,因此不一定总会产生跳变。

ID卡(如EM4100)输出的数据已经是曼彻斯特编码了。需要对捕获的信号进行曼彻斯特解码(不是编码),才能得到正确的数据位。

曼彻斯特编码的方式一般有两种:

image

我们使用的EM4100属于第一种。即:1用 0 1表示,0 用 1 0表示。

image

协议规定:1 bit 占用 64 个载波周期,载波频率:fc=125 kHz

所以:数据位速率就是:

image

image

image

所以:全位脉宽为512us,半位脉宽为256us。

当 64 位的最后一位发完之后,芯片会立刻从第一位重新开始发送,一直循环,直到磁场消失(掉电)。

image

image

我们使用状态机的方法进行数据解析:

 

#include "Time_Caputer.h"

/*接收RFID数据  变量*/
	// FreeRTOS队列句柄,用于存放接收到的原始数据(128字节的数组)
	QueueHandle_t xHalfBitsQueue = NULL;
	// 全局标志位,用于通知主程序RFID数据已接收完成
	uint8_t g_bitResevData = false;
	// RFID状态机上下文结构体,保存状态机的所有状态信息,初始化为0
	rfid_sm_context_t g_sm;
	//volatile uint8_t g_bDataReady = FALSE;  // volatile 很重要,因为会被中断和主程序同时访问
	uint8_t g_ucHalfBits[128];              // 存储128个原始电平

void Time_Caputer_init(void)
{
    TIM_ICInitType TIM_ICInitStructure;
    TIM_TimeBaseInitType TIM_TimeBaseStructure1;
    
    /* 0. 使能TIM3时钟(必须放在最前面!) */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);
    
    /* 1. GPIO配置 */
    Time_Caputer_GPIO_Configuration();
    
    /* 2. 定时器时基配置 */
    // 假设系统时钟是64MHz
    // 64MHz/(255+1) = 250kHz,每个计数4μs
    TIM_TimeBaseStructure1.Period = 65535;           // 最大计数值
    TIM_TimeBaseStructure1.Prescaler = 255;          // 256分频,每个计数4μs
    TIM_TimeBaseStructure1.ClkDiv = TIM_CLK_DIV1;    // 时钟不分频
    TIM_TimeBaseStructure1.CntMode = TIM_CNT_MODE_UP; // 向上计数
    
    // 先配置时基
    TIM_InitTimeBase(TIM3, &TIM_TimeBaseStructure1);
    
    /* 3. 输入捕获配置 - 更完整的配置 */
    // 通道2配置
    TIM_ICInitStructure.Channel     = TIM_CH_2;
    TIM_ICInitStructure.IcPolarity  = TIM_IC_POLARITY_BOTHEDGE; // 双边沿触发
    TIM_ICInitStructure.IcSelection = TIM_IC_SELECTION_DIRECTTI; // 直接输入
    TIM_ICInitStructure.IcPrescaler = TIM_IC_PSC_DIV1;          // 不分频,每个边沿都捕获
    TIM_ICInitStructure.IcFilter    = 0x8;                      // 8个时钟滤波(约32μs滤波)
    
    // 初始化输入捕获
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
    
    /* 4. 重置计数器 */
    TIM_SetCnt(TIM3, 0);  
    
    /* 5. 清除所有中断标志 */
    TIM_ClrIntPendingBit(TIM3, TIM_INT_CC2 | TIM_INT_UPDATE);
    
    /* 6. 中断配置 */
    Time_Caputer_NVIC_Configuration();
    
    /* 7. 使能中断 */
    // 捕获比较中断(通道2)
    TIM_ConfigInt(TIM3, TIM_INT_CC2, ENABLE);
    // 溢出中断(用于超时检测)
    TIM_ConfigInt(TIM3, TIM_INT_UPDATE, ENABLE);
}

void Time_Caputer_start(void)
{
    /* 现在只需要使能定时器 */
    TIM_Enable(TIM3, ENABLE);
}

void Time_Caputer_GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;
    
    GPIO_InitStruct(&GPIO_InitStructure);
    
    /* TIM3通道2 (PB.05) 配置 */
    GPIO_InitStructure.Pin        = GPIO_PIN_5;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_AF_PP;      // 复用推挽
    GPIO_InitStructure.GPIO_Current = GPIO_DC_LOW;        // 低驱动
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM3;    // 复用功能2:TIM3
    
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
}

void Time_Caputer_NVIC_Configuration(void)
{
    NVIC_InitType NVIC_InitStructure;
    
    /* 配置TIM3中断 */
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;       // 较高优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);
}

// ==================== 状态转换表 ====================
static const rfid_state_transition_t state_transition_table[] = 
	{
    /*******************************************************************
     * 状态1:空闲状态 (RFID_STATE_IDLE)
     *******************************************************************/
	{
        .current_state = RFID_STATE_IDLE,      			// 当前状态:空闲
        .event = RFID_EVT_RISING_EDGE,         			// 事件:检测到上升沿
        .next_state = RFID_STATE_WAIT_SECOND_EDGE, 		// 下一状态:等待第二个边沿
        .callback = on_idle_rising_edge        			// 回调函数:处理上升沿事件
    },
    /*******************************************************************
     * 状态2:等待第二个边沿 (RFID_STATE_WAIT_SECOND_EDGE)
     *******************************************************************/
	{
        .current_state = RFID_STATE_WAIT_SECOND_EDGE, 	// 当前状态:等待第二个边沿
        .event = RFID_EVT_INTERVAL_256US,      			// 事件:间隔为256μs(半位)
        .next_state = RFID_STATE_CHECK_SYNC,   			// 下一状态:检查同步头
        .callback = on_wait_second_256us       			// 回调函数:处理256μs间隔事件
    },
	{
		.current_state = RFID_STATE_WAIT_SECOND_EDGE,
		.event = RFID_EVT_INVALID_INTERVAL,         	// 统一的不合格间隔事件
		.next_state = RFID_STATE_IDLE,
		.callback = on_check_sync_invalid               // 统一的失败处理
	},
	{
		.current_state = RFID_STATE_WAIT_SECOND_EDGE,
		.event = RFID_EVT_INTERVAL_512US,         	
		.next_state = RFID_STATE_IDLE,
		.callback = on_check_sync_invalid               // 统一的失败处理
	},
    /*******************************************************************
     * 状态3:检查同步头 (RFID_STATE_CHECK_SYNC)
     *******************************************************************/
	{
        .current_state = RFID_STATE_CHECK_SYNC, // 当前状态:检查同步头
        .event = RFID_EVT_INTERVAL_256US,      // 事件:间隔为256μs(半位)
        .next_state = RFID_STATE_CHECK_SYNC,   // 下一状态:保持检查同步头状态
        .callback = on_sync_check_256us        // 回调函数:处理256μs间隔,计数同步头
    },
	{
		.current_state = RFID_STATE_CHECK_SYNC,
		.event = RFID_EVT_INVALID_INTERVAL,         	// 统一的不合格间隔事件
		.next_state = RFID_STATE_IDLE,
		.callback = on_check_sync_invalid               // 统一的失败处理
	},
    /*******************************************************************
     * 状态4:接收数据 (RFID_STATE_RECEIVE_DATA)
     *******************************************************************/
	{
        .current_state = RFID_STATE_RECEIVE_DATA, // 当前状态:接收数据
        .event = RFID_EVT_INTERVAL_512US,      // 事件:间隔为512μs(全位)
        .next_state = RFID_STATE_RECEIVE_DATA, // 下一状态:保持接收数据状态
        .callback = on_data_512us              // 回调函数:存储2个相同电平(全位)
    },
    {
        .current_state = RFID_STATE_RECEIVE_DATA, // 当前状态:接收数据
        .event = RFID_EVT_INTERVAL_256US,      // 事件:间隔为256μs(半位)
        .next_state = RFID_STATE_RECEIVE_DATA, // 下一状态:保持接收数据状态
        .callback = on_data_256us              // 回调函数:存储1个电平(半位)
    },
	{
		.current_state = RFID_STATE_RECEIVE_DATA,
		.event = RFID_EVT_INVALID_INTERVAL,         	// 统一的不合格间隔事件
		.next_state = RFID_STATE_IDLE,
		.callback = on_check_sync_invalid               // 统一的失败处理
	},
    /* 结束标记 */
    // 状态转换表的结束标记,用于遍历时检测表尾
    {RFID_STATE_COUNT, RFID_EVT_NONE, RFID_STATE_IDLE, NULL}
	};
	// ==================== 回调函数实现 ====================
/**
 * @brief 空闲状态上升沿事件回调函数
 * @param current_level 上升沿发生后的引脚电平状态(应为1,表示高电平)
 * @param interval 时间间隔(此参数在IDLE状态下始终为0)
 * 示例时序:
 * 空闲状态: 低电平 → 上升沿发生 → 记录[0,1] → 等待第二个边沿
 */	
	void on_idle_rising_edge(uint8_t current_level, uint16_t interval)
	{
		// 清零计数器,准备开始新的帧接收
		g_sm.sync_count = 1;        // 同步头边沿计数清零
		g_sm.half_bit_count = 0;    // 半位计数清零
		g_sm.data_bit_count = 0;    // 数据位计数清零
		
		// 记录第二个电平(上升沿后的高电平)到缓冲区,并且补充第一个0
		if(g_sm.half_bit_count < 128)  // 检查缓冲区是否未满
		{
			g_sm.half_bits[g_sm.half_bit_count++] = 0;
			g_sm.half_bits[g_sm.half_bit_count++] = current_level;
		}
		
		// 调试输出:打印检测到第一个上升沿的信息
		#ifdef RFID_DEBUG
		printf("IDLE: First rising edge detected\n");
		#endif
	}
/**
 * @brief 等待第二个边沿状态 - 256μs间隔回调函数
 * 
 * 典型调用场景:
 * - 检测到第一个逻辑"1"后,256μs内出现下一个边沿
 * - 验证同步头开始的正确性
 * - 如果间隔不是256μs,则触发on_check_sync_invalid函数重置状态机
 */
	void on_wait_second_256us(uint8_t current_level, uint16_t interval)
	{
		// 存储第二个电平到缓冲区
		if(g_sm.half_bit_count < 128)  // 检查缓冲区是否未满
		{
			g_sm.half_bits[g_sm.half_bit_count++] = current_level;
		}
		
		// 设置同步头计数为1,表示已检测到第一个逻辑"1"(一个完整的"01"模式)
		(g_sm.sync_count)++;
		// 调试输出:打印256μs间隔信息和同步计数
		#ifdef RFID_DEBUG
		printf("WAIT_SECOND: 256μs interval, sync count=%d\n", g_sm.sync_count);
		#endif
	}
/**
 * @brief 无效时间间隔处理回调函数
 * @param current_level 当前引脚电平状态(0=低电平,1=高电平)
 * @param interval 检测到的时间间隔(单位:微秒)
 * @warning 此函数会清空半位缓冲区和同步计数器,确保状态机从头开始新的数据接收。
*/
	void on_check_sync_invalid (uint8_t current_level, uint16_t interval)
	{
		// 无效时间间隔,丢弃数据
		g_sm.half_bit_count = 0;
		g_sm.sync_count = 0;
		
		#ifdef RFID_DEBUG
		printf("WAIT_SECOND: Invalid interval %dμs, reset\n", interval);
		#endif
	}
/**
 * @brief 同步头检查状态 - 256μs间隔回调函数   
 * @details 
 * EM4100协议同步头由9个连续的逻辑"1"组成,每个逻辑"1"对应曼彻斯特编码的"01"模式,
 * 每个半位持续256μs。本函数通过计数连续256μs间隔的数量来验证同步头。
 * 函数执行流程:
 * 1. 将当前电平存入半位缓冲区,构建完整的原始数据序列
 * 2. 递增同步头计数器(sync_count),跟踪已检测到的256μs间隔数量
 * 3. 检查是否已收到完整的同步头(同步头计数器≥17时触发完成标志)
 */
	void on_sync_check_256us(uint8_t current_level, uint16_t interval)
	{
		// 连续256μs间隔,同步头的一部分
		
		// 存储电平
		if(g_sm.half_bit_count < 128 && g_sm.sync_count <= 16)
		{
			g_sm.half_bits[g_sm.half_bit_count++] = current_level;
		}
		
		// 增加同步计数
		g_sm.sync_count++;
		
		#ifdef RFID_DEBUG
		printf("CHECK_SYNC: 256μs interval, sync count=%d\n", g_sm.sync_count);
		#endif
		
		// 检查是否收到完整的同步头(9个逻辑"1" = 18个间隔)
		// 注意:第一个"1"已在WAIT_SECOND状态计数,所以总共需要17个
		if(g_sm.sync_count >= 17)  // 9个"1" = 18个间隔 - 1(已计数)
		{
			// 设置同步完成标志
			g_sm.sync_complete_flag = 1;
			
			#ifdef RFID_DEBUG
			printf("CHECK_SYNC: Sync header complete!\n");
			#endif
		// 立即处理内部事件,触发状态转换
        process_state_machine(RFID_EVT_SYNC_OK, current_level, interval);
		}

	}

/**
 * @brief 512μs间隔处理(完整数据位)
 * @note 每个完整数据位存储2个相同的电平
 */
	void on_data_512us(uint8_t current_level, uint16_t interval)
	{
		// 存储2个相同的电平
		if(g_sm.half_bit_count < 128)
		{
			g_sm.half_bits[g_sm.half_bit_count++] = current_level;
			if(g_sm.half_bit_count < 128)
			{
				g_sm.half_bits[g_sm.half_bit_count++] = current_level;
			}
		}
		
		#ifdef RFID_DEBUG
		printf("DATA: 512μs, level=%d, half_bits=%d\n", 
			   current_level, g_sm.half_bit_count);
		#endif
		
		// 检查是否收到完整数据(128个半位 = 64个数据位)
		// 注意:我们从第17个半位开始计数,所以需要接收111个半位
		if(g_sm.half_bit_count >= 128)  // 17 + 111 = 128
		{
			g_sm.data_complete_flag = 1;
			process_state_machine(RFID_EVT_DATA_OK, current_level, interval);
		}
	}

/**
 * @brief 256μs间隔处理(半位)
 * @note 连续相同位时的中间跳变,只存储1个电平
 */
	void on_data_256us(uint8_t current_level, uint16_t interval)
	{
		// 存储1个电平
		if(g_sm.half_bit_count < 128)
		{
			g_sm.half_bits[g_sm.half_bit_count++] = current_level;
		}
		
		#ifdef RFID_DEBUG
		printf("DATA: 256μs, level=%d, half_bits=%d\n", 
			   current_level, g_sm.half_bit_count);
		#endif
		
		// 检查是否收到完整数据
		if(g_sm.half_bit_count >= 128)
		{
			g_sm.data_complete_flag = 1;
			process_state_machine(RFID_EVT_DATA_OK, current_level, interval);
		}
	}

/**
 * @brief 数据接收完成回调函数(队列发送)
 */
	void on_frame_complete(void)
	{
		// 声明队列句柄
		extern QueueHandle_t xRFIDDataQueue;
		
		#ifdef RFID_DEBUG
		printf("FRAME_COMPLETE: Sending data to queue\n");
		#endif
		
		// 1. 检查数据长度
		if (g_sm.half_bit_count < 128) 
		{
			#ifdef RFID_DEBUG
			printf("FRAME_COMPLETE: Error - Only %d half bits\n", g_sm.half_bit_count);
			#endif
			rfid_state_machine_reset();
			return;
		}
		
		// 2. 创建并发送数据包
		BaseType_t xHigherPriorityTaskWoken = pdFALSE;
		
		if (xRFIDDataQueue != NULL) {
			// 直接使用全局g_sm.half_bits数组
			uint32_t timestamp = xTaskGetTickCountFromISR();
			
			// 发送三个参数:数据指针、长度、时间戳
			// 注意:这里假设队列接收一个结构体,或者你可以简化发送方式
			BaseType_t xStatus = xQueueSendFromISR(xRFIDDataQueue, 
												   &g_sm.half_bits[0], 
												   &xHigherPriorityTaskWoken);
			
			if (xStatus == pdPASS) 
			{
				g_bitResevData = true;
			}
		}
		
		// 3. 重置状态机
		rfid_state_machine_reset();
	}

// 计算数组大小
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/**
 * @brief  RFID 		 解码状态机驱动入口:根据“事件 + 当前电平 + 边沿间隔”查表执行回调并完成状态跳转。
 * @param  event         状态机事件类型,用于匹配状态转换表。
 * @param  current_level 当前边沿发生后引脚的电平状态(0=低,1=高),用于记录半位电平序列/辅助校验。
 * @param  interval      相邻两次边沿之间的时间间隔
 */
void process_state_machine(rfid_event_t event, uint8_t current_level, uint16_t interval)
{
  // ==================== 步骤1:处理内部事件标志 ====================
    // 目的:检查是否有内部事件标志被设置,如果有,将它们转换为对应的事件
    // 解释:在回调函数中可能会设置一些内部标志(如sync_complete_flag),
    //       这些标志需要在下一个处理周期转换为具体的事件
    if(g_sm.sync_complete_flag)
    {
        // 同步完成标志被设置且当前事件为RFID_EVT_NONE时,
        // 将事件替换为RFID_EVT_SYNC_OK(同步完成事件)
        event = RFID_EVT_SYNC_OK;
		g_sm.state =RFID_STATE_RECEIVE_DATA;
        // 清除标志,防止重复处理
        g_sm.sync_complete_flag = 0;
		// 调试输出
        #ifdef RFID_DEBUG
        printf("PROCESS: Internal event SYNC_OK triggered\n");
        #endif
    }
    else if(g_sm.data_complete_flag)
    {
        // 清除标志,防止重复处理
        g_sm.data_complete_flag = 0;
		// 调试输出
        #ifdef RFID_DEBUG
        printf("PROCESS: Internal event DATA_OK triggered\n");
        #endif
		// 直接调用帧完成处理函数
        on_frame_complete();
        return;  // 直接返回,不进行后续处理
    }
    // ==================== 1. 遍历状态转换表,找匹配项 ====================
    // 说明:状态机由 state_transition_table 驱动,
    //       这里就是“根据当前状态 + 当前事件”去查表找下一步怎么走。
	else
	{
	for(int i = 0; i < ARRAY_SIZE(state_transition_table); i++)
		{
        if(state_transition_table[i].current_state == g_sm.state && state_transition_table[i].event == event)
        {
            // 执行回调函数
            if(state_transition_table[i].callback != NULL)
            {
                state_transition_table[i].callback(current_level, interval);
            }
			// 只有内部事件标志没有被置位的时候,才使用表中的next_state
			if(!(g_sm.sync_complete_flag || g_sm.data_complete_flag))
			{
				
				 g_sm.state = state_transition_table[i].next_state;
			}
            // 状态转换
           
            
            // 更新电平记录
            g_sm.last_level = current_level;
            
            #ifdef RFID_DEBUG
            printf("STATE: %d -> %d, Event: %d\n", 
                   state_transition_table[i].current_state,
                   state_transition_table[i].next_state,
                   event);
            #endif
            
            break;
        }
		}		
	}

}
// ==================== 定时器状态结构体 ====================
	typedef struct 
	{
		uint32_t last_capture_time;     // 上次捕获时间(32位组合时间)
		uint16_t overflow_count;        // 溢出计数(用于扩展16位定时器到32位)
		uint8_t last_level;             // 上次电平状态(0=低,1=高)
		uint32_t last_edge_tick;        // 上次边沿时间(用于超时检测)
	} timer_state_t;

// 全局定时器状态变量(volatile确保中断和主程序正确访问)
	static volatile timer_state_t g_timer_state = {0};

/**
 * @brief TIM3 中断服务函数(输入捕获 + 溢出超时管理)
 * @note
 * - TIM3 计数分辨率为 4us/tick(64MHz / 256 = 250kHz),间隔换算为 interval_us = interval_ticks * 4。
 * - 输入捕获配置为双边沿触发,current_level 通过读取 PB5 电平得到(1=高,0=低)。
 */
	void TIM3_IRQHandler(void)
	{
		// 1. 检查并处理输入捕获中断(通道2)
		if (TIM_GetIntStatus(TIM3, TIM_INT_CC2) == SET) 
		{
			// 清除中断标志,防止重复进入中断
			TIM_ClrIntPendingBit(TIM3, TIM_INT_CC2);
			
			// 获取当前捕获值(定时器在边沿发生时的计数值)
		   uint16_t current_capture = TIM_GetCap2(TIM3);
			
			// 读取当前引脚电平(PB.05),判断是上升沿还是下降沿
			// 1 = 上升沿(刚刚变为高电平),0 = 下降沿(刚刚变为低电平)
			uint8_t current_level = (GPIO_ReadInputDataBit(GPIOB, GPIO_PIN_5) == SET) ? 1 : 0;
			
			// 更新上次边沿时间,用于超时检测
			g_timer_state.last_edge_tick = xTaskGetTickCountFromISR();
			
			// ============ 根据当前状态进行处理 ============
			switch (g_sm.state) 
			{
				// 情况1:空闲状态,等待第一个上升沿
				case RFID_STATE_IDLE:
					// 空闲状态只处理上升沿,忽略下降沿
					if (current_level == 1) 
					{
						// 记录起始时间(开始一个新的帧接收)
						g_timer_state.last_capture_time = current_capture;  // 捕获值作为起始时间
						g_timer_state.overflow_count = 0;                   // 重置溢出计数
						g_timer_state.last_level = current_level;           // 记录当前电平
						
						// 触发上升沿事件,通知状态机
						// 参数:RFID_EVT_RISING_EDGE = 上升沿事件
						//       current_level = 当前电平(1 = 高电平)
						//       0 = 第一次边沿没有时间间隔
						process_state_machine(RFID_EVT_RISING_EDGE, current_level, 0);
						
						#ifdef RFID_DEBUG
						printf("IDLE: 检测到上升沿,电平=%d\n", current_level);
						#endif
					} 
					else 
					{
						// 下降沿,忽略(在空闲状态我们只关心上升沿)
						#ifdef RFID_DEBUG
						printf("IDLE: 下降沿被忽略\n");
						#endif
					}
					break;
					
				// 情况2:非空闲状态(等待第二个边沿、检查同步头、接收数据)
				// 状态2:等待第二个边沿
				case RFID_STATE_WAIT_SECOND_EDGE:
				// 状态3:检查同步头
				case RFID_STATE_CHECK_SYNC:
				// 状态4:接收数据
				case RFID_STATE_RECEIVE_DATA:
				{	
					// 计算时间差(考虑定时器溢出)
					// 步骤1:将16位捕获值扩展为32位时间值
					// current_capture = 当前捕获值(16位,0-65535)
					// overflow_count = 定时器溢出次数
					// 组合时间 = 当前捕获值 + 溢出次数 * 65536
					uint32_t current_time = current_capture + (g_timer_state.overflow_count * 65536UL);
					
					// 步骤2:获取上次捕获时间
					uint32_t last_time = g_timer_state.last_capture_time;
					
					// 步骤3:计算时间间隔(以定时器计数值为单位)
					uint16_t interval_ticks;
					
					if (current_time >= last_time) 
					{
						// 正常情况:当前时间大于上次时间,直接相减
						interval_ticks = (uint16_t)(current_time - last_time);
					} 
					else 
					{
						// 处理溢出回绕:定时器从65535溢出到0
						// 计算从上次时间到65535的差值,加上从0到当前时间的差值
						interval_ticks = (uint16_t)((0xFFFFFFFFUL - last_time) + current_time + 1);
					}
					
					// 转换为微秒(每个tick=4μs,因为64MHz/256分频=250kHz=4μs/tick)
					uint16_t interval_us = interval_ticks * 4;
					
					// 根据间隔时间判断事件类型(允许±20%的误差提高抗干扰性)
					rfid_event_t interval_event = RFID_EVT_INVALID_INTERVAL;
					
					if (interval_us >= 204 && interval_us <= 308) 
					{ 
						// 256μs ±20% 范围(204-308μs)
						interval_event = RFID_EVT_INTERVAL_256US;
					} 
					else if (interval_us >= 409 && interval_us <= 615) 
					{ 
						// 512μs ±20% 范围(409-615μs)
						interval_event = RFID_EVT_INTERVAL_512US;
					}
					else 
					{
						// 不在有效范围内的间隔
						interval_event = RFID_EVT_INVALID_INTERVAL;
					}
					// 更新记录:将这次捕获作为下一次计算的"上次捕获"
					g_timer_state.last_capture_time = current_capture;
					g_timer_state.last_level = current_level;
					
					// 触发事件到状态机
					process_state_machine(interval_event, current_level, interval_us);
					
					break;
			}
		}
	}
		// 2. 检查并处理溢出中断(更新中断)
		if (TIM_GetIntStatus(TIM3, TIM_INT_UPDATE) == SET) 
		{
			// 清除溢出中断标志
			TIM_ClrIntPendingBit(TIM3, TIM_INT_UPDATE);
			
			// 增加溢出计数(用于时间间隔计算)
			g_timer_state.overflow_count++;
			
			// 超时检测:如果超过5ms没有边沿,回到空闲状态
			// 获取当前系统滴答数
			uint32_t current_tick = xTaskGetTickCountFromISR();
			
			// 检查是否超时(5ms)
			if ((current_tick - g_timer_state.last_edge_tick) > pdMS_TO_TICKS(5)) 
			{
				if (g_sm.state != RFID_STATE_IDLE) 
				{
					// 如果不是空闲状态,说明接收过程被打断,直接调用无效间隔回调函数
					// 这相当于触发了RFID_EVT_INVALID_INTERVAL事件
					#ifdef RFID_DEBUG
					printf("TIMEOUT: 5ms内无边沿,触发无效间隔事件\n");
					#endif
					
					// 直接调用on_check_sync_invalid  回调函数(参数为0,0,因为超时没有具体电平和间隔)
					// 这个函数会重置状态机
					on_check_sync_invalid (0, 0);
				}
				
				// 重置超时检测(无论是否在空闲状态都重置)
				g_timer_state.last_edge_tick = current_tick;
			}
		}

	}
/**
 * @brief  RFID状态机复位函数。
 */
	void rfid_state_machine_reset(void)
	{
		g_sm.state = RFID_STATE_IDLE;
		g_sm.last_capture = 0;
		g_sm.sync_count = 0;
		g_sm.data_bit_count = 0;
		g_sm.half_bit_count = 0;
		g_sm.current_level = 0;
		g_sm.last_level = 0;
		g_sm.timeout_timer = 0;
		g_sm.sync_complete_flag = 0;
		g_sm.data_complete_flag = 0;
		
		memset(g_sm.half_bits, 0, sizeof(g_sm.half_bits));
	}


#ifndef __TIME_CAPUTER_H__
#define __TIME_CAPUTER_H__
#include "n32wb03x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "FreeRtos_task.h"
#include <string.h>


// ==================== 宏定义 ====================
// 时间定义(假设定时器频率1MHz,1计数=1μs)
#define FULL_BIT_TIME     512     // 全位时间512μs
#define HALF_BIT_TIME     256     // 半位时间256μs
#define ERROR_MARGIN      40      // 误差范围±40μs
#define FULL_BIT_MIN      (FULL_BIT_TIME - ERROR_MARGIN)
#define FULL_BIT_MAX      (FULL_BIT_TIME + ERROR_MARGIN)
#define HALF_BIT_MIN      (HALF_BIT_TIME - ERROR_MARGIN)
#define HALF_BIT_MAX      (HALF_BIT_TIME + ERROR_MARGIN)
#define BIT_HAFE_TIME     768     // 1.5倍位时间,用于超时检测

// 引脚定义
#define DATA_PORT         GPIOB
#define DATA_PIN          GPIO_Pin_5
#define DATA_TIMER        TIM3
#define TIMEOUT_TIMER     TIM2

// 调试开关
// #define RFID_DEBUG

// ==================== 类型定义 ====================

// ==================== 状态枚举 ====================
typedef enum {
    RFID_STATE_IDLE = 0,           // 空闲:等待第一个上升沿
    RFID_STATE_WAIT_SECOND_EDGE,   // 等待第二个边沿
    RFID_STATE_CHECK_SYNC,         // 检查同步头
    RFID_STATE_RECEIVE_DATA,       // 接收数据
    RFID_STATE_COUNT               // 状态数量(用于状态转换表结束标记)
} rfid_state_t;

// ==================== 事件枚举 ====================
typedef enum {
    RFID_EVT_NONE = 0,           // 无事件
    RFID_EVT_RISING_EDGE,        // 上升沿
    RFID_EVT_INTERVAL_256US,     // 256μs间隔(合格)
    RFID_EVT_INTERVAL_512US,     // 512μs间隔(合格)
    RFID_EVT_INVALID_INTERVAL,   // 不合格间隔(统一事件)
    RFID_EVT_SYNC_OK,            // 同步头验证成功(内部事件)
    RFID_EVT_DATA_OK,            // 数据接收完成(内部事件)
    RFID_EVT_COUNT               // 事件数量
} rfid_event_t;

// ==================== 数据结构 ====================

// 状态转换回调函数类型
typedef void (*rfid_state_callback_t)(uint8_t, uint16_t);

// 状态转换表项
typedef struct {
    rfid_state_t current_state;     // 当前状态
    rfid_event_t event;             // 事件
    rfid_state_t next_state;        // 下一个状态
    rfid_state_callback_t callback; // 回调函数
} rfid_state_transition_t;

// 状态机上下文
typedef struct {
    rfid_state_t state;             // 当前状态
    uint16_t last_capture;          // 上次捕获值
    uint8_t sync_count;             // 同步头边沿计数
    uint8_t data_bit_count;         // 数据位计数
    uint8_t half_bit_count;         // 半位计数
    uint8_t half_bits[128];         // 原始电平缓冲区
    uint8_t current_level;          // 当前电平
    uint8_t last_level;             // 上次电平
    uint32_t timeout_timer;         // 超时计时器
    uint8_t sync_complete_flag;     // 同步完成标志
    uint8_t data_complete_flag;     // 数据完成标志
} rfid_sm_context_t;

// RFID数据包结构(用于队列传输)
typedef struct {
    uint8_t half_bits[128];         // 半位数据
    uint8_t half_bit_count;         // 半位数量
    uint8_t data_bit_count;         // 数据位数量
    uint32_t timestamp;             // 时间戳
} rfid_data_packet_t;

// ==================== 全局变量声明 ====================
extern QueueHandle_t xRFIDDataQueue;  // RFID数据队列(更新为正确名称)
extern uint8_t g_bitResevData;        // 数据接收标志
extern rfid_sm_context_t g_sm;        // 状态机上下文

// ==================== 函数声明 ====================

// 状态机初始化函数
void rfid_state_machine_init(void);

// 中断处理函数
void TIM3_IRQHandler(void);
void TIM2_IRQHandler(void);

// 状态机处理函数
void process_state_machine(rfid_event_t event, uint8_t current_level, uint16_t interval);

// 状态机重置函数
void rfid_state_machine_reset(void);

// ==================== 回调函数声明 ====================

// 空闲状态回调函数
void on_idle_rising_edge(uint8_t current_level, uint16_t interval);

// 等待第二个边沿状态回调函数
void on_wait_second_256us(uint8_t current_level, uint16_t interval);


// 检查同步头状态回调函数
void on_sync_check_256us(uint8_t current_level, uint16_t interval);
void on_sync_ok(uint8_t current_level, uint16_t interval);

// 接收数据状态回调函数
void on_data_512us(uint8_t current_level, uint16_t interval);
void on_data_256us(uint8_t current_level, uint16_t interval);

// 数据完成处理回调函数
void on_frame_complete(void);

void on_check_sync_invalid (uint8_t current_level, uint16_t interval);


void Time_Caputer_init(void);
void Time_Caputer_start(void);
void Time_Caputer_GPIO_Configuration(void);
void Time_Caputer_NVIC_Configuration(void);
#endif

 

posted @ 2025-12-11 21:56  小小卡拉  阅读(47)  评论(0)    收藏  举报