完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
请教各位一个问题,实在是没有查问题的方向了。 我用ADC的DMA模式,定时器定时采样。ADC的触发是选用的定时器的事件更新,dma也是非连续写入的。DMA完成一半和全部完成分别中断一次。ConvHalfCpltCallback就打印之前一半的数据,ConvCpltCallback就打印后一半的数据。这样就可以形成双缓冲。但是波形每次采样,都会突变,看起来像是频率周期改变了,但是已经排除了输入信号源的问题。不知道有没有大佬指教下是什么原因。 `#define NUM_MAX 1024 define NUM_HALF NUM_MAX/2 uint16_t AdcBuf[NUM_MAX]; short puthalf=0; short putplt=0; short putcpl=0; void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) { putcpl=1; // printf(“半完成\r\n”); puthalf=1; // putcpl=1; } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { // printf(“完成\r\n”); putplt=1; // putcpl=0; // HAL_ADC_Stop(&hadc1);//此处stop经测试不能用hal_adc_stop_dma } int main(void) { MX_GPIO_Init(); MX_DMA_Init(); MX_ADC1_Init(); MX_TIM3_Init(); int count = 1; HAL_ADCEx_Calibration_Start(&hadc1);//校准adc引脚 // HAL_TIM_Base_Start(&htim3);//定时器 //HAL_ADC_Start_DMA(&hadc1, (uint32_t*)AdcBuf, NUM_MAX); while (count++) { // LOG_D("Hello RT-Thread!");
} return RT_EOK; } |
|
相关推荐
8个回答
|
|
你上面贴出来的代码跑出来的效果就是你上面贴出来的曲线吗?粗略看了一下你代码,怎么感觉怪怪的。给我的感觉就是你想做延续触发,但又没实现的感觉。而且逻辑貌似有问题啊。我怎么感觉在half中断来之前,你会一直在start定时器和ADC啊。其实一般来说,如果你数据处理的速度比你采集数据快的话,定时器可以一直跑着的,这也是双缓冲区的意义。采集一个缓冲区的时候处理另外一个的数据。除非你用到的算法很复杂,数据处理的很慢,再考虑停止触发定时器。而且我看你触发信号是1ms的。1K的采样率是很低的,采集512点就512ms,就算那边数据处理是做个FFT都来的急的。没必要停止
|
|
|
|
是这样的,我希望循环采集,所以start放在循环里了。我的逻辑是,开启adc采集,halfcallback回调就打印前一半,convcpltcallback就打印后一半。然后循环往复。关了adc是考虑打印速度比dma慢。
请教下,您觉得应该怎么设计比较好?谢谢 曲线是我跑出来的,第二轮数据就如上图 有异常改变。我在adc启动后加延时就没问题,取消就会这样。不知道为什么? |
|
|
|
看你的图表,并不是后半段才出的错误哦,是前半段的大概220以后的数据。而且说实话,我也觉得不能确定你220之前是否正确。实现任何功能都不能急于求成,慢慢来,实现某功能不是目的,学到更多的东西才更重要。
我简单说几个我的建议吧,具体的你可以自己慢慢搞。 1,你的main函数的while循环里面,本身就应该有一个delay函数,或者其他能挂起的机制。要不然,你的main函数的线程不退出,比他低优先级的线程就都运行不了了 2,既然已经用了系统,就最好不用全局标志位了,用信号量或者事件等线程间同步机制会更好。正好实现了上面的挂起等待功能。 3,就算要实现打印数据,建议不要用rt_kprintf,也不要用字符串。字符串传输本身就效率低。可以打包成16进制的帧发送。如果发送带宽还不够,也可以简单的压缩一下数据,比如每个ADC值,只发送相对前一个点的相对变化量。以此来减小发送的数据量。串口发送也可以用非阻塞的方式,要么中断,要么DMA。如果只是想实现你目前的功能,串口在512ms内传输512个AD值,也还是很轻松的。就按115200波特率算,1ms也能传输11字节,你1ms的AD值,小于16位的AD就只有两字节,大于16位的也才4字节。其实依然可以连续采样,不停止。 4,如果要提高采样频率,确实会出现发送不及时的情况,需要停止采样。要做此功能,建议用信号量等同步机制去做。自己梳理一下逻辑。你目前的简单做法其实也能实现,只是单纯的逻辑问题。并不复杂,建议还是自己去解决一下。收获会更多。 |
|
|
|
|
|
|
|
|
|
|
|
左半拉是正常的,信号源100hz(10ms),采样1ms 1024次。差不多会读到100个周期。图片是前50次的。差不多一半的时候突变了。
单步调试的时候,没有问题。跑起来反而错了。我认为是打印执行的时候,影响到了。程序加了dealy就可以。但是程序时序比较严格,不允许使用delay。请问有什么方法可以解决吗? |
|
|
|
采样功能放在循环外没事,放在循环里就不行了。二次采样就出现上述问题。
|
|
|
|
哦,你用了几个标志。然后线程里判断这几个标志。可能标志状态错了,不是 1 的时候判断是 1 了。
按照你说的1024次差不多是100个周期,DMA半传输中断应该有50个周期数据,你绘制的好像没这么多周期吧。 单步调试时,可能过程比较清晰,在你按下一步的时候,DMA 已经采样完了。 你这样,500ms才有一次中断,我觉得用完成量做消息同步也没问题。在中断里把数据拷贝到 AdcBuf 里。 全传输完成中断之后在线程里处理所有数据,处理完所有数据之后再启动下一次采样。 尽量少用 rt_kprintf 打印吧,你们用的串口驱动都耗用执行时间的。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
883 浏览 0 评论
AI模型部署边缘设备的奇妙之旅:如何在边缘端部署OpenCV
3025 浏览 0 评论
tms320280021 adc采样波形,为什么adc采样频率上来波形就不好了?
1409 浏览 0 评论
2039 浏览 0 评论
1574 浏览 0 评论
75142 浏览 21 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 17:35 , Processed in 1.186757 second(s), Total 85, Slave 69 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号