打印

STM32F407的DMA问题

[复制链接]
9652|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 lisn1234 于 2013-6-6 21:33 编辑

请教高手一个问题:

最近在用STM32F407ZG的片子,用到了SPI的DMA模式,来采集外部数据的。
原来是用103的芯片,程序可以运行,才改的407,配置什么的都有小的改动(固件库不太一样了)

但是不知道是不是设置有问题,我的程序总是到了
while(DMA_GetFlagStatus(DMA2_Stream2,DMA_FLAG_TCIF2)==RESET);
这一行停住,不会继续往下运行

代码如下,还请大家帮忙看看,小弟鞠躬了~
void rt_hw_adc_init(void)
{
        SPI_InitTypeDef SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  
        /* DMA2 clock source enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
        /* SPI1、GPIOA clock source enable */
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 ,ENABLE);

        GPIO_PinAFConfig(GPIOA, GPIO_PinSource5,  GPIO_AF_SPI1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource6,  GPIO_AF_SPI1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource7,  GPIO_AF_SPI1);

  /*SPI1 port_init*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;  
        GPIO_Init(GPIOA, &GPIO_InitStructure);
               
  /* Configure SPI1 pins:  NSS ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
        ADC_Enable;                                                                                                                                                                                                                //启用ADC128S102

  /* SPI1 Configuration (Master, 16 MBaud) --------------------------------*/
        SPI_I2S_DeInit(SPI1);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;  
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;  
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;  
  SPI_Init(SPI1, &SPI_InitStructure);
  /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);
  
  DMA_DeInit(DMA2_Stream2);//只用到了SPI1_RX
//         DMA_StructInit( &DMA_InitStructure);
        DMA_InitStructure.DMA_BufferSize = SPI1_BufferSize;
        DMA_InitStructure.DMA_Channel = DMA_Channel_3;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&SPI1_Buffer_Rx;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Address;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_Init(DMA2_Stream2, &DMA_InitStructure);
        
        /* Enable DMA2 Stream2 */
  DMA_Cmd(DMA2_Stream2,ENABLE);
        
        /* Enable SPI1 Rx DMA Request */   
  SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);

         DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2 | DMA_FLAG_TCIF2);

}

/*******************************************************************************/

void adc(void)
{
        rt_hw_adc_init();
        while(1)
        {               
                while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET);
                SPI_I2S_SendData(SPI1,ADC_CHANNEL3);
                 re = rt_mq_send(&mq3, &SPI1_Buffer_Rx[2], 2);
               
               
                //Waiting for the DMA2 transfer complete flag to be setted
                while(DMA_GetFlagStatus(DMA2_Stream2,DMA_FLAG_TCIF2)==RESET);//就是总卡在这里
                DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF2);rt_kprintf("flag cleared!\r\n");        
               
                 rt_thread_delay( 45 );
        }
}

下面是103芯片运行成功的代码
static void rt_hw_adc_init(void)
{
        SPI_InitTypeDef SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  
        /* DMA1 clock source enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        /* SPI1、GPIOA and AFIO clock source enable */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 |RCC_APB2Periph_GPIOA
                                                                                                 |RCC_APB2Periph_AFIO,ENABLE);

  /*SPI1 port_init*/
  /* Configure SPI1 pins: SCK, NSS and MOSI ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* Configure SPI1 pins:  NSS ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
        ADC_Enable;                                                                                                                                                                                                                //启用ADC128S102

  /* SPI1 Configuration (Master, 4.5 MBaud) --------------------------------*/
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode =  SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;  
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;  
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;  
  SPI_Init(SPI1, &SPI_InitStructure);
  /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);
  
        /*DMA1 Channel2 Configuration*/
  DMA_DeInit(DMA1_Channel2);
  DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&SPI1_Buffer_Rx;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = SPI1_BufferSize;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel2, &DMA_InitStructure);
  /* Enable DMA1 Channel2 */
  DMA_Cmd(DMA1_Channel2,ENABLE);
        /* Enable SPI1 Rx DMA Request */   
  SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);
}

void adc(void)
{
        rt_hw_adc_init();
        while(1)
        {
                while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET);
                SPI_I2S_SendData(SPI1,ADC_CHANNEL3);                                                                                                               
                re = rt_mq_send(&mq3, &SPI1_Buffer_Rx[2], 2);
                               
                //Waiting for the DMA1 transfer complete flag to be setted
                while(!DMA_GetFlagStatus(DMA1_FLAG_TC2));
                DMA_ClearFlag(DMA1_FLAG_TC2);
               
                rt_thread_delay( 45 );
        }
}

评论
cslovepp 2019-10-14 11:28 回复TA
大神,咨询一下你这个卡在 while(DMA_GetFlagStatus(DMA2_Stream2,DMA_FLAG_TCIF2)==RESET);//就是总卡在这里 解决了吗?能说一下方法吗? 
沙发
ticomi| | 2013-6-7 17:32 | 只看该作者
看下F4的资料介绍,是否通道配置有问题?这几个系列的DMA与SPI的通道和Stream似乎不太一样的。建议你看下。

使用特权

评论回复
板凳
trumpxp| | 2013-6-7 18:53 | 只看该作者
查一查技术手册   个人认为应该是寄存器设置问题   这一块  如果设置有问题  还是比较头疼的   个人的见解

使用特权

评论回复
地板
lisn1234|  楼主 | 2013-6-9 10:21 | 只看该作者
ticomi 发表于 2013-6-7 17:32
看下F4的资料介绍,是否通道配置有问题?这几个系列的DMA与SPI的通道和Stream似乎不太一样的。建议你看下。 ...

感谢解答~~
您是说这一块的说明吗?
我觉得是按照这个设置的,没什么问题啊……
能在具体点吗?

DMA.jpg (108.06 KB )

DMA.jpg

使用特权

评论回复
5
lisn1234|  楼主 | 2013-6-9 10:23 | 只看该作者
trumpxp 发表于 2013-6-7 18:53
查一查技术手册   个人认为应该是寄存器设置问题   这一块  如果设置有问题  还是比较头疼的   个人的见解 ...

感谢解答~
能不能再具体一点啊,现在调试的没什么头绪……

使用特权

评论回复
6
ticomi| | 2013-6-9 10:24 | 只看该作者
lisn1234 发表于 2013-6-9 10:21
感谢解答~~
您是说这一块的说明吗?
我觉得是按照这个设置的,没什么问题啊……

你试试Stream0 是否可以?我用Stream2时也出现一些问题,改为0后可以。

原因我也不知道。

使用特权

评论回复
7
lisn1234|  楼主 | 2013-6-9 10:34 | 只看该作者
ticomi 发表于 2013-6-9 10:24
你试试Stream0 是否可以?我用Stream2时也出现一些问题,改为0后可以。

原因我也不知道。 ...

好的!谢谢您了!

使用特权

评论回复
8
ticomi| | 2013-6-9 10:37 | 只看该作者
lisn1234 发表于 2013-6-9 10:34
好的!谢谢您了!

不客气,如果你调试通了,麻烦告知一下,我的DMA配置也有一些问题。

谢谢!

使用特权

评论回复
9
lisn1234|  楼主 | 2013-6-15 14:29 | 只看该作者
ticomi 发表于 2013-6-9 10:37
不客气,如果你调试通了,麻烦告知一下,我的DMA配置也有一些问题。

谢谢! ...

帮个帮吧,我的还是有点问题,想再请教一下

要不加个qq吧,我的是946678311

使用特权

评论回复
10
ticomi| | 2013-6-15 15:38 | 只看该作者
lisn1234 发表于 2013-6-15 14:29
帮个帮吧,我的还是有点问题,想再请教一下

要不加个qq吧,我的是946678311 ...

你参考下ST官方的例程,把你的问题点列出来。我试试能不能解决。

我不大喜欢使用QQ,请谅解。

使用特权

评论回复
11
lisn1234|  楼主 | 2013-6-18 11:12 | 只看该作者
本帖最后由 lisn1234 于 2013-6-18 11:14 编辑
ticomi 发表于 2013-6-15 15:38
你参考下ST官方的例程,把你的问题点列出来。我试试能不能解决。

我不大喜欢使用QQ,请谅解。 ...

你好~~(前几天本科毕设一直在准备论文和答辩呢,好不容易才有空闲)
我现在遇到的问题是这样的:
1、介绍一下功能吧:用了ADC128S102这个芯片,模拟输入用了6个通道,数字输出是符合SPI格式的,接上STM32的SPI1。需要用STM32的SPI发送数值来选通这6个通道其中之一,把转换后的值用DMA读进来。

2、我能不能只用SPI_RX的DMA呢?这样的话是不是选通的时候就要SPI_SEND(一个选通的值)?

3、如果我按照官方例程SPI_TwoBoards/SPI_DataExchangeDMA那样RX和TX都配置成DMA,这个选通的数值怎么发送呢?
      6个通道循环采样,难道要每个通道每次SPI_Cmd(SPIx, ENABLE);来接收吗?

太感谢您了,百忙之中抽空看我的帖子,我实在是个新手,周围也没人带我,可能问的问题比较弱智,不要笑话哦。。。


QQ截图20130618111329.jpg (43.1 KB )

QQ截图20130618111329.jpg

使用特权

评论回复
12
ticomi| | 2013-6-18 13:30 | 只看该作者
lisn1234 发表于 2013-6-18 11:12
你好~~(前几天本科毕设一直在准备论文和答辩呢,好不容易才有空闲)
我现在遇到的问题是这样的:
1、介绍 ...

你好,不客气。

我的理解是这样的,我也是这样设计的,但是DMA部分有些小问题,还在调试中。

你的设计我认为是正确的。

使用特权

评论回复
13
lisn1234|  楼主 | 2013-6-18 14:39 | 只看该作者
ticomi 发表于 2013-6-18 13:30
你好,不客气。

我的理解是这样的,我也是这样设计的,但是DMA部分有些小问题,还在调试中。

这么说你也是用的一个类似的ADC了?好难得啊~~可以看看你的配置、采样部分程序吗?我现在不太明白具体怎么去采样。

列出来不方便的话能给我发个邮箱不?lisn1234@126.com

使用特权

评论回复
14
ticomi| | 2013-6-18 15:27 | 只看该作者
lisn1234 发表于 2013-6-18 14:39
这么说你也是用的一个类似的ADC了?好难得啊~~可以看看你的配置、采样部分程序吗?我现在不太明白具体怎 ...

你好,我用的ADC和你的不一样,但是原理差不多。代码是公司的,不方便提供,请理解。

这个ADC我不熟悉,你看下ADC的资料手册,分析好时序,然后根据时序确定程序。

DMA配合SPI时,需要读取数据的时,需要发送一些数据,如读取2个字节则要发送2个任意数据(不要是指令),这样就可以产生SPI时序,同时就可以读取SPI中的数据到DMA中。

使用特权

评论回复
15
cjhk| | 2013-6-18 20:43 | 只看该作者
不是很了解   楼主   帮你顶一个   再看看别人的意见吧   顶一个   

使用特权

评论回复
16
lisn1234|  楼主 | 2013-6-24 23:26 | 只看该作者
ticomi 发表于 2013-6-18 15:27
你好,我用的ADC和你的不一样,但是原理差不多。代码是公司的,不方便提供,请理解。

这个ADC我不熟悉, ...

嗨,你好~~
这几天又试了试,现在SPI和DMA算是通了,发送没问题,就是好像还没把ADC芯片启动起来,所以收不到采样的值。
想请教一下,你知道SPI_I2S_DMACmd和SPI_Cmd在ENABLE的时候有先后顺序吗?我需要先SPI_Cmd(ENABLE),有了时钟信号再去对ADC芯片进行使能,然后再SPI_I2S_DMACmd(ENABLE)进行正常的采样。这样不知道可以吗?

使用特权

评论回复
17
ticomi| | 2013-6-25 08:13 | 只看该作者
lisn1234 发表于 2013-6-24 23:26
嗨,你好~~
这几天又试了试,现在SPI和DMA算是通了,发送没问题,就是好像还没把ADC芯片启动起来,所以收 ...

没有启动原因很多,先看下发送的数据是否正确?不是能发送就是正确的,还有参考下ADC的手册看下协议部分?我是先启动SPI,然后启动DMA的,供你参考

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

26

帖子

1

粉丝