关于串口的读取是有固定套路的,所以这里单独拉出来讲一下,后面用到串口时候,直接复制粘贴就可以了。
本文从cubmax配置到代码的编写
点开串口8(其他串口一样)
点开asynchronous
点开中断,这个必须要点
点开dma,循环模式 数据长度炫byte(这些参数需要自己网上查,还有dma的作用这些基础的东西都要了解一下)
看要用多少波特率的串口,发送端接收端要一样不然接收不到
时钟点到最高,这里是168hz
1是项目名称
2路径不能有中文
3炫mdk右边那个电5
四个点上去
生成代码
main函数内2句话初始化一下
其中可以去查查UART_IT_IDLE空闲中断跟其他帧中断之间的区别,这里一半用空闲中断
XYZ_BUFFER是数组首地址
串口收到的消息会放到这个数组内
因为陀螺仪数据是11位所以这边11位11位地收数据
unsigned char XYZ_BUFFER[20];//陀螺仪
中断内的函数:
void UART8_IRQHandler(void)
{
/* USER CODE BEGIN UART8_IRQn 0 */
uint16_t temp;
uint8_t j=0,sum=0;
if(__HAL_UART_GET_FLAG(&huart8,UART_FLAG_IDLE)==SET)//标志位:如果检测到收到数据了就进入这个if
{
__HAL_UART_CLEAR_IDLEFLAG(&huart8);//清除标志位,方便下次收数据
HAL_UART_DMAStop(&huart8);// 1
temp=11-hdma_uart8_rx.Instance->NDTR;// 2
HAL_UART_Transmit_DMA(&huart8,XYZ_BUFFER,temp); //3
for(j=0;j<10;j++)
sum+=XYZ_BUFFER[j];
if(sum==XYZ_BUFFER[10]&&XYZ_BUFFER[1]==0x53)
{
Roll=(float)((XYZ_BUFFER[3]<<8)|XYZ_BUFFER[2])/32768*180;
// Pich=(float)((XYZ_BUFFER[5]<<8)|XYZ_BUFFER[4])/32768*180;
Yaw =(float)((XYZ_BUFFER[7]<<8)|XYZ_BUFFER[6])/32768*180;
}}
HAL_UART_Receive_DMA(&huart8,XYZ_BUFFER,11); //4
/* USER CODE END UART8_IRQn 0 */
HAL_UART_IRQHandler(&huart8);
/* USER CODE BEGIN UART8_IRQn 1 */
/* USER CODE END UART8_IRQn 1 */
}
代码中分为1234部
1:前面说了,单片机接收到串口的数据之后,会通过dma直接把数据送到cpu,这样操作大大提高了信息传输速度,但是有一个小问题,就是串口可能没发够11位数据,所以第一步要暂停dma接收,
2:因为我们要11byte数据,所以用11减去ndtr寄存器(这个寄存器记录当前代码收到几个数据)比如收到5个,temp就=11-5=6
3:凑齐11个byte数据,所以向CPU再发送temp个,比如前面只有5个,这里发送6个
至此,CPU内也就是XYZ_BUFFER这个数组内已经有11个数据了,但是,还没完,我们是随便抽取了一段连续的11字节数据,所以会遇到这种情况,就是这11位数据不是一段有效帧,而是无效帧(无效帧:比如传感器的数据为1 2 3 4 … 11 ,而我们接收到的数据却是:8 9 10 11 1 …7;也就是截取到前一半和后一半)为了判断这一帧数据是不是有效数据,在3和4之间做的就是判断,具体如何判断有效帧一般产品介绍书会说,陀螺仪这11帧数据有个数据校验帧
懒得找说明书,我直接贴了:从第一个数据到底10个数据累加会等于底11个数据校验帧
串口读取结束,我们拿到了需要的数据,并且将它存入结构体xyz
4:重新发送11帧