搜索
bottom↓
回复: 31

发一个stm32f4xx dma接收未知数据长度调试通过

[复制链接]

出0入0汤圆

发表于 2012-12-14 10:07:21 | 显示全部楼层 |阅读模式
本帖最后由 hpdell 于 2012-12-14 10:13 编辑

参考stm32f1xx的帖子修改而来,望多多指教

在此感谢感谢!!!11
http://www.amobbs.com/forum.php? ... C%E5%8F%91%E9%80%81


顺便请教下,我想用DMA发送一个字符或者多个字符时,调试没有成功,请大仙们指点指点一下!


此工程文件不含固件库,使用者需要自己增加固件库,固件库与本工程文件放同一目录就可以了,路径请自行修改!!


//USART1使用DMA接收数据中断服务程序, DMA接收完成中断
void DMA2_Stream5_IRQHandler(void)
{
   /* Test on DMA Stream Transfer Complete interrupt */
   if(DMA_GetITStatus(DMA2_Stream5, DMA_IT_TCIF5))       //此处是我增加,不然单片机会不停的发送数据给pc机
   {     
      DMA_ClearITPendingBit(DMA2_Stream5,DMA_IT_TCIF5);
      DMA_ClearITPendingBit(DMA2_Stream5,DMA_IT_TEIF5);
      DMA_Cmd(DMA2_Stream5, DISABLE);                                //关闭DMA,防止处理其间有数据
      DMA2_Stream5->NDTR = RECAVEMAXCOUNT;                //重装填
      DMA_Cmd(DMA2_Stream5, ENABLE);                                //处理完,重开DMA
   }
}



//USART1使用DMA发数据中断服务程序
void DMA2_Stream7_IRQHandler(void)
{
   if(DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7) != RESET)
   {
      DMA_ClearITPendingBit(DMA2_Stream7,DMA_IT_TCIF7);
      DMA_ClearITPendingBit(DMA2_Stream7,DMA_IT_TEIF7);
      USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
      DMA_Cmd(DMA2_Stream7, DISABLE);                        //关闭DMA
      USART1_TxFinish = 1;                                                        //置DMA传输完成
   }
}

工程文件:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入4汤圆

发表于 2012-12-14 14:08:31 | 显示全部楼层
既然是 未知长度  怎么又有 接收完成中断?

出0入0汤圆

 楼主| 发表于 2012-12-15 12:12:49 | 显示全部楼层
acmilannast 发表于 2012-12-14 14:08
既然是 未知长度  怎么又有 接收完成中断?

我也是刚搞stm不久,有些东东我也不太明白。

出0入24汤圆

发表于 2012-12-15 13:47:26 | 显示全部楼层
接收未知长度数据,总线空闲中断最好使了。

出0入0汤圆

 楼主| 发表于 2012-12-15 16:39:43 | 显示全部楼层
20061002838 发表于 2012-12-15 13:47
接收未知长度数据,总线空闲中断最好使了。

你好,你看看上面的程序,还有那些需要修改的啊??? 望指点指点

出0入24汤圆

发表于 2012-12-15 19:21:38 | 显示全部楼层
发送应该用是DMA中断
接收用USART总线空闲中断,不用DMA中断

出0入0汤圆

发表于 2012-12-15 22:43:21 | 显示全部楼层
20061002838 发表于 2012-12-15 19:21
发送应该用是DMA中断
接收用USART总线空闲中断,不用DMA中断

请教一下:接收时使用总线空闲中断,相对于DMA接收完成中断,有哪些好处呢?

出0入24汤圆

发表于 2012-12-15 23:32:51 | 显示全部楼层
eehong 发表于 2012-12-15 22:43
请教一下:接收时使用总线空闲中断,相对于DMA接收完成中断,有哪些好处呢? ...

你都不知道你接收的数据长度是多少,怎么用DMA完成中断?DMA是完成你设定数量的传输之后触发传输完成中断的。
用总线空闲中断+DMA,DMA缓冲区长度设置成大于最大接收数据长度,单片机接收完一帧数据后,总线恢复空闲状态,进入空闲中断,读DMA剩余传输数量可以获得接收数据的长度。这样接收到一帧数据,单片机只中断了一次,而且是实时响应的。
我看你的程序里面用的是DMA传输完成,你如何保证你的实时性?

出0入0汤圆

发表于 2012-12-15 23:38:56 | 显示全部楼层
20061002838 发表于 2012-12-15 23:32
你都不知道你接收的数据长度是多少,怎么用DMA完成中断?DMA是完成你设定数量的传输之后触发传输完成中断 ...

接收数据长度未知确实是这样。谢谢。
需要补充下,因为我这用的RS485通讯,数据长度在通讯帧的前几个字节,因此可以看做都是已知的。
其实,我想知道的是,在知道待接收数据长度的情况下,使用空闲中断的优势。再次谢谢!

出0入24汤圆

发表于 2012-12-16 00:09:04 | 显示全部楼层
eehong 发表于 2012-12-15 23:38
接收数据长度未知确实是这样。谢谢。
需要补充下,因为我这用的RS485通讯,数据长度在通讯帧的前几个字节 ...

你都知道接收数据长度了,还用总线空闲中断干嘛? 你这个帖子名字起的有意思。

用总线空闲中断还有一个好处就是DMA接收可以不被打断,可以工作在循环模式,这一点在多主系统里有优势。如果你用DMA中断,在处理中断的过程中,有数据来了,而DMA又没有重新开启,这就会导致丢失数据。

出0入0汤圆

发表于 2012-12-16 00:15:46 | 显示全部楼层
20061002838 发表于 2012-12-16 00:09
你都知道接收数据长度了,还用总线空闲中断干嘛? 你这个帖子名字起的有意思。

用总线空闲中断还有一个 ...

不好意思,俺其实是个路过打酱油的,楼主不知跑哪了。
对你的回答,再次表示感谢。

出0入4汤圆

发表于 2012-12-17 15:31:55 | 显示全部楼层
20061002838 发表于 2012-12-15 19:21
发送应该用是DMA中断
接收用USART总线空闲中断,不用DMA中断

An Idle character  is interpreted as an entire frame of “1”s followed by the start bit of the next
frame which contains data (The number of “1” ‘s will include the number of stop bits)。
在线路为全"1"(空闲)之后出现一个"start bit"才判定是IDLE;

这样的话 需要发送方 发送一个空闲帧  DAM才能起作用 ! 不知我的理解是否有问题?

出0入24汤圆

发表于 2012-12-17 20:45:18 | 显示全部楼层
acmilannast 发表于 2012-12-17 15:31
An Idle character  is interpreted as an entire frame of “1”s followed by the start bit of the ne ...

不是的,你理解错了
一帧数据发送完成之后,发送端Tx返回空闲状态,也就是高电平
STM32会检测这个高电平的时间,超过一定时间就认为是总线空闲
发送端不需要额外的处理,只要保证两帧不是连在一起就行了,这个我用电脑发送验证过的,而且还是USB转串口。

出0入24汤圆

发表于 2012-12-17 20:46:03 | 显示全部楼层
eehong 发表于 2012-12-16 00:15
不好意思,俺其实是个路过打酱油的,楼主不知跑哪了。
对你的回答,再次表示感谢。 ...

呵呵,把你当成LZ了

出0入4汤圆

发表于 2012-12-18 10:26:48 | 显示全部楼层
20061002838 发表于 2012-12-17 20:45
不是的,你理解错了
一帧数据发送完成之后,发送端Tx返回空闲状态,也就是高电平
STM32会检测这个高电平 ...

好的 谢谢!难道是手册有误? 我也做个验证试试... 如果可以真的能大大减轻 mcu负担!

出0入4汤圆

发表于 2012-12-18 11:59:49 | 显示全部楼层
acmilannast 发表于 2012-12-18 10:26
好的 谢谢!难道是手册有误? 我也做个验证试试... 如果可以真的能大大减轻 mcu负担! ...

OK,验证可以! 115200下 电脑转串口 做主机,完全OK。

出0入4汤圆

发表于 2012-12-18 12:04:46 | 显示全部楼层
// 初始化
void InitDMA1Chanle5ForUSART1_RX(void)
{
       
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

        DMA_DeInit(DMA1_Channel5);
       
        DMA_InitStructure.DMA_BufferSize         = 512;
        DMA_InitStructure.DMA_DIR                        = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_M2M                        = DMA_M2M_Disable;
        DMA_InitStructure.DMA_MemoryBaseAddr =  (u32)UART1_REC_Buffer1;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_MemoryInc        = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_Mode                        = DMA_Mode_Normal;
        DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_Priority                = DMA_Priority_VeryHigh;
        DMA_Init(DMA1_Channel5,&DMA_InitStructure);
       
        DMA_Cmd(DMA1_Channel5,ENABLE);

}
void InitUSART1(void)
{
          /* Enable USART1 Clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
       
       
        /* Config USART1 Parameter */
        UART_InitStrcture.USART_BaudRate         = 115200;
        UART_InitStrcture.USART_Mode                = USART_Mode_Rx|USART_Mode_Tx;
        UART_InitStrcture.USART_Parity                = USART_Parity_No;
        UART_InitStrcture.USART_StopBits        = USART_StopBits_1;
        UART_InitStrcture.USART_WordLength        = USART_WordLength_8b;
        UART_InitStrcture.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_Init(USART1,&UART_InitStrcture);


        /*Config UART_IO:PA9-->TXD  PA10-->RXD */
        GPIO_InitStrcture.GPIO_Pin         = GPIO_Pin_9;
        GPIO_InitStrcture.GPIO_Mode        = GPIO_Mode_AF_PP;
        GPIO_InitStrcture.GPIO_Speed        = GPIO_Speed_10MHz;
        GPIO_Init(GPIOA,&GPIO_InitStrcture);
        GPIO_InitStrcture.GPIO_Pin        = GPIO_Pin_10;
        GPIO_InitStrcture.GPIO_Mode        = GPIO_Mode_IPU;
        GPIO_Init(GPIOA,&GPIO_InitStrcture);

       
        /* Config USART1 Interrupt */
        USART_ITConfig(USART1,USART_IT_TC,DISABLE);
    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
       
         USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
     USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);

     USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
       
        NVIC_InitStructure.NVIC_IRQChannel         = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd        = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
       
        /*Enable USART1  */
        USART_Cmd(USART1,ENABLE);


}

//中断处理函数
void USART1_IRQHandler(void)//2uS
{
        u32 temp,i;
    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
        {
      
                //USART_ClearFlag(USART1,USART_IT_IDLE);
        temp = USART1->SR;
        temp = USART1->DR; //清USART_IT_IDLE标志
        DMA_Cmd(DMA1_Channel5,DISABLE);
        temp = (512-DMA1_Channel5->CNDTR);
        for(i=0;i<temp;i++)// 数据转移(可优化)
        {
            InsertLineQueue(&Comm_Main,UART1_REC_Buffer1);
        }
        RecLED_On = TRUE;
                DMA1_Channel5->CNDTR = 512;
        DMA_Cmd(DMA1_Channel5,ENABLE);
        }
}

出0入24汤圆

发表于 2012-12-18 12:17:59 | 显示全部楼层
acmilannast 发表于 2012-12-18 12:04
// 初始化
void InitDMA1Chanle5ForUSART1_RX(void)
{

是的,总线空闲中断可以极大减轻CPU负担
而且发送端不需要做什么特殊处理

出0入0汤圆

发表于 2013-3-23 12:02:23 | 显示全部楼层
mark,有参考价值

出0入0汤圆

发表于 2013-3-23 13:34:27 | 显示全部楼层
學習了~

出0入0汤圆

发表于 2013-4-15 21:00:10 | 显示全部楼层
我也以為要發全為1的幀,還好睇到此貼,謝謝各位前輩啦,^_^

出0入0汤圆

发表于 2013-10-4 18:43:04 | 显示全部楼层
好帖,mark

出0入0汤圆

发表于 2014-5-7 11:20:13 | 显示全部楼层
不知道楼主写出F4的双缓冲模式的代码了么?
不知道这两句你使用了么?
        DMA_DoubleBufferModeConfig(DMA1_Stream3,
                                                        (uint32_t)Buffer1/*Memory1BaseAddr*/,
                                                         DMA_Memory_1/*Memory x is the current buffer,当前第一个开始传输的memory
                                                                                         不使用DoubleBuffer模式的时候,默认当前的memory是第一个*/);
        DMA_DoubleBufferModeCmd(DMA1_Stream3, ENABLE);

出0入0汤圆

发表于 2014-5-14 08:42:39 | 显示全部楼层
20061002838 发表于 2012-12-15 13:47
接收未知长度数据,总线空闲中断最好使了。


我感觉楼主的DMA接收中断是这个意思!

接受未知长度的数据,只有一个起点,即串口数据接受中断,在此函数中
初始化DMA开始传输。终点无非两个,一,DMA没有接受完成,串口进入总  
线空闲中断,在空闲中断中获取收到的数据量,然后结束DMA传输,二,
DMA接受完成,进入DMA接收完成中断,关闭DMA接收 。

出0入0汤圆

发表于 2014-8-26 10:39:14 | 显示全部楼层
你好,感谢你的分享,
http://blog.csdn.net/jdh99/article/details/8444474

能讲讲里面的中断函数什么意思?没看明白,谢谢,

出0入0汤圆

发表于 2015-4-16 22:42:41 | 显示全部楼层
楼主你的程序有没有在F0上面测试过。我发现F1可以通过,F0就不行。

出0入0汤圆

发表于 2015-4-16 22:45:43 | 显示全部楼层
20061002838 发表于 2012-12-15 23:32
你都不知道你接收的数据长度是多少,怎么用DMA完成中断?DMA是完成你设定数量的传输之后触发传输完成中断 ...

F0测试了下发现通不过,F1测试通过,你有没有测试过F0的。可以进空闲中断,但是读取的DMA传送数量每次都是不一样的。随机的。但是我测试的数据是固定的。很奇怪

出0入0汤圆

 楼主| 发表于 2015-4-17 09:00:58 | 显示全部楼层
logosz 发表于 2015-4-16 22:45
F0测试了下发现通不过,F1测试通过,你有没有测试过F0的。可以进空闲中断,但是读取的DMA传送数量每次都 ...

你好,f0的我没有那个板子,反正每次你发送多少,他能够收到与你发送同样的数据就可以了啊,不过应该是你发送多少,他会自动接收多少的

这个我在f4上面使用是完全没有任何问题的哦,f0的你再研究研究啊,有什么结果也请发上来分享一下哦,你再看看f0的支不支持空闲模式或者是设置

有什么不一样的地方 。

出0入0汤圆

发表于 2015-4-17 13:29:26 | 显示全部楼层
hpdell 发表于 2015-4-17 09:00
你好,f0的我没有那个板子,反正每次你发送多少,他能够收到与你发送同样的数据就可以了啊,不过应该是你 ...

F0有多个串口的,但是不是所有串口都支持timeout功能。我现在用的这个串口号没有timeout功能,所以用的是串口空闲中断+DMA,在串口空闲中断中把DMA传输到内存中的数据复制到变量中。


但是F1可以通过,F0测试不过。

出0入0汤圆

发表于 2015-12-19 07:02:56 | 显示全部楼层
请教一下,DMA 用总线空闲中断的时候,有时候正常 有时候不正常 不知道你碰到过没有!

出0入0汤圆

 楼主| 发表于 2015-12-19 11:13:27 | 显示全部楼层
weidadejang 发表于 2015-12-19 07:02
请教一下,DMA 用总线空闲中断的时候,有时候正常 有时候不正常 不知道你碰到过没有! ...

木有遇到过哟

出0入0汤圆

发表于 2017-9-8 10:16:51 | 显示全部楼层
现在用STM32F407,学习了!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 15:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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