国内网站制作特点,jsp网站空间网站开发,网页设计对板式的要求,高端网站建设公司价格目录 前言
初识串口-轮询模式
串口中断模式收发
串口DMA模式
蓝牙模块与数据包解析 前言
前面我们简单介绍过串口的原理和初步的使用方式#xff0c;例如怎么配置和简单的收发#xff0c;同时我们对串口有了一个初步的了解#xff0c;这里我们来深入的来使用一下串口
…目录 前言
初识串口-轮询模式
串口中断模式收发
串口DMA模式
蓝牙模块与数据包解析 前言
前面我们简单介绍过串口的原理和初步的使用方式例如怎么配置和简单的收发同时我们对串口有了一个初步的了解这里我们来深入的来使用一下串口
初识串口-轮询模式
这里我们不介绍如何使用STM32CubeMX配置串口我们默认使用USART1同时波特率为115200首先让我们来使用串口发送一些数据 这里我们定义了一个数组数组的内容为Hello Wrold在主循环中我们调用了一个函数
HAL_UART_Transmit(huart,pData,Size,Timeout)
huart 第一个参数为要操作串口的指针这里要填写 huart1 如果设置2那就换成 huart2
pData 第二个参数填的是需要发送信息的指针 uint8_t *message
Size 第三个参数填的是数据字符串的长度 我们可以使用关键字 strlen(message) 识别长度
Timeout 第四个为发送数据的时间超过这个时间就停止发送 单位 毫秒
完整的代码例子 HAL_UART_Transmit(huart1 , (uint8_t *)message , strlen(message) , 50 ) 发送的解决了之后我们来使用轮询模式接收一些数据
让我们讲发送的代码注释掉同时再定义一个接收用的数组这里我们直接使用uint8_t来定义他和char是相同的作用串口接收的参收与串口发送的参数一模一样
第一个参数也使用哪个串口来接收数据也是需要填地址第二个参数是用来接收数据的指针也就是receiveData的首地址第三个还是一样最后一个参数我们设置为 HAL_MAX_DELAY 为最大时间就一直等待没有超时时间如果使用uint8_t定义数组第二个参数就不需要强制类型转换了
HAL_UART_Receive(huart1 , receiveData , strlen(receiveData) , HAL_MAX_DELAY )
编写一个使用串口控制红绿蓝三个灯的颜色
上电默认电平为高如果串口第二位接收到0了则将电平拉低同时串口根据第一位接收的数据来控制红绿蓝灯的亮灭 轮询模式不够灵活同时会阻塞程序或者程序会阻塞串口收发而且只能确定串口数据长度我们接下来会学习中断模式串口收发数据
串口中断模式收发 中断的发送函数与普通轮询模式的发送函数差别不大只在后面加上了IT同时没有超时时间
HAL_UART_Transmit_IT(huart1 , receiveData , strlen(receiveData) )
接收的函数也大致相同
HAL_UART_Receive_IT(huart1 , receiveData , 2)
不过需要注意由于不会堵塞数据也就是还没等到接收到数据就会接着向下执行下去这就会造成执行到下次循环时可能上次的数据还没有接收完就又开始执行串口中断接收了所以我们需要放在循环前只执行一次注意接收一次之后需要重新开启接收中断
而当我们需要再次接收时我们可以在串口中断回调函数中再次开启接收中断就可以了 我们将while中的逻辑代码复制粘贴到串口接收中断回调函数中这样可以帮助节约cpu资源使用中断非常简单在cubemx中勾选开启中断同时在函数后面加上_IT后缀以及将处理逻辑移入到串口中断函数中即可我们成功的解决了串口堵塞程序的问题那如何接收不确定长度的数据呢能否进一步减少CPU的占用呢
串口DMA模式
虽然中断方式相较于轮询模式已经节约了很多cpu资源但对于cpu本身来说却是屡屡被打断疲于在中断搬运数据与处理正常任务代码间辗转反侧那我们能否进一步提升效率给cpu找一个帮助搬运数据的小助手这时候DMA的用处就显现出来了DMA全称叫直接内存访问
打开cubemx找到USART1设置界面找到DMA Settings点击下面的Add就可以添加DMA通道 在这里设置的DMA发送通道DMA通道7为专门为USART2发送设置的数据搬运方向由内存向外设搬运也就是从内存变量向发送数据寄存器进行搬运优先级默认为低可以自己选择其他参数CubeMX已经帮我们配置好了默认即可之后我们再添加一个USART2_RX的通道就行了 DMA模式的发送函数也就是把中断的_IT切换成了DMA参数依旧是用哪个串口发送要发送的变量以及发送的字节数接收函数也是一样
需要注意的是即使使用了DMA其实还是有中断参与其中的例如中断接收回调函数RxCpltCallback还是由中断触发当然这次就不是串口的中断了而是DMA传输中断说完了DMA的用法我们来看看如何接收不定长数据
其实接收不定长数据非常简单主要靠的是串口空闲中断此中断的触发条件与接收的字节数无关只有当RX引脚上无后续数据进入也就是串口接受从忙率转变为空闲时才会触发这里我们就可以认为当串口空闲中断时一帧数据包就发送完成了
这里我们需要将串口接收函数替换为HAL封装的一个拓展函数
HAL_UARTEx_ReceiveToIdle_DMA(huart2 , receiveData , 50)
我们可以注意这个函数也有阻塞DMA和中断三个版本我们这里选择DMA模式由于是接收不定长数据这里我们可以将receiveData这个数组改大一点改成50而这函数的最后一个参数是填写一次能接收的最大数据长度一般就是填写接收数组的长度来避免接收数据太长而导致数组越界
此时我们要用的中断函数也变了
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart , uint16_t size)
这个回调函数和中断回调函数的区别就是他的参数中多了一个 size 长度因为之前中断回调函数是接收定长数据我们已知了数据长度我们需要size入参来得知本次到底接收了几字节的数据 我们在下面这个回调函数中先判断一下是不是USART2接收了我们将接收到的函数重新发送回串口助手中要注意这里发送函数的第三个参数要改成回调函数参数中的size来发送与接收相同的字节数最后别忘记再次开启接收中断
可以发现我们再次发送R1发现数据返回来了但是灯没有点亮也就能证明使用ReceiveToldle函数后不再调用RxCpltCallback回调函数而是使用了RxEventCallback回调函数我们再尝试将数据增长发现数据正常返回这就说明我们完美的实现了不定长数据接收
我们需要注意在这个函数中需要重新开启接收中断但是我们使用普通模式或者中断模式的Toldle函数也是可以的唯独DMA模式有个恼人之处DMA的传输过半中断也会触发这个回调函数就是说如果接收的数据量达到我们设置的最大值的一半的时候也会触发一次回调函数使用一个很大的接收数组虽然能解决问题但也是治标不治本此方案的正确解决办法则是关闭DMA传输过半中断
__HAL_DMA_DISABLE_IT(hdma_usart2_rx , DMA_IT_HT)
第一个参数我们填写DMA通道的指针地址第二个参数我们填写需要关闭的中断
注意别忘记在初始化中加上这一句否则第一次接收依旧会出现问题