硬汉嵌入式论坛

 找回密码
 立即注册
查看: 480|回复: 9
收起左侧

[技术讨论] DMA与回调函数

[复制链接]

1

主题

9

回帖

12

积分

新手上路

积分
12
发表于 2023-11-30 17:24:03 | 显示全部楼层 |阅读模式
本帖最后由 从未遗忘 于 2023-11-30 17:32 编辑

今天写DMA的时候发现,串口在开启DMA时,    DMA中断函数  和   串口回调函数  都可以完成同样的回调处理,那DMA模式和回调函数方式谁更好呢?DMA中断函数比如DMA1_Channel1_IRQHandler频繁进中断,在使用时会影响CPU工作吗?因为是中断,但是我不确定DMA的中断也是CPU处理吗?


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
        uint8_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
        if((tmp_flag != RESET))//通过标志位判断接收是否结束
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
                HAL_UART_DMAStop(&huart1);
                uint8_t temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);                 
                UART3_LEN =UART3_RX_BUF_SIZE-temp; //计算出数据长度
                HAL_UART_Transmit_DMA(&huart1,g_RxBuf3,UART3_LEN);
                HAL_UART_Receive_DMA(&huart1,g_RxBuf3,UART3_RX_BUF_SIZE);//开启DMA接收,方便下一次接收数据       
        }
}


void DMA1_Channel1_IRQHandler(void)
{       
        uint8_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
        if((tmp_flag != RESET))//通过标志位判断接收是否结束
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
                HAL_UART_DMAStop(&huart1);
                uint8_t temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);                 
                UART3_LEN =UART3_RX_BUF_SIZE-temp; //计算出数据长度
                HAL_UART_Transmit_DMA(&huart1,g_RxBuf3,UART3_LEN);
                HAL_UART_Receive_DMA(&huart1,g_RxBuf3,UART3_RX_BUF_SIZE);//开启DMA接收,方便下一次接收数据       
        }
}



在实际测试如果收发同时进行,如果发的快了,回调函数会有一直传0的现象。感觉DMA1_Channel1_IRQHandler处理更稳定呢?
回复

使用道具 举报

75

主题

684

回帖

909

积分

金牌会员

积分
909
发表于 2023-11-30 19:38:08 | 显示全部楼层
DMA中断会占用CPU,看你的应用建议不开DMA中断,使用空闲中断就好了
回复

使用道具 举报

1

主题

9

回帖

12

积分

新手上路

积分
12
 楼主| 发表于 2023-11-30 19:55:11 | 显示全部楼层
庄永 发表于 2023-11-30 19:38
DMA中断会占用CPU,看你的应用建议不开DMA中断,使用空闲中断就好了

好嘞,谢谢您
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2023-12-1 08:14:07 | 显示全部楼层

中断里面的代码都需要cpu参与的。
但是,还是有区别。 串口中断打开的话,每收到一个字节都会进中断的,比较费时。 dma中断打开的话,比如dma一次有100个数据,那么只会在第50个数据(传输一半),和第100个数据(传输完成)时候产生中断。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106754
QQ
发表于 2023-12-1 08:58:43 | 显示全部楼层
使用串口DMA中断,特别注意这个问题

等待DMA传输完成后,还有等待TC发送完成标志才是真正的结束。


回复

使用道具 举报

1

主题

9

回帖

12

积分

新手上路

积分
12
 楼主| 发表于 2023-12-1 09:10:22 | 显示全部楼层
caicaptain2 发表于 2023-12-1 08:14
中断里面的代码都需要cpu参与的。
但是,还是有区别。 串口中断打开的话,每收到一个字节都会进中断的, ...

明白,网上说DMA的数据传送分为预处理、数据传送和后处理3个阶段。

(1)预处理

由CPU完成一些必要的准备工作。首先,CPU执行几条I/O指令,用以测试I/O设备状态,向DMA控制器的有关寄存器置初值,设置传送方向、启动该设备等。然后,CPU继续执行原来的程序,直到I/O设备准备好发送的数据(输入情况)或接受的数据(输出情况)时,I/O设备向DMA控制器发送DMA请求,再由DMA控制器向CPU发送总线请求(统称为DMA请求),用以传输数据。

(2)数据传送

DMA的数据传输可以以单字节(或字)为基本单位,对于以数据块为单位的传送(如银盘),DMA占用总线后的数据输入和输出操作都是通过循环来实现。需要特别之处的是,这一循环也是由DMA控制器(而不是通过CPU执行程序)实现的,即数据传送阶段是完全由DMA(硬件)来控制的。

(3)后处理

DMA控制器向CPU发送中断请求,CPU执行中断服务程序做DMA结束处理,包括检验送入主存的数据是否正确,测试传送过程中是否出错(错误则转入诊断程序)和决定是否继续使用DMA传送其他数据块等。

感觉使用DMA传输怎么都会进入中断的话,会比串口中断好些
回复

使用道具 举报

1

主题

9

回帖

12

积分

新手上路

积分
12
 楼主| 发表于 2023-12-1 09:15:31 | 显示全部楼层
eric2013 发表于 2023-12-1 08:58
使用串口DMA中断,特别注意这个问题

等待DMA传输完成后,还有等待TC发送完成标志才是真正的结束。

/**
  * @brief  Clear the DMA Channel pending flags.
  * @param  __HANDLE__ DMA handle
  * @param  __FLAG__ specifies the flag to clear.
  *          This parameter can be any combination of the following values:
  *            @arg DMA_FLAG_TCx  Transfer complete flag
  *            @arg DMA_FLAG_HTx  Half transfer complete flag
  *            @arg DMA_FLAG_TEx  Transfer error flag
  *            @arg DMA_FLAG_GLx  Global interrupt flag
  *         Where x can be from 1 to 8 to select the DMA Channel x flag.
  * @retval None
  */
确实,写的时候发现HAL_UART_Transmit_DMA()如果不在发送中断里清标志位只能发送一次然后卡死
回复

使用道具 举报

8

主题

19

回帖

43

积分

新手上路

积分
43
发表于 2023-12-1 09:20:22 | 显示全部楼层
串口使用DMA,发送和接收都需要打开串口dma中断,其中发送可以直接使用,关心串口最后的回调函数即可,至于接收利用空闲在串口中断里,判断标志位,即可,把接收的缓存设置大点是正常接收量的2-3倍,而可以不关心DMA接收中断,直接调用空闲即可。
回复

使用道具 举报

3

主题

122

回帖

131

积分

初级会员

积分
131
发表于 2023-12-1 10:39:15 | 显示全部楼层
eric2013 发表于 2023-12-1 08:58
使用串口DMA中断,特别注意这个问题

等待DMA传输完成后,还有等待TC发送完成标志才是真正的结束。

如果是usart发送使用DMA,这个TC发送完成标志是dma的TC还是USART的TC,个人感觉应该是后者的,我现在RS485就是等UART的TC标志然后关dma通道,之后转换为接收模式
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106754
QQ
发表于 2023-12-1 16:03:39 | 显示全部楼层
skyshine 发表于 2023-12-1 10:39
如果是usart发送使用DMA,这个TC发送完成标志是dma的TC还是USART的TC,个人感觉应该是后者的,我现在RS48 ...

是的,USART的TC

STM32的485串口DMA切换收发的正确姿势
https://www.armbbs.cn/forum.php? ... 9441&fromuid=58
(出处: 硬汉嵌入式论坛)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-4 11:34 , Processed in 0.181396 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表