本帖最后由 tomzbj 于 2019-10-16 15:59 编辑
程序如下, ADC和DMA配置部分略, 大概流程是先设置dc->config里的num_samples, 然后调用ADCDMA_StartTransmission, 启动DMA.
在DMA2_Channel1_IRQHandler里判断是全满还是半满中断, 然后调用 ADCDMA_IRQHandler来把DMA缓冲区内容交替保存到外部spi sram.
现在的问题是发现每次会丢最前面的几个数据, 刚好前几个数据还比较重要.
用gt.t1 / t2 / t3记录DWT->CYCCNT发现, 从t2到t3一直是准确的500ms没有问题, 但从t1到t2最少是503ms, 多的时候达到588ms. 不知道这几十ms的时间耗在哪里了?
- typedef struct { unsigned long t1, t2, t3; } tt_t;
- tt_t gt;
- void ADCDMA_StartTransmission(void)
- {
- extern tt_t gt;
- gt.t1 = DWT->CYCCNT; // 记录起始时间
- DMA_Cmd(DMA2_Channel1, DISABLE);
- DMA2_Channel1->CMAR = (unsigned long)g.adc_buffer;
- DMA2_Channel1->CNDTR = MAX_SAMPLES;
- DMA_Cmd(DMA2_Channel1, ENABLE);
- ADC_DMACmd(ADC2, ENABLE);
- }
- void ADCDMA_StopTransmission(void)
- {
- ADC_DMACmd(ADC2, DISABLE);
- printf("Data acquisition done!
");
- }
- void ADCDMA_IRQHandler(int dma_type)
- {
- DataConfig_t* pdc = DC_Get();
- int size;
- static unsigned long spisram_addr = 0;
- unsigned short* buf;
- buf = g.adc_buffer;
- if(dma_type == DMA_IT_TC)
- buf = &g.adc_buffer[MAX_SAMPLES / 2];
- size = MAX_SAMPLES / 2;
- if(pdc->config.num_samples < size)
- size = pdc->config.num_samples;
- extern tt_t gt;
- if(spisram_addr == 0) {
- gt.t2 = DWT->CYCCNT; // 记录第一次进中断时间
- }
- else if(spisram_addr == size * sizeof(g.adc_buffer[0])) {
- gt.t3 = DWT->CYCCNT; // 记录第二次进中断时间
- }
- SPISRAM_FastWrite(spisram_addr, size * sizeof(g.adc_buffer[0]), buf);
- putchar('.'); fflush(stdout);
- pdc->config.num_samples -= size;
- spisram_addr += size * sizeof(g.adc_buffer[0]);
- if(pdc->config.num_samples <= 0) {
- ADCDMA_StopTransmission();
- spisram_addr = 0;
- }
- }
- void DMA2_Channel1_IRQHandler(void)
- {
- if(DMA_GetITStatus(DMA2_IT_TC1) != RESET) {
- ADCDMA_IRQHandler(DMA_IT_TC);
- DMA_ClearITPendingBit(DMA2_IT_TC1);
- }
- if(DMA_GetITStatus(DMA2_IT_HT1) != RESET) {
- ADCDMA_IRQHandler(DMA_IT_HT);
- DMA_ClearITPendingBit(DMA2_IT_HT1);
- }
- }
复制代码
--------------------------已解决----------------
改为不用ADC_DMACmd, 只用DMA_Cmd(DMA2_Channel1, DISABLE)和DMA_Cmd(DMA2_Channel1, ENABLE)来控制启动和停止DMA传输, 可以了.
看来ADC_DMACmd之后确实会延迟一小段时间再启动传输.
你说放在StartTransmission的结尾? 试了,没区别啊。
那几个函数都只是改几个标志位的事,没啥实质操作。
一周热门 更多>