记一次单片机曼彻斯特解码调试

博客参考:https://blog.csdn.net/Stack_/article/details/116952678

发送数据时序
在这里插入图片描述
相比ID卡,解码思路差不多,但这个时序是要简单一些的,特点是有起始头码,数据一共3个字节(24位),发码间隔时间150ms,没有校验码

解码思路:
1.设置外部中断边沿触发
2.设置定时器计数,进入外部中断后关闭定时器计数,然后读取定时器计数值TH0和TL0的值,再开启定时器计数,根据定时器计数值判断4T,T,2T的值的范围
3.设置头码检验,也就是定时器计数值在4T范围内
4.设置数据检验,并且记录这一次的值。由于头码是一段低电平,那么标记头码低电平状态,头码之后的第一次是上升沿中断,并且读取到定时器计数值是T范围的值,记录这一次的状态,不记录这一次的数据。下一次下降沿中断再次读取到定时器计数值是T范围的值,那么记录下这次读取到的值为0,并且记录为低电平状态
5.如果上一次为低电平状态,并且在下降沿读到2T,那么说明数据跳变为1了,记录为高电平状态,如果在上升沿读到T,说明数据还是0,记录为低电平状态;如果上一次为高电平状态,并且在下降沿读到T,说明数据是1,记录为高电平状态,如果上升沿读到2T,那么数据是0,记录为低电平状态。

//外部中断0处理函数
{  
	static U8	XDATA dataenflag=0;
	static U8	XDATA LastState=0;
	static U16	XDATA WaveNow=0;
	static U8	XDATA DataStateFlag=0;
	static U8	XDATA RfState=0;
	static U8 XDATA Invcnt=0;
	U8 XDATA i=0;	
	T0En(OFF);
	
	// 判断上升沿还是下降沿
	Invcnt = R_FLAG & 0x07;
	if(Invcnt & 0x04)
	{
		DataStateFlag=DATA_STATE_H;//上升沿
	}
	else
	{
		DataStateFlag=DATA_STATE_L;//下降沿
	}
	
	WaveNow=0; 
	WaveNow=((U16)TH0)&0x00ff; 
	WaveNow=(WaveNow<<8)&0xff00; 
	WaveNow+=(((U16)TL0)&0x00ff); 
	TH0=TL0=0;
	T0En(ON);
/*接收足够的数据判断T,2T,4T的值的范围*/
	#if 0
	g_u8Tesetbuf[g_u8Tesetcnt]=WaveNow;
	if(++g_u8Tesetcnt>=59)
	{
		g_u8Teseflag=1;
	}
	else
	{
		T0En(ON);
	}
	#endif

	#if 1
	switch(RfState)
	{
		case 0:  //找头
			if(DataStateFlag==DATA_STATE_H)
			{
				if((WaveNow>RF_STAR_MIX)&&(WaveNow<RF_STAR_MAX))
				{
					RfState=1;
					g_u8Tesetcnt=0;
					Invcnt=0;
					LastState=DATA_TYPE_L;
				}	
			}
			break;			
		#if 1
		case 1:
			//g_u8Teseflag=1;
			if(LastState==DATA_TYPE_L)
			{
				if(DataStateFlag==DATA_STATE_L)
				{
					if((WaveNow>RF_DATA_B_MIX)&&(WaveNow<RF_DATA_B_MAX))
					{
						g_u8Tesetbuf[g_u8Tesetcnt]=0x01;
						dataenflag=1;
						LastState=DATA_TYPE_H;
					}
					//else if((WaveNow<RF_DATA_A_MIX)||(WaveNow>RF_DATA_B_MAX))
					else if(WaveNow>RF_DATA_B_MAX)
					{
						dataenflag=2;		//  异常值
					}
					else{dataenflag=0;}
				}
				else if(DataStateFlag==DATA_STATE_H)
				{
					//if((WaveNow>RF_DATA_A_MIX)&&(WaveNow<RF_DATA_A_MAX))
					if((WaveNow<RF_DATA_A_MAX))
					{
						g_u8Tesetbuf[g_u8Tesetcnt]=0x00;
						dataenflag=1;
						LastState=DATA_TYPE_L;
					}
					else if((WaveNow>RF_DATA_B_MAX))
					{
						dataenflag=2;		//  异常值
					}
					else{dataenflag=0;}
				}
				
			}
			
			else if(LastState==DATA_TYPE_H)
			{
				if(DataStateFlag==DATA_STATE_L)
				{
					//if((WaveNow>RF_DATA_A_MIX)&&(WaveNow<RF_DATA_A_MAX))
					if((WaveNow<RF_DATA_A_MAX))
					{
						g_u8Tesetbuf[g_u8Tesetcnt]=0x01;
						dataenflag=1;
						LastState=DATA_TYPE_H;
					}
					else if((WaveNow>RF_DATA_B_MAX))
					{
						dataenflag=2;		//  异常值
					}					
					else{dataenflag=0;}
				}
				else if(DataStateFlag==DATA_STATE_H)
				{
					if((WaveNow>RF_DATA_B_MIX)&&(WaveNow<RF_DATA_B_MAX))
					{
						g_u8Tesetbuf[g_u8Tesetcnt]=0x00;
						dataenflag=1;
						LastState=DATA_TYPE_L;
					}
					else if((WaveNow>RF_DATA_B_MAX))
					{
						dataenflag=2;		//  异常值
					}					
					else{dataenflag=0;}
				}
			}
			/**/
			if(dataenflag==1)
			{
				dataenflag=0;
				if(g_u8Tesetcnt<23)
				{
					g_u8Tesetcnt++;
				}
				else
				{
					for(i=0;i<24;i++)
					{
						g_u8Tesetbuf2[i]=g_u8Tesetbuf[i];
					}
					g_u8Teseflag=1;
					RfState=0;

				}
			}
			else if(dataenflag==2)
			{
				g_u8DATAflag=WaveNow;//看看出错情况
				RfState=0;
				g_u8Tesetcnt=0;
			}
			break;
		#endif
		default:break;
	}
	#endif			    
	
	IE0 = 0;	// 清除中断标志
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
曼切斯特码是一种常用的数字信号编码方式,通常用于串行通信中。在曼切斯特编码中,每个比特时间被分为两个等长的时间段,每个比特发送两个信号,一个是高电平表示1,一个是低电平表示0。因此,在曼切斯特编码中,数据传输速率是原始数据速率的两倍。 曼切斯特编码的优点是可以在传输过程中自动进行时钟同步,同时也可以检测传输错误。但是,曼切斯特编码的缺点是需要传输的数据量增加一倍,传输效率降低。 在STM32单片机中,可以使用外部中断方式来接收曼切斯特编码的数据。具体的解码程序可以根据实际的应用场景和曼切斯特编码的格式进行编写。以下是一个简单的曼切斯特码波形解码程序,供参考: ```c #include "stm32f10x.h" #define MANCHESTER_BUFFER_SIZE 8 volatile uint8_t manchester_buffer[MANCHESTER_BUFFER_SIZE]; volatile uint8_t manchester_index = 0; void EXTI0_IRQHandler(void) { if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET) // Start bit { manchester_index = 0; } else // Data bit { if (manchester_index < MANCHESTER_BUFFER_SIZE) { manchester_buffer[manchester_index] = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_SET ? 1 : 0; manchester_index++; } } EXTI_ClearITPendingBit(EXTI_Line0); } int main(void) { // Initialize GPIOA and EXTI0 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitTypeDef gpio_init; gpio_init.GPIO_Pin = GPIO_Pin_0; gpio_init.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &gpio_init); EXTI_InitTypeDef exti_init; exti_init.EXTI_Line = EXTI_Line0; exti_init.EXTI_Mode = EXTI_Mode_Interrupt; exti_init.EXTI_Trigger = EXTI_Trigger_Rising_Falling; exti_init.EXTI_LineCmd = ENABLE; EXTI_Init(&exti_init); NVIC_EnableIRQ(EXTI0_IRQn); while (1) { // Wait for data reception complete if (manchester_index == MANCHESTER_BUFFER_SIZE) { // Decode Manchester code uint8_t data = 0; uint8_t i; for (i = 0; i < MANCHESTER_BUFFER_SIZE; i += 2) { if (manchester_buffer[i] == 0 && manchester_buffer[i + 1] == 1) { data = (data << 1) | 0; } else if (manchester_buffer[i] == 1 && manchester_buffer[i + 1] == 0) { data = (data << 1) | 1; } else // Invalid code { break; } } // Do something with the decoded data // ... // Reset buffer and index memset(manchester_buffer, 0, sizeof(manchester_buffer)); manchester_index = 0; } } } ``` 在这个程序中,PA0被配置为输入上拉,并使用外部中断0来检测信号变化。当检测到起始位时,重置缓冲区和索引。当检测到数据位时,将数据存储在缓冲区中,并增加索引。当缓冲区被填满时,对曼切斯特编码进行解码,并执行一些操作。最后,重置缓冲区和索引,等待下一次数据传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值