DMA与回调函数
本帖最后由 从未遗忘 于 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处理更稳定呢?
DMA中断会占用CPU,看你的应用建议不开DMA中断,使用空闲中断就好了 庄永 发表于 2023-11-30 19:38
DMA中断会占用CPU,看你的应用建议不开DMA中断,使用空闲中断就好了
好嘞,谢谢您
中断里面的代码都需要cpu参与的。
但是,还是有区别。 串口中断打开的话,每收到一个字节都会进中断的,比较费时。 dma中断打开的话,比如dma一次有100个数据,那么只会在第50个数据(传输一半),和第100个数据(传输完成)时候产生中断。 使用串口DMA中断,特别注意这个问题
等待DMA传输完成后,还有等待TC发送完成标志才是真正的结束。
https://img.anfulai.cn/dz/attachment/forum/202111/06/115811qamtx905z6kzds9x.png
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传输怎么都会进入中断的话,会比串口中断好些 eric2013 发表于 2023-12-1 08:58
使用串口DMA中断,特别注意这个问题
等待DMA传输完成后,还有等待TC发送完成标志才是真正的结束。
/**
* @briefClear 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_TCxTransfer complete flag
* @arg DMA_FLAG_HTxHalf transfer complete flag
* @arg DMA_FLAG_TExTransfer error flag
* @arg DMA_FLAG_GLxGlobal interrupt flag
* Where x can be from 1 to 8 to select the DMA Channel x flag.
* @retval None
*/
确实,写的时候发现HAL_UART_Transmit_DMA()如果不在发送中断里清标志位只能发送一次然后卡死 串口使用DMA,发送和接收都需要打开串口dma中断,其中发送可以直接使用,关心串口最后的回调函数即可,至于接收利用空闲在串口中断里,判断标志位,即可,把接收的缓存设置大点是正常接收量的2-3倍,而可以不关心DMA接收中断,直接调用空闲即可。 eric2013 发表于 2023-12-1 08:58
使用串口DMA中断,特别注意这个问题
等待DMA传输完成后,还有等待TC发送完成标志才是真正的结束。
如果是usart发送使用DMA,这个TC发送完成标志是dma的TC还是USART的TC,个人感觉应该是后者的,我现在RS485就是等UART的TC标志然后关dma通道,之后转换为接收模式 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?mod=viewthread&tid=109441&fromuid=58
(出处: 硬汉嵌入式论坛)
页:
[1]