LL库通过串口+DMA方式发送数据

在RM0038(L151的手册)中的Chapter 27.3.13 Continuous communication using DMA章节有配置的方式和顺序:


Transmission using DMA:

DMA mode can be enabled for transmission by setting DMAT bit in the USART_CR3 register.

这个是使用了API:LL_USART_EnableDMAReq_TX来实现的。


按照该手册描述配置顺序为:

1.Write the USART_DR register address in the DMA control register to configure it as the destination of the transfer. The data will be moved to this address from memory after each TXE event.
2. Write the memory address in the DMA control register to configure it as the source of the transfer. The data will be loaded into the USART_DR register from this memory area after each TXE event.
3. Configure the total number of bytes to be transferred to the DMA control register.
4. Configure the channel priority in the DMA register
5. Configure DMA interrupt generation after half/ full transfer as required by the application.
6. Clear the TC bit in the SR register by writing 0 to it.
7. Activate the channel in the DMA register.


按照描述,我们初始化DMA和USART1(使用Stm32CubeMX默认生成的工程,屏蔽了DMA的中断)后:

1. 配置外设和memory的地址(LL_DMA_SetPeriphAddress和LL_DMA_SetMemoryAddress)

2.设置DMA传输数量LL_DMA_SetDataLength

3. 清除TC标志(LL_USART_ClearFlag_TC ) 该步骤很重要,如果没有清除,一旦使能TC中断,就会执行中断操作

4. 使能TCIE中断(LL_USART_EnableIT_TC)

5. 使能DMA(LL_DMA_EnableChannel)

6. 发送DMA传输请求(LL_USART_EnableDMAReq_TX)


USART1_IRQHandler中断里面:

1.检测TC标志(LL_USART_IsActiveFlag_TC)

2. 关闭TC中断(LL_USART_DisableIT_TC) 防止反复进入TC中断

3. 关闭DMA通道(LL_DMA_DisableChannel)


总结:一定要先清除标志位,然后再使能该标志位的中断


另外,发送完成中断,应该使用Uart的TC标志,而不应该是DMA的发送完成标志TCIF。

前者,表示数据全部传输到了uart的输出线上(所有的Data+1个空闲byte时间)

后者,仅仅表示数据全部传给了Uart的DR。DR到外设线上是有一段缓存区的。






  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是一个使用LL实现DMA串口发送的例程,可供参考: ```c #include "stm32f4xx_ll_bus.h" #include "stm32f4xx_ll_dma.h" #include "stm32f4xx_ll_gpio.h" #include "stm32f4xx_ll_usart.h" #define USART_TX_PORT GPIOA #define USART_TX_PIN LL_GPIO_PIN_9 #define USART_TX_AF LL_GPIO_AF_7 #define BUFFER_SIZE 64 // 定义DMA传输完成标志 volatile uint8_t dma_tx_complete = 0; uint8_t tx_buffer[BUFFER_SIZE] = "Hello, World!\r\n"; void USART_DMA_Init(void) { // 使能USART1、DMA2、GPIOA时钟 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); // 配置USART1引脚 LL_GPIO_SetPinMode(USART_TX_PORT, USART_TX_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_8_15(USART_TX_PORT, USART_TX_PIN, USART_TX_AF); LL_GPIO_SetPinSpeed(USART_TX_PORT, USART_TX_PIN, LL_GPIO_SPEED_FREQ_VERY_HIGH); LL_GPIO_SetPinOutputType(USART_TX_PORT, USART_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL); // 配置USART1 LL_USART_InitTypeDef usart_init_struct; LL_USART_StructInit(&usart_init_struct); usart_init_struct.BaudRate = 115200; LL_USART_Init(USART1, &usart_init_struct); // 配置USART1 DMA发送模式 LL_USART_EnableDMAReq_TX(USART1); LL_DMA_SetChannelSelection(DMA2, LL_DMA_STREAM_7, LL_DMA_CHANNEL_4); LL_DMA_ConfigTransfer(DMA2, LL_DMA_STREAM_7, LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE | LL_DMA_PRIORITY_MEDIUM | LL_DMA_MEMORY_SINGLE); LL_DMA_ConfigAddresses(DMA2, LL_DMA_STREAM_7, (uint32_t)tx_buffer, (uint32_t)&USART1->DR, LL_DMA_GetDataTransferDirection(DMA2, LL_DMA_STREAM_7)); LL_DMA_SetDataLength(DMA2, LL_DMA_STREAM_7, BUFFER_SIZE); // 使能DMA传输完成中断 LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_7); // 使能USART1 DMA发送和USART1 LL_USART_EnableDMAReq_TX(USART1); LL_USART_Enable(USART1); } int main(void) { USART_DMA_Init(); // 开始DMA传输 LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_7); while (!dma_tx_complete); return 0; } /** * @brief DMA2 Stream7传输完成中断处理函数 */ void DMA2_Stream7_IRQHandler(void) { if (LL_DMA_IsActiveFlag_TC7(DMA2)) { LL_DMA_ClearFlag_TC7(DMA2); dma_tx_complete = 1; } } ``` 在这个例程中,我们使用了USART1和DMA2的通道4和流7来实现串口发送。首先,我们对USART1进行了初始化,并将其设置为使用DMA发送模式。然后,我们配置了DMA2的通道4和流7,以实现从内存中的缓冲区发送数据到USART1的数据寄存器中。最后,我们启用了DMA传输完成中断,并在主循环中等待DMA传输完成标志的设置。 需要注意的是,这个例程中使用了LL(即Low Level),而不是HALLL是一个更底层的,可以提供更好的性能和更小的代码尺寸,但也需要更多的手动配置。如果你对LL不熟悉,建议先学习一下HAL

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值