硬汉嵌入式论坛

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

[技术讨论] dma可以进入中断,但是无法检测到传输完成。

  [复制链接]

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
发表于 2024-1-18 17:00:39 | 显示全部楼层 |阅读模式
本帖最后由 ssssssss 于 2024-1-18 17:09 编辑

dma可以进入中断,但是无法检测到传输完成


可以进入断点1,但是无法进入断点2,是什么问题呢?
456捕获.PNG
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106685
QQ
发表于 2024-1-18 17:06:27 | 显示全部楼层
注意正确的操作姿势,那个HAL_DMA_IRQHandler里面已经处理传输完成中断了,有个对应的传输完成回调函数。

所以你后面判断flag不会再检测到了。
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-19 09:57:10 | 显示全部楼层
本帖最后由 ssssssss 于 2024-1-19 17:26 编辑
eric2013 发表于 2024-1-18 17:06
注意正确的操作姿势,那个HAL_DMA_IRQHandler里面已经处理传输完成中断了,有个对应的传输完成回调函数。
...

改良之后,我给pa6引脚发串口数据波特率115200,想通过定时器触发dma读取io口寄存器电平,把串口数据通过这种方式解析出来。
发第一个字节,顺利触发外部中断,和定时器触发的dma传输完成中断,等待一会,发送第二个字节的时候无法触发dma中断了。如下图。dma模式为DMA_NORMAL模式,我现在可能第二次没有完全打开dma或者定时器,不知道是什么原因?
4455捕获.PNG
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106685
QQ
发表于 2024-1-20 08:52:05 | 显示全部楼层
ssssssss 发表于 2024-1-19 09:57
改良之后,我给pa6引脚发串口数据波特率115200,想通过定时器触发dma读取io口寄存器电平,把串口数据通过 ...

这个处理依然不合理,HAL_DMA_IRQHandle里面有个传输完成回调函数的,在这个里面处理。

HAL库默认是半传输完成中断和传输完成中断都开启的,你做的这个DMA中断里面,这种方式,没处理版传输完成中断。
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-22 10:56:19 | 显示全部楼层
eric2013 发表于 2024-1-20 08:52
这个处理依然不合理,HAL_DMA_IRQHandle里面有个传输完成回调函数的,在这个里面处理。

HAL库默认是半 ...

按照您说的,上面的问题已经解决了,但是又有一个新的问题,dma采集时间间隔不受tim3控制,我之前是用115200的波特率去发送数据,采集时间间隔是8个us,可以采集到正确的编码数据,现在换成19200波特率,那么我的采集时间间隔应该是52us。我将定时器采集时间改为52后,采集不到正确数据,无论我改 htim3.Init.Period的值是多少都是只能采集正确115200波特率的数据。
112捕获.PNG
113捕获.PNG
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106685
QQ
发表于 2024-1-23 08:16:32 | 显示全部楼层
ssssssss 发表于 2024-1-22 10:56
按照您说的,上面的问题已经解决了,但是又有一个新的问题,dma采集时间间隔不受tim3控制,我之前是用115 ...

借鉴下这个。

基于STM32F4的模拟串口实现,采用TIM+DMA方案,支持任意GPIO设置
https://www.armbbs.cn/forum.php? ... 6595&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-23 14:21:22 | 显示全部楼层
本帖最后由 ssssssss 于 2024-1-23 16:23 编辑
eric2013 发表于 2024-1-23 08:16
借鉴下这个。

基于STM32F4的模拟串口实现,采用TIM+DMA方案,支持任意GPIO设置

1。经过我的验证,之前的代码OK,貌似我修改了定时器参数,点击编译,iar没有把修改的内容编译,只有我clean代码后,修改的定时器参数才能生效。硬汉哥是否遇到过这种情况。

2。推荐我看的这个串口数据解析代码en.stsw-stm32156,这个代码用的是定时器输入捕获,主要目的是什么?
/*/* Enable the TIM Update DMA request */
  __HAL_TIM_ENABLE_DMA(&TimHandle, TIM_DMA_CC2);
回复

使用道具 举报

3

主题

120

回帖

129

积分

初级会员

积分
129
发表于 2024-1-23 15:00:58 | 显示全部楼层
ssssssss 发表于 2024-1-23 14:21
1。经过我的验证,之前的代码OK,貌似我修改了定时器参数,点击编译,iar没有把修改的内容编译,只有我cl ...

没找到原始代码,github上有别人fork的stm32arduino的代码,但版本很老,主仓库都没有这部分了
回复

使用道具 举报

3

主题

120

回帖

129

积分

初级会员

积分
129
发表于 2024-1-23 15:05:49 | 显示全部楼层
ssssssss 发表于 2024-1-23 14:21
1。经过我的验证,之前的代码OK,貌似我修改了定时器参数,点击编译,iar没有把修改的内容编译,只有我cl ...

这个应该就是中断里用的,看了下,接收处理就用的这个函数
[C] 纯文本查看 复制代码
  stm32_interrupt_enable(port_rx, STM_GPIO_PIN(g_uartEmul_config[UART1_EMUL_E].pin_rx),
                          UART_EMUL_EXTI_RX, GPIO_MODE_IT_FALLING);
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-23 15:29:30 | 显示全部楼层
skyshine 发表于 2024-1-23 15:05
这个应该就是中断里用的,看了下,接收处理就用的这个函数
[mw_shl_code=c,true]  stm32_interrupt_enab ...

怎么感觉不是我看的代码?
回复

使用道具 举报

3

主题

120

回帖

129

积分

初级会员

积分
129
发表于 2024-1-23 15:49:01 | 显示全部楼层
ssssssss 发表于 2024-1-23 15:29
怎么感觉不是我看的代码?

我回复的是你编辑之前的内容,说好像没用到中断的那个
回复

使用道具 举报

3

主题

120

回帖

129

积分

初级会员

积分
129
发表于 2024-1-23 16:02:04 | 显示全部楼层
ssssssss 发表于 2024-1-23 14:21
1。经过我的验证,之前的代码OK,貌似我修改了定时器参数,点击编译,iar没有把修改的内容编译,只有我cl ...

你说的这个en.stsw-stm32156现在下载不了,要么转圈圈要么不显示,ST现在的官网是越来越卡了
Annotation.png
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-23 16:24:25 | 显示全部楼层
本帖最后由 ssssssss 于 2024-1-23 16:26 编辑
skyshine 发表于 2024-1-23 16:02
你说的这个en.stsw-stm32156现在下载不了,要么转圈圈要么不显示,ST现在的官网是越来越卡了

可以下载,硬汉哥给的链接里面 有的,下载后帮忙也看看,st给的这个接收串口的原理是啥,怎么会用到输入捕获呢?
回复

使用道具 举报

3

主题

120

回帖

129

积分

初级会员

积分
129
发表于 2024-1-24 11:17:01 | 显示全部楼层
本帖最后由 skyshine 于 2024-1-24 11:22 编辑
ssssssss 发表于 2024-1-23 16:24
可以下载,硬汉哥给的链接里面 有的,下载后帮忙也看看,st给的这个接收串口的原理是啥,怎么会用到输入 ...

我猜应该是测起始位结束时间的,测到以后设定之后定时触发dma的时间
文档里2.3.2 流程图里有个检测起始位,也可能是检测起始位脉冲长度是否有效的
https://www.st.com/resource/en/a ... icroelectronics.pdf
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-24 15:33:15 | 显示全部楼层
skyshine 发表于 2024-1-24 11:17
我猜应该是测起始位结束时间的,测到以后设定之后定时触发dma的时间
文档里2.3.2 流程图里有个检测起始 ...

这个图给人感觉是接收多个字节的的流程图。如果是多个字节,第一个字节起始信号来了,外部中断检测到,然后进入byte接收,一个字节接收完后,进入dma传输完成中断处理,如果第二个字节来了,就没有再外部中断检测起始信号,byte接收完后进入dma传输完成中断,直到最后一个字节接收完成,然后关闭外部中断。
6截图20240124152808.png
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-25 11:26:25 | 显示全部楼层
skyshine 发表于 2024-1-24 11:17
我猜应该是测起始位结束时间的,测到以后设定之后定时触发dma的时间
文档里2.3.2 流程图里有个检测起始 ...

如果按照以下段落看的话,又好像是每一个字节都会使用外部中断检测起始位
u捕获.PNG
回复

使用道具 举报

3

主题

120

回帖

129

积分

初级会员

积分
129
发表于 2024-1-25 12:00:49 | 显示全部楼层
ssssssss 发表于 2024-1-25 11:26
如果按照以下段落看的话,又好像是每一个字节都会使用外部中断检测起始位

对的,外部中断触发以后开启dma,关闭外部中断,输入捕获设置为半比特对应时间,定时器时间到以后读取GPIO电平,dma传输长度就是起始位1位+数据位8位/9位+停止位1位/2位。dma传输完成后处理字节数据,再次开启外部中断
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-26 13:53:37 | 显示全部楼层
本帖最后由 ssssssss 于 2024-1-26 13:54 编辑
skyshine 发表于 2024-1-25 12:00
对的,外部中断触发以后开启dma,关闭外部中断,输入捕获设置为半比特对应时间,定时器时间到以后读取GPI ...

TIM1->CCR2 = ((TIM1->CNT + (tmp_arr / 2)) % tmp_arr);
半bit时间的设定没看懂。

[C] 纯文本查看 复制代码
static void UART_Emul_ReceiveFrame(UART_Emul_HandleTypeDef *huart, uint32_t *pData)
{
  uint32_t tmp_sr =0;
  uint32_t tmp_ds =0;
  uint32_t tmp_size =0;
  uint32_t tmp_arr =0;

	tmp_arr = TIM1->ARR;
  tmp_ds = (uint32_t)pData;
  tmp_sr = (uint32_t) & (huart->RxPortName->IDR);
  tmp_size =  __HAL_UART_EMUL_FRAME_LENGTH(huart);

  /* Enable the transfer complete interrupt */
  __HAL_DMA_ENABLE_IT(&hdma_rx, DMA_IT_TC);

  /* Enable the transfer Error interrupt */
  __HAL_DMA_ENABLE_IT(&hdma_rx, DMA_IT_TE);

  /* Configure DMA Stream data length */
  hdma_rx.Instance->NDTR = tmp_size;

  /* Configure DMA Stream source address */
  hdma_rx.Instance->PAR = tmp_sr;

  /* Configure DMA Stream destination address */
  hdma_rx.Instance->M0AR = tmp_ds;

  /* Enable the Peripheral */
  __HAL_DMA_ENABLE(&hdma_rx);

  if ((huart_emul->RxXferCount == 1)||(huart->State != HAL_UART_EMUL_STATE_BUSY_TX_RX))
  {
    TIM1->CCR2 = ((TIM1->CNT + (tmp_arr / 2)) % tmp_arr);
  }

  /* Enable the TIM Update DMA request */
  __HAL_TIM_ENABLE_DMA(&TimHandle, TIM_DMA_CC2);

  /* Enable Timer */
  __HAL_TIM_ENABLE(&TimHandle);

}

回复

使用道具 举报

2

主题

7

回帖

13

积分

新手上路

积分
13
发表于 2024-1-29 13:12:09 | 显示全部楼层
为什么不直接在dma完成中断中处理,判断?而是在串口中断..
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
 楼主| 发表于 2024-1-29 15:11:07 | 显示全部楼层
fengdaokanhai 发表于 2024-1-29 13:12
为什么不直接在dma完成中断中处理,判断?而是在串口中断..

这里没有用到串口中断,是外部中断和定时器+dma
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-29 16:35 , Processed in 0.240561 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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