AGV项目底层总结二

接着《AGV项目底层总结一》这篇博客,就AGV项目底层的代码设计技巧来进行讲解。

串口数据接收处理

串口指令的接收所用中断的方式,同时在中断里进行数据帧的识别,接收完整一帧数据后标志位置1,在main函数中通过标志位的判断来进行接收到指令的相应处理。

//串口1中断服务程序
void USART1_IRQHandler(void)                	
{
	u8 Res;
	static u8 reci_step = 0;								//数据接收状态机
	static u8 length = 0,i = 0;								//指令长度计数指针
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	{
		Res = USART1->DR;								//(USART1->DR);	//读取接收到的数据
		switch(reci_step)
		{
			case 0:										//接收判断帧头0xcd
				if(Res == 0xcd){
					reci_step = 1;
					USART1_RX_STA = 1;					//开始接收数据帧状态
				}
				else reci_step = 0;
				break;
			case 1:										//接收判断帧头0xaa
				if(Res == 0xaa) reci_step = 2;
				else reci_step = 0;
				break;
			case 2:										//接收判断帧头0x55
				if(Res == 0x55) reci_step = 3;
				else reci_step = 0;
				break;
			case 3:										//接收指令长度
				length = Res;
				i = 0;
				USART1_RX_BUF[i++] = Res;
				reci_step = 4;
				break;
			case 4:										//接收完整数据
				USART1_RX_BUF[i++] = Res;
				if(i > length){
					reci_step = 0;
					USART1_RX_STA = 2;				   //数据帧接收完成状态
				}
				break;
			default:
				reci_step = 0;
				break;
		}
	}
}

数据总汇—结构体

在嵌入式的项目中,往往离不开许多数据的采集,本项目中数据采集后需要将数据通过串口进行传递,问题在于我们采集出来的数据大都是以变量的形式单独存。那么再批量发送之前,我们首先要做的就是将采集到的所有数据进行总汇。在项目中我们定义了一个结构体用来存放采集的所有数据,然后将此结构体的数据转移至数组中以便统一发送。话不多说,直接上代码。

//.h文件
#define SENSOR_DLEN 23

typedef struct {
    int status;       //小车状态
    float power;      //电源电压
    float theta;      //方位角
    int encoder_ppr;  //旋转一圈脉冲数
    int encoder_delta_r;//右轮编码器
    int encoder_delta_l;
    int encoder_delta_car;//两车轮中心位移
    float omga_r;       //右轮转速
    float omga_l;
    float distance1;  //第一个超声波距离值
    float distance2;
    float distance3;
    float distance4;
    float IMU[9];    //9轴数据
    unsigned int time_stamp;//时间戳
}UPLOAD_STATUS;

extern UPLOAD_STATUS SENSOR_DATA;
//.c文件
UPLOAD_STATUS SENSOR_DATA;
u8 SendBuff[119]; //发送缓存数组
void SEND_SENSOR_DATA(void)
{
	//调用DMA控制发送数据
	int i;
	static int j = 0;
	SendBuff[0] = 0xcd;
	SendBuff[1] = 0xeb;
	SendBuff[2] = 0xd7;
	SendBuff[3] = sizeof(SENSOR_DATA)/4*5;
  for(i = 0; i < SENSOR_DLEN; i++)
  {
		SendBuff[4+i*5] = *(((u8 *)(&SENSOR_DATA))+i*4+0); 
		SendBuff[5+i*5] = *(((u8 *)(&SENSOR_DATA))+i*4+1); 
		SendBuff[6+i*5] = *(((u8 *)(&SENSOR_DATA))+i*4+2); 
		SendBuff[7+i*5] = *(((u8 *)(&SENSOR_DATA))+i*4+3); 
		SendBuff[8+i*5] =  0x20;
  }
	USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送
	MYDMA_Enable(DMA1_Channel4,119);//搬运一次串口数据
	SENSOR_DATA.time_stamp++;//每发送一次时间戳加1
}

多字节数据的串口发送

总所周知,串口一次发送最多1个字节(8bit),当遇到多字节的数据需要通过其发送时,应该先对数据进行字节提取,然后按字节将数据进行串口发送。那么如何进行字节提取呢?现在介绍两种多字节数据的字节提取方式,直接上代码。

uint32_t rd_state;  
abh_receive[3] = *(((uint8_t *)(&rd_state))+3);  //可适用于浮点型
abh_receive[4] = *(((uint8_t *)(&rd_state))+2); 
abh_receive[5] = *(((uint8_t *)(&rd_state))+1); 
abh_receive[6] = *(((uint8_t *)(&rd_state))+0); 
	
abh_receive[7] =  last_pulse1 >>24; 			 //只适用于整形
abh_receive[8] =  last_pulse1 >>16; 
abh_receive[9] =  last_pulse1 >>8 ; 
abh_receive[10] = last_pulse1  	  ;  

你可能感兴趣的:(STM32)