本帖最后由 dh2964169 于 2018-3-4 15:26 编辑 总体描述: 利用STM32F429中的SPI通信方式,来为AD7357芯片提供采样时钟,并且获取采集的数据,SPI配置为只接受模式,再加上DMA方式存储SPI获得的数据。(测试信号100KHz正弦信号,代码后面贴出来)请大家帮我看看,谢谢 问题:当SPI使用32分频(1.4MHz的sck)的时候能够采集到正确的信号,但是16分频(sck=2.8MHz)就不能采样到准确的信号? |
32åé¢éé100KHzæ£å¼¦ä¿¡å·
16åé¢éé100KHzæ£å¼¦ä¿¡å·
也就是说程序这边比较单纯了。
建议好好琢磨下你用的ADC端相关配置及线路,拿出相应芯片手册再研究下。
评分
查看全部评分
谢谢您的关注和提醒。 确实,开始没有弄清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
使ç¨DMAä¸æçMISOä¸SCK
#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);
}
}
//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);
}
__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´«Êä
}
评分
查看全部评分
1. 不会快的,SPI的还能支持更高的通信速度,理论上DMA存取数据到缓存数组中也应该能跟得上吧(此处不敢确定);2. AD支持的最大SCLK=80MHz;
3. sclk的图像如下所示;
16åé¢çSCK
16åé¢çMISO
这个SCLK应该没有问题吧
这个以前倒是没有考虑到。我看了看,SCK和MISO长度差不多,而且较短,但是CS有些长。在程序中本来加入了delay(),所以应该不是这方面的问题。
疑虑:会不会是DMA取数据过程中发生了覆盖之类的
程序用的就是KEIL5,波形用的示波器
这个波形工具觉得不错,哈哈
CS 不是高速信号,长一点无所谓,不加 delay 应该也是没有问题的。DMA 溢出是有可能,这么快的速率 DMA 缓冲区要大一点才行,这只能估算一下 DMA 用量,对照着检查代码了。