STM32自动小车通信数据处理

通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。 USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。使用多缓冲器配置的DMA方式,可以实现高速数据通信。

USART框图
USART框图

USART配置程序



/* USART1
init function */

static void
MX_USART1_UART_Init(void)

{

 

  huart1.Instance = USART1;

  huart1.Init.BaudRate = 115200;

  huart1.Init.WordLength = UART_WORDLENGTH_8B;

  huart1.Init.StopBits = UART_STOPBITS_1;

  huart1.Init.Parity = UART_PARITY_NONE;

  huart1.Init.Mode = UART_MODE_TX_RX;

  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;

  huart1.Init.OverSampling =
UART_OVERSAMPLING_16;

  if (HAL_UART_Init(&huart1) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

}

 

中断回调程序和通信处理程序:

//串口接收函数

void (*
g_usartRxFunc)(uint8_t data,USART_TypeDef* USARTx);

 

//串口接收函数配置

void
USART_RxFuncConfig(void (* func)(uint8_t data,USART_TypeDef* USARTx))

{

              g_usartRxFunc = func;

}

void
USART1_IRQHandler(void)        

{

       uint8_t bt;

       if(USART1->SR&(1<<5))

       {     


              bt = (USART1->DR&(uint8_t)0x00FF);

              g_usartRxFunc(bt,USART1);

       }

}

 

#define
UART_COM_STAT      '<'                        //串口通信开始字节

#define
UART_COM_END                  '>'                        //串口通信结束字节

 

 

UartBufTypedef
g_ComData[3];                        //串口接收缓冲区

 

/* Receive
-------------------------------------------------------------------*/

 

//串口字节流写入到缓冲区

void
USART_RxToBuf(uint8_t data,USART_TypeDef* USARTx)

{

       uint8_t cur = 0;

       

       //读取通信端口选择缓冲区

       if(USARTx == USART1)

       {

              cur = 0;

       }

       else if(USARTx == USART2)

       {

              cur = 1;

       }

       else if(USARTx == USART3)

       {

              cur = 2;

       }

       //将数据写入

       

       //上一次消息处理结束

       if(g_ComData[cur].Over == 0)

       {

              //开始

              if(data == UART_COM_STAT )

              {

                     //长度清零

                     g_ComData[cur].Len = 0;

              }

              //结束

              else if(data == UART_COM_END)

              {

                     //接收结束

                     g_ComData[cur].Over = 1;

              }

              //数据

              else

              {

                     //写入数据

                     g_ComData[cur].Buf[g_ComData[cur].Len]
= data;

                     //移动光标

                     g_ComData[cur].Len =
(g_ComData[cur].Len + 1) % 100;

              }

       }

}

 

/* Handle
--------------------------------------------------------------------*/

 

//设定电机速度

void
setMotoSpeed(uint8_t * cmd)

{

       //测试暂定协议 <MSXXXSXXX> S速度符号 XXX速度值 毫米每秒

       

       int16_t speed[2] = {0,0};

       

       //左侧速度

       speed[0] = (cmd[2] - 0x30) * 100

                                          +(cmd[3]
- 0x30) * 10

                                          +(cmd[4]
- 0x30);

       

       speed[0] = (cmd[1] == 'A') ? speed[0] :
-speed[0];

       

       //右侧速度

       speed[1] = (cmd[6] - 0x30) * 100

                                          +(cmd[7]
- 0x30) * 10

                                          +(cmd[8]
- 0x30);

       

       speed[1] = (cmd[5] == 'A') ? speed[1] :
-speed[1];

       

       //设置速度

       SetTargetSpeed(speed[0],speed[0],speed[1],speed[1]);

       

}

 

//ROS速度指令解析与速度发布

void
ROS_SpeedDataSubscribe(uint8_t * cmd)

{

       //通信协议

       //<RSXXXSRRRR> R 标识 S符号+- XXX线速度 mm/s RRR角速度 rad/s * 100

       

       //速度的分解与合成详见图解

       

       //线速度

       float vx =  (cmd[2] - 0x30) * 100

            
     +(cmd[3] - 0x30) * 10

                 
+(cmd[4] - 0x30);

       

       vx = (cmd[1] == 'A') ? vx : -vx;

       

       //角速度

       float w = 
(cmd[6] - 0x30) 

                 
+(cmd[7] - 0x30) * 0.1

                                           +(cmd[8] - 0x30) * 0.01

                                           +(cmd[9] - 0x30) * 0.001;

       

       w = (cmd[5] == 'A') ? w : -w;

       

       //差分底盘合速度各个速度点的的速度分解

       float va = (w * 187.833)/0.891749586;

       

       int16_t speed[4];

       

       speed[0] = vx + va;

       speed[1] = vx + va;

       speed[2] = vx - va;

       speed[3] = vx - va;

       

       SetTargetSpeed(speed[1],speed[0],speed[3],speed[2]);

 

}

 

//发送电量信息

void
sendBatteryVoltage(uint8_t * cmd)

{

       uint8_t str[50];

       

       float ctv = (cmd[1] - 0x30) * 10           + 

                                                 (cmd[2]
- 0x30)                      +

                                                 (cmd[3]
- 0x30) * 0.1      +

                                                 (cmd[4]
- 0x30) * 0.01     ;

       

       float mtv = (cmd[5] - 0x30) * 10          + 

                                                 (cmd[6]
- 0x30)                      +

                                                 (cmd[7]
- 0x30) * 0.1      +

                                                 (cmd[8]
- 0x30) * 0.01     ;

       

       sprintf((char*)str,"<V%c%c%c%c%c%c%c%c>",

              cmd[1],cmd[2],cmd[3],cmd[4],cmd[5],cmd[6],cmd[7],cmd[8]);

       

       USART_SendString(USART3,str);

}

 

//发送检测请求

void
sendBatteryVoltageMeasure(uint8_t * cmd)

{

       USART_SendString(USART2,(uint8_t
*)"<V>");

}

 

/* Analysis
------------------------------------------------------------------*/

 

//ROS数据接收处理

void
ROS_RxBufAnalysis(UartBufTypedef * buf)

{

       //完整性被使能

       if(buf->Over == 1)

       {     

              //通信协议

              //开始 ‘<’ 结束 '>'

              //[0] 标识 [n] 数据

              switch(buf->Buf[0])

              {

                     case 'M'://移动速度控制 

                     {

                            setMotoSpeed(buf->Buf);

                            break;

                     }

                     case 'R'://线速度角速度控制模式

                     {

                            ROS_SpeedDataSubscribe(buf->Buf);

                            break;

                     }

                     case 'V'://发起电量检测请求

                     {

                            sendBatteryVoltageMeasure(buf->Buf);

                            break;

                     }

              }

              //清除未完成标志位

              buf->Over = 0;

       }

}

 

//控制器数据接收处理

void
Ctrller_RxBufAnalysis(UartBufTypedef * buf)

{

       //完整性被使能

       if(buf->Over == 1)

       {     

              //通信协议

              //开始 ‘<’ 结束 '>'

              //[0] 标识 [n] 数据

              switch(buf->Buf[0])

              {

                     case 'V'://电池组数据

                     {

                            sendBatteryVoltage(buf->Buf);

                            break;

                     }

              }

              //清除未完成标志位

              buf->Over = 0;

       }

}

 

/*Setup and
Loop function ----------------------------------------------------*/

 

//通信处理初始化

void
comHandleSetup(void)

{

       //配置串口接收函数

       USART_RxFuncConfig(USART_RxToBuf);

}

 

//通信处理循环

void
comHandleLoop(void)

{

       //接收缓冲区数据解析

       ROS_RxBufAnalysis(&g_ComData[2]);

       ROS_RxBufAnalysis(&g_ComData[0]);

       Ctrller_RxBufAnalysis(&g_ComData[1]);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值