你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

F429中提高通信速度后SPI+DMA接收AD芯片数据不对?

[复制链接]
dh2964169 提问时间:2018-3-4 15:16 /
本帖最后由 dh2964169 于 2018-3-4 15:26 编辑

总体描述:      利用STM32F429中的SPI通信方式,来为AD7357芯片提供采样时钟,并且获取采集的数据,SPI配置为只接受模式,再加上DMA方式存储SPI获得的数据。(测试信号100KHz正弦信号,代码后面贴出来)请大家帮我看看,谢谢
问题:当SPI使用32分频(1.4MHz的sck)的时候能够采集到正确的信号,但是16分频(sck=2.8MHz)就不能采样到准确的信号?




32分频采集100KHz正弦信号

32分频采集100KHz正弦信号

16分频采集100KHz正弦信号

16分频采集100KHz正弦信号
收藏 评论33 发布时间:2018-3-4 15:16

举报

33个回答
xmshao 回答时间:2018-3-12 16:15:42
dh2964169 发表于 2018-3-9 00:54
只有dma传输完成标志位中断,并设置了一个中断服务函数,来打印得到的500个采样数据;请指教不足的地方, ...

也就是说程序这边比较单纯了。
建议好好琢磨下你用的ADC端相关配置及线路,拿出相应芯片手册再研究下。
butterflyspring 回答时间:2018-3-5 17:23:44
你这个i--在while里面?你没有到DMA的接收完成中断?你最好检测两个频率下的miso和clk的区别.

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

dh2964169 回答时间:2018-3-6 10:29:05
本帖最后由 dh2964169 于 2018-3-6 10:31 编辑
butterflyspring 发表于 2018-3-5 17:23
你这个i--在while里面?你没有到DMA的接收完成中断?你最好检测两个频率下的miso和clk的区别. ...

谢谢您的关注和提醒。       确实,开始没有弄清DMA的功能,认为i=DMA缓冲区的大小,让SPI运行i次即获得data组采样数据;并且以为i--的运行不会对运行过程产生明显的影响(现在回想,这是一种麻烦的做法)。现在在您的提示下,改用了DMA传输完成进行中断。
      但是,和以前的结果一样;我贴出两种情况的代码 和 SCLK与MISO图。请帮再看看为什么还是不能在16分频采样到准确的波形呢?

一  使用 i-- 未使用中断方式
        SPIx_Init();                                                                  //SPI初始化
        GPIO_SetBits(AD_CS_GPIO_PORT,AD_CS_PIN);                  //CS置1
        Rheostat_DMA_Mode_Config();                                            //DMA初始化
        MyDMA_Enable(RHEOSTAT_ADC_DMA_STREAM,numlength);  //使能DMA
        SPI_I2S_DMACmd (AD_SPI,SPI_I2S_DMAReq_Rx,ENABLE);    //SPI_DMA功能使能
        
        while (1)
        {                 
                GPIO_ResetBits(AD_CS_GPIO_PORT,AD_CS_PIN);         //CS置0                  
                         Delay(5);                                   
               
                SPI_Cmd(AD_SPI, ENABLE);                                        //SPI开启        
                             data=SPIx_ReadWriteByte();                                //产生16个周期的读取数据
                SPI_Cmd(AD_SPI, DISABLE);                                       //SPI关闭

                    Delay(140);                                                                //延时时间稍长,为的是让CS=1前,关闭SPI,否则CS=1与sck有重合
                GPIO_SetBits(AD_CS_GPIO_PORT,AD_CS_PIN);                 //CS置1
                    i--;
                    Delay(5);                                                                  
        }

二   去掉i--,并使用DMA中断传输完成中断,在中断服务函数打印缓存数据
        SPIx_Init();                                                                                       //SPI初始化
        GPIO_SetBits(AD_CS_GPIO_PORT,AD_CS_PIN);                                       //CS置1
        Rheostat_DMA_Mode_Config();                                                           //DMA初始化
        DMAxx_NVIC();                                                                                 //DMA中断配置
        DMA_ITConfig(RHEOSTAT_ADC_DMA_STREAM,DMA_IT_TC,ENABLE );   //传输完成中断使能

        MyDMA_Enable(RHEOSTAT_ADC_DMA_STREAM,numlength);                //使能DMA
        SPI_I2S_DMACmd (AD_SPI,SPI_I2S_DMAReq_Rx,ENABLE);                  //SPI_DMA功能使能
        
        while (i)
        {                 
                GPIO_ResetBits(AD_CS_GPIO_PORT,AD_CS_PIN);         //CS置0                  
                         Delay(5);                                   
               
                SPI_Cmd(AD_SPI, ENABLE);                                        //SPI开启        
                             data=SPIx_ReadWriteByte();                                //产生16个周期的读取数据
                SPI_Cmd(AD_SPI, DISABLE);                                       //SPI关闭

                    Delay(140);                                                                //延时时间稍长,为的是让CS=1前,关闭SPI,否则CS=1与sck有重合
                GPIO_SetBits(AD_CS_GPIO_PORT,AD_CS_PIN);                 //CS置1
                    Delay(5);                                                                  
        }

///////////////////////////中断服务函数//////////////////////////////////
        void DMA1_Stream0_IRQHandler(void)  

       {        
                 for (j=numlength;j>1;j--)
              {        
                printf("%d\n",ADC_ConvertedValue[j]);
              }
               DMA_ClearITPendingBit(DMA1_Stream0,DMA_IT_TCIF0);         //清除完成中断标志位
       }

结果图:


使用i--情况,SCK与MISO

使用i--情况,SCK与MISO

使用DMA中断的MISO与SCK

使用DMA中断的MISO与SCK
dh2964169 回答时间:2018-3-4 15:22:53
//////////////////////主函数//////////////////////////////
#include "stm32f4xx.h"
#include "ad9833.h"
#include "bsp_debug_usart.h"
#include "dsp_dma.h"
#include "dsp_spi.h"

extern __IO uint16_t ADC_ConvertedValue[numlength];
extern __IO uint16_t ADC_ConvertedValue1[numlength];
u16  data;
float   ADC_Vol_A;   
float   ADC_Vol_B;
float   ADC_ConvertedValue_A;
float   ADC_ConvertedValue_B;
int i=numlength,j=numlength;
       
static void Delay(__IO uint32_t nCount)       
{
        for(; nCount != 0; nCount--);
}

int main()
{               
        AD9833_GPIO_Init();            
        AD9833_reset();                          
        AD9833_Init(100000);         
       
        Debug_USART_Config();
        printf("SPI+DMA实验\n");
        IO_GPIO_Init();            
        IO_Enalbel();               

  SPIx_Init();              
        GPIO_SetBits(AD_CS_GPIO_PORT,AD_CS_PIN);          
       
        Rheostat_DMA_Mode_Config();                       //初始化
        MyDMA_Enable(RHEOSTAT_ADC_DMA_STREAM,numlength);  //使能DMA
        SPI_I2S_DMACmd (AD_SPI,SPI_I2S_DMAReq_Rx,ENABLE); //SPI_DMA功能使能
       
        while (i)
        {                 
                GPIO_ResetBits(AD_CS_GPIO_PORT,AD_CS_PIN);      //CS置0
                    Delay(5);                              
               
                SPI_Cmd(AD_SPI, ENABLE);                  //SPI使能
                             data=SPIx_ReadWriteByte();                   
               SPI_Cmd(AD_SPI, DISABLE);                 //SPI关闭

                    Delay(140);                                 
                GPIO_SetBits(AD_CS_GPIO_PORT,AD_CS_PIN);              //CS置1
                    i--;
                    Delay(5);                        
        }
        for (j=numlength;j>1;j=j-1)
{       
                printf("%d\n",ADC_ConvertedValue[j]);
                 Delay(10);  
}
}




dh2964169 回答时间:2018-3-4 15:24:55
#include "dsp_spi.h"
//SPI3


void SPIx_Init(void)
{   
                SPI_InitTypeDef   SPI_InitStructure;   
                GPIO_InitTypeDef  GPIO_InitStructure;  
                RCC_AHB1PeriphClockCmd(AD_SPI_SCK_GPIO_CLK|AD_SPI_MISO_GPIO_CLK|AD_SPI_MOSI_GPIO_CLK|AD_CS_GPIO_CLK, ENABLE);
          AD_SPI_CLK_INIT(AD_SPI_CLK,ENABLE);             //SPIʱÖÓʹÄÜ
       
    GPIO_PinAFConfig(AD_SPI_SCK_GPIO_PORT,AD_SPI_SCK_PINSOURCE,AD_SPI_SCK_AF);   //PC10¸´ÓÃSPI3µÄSCLK
    GPIO_PinAFConfig(AD_SPI_MISO_GPIO_PORT,AD_SPI_MISO_PINSOURCE,AD_SPI_MISO_AF);  //PC11¸´ÓÃSPI3µÄMISO

                        GPIO_InitStructure.GPIO_Pin = AD_SPI_SCK_PIN;
                        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;         //¸´ÓÃ
                        GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;     //50MHz
                        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;         //SCK¿ÕÏÐÉèÖÃΪ¸ßµçƽ£¬¹ÊΪÉÏÀ­
                GPIO_Init(AD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);  //³õʼ»¯PC10

            GPIO_InitStructure.GPIO_Pin = AD_SPI_MISO_PIN;
    GPIO_Init(AD_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

                  GPIO_InitStructure.GPIO_Pin = AD_CS_PIN;       
            GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT ;           
      GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;           
            GPIO_InitStructure.GPIO_Speed=GPIO_Fast_Speed;         
          GPIO_Init(AD_CS_GPIO_PORT, &GPIO_InitStructure);      

                  GPIO_SetBits(AD_CS_GPIO_PORT,AD_CS_PIN);       
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;  //ģʽ£¬µ¥Ïß½ÓÊÕģʽ
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                   //ģʽѡÔñ;Ö÷¿Ø·¢³öSCLKÐźÅ

    SPI3->CR1|=1<<10;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;              //ÉèÖÃSPIµÄÊý¾Ý´óС
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                     //´®ÐÐͬ²½Ê±ÖӵĿÕÏÐ״̬
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                    //´®ÐÐͬ²½Ê±ÖÓ²ÉÑù±ßÑØ
    SPI_InitStructure.SPI_NSS  = SPI_NSS_Soft;                      //NSSÓÉÓ²¼þ»¹ÊÇÈí¼þ¿ØÖÆ
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; //·ÖƵϵÊý
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;              //¸ßλÓÐЧ
    SPI_InitStructure.SPI_CRCPolynomial = 7;                        //CRCУÑé
    SPI_Init(AD_SPI, &SPI_InitStructure);                           //SPI³õʼ»¯
                 

}   

u16 SPIx_ReadWriteByte(void)
{  
        u8 retry=0;         
                       
                while (SPI_I2S_GetFlagStatus(AD_SPI, SPI_I2S_FLAG_RXNE) == RESET)
        {
                retry++;
                if(retry>200)
                        return 0;
        }                
                        return SPI_I2S_ReceiveData(AD_SPI);
       
}




dh2964169 回答时间:2018-3-4 15:25:44
#include "dsp_dma.h"

__IO uint16_t ADC_ConvertedValue[numlength];
__IO uint16_t ADC_ConvertedValue1[numlength];

void Rheostat_DMA_Mode_Config(void)
{

  DMA_InitTypeDef  DMA_InitStructure;                           
        RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK,ENABLE);         
  DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL;              //ͨµÀÑ¡Ôñ
  DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_SPI_DR_ADDR;       //DMAÍâÉèµØÖ·
  DMA_InitStructure.DMA_Memory0BaseAddr =  (u32)ADC_ConvertedValue;      //DMA´æ´¢Æ÷µØÖ·
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                //ÍâÉèµ½´æ´¢Æ÷ģʽ
  DMA_InitStructure.DMA_BufferSize = numlength;                          //Êý¾Ý´«ÊäÁ¿
  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_PeripheralDataSize_HalfWord;//´æ´¢Æ÷Êý¾Ý³¤¶È
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                          //ʹÓÃÆÕͨģʽ£¬Ò»´Î´æ´¢
  //²»Ê¹ÓÃÑ­»·Ä£Ê½ÊÇÒòΪAD²ÉÑùµÄËÙÂʸßÓÚÊý¾Ý·¢Ë͵ÄËٶȣ¬±ÜÃ⸲¸ÇÊý¾Ý
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                //ÖеÈÓÅÏȼ¶
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;            //´æ´¢Æ÷Í»·¢µ¥´Î´«Êä
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    //ÍâÉèÍ»·¢µ¥´Î´«Êä

  DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);                 //³õʼ»¯DMA Stream  
       
}

void MyDMA_Enable(DMA_Stream_TypeDef *DMA_streamx,u16 ndtr)
        {
          DMA_Cmd(DMA_streamx ,DISABLE );                                      //¹Ø±ÕDMA
                while(DMA_GetCmdStatus (DMA_streamx )!=DISABLE ){}                   //È·±£DMA¿ÉÒÔ±»ÉèÖÃ
                DMA_Cmd (DMA_streamx,ENABLE);                                        //¿ªÆôDMA´«Êä
        }


maxtch 回答时间:2018-3-4 20:16:35
是不是太快了?示波器检查一下 SCLK 频率,然后对照一下 ADC 芯片手册上记载的最大频率。另外,这么快的信号要注意射频传输线效应。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

dh2964169 回答时间:2018-3-4 20:46:52
maxtch 发表于 2018-3-4 20:16
是不是太快了?示波器检查一下 SCLK 频率,然后对照一下 ADC 芯片手册上记载的最大频率。另外,这么快的信 ...

1.  不会快的,SPI的还能支持更高的通信速度,理论上DMA存取数据到缓存数组中也应该能跟得上吧(此处不敢确定);2.  AD支持的最大SCLK=80MHz;
3.  sclk的图像如下所示;



16分频的SCK

16分频的SCK

16分频的MISO

16分频的MISO
dh2964169 回答时间:2018-3-4 21:04:28
dh2964169 发表于 2018-3-4 20:46
1.  不会快的,SPI的还能支持更高的通信速度,理论上DMA存取数据到缓存数组中也应该能跟得上吧(此处不敢 ...

这个SCLK应该没有问题吧
uwyciw100 回答时间:2018-3-5 10:23:08
请问楼主,使用的这个调试软件是什么工具?
maxtch 回答时间:2018-3-5 12:28:03
板子上这 SPI 的三个高速信号有没有做等长线处理?如果 SCK 的长度和 MISO、MOSI 差的太多,在这么快的速度下也是会有问题的。别忘了光速有限。
dh2964169 回答时间:2018-3-5 14:31:37
maxtch 发表于 2018-3-5 12:28
板子上这 SPI 的三个高速信号有没有做等长线处理?如果 SCK 的长度和 MISO、MOSI 差的太多,在这么快的速度 ...

这个以前倒是没有考虑到。我看了看,SCK和MISO长度差不多,而且较短,但是CS有些长。在程序中本来加入了delay(),所以应该不是这方面的问题。

疑虑:会不会是DMA取数据过程中发生了覆盖之类的
dh2964169 回答时间:2018-3-5 14:32:22
uwyciw100 发表于 2018-3-5 10:23
请问楼主,使用的这个调试软件是什么工具?

程序用的就是KEIL5,波形用的示波器
uwyciw100 回答时间:2018-3-5 16:47:05
dh2964169 发表于 2018-3-5 14:32
程序用的就是KEIL5,波形用的示波器

这个波形工具觉得不错,哈哈
maxtch 回答时间:2018-3-5 17:03:37
dh2964169 发表于 2018-3-5 14:31
这个以前倒是没有考虑到。我看了看,SCK和MISO长度差不多,而且较短,但是CS有些长。在程序中本来加入了d ...

CS 不是高速信号,长一点无所谓,不加 delay 应该也是没有问题的。DMA 溢出是有可能,这么快的速率 DMA 缓冲区要大一点才行,这只能估算一下 DMA 用量,对照着检查代码了。
123下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版