串口通讯(DMA模式)

在高级语言中,I/O 流输入(input)操作一般都要求指定要读取的数据的最大长度(字节数)。当接收到至少1字节、最多所指定的字节数时,函数返回。

STM32 串口接收数据时,HAL API 要求指定数据长度。但无论轮询、中断或是DMA方式,都必须完整地接收到这么多字节,程序流程才继续。如何接收变长消息,我想不到特别好的实现方式。一种方式是,轮询加超时。另一种方式是,设计消息协议,使消息头为定长,且消息头内包含消息体的长度。但是,如果通讯异常,导致消息数据错误或丢失,那么,还是缺少“提前返回”的机制。

相对来说,轮询加超时的方式似乎更好些。效率低,但是是可靠的。我也不确定。

DMA是STM32内的一个硬件模块,它独立于CPU在外围设备和内存之间进行数据传输,解放了CPU。每个型号的STM32 MCU有1-2个DMA,每个DMA有一定数量的Channel。每个Channel两端分别绑定到外围设备和内存。每个Channel可与哪种外围设备绑定,这是STM32设计时固定下来的,要查询参考手册得知。

Nucleo-F303RE 的 USART2 支持DMA。使用 DMA模式发送数据,要启用 DMA Channel的中断和USART2的中断。数据发送完成时,HAL会触发USART2 的中断进而调用中断回调函数。概况起来:

  • 调用 HAL_UART_Transmit_DMA() 函数发送数据
  • 实现 HAL_UART_TxCpltCallback() 回调函数。当数据发送完成后,此函数被HAL调用

下面的例程使用 DMA 方式依次从串口发送3条消息。App_loop() 在main() 函数的主循环中被调用。当串口数据发送完成时,txDone 标志被置1,此时将闪烁 LED(blink()),并发送下一条消息:

static void blink();

static const char * msgArr[] = { "We still can find a way\n", //
        "Because nothing lasts for ever\n", //
        "Event the cold November rain\n" };

static int msgIndex = 0;
volatile uint8_t txDone = 1;

void App_loop() {

    if (txDone) {
        blink();
        txDone = 0;

        const char * msg = msgArr[msgIndex];
        HAL_UART_Transmit_DMA(&huart2, (uint8_t *) msg, strlen(msg));

        msgIndex = (1 + msgIndex) % 3;
    }
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
    txDone = 1;
}

从Cube HAL的角度来说,就这么多。

原文地址:https://www.cnblogs.com/vinccc/p/8296103.html

时间: 2024-10-29 09:51:54

串口通讯(DMA模式)的相关文章

Cypress EZ-USB FX3 DMA模式下的串口通讯

由于公司设备升级后出了问题,需要对USB驱动进行修改,原本使用的是寄存器模式进行UART传输,但是由于FX3寄存器模式会出现长时间延时等待的问题,不得不对其传输模式进行修改.虽然赛普拉斯的EZ-USB FX3系列芯片功能强大,成本适中,但共享资源太少,API参考手册里面的干货不多,直接导致开发困难,出现问题只能去官方社区寻找答案.新模式的开发也不是一帆风顺,找来找去,只有在固件库中找到了UartLpDmaMode这个例程还比较相似.于是便在其基础上进行修改. 在UartLpDmaMode例程中,

串口通讯

STM32串口通讯有3种形式:轮询(阻塞式).中断.DMA.我不知道中断方式的串口通讯有什么适合的应用场景:每接收/发送一个字节,就要发生一次中断,这对CPU反而是一种浪费.使用Cube HAL,轮询式的串口通讯最简单了,发送和接收数据分别有一个函数: HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); HAL_Status

(三) UART 串口通讯

UART  : university asynchronous receiver and transmitter UART  // 通用异步接收器和发送器 为什么要有串口:因为许多嵌入式设备没有显示屏,无法获得设备的实事数据信息,所以可以通过 UART 串口和超级终端相连,打印嵌入式设备输出信息.也可以通过串口跟踪和调试. 比如设备: 网络路由器.交换机通过串口配置, GPS接收器通过串口输出GPS接收的数据. 1.异步通信技术:发送和接收方没有同步时钟,只有数据线,但是协商好了协议,(固定频率

多机串口通讯

★使用器件 使用了3块80c51的单片机,其中U1为主机控制其他两个从机U2,U3.每个单片机上都有一个数码管用来显示数据.主机上有两个按键KEY_1,KEY_2,分别用来控制不同的从机. ★实现目标 主要实现的目标就是通过写多机通讯来了解他们其中的协议,以及简单协议的写法!本程序主要达到了一下效果,主机可以通过发送命令来控制从机:发送数据给从机.接收从机的数据.然后将从机或者主机显示的数据显示在数码管上. ★协议要求 1.地址:主机的地址设置为0x01,从机1(U3)的地址为0x03,从机2(

STM32的串口采用DMA方式接收数据测试(转)

STM32的串口采用DMA方式接收数据测试 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.   参考链接:http://www.amobbs.com/forum.PHP?mod=viewthread&tid=5511863&highlight=dma%E6%8E%A5%E6%94%B6   环境: 主机:WINXP 开发环境:MDK4.23 MCU:STM32F103CBT6 说明: 串口可以配置成用DMA的方式接收数据,不过DMA需要定长才

串口通讯方式1编程

在上位机上用串口调试助手发送一个字符X,单片机收到字符后返回给上位机"I get X",串口波特率设为9600bps. #include<reg52.h> #define uchar unsigned char unsigned char flag,a,i; uchar code table[]="I get"; void init() { TMOD=0x20;  //设定T1定时器的工作模式2 TH1=0xfd; //T1定时器装初值 TL1=0xfd

【转载】使用Win32API实现Windows下异步串口通讯

一,异步非阻塞串口通讯的优点 读写串行口时,既可以同步执行,也可以重叠(异步)执行.在同步执行时,函数直到操作完成后才返回.这意味着在同步执行时线程会被阻塞,从而导致效率下降.在重叠执行时,即使操作还未完成,调用的函数也会立即返回.费时的I/O操作在后台进行,这样线程就可以干别的事情.例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作."重叠"一词的含义就在于此. 二,异步非阻塞串口通讯的基本原理首先,确定要打开的串口名.波特率.奇偶校验方式.数据位.

13.串口通讯的高级方式

1.FIFO模式及其作用(1)典型的串口设计,发送/接收缓冲区只有1字节,每次发送/接收只能处理1帧数据.这样在单片机中没什么问题,但是到复杂SoC中(一般有操作系统的)就会有问题,会导致效率低下,因为CPU需要不断切换上下文.(2)解决方案就是想办法扩展串口控制器的发送/接收缓冲区,譬如将发送/接收缓冲器设置为64字节,CPU一次过来直接给发送缓冲区64字节的待发送数据,然后transmitter慢慢发,发完再找CPU再要64字节.但是串口控制器本来的发送/接收缓冲区是固定的1字节长度的,所以

串口通信DMA中断

这是以前学32的时候写的,那时候学了32之后感觉32真是太强大了,比51强的没影.关于dma网上有许多的资料,亲们搜搜,这里只贴代码了,其实我也想详详细细地叙述一番,但是自己本身打字就慢,还有好多事情要做!代码是我亲自都在板子上测试过的,,当然粘贴/复制过去可能也不会尽如人意,知识这东西总是有许多道不清说不明的东西在里头,往往总是不经一番彻骨寒,哪得梅花扑鼻香.推荐一本书吧!这是野火出的.(是为了凑够150个字,否则不让提交) 这本书自从在图书馆借来就从来没有再放回去,总是在续借.像是在打广告了