完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
//////////////////////主函数//////////////////////////////
#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("%dn",ADC_ConvertedValue[j]); Delay(10); } } |
|
|
|
#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); } |
|
|
|
#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´«Êä } |
|
|
|
是不是太快了?示波器检查一下 SCLK 频率,然后对照一下 ADC 芯片手册上记载的最大频率。另外,这么快的信号要注意射频传输线效应。
|
|
|
|
1. 不会快的,SPI的还能支持更高的通信速度,理论上DMA存取数据到缓存数组中也应该能跟得上吧(此处不敢确定);2. AD支持的最大SCLK=80MHz; 3. sclk的图像如下所示; |
|
|
|
htxk 发表于 2018-8-16 07:44 这个SCLK应该没有问题吧 |
|
|
|
请问楼主,使用的这个调试软件是什么工具?
|
|
|
|
板子上这 SPI 的三个高速信号有没有做等长线处理?如果 SCK 的长度和 MISO、MOSI 差的太多,在这么快的速度下也是会有问题的。别忘了光速有限。
|
|
|
|
wang222221 发表于 2018-8-16 08:13 这个以前倒是没有考虑到。我看了看,SCK和MISO长度差不多,而且较短,但是CS有些长。在程序中本来加入了delay(),所以应该不是这方面的问题。 疑虑:会不会是DMA取数据过程中发生了覆盖之类的 |
|
|
|
|
|
|
|
|
|
|
|
htxk 发表于 2018-8-16 08:18 CS 不是高速信号,长一点无所谓,不加 delay 应该也是没有问题的。DMA 溢出是有可能,这么快的速率 DMA 缓冲区要大一点才行,这只能估算一下 DMA 用量,对照着检查代码了。 |
|
|
|
你这个i--在while里面?你没有到DMA的接收完成中断?你最好检测两个频率下的miso和clk的区别.
|
|
|
|
本帖最后由 dh2964169 于 2018-3-6 10:31 编辑 谢谢您的关注和提醒。 确实,开始没有弄清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("%dn",ADC_ConvertedValue[j]); } DMA_ClearITPendingBit(DMA1_Stream0,DMA_IT_TCIF0); //清除完成中断标志位 } 结果图: |
|
|
|
再贴出两种方式的采集数据,并在EXCEL中绘制的波形图(两种情况波形都差不多,但是无法得到标准的波形) |
|
|
|
wang222221 发表于 2018-8-16 09:02 现在只需要对100KHz的正弦信号,采取500个点,也就是DMA缓存500个数据就行了,spi的sclk才2.8MHz,DMA存取的速度很快,所以又觉得不是DMA 溢出问题,有些矛盾。请帮我在观察下,那里还有问题呢,谢谢啦 |
|
|
|
htxk 发表于 2018-8-16 09:53 DMA 的溢出问题不是速度太慢 FIFO 溢出,而是分配的内存区域太小或者和别的东西重叠导致的指针溢出。500 个数据就要分配 1k 到 2k 的内存缓冲区,你给够了吗? |
|
|
|
wang222221 发表于 2018-8-16 10:03 啊啊,我直接是定义了一个数组变量ADC_ConvertedValue[500],然后让DMA指向这个数组,当500个数据存入了这个数组后,再在DMA完成中断服务函数中打印出、 好像我理解的太简单了,随意定义一个数组就可以装数据了。请问下@maxtch 我该如何去解决这个,请给与指点啊,谢谢你 |
|
|
|
htxk 发表于 2018-8-16 10:09 我做嵌入式到现在还没用到过这么大数据流量用单片机处理的东西,到了这种数据吞吐我一般就直接上能跑 Linux 的高速 SoC 了。 DMA 的内存分配往往有特殊要求,你要看芯片手册里面是怎么描述的。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1223 浏览 1 评论
945 浏览 0 评论
MCU友好过渡MPU,米尔基于STM32MP135开发板裸机开发应用笔记
625 浏览 0 评论
自定义系统时钟频率后,用库函数和微带两种方式点亮LED灯,为什么灯的闪烁频率不一致?
1520 浏览 2 评论
1737 浏览 2 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-23 17:38 , Processed in 0.719941 second(s), Total 85, Slave 71 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号