完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1. 问题描述
我使用rtt4.1.1版本,其中adc采样直接采用cubemx生成的库函数,用DMA读取方式读取AD的值。并在DMA中断内回调AD值计算函数。 结果在做滑动平均值滤波的时候出现了问题。一个未初始化的全局变量在第二次进入中断的时候被意外赋值了。这造成了计算结果的不正确。如果用static修饰这个变量后,则不会出现这个状况。下面是问题描述。 2. 变量声明 int32_t voltage_rms_sum_a; int32_t voltage_rms_sum_b; int32_t voltage_rms_sum_c; 3.滑动平均值滤波 if (adc_convert_full == 1) { voltage_rms_a = (int)(sqrtf(voltage_square_add_a/20)*10); voltage_rms_b = (int)(sqrtf(voltage_square_add_b/20)*10); voltage_rms_c = (int)(sqrtf(voltage_square_add_c/20)*10); voltage_square_add_a = voltage_square_add_a-voltage_square_a[adc_convert_cnt]; voltage_square_add_b = voltage_square_add_b-voltage_square_b[adc_convert_cnt]; voltage_square_add_c = voltage_square_add_c-voltage_square_c[adc_convert_cnt]; voltage_rms_buf_a[rms_average_calc_cnt]= voltage_rms_a; voltage_rms_sum_a=voltage_rms_sum_a+voltage_rms_buf_a[rms_average_calc_cnt]; voltage_rms_buf_b[rms_average_calc_cnt]= voltage_rms_b; voltage_rms_sum_b=voltage_rms_sum_b+voltage_rms_buf_b[rms_average_calc_cnt]; voltage_rms_buf_c[rms_average_calc_cnt]= voltage_rms_c; voltage_rms_sum_c=voltage_rms_sum_c+voltage_rms_buf_c[rms_average_calc_cnt]; rms_average_calc_cnt++; } 4. 问题 adc_convert_full这个变量被设计为20次中断后开始滤波,意味着20次循环后,才会进入if语句。但是如果用断点调试后发现,第一次进入时。 第20行,voltage_rms_sum_c变量为0,但是第二次进入中断后,voltage_rms_sum_c变量为0被赋值为一个意外的值。我看了内存的分配,也没有发现内存重复的情况。 5. 临时解决办法 将voltage_rms_sum_a、voltage_rms_sum_b、voltage_rms_sum_c增加static修饰,可以解决问题,但是我不明白为什么会这样。 |
|
相关推荐
1个回答
|
|
在这个问题中,您在使用RTT4.1.1版本进行滑动平均值滤波时遇到了一个未初始化的全局变量在第二次进入中断时被意外赋值的问题。这导致了计算结果的不正确。当您使用`static`修饰这个变量后,问题得到了解决。下面我将详细分析这个问题的原因和解决方法。
1. 问题原因: 在您的代码中,`voltage_rms_sum_a`、`voltage_rms_sum_b`和`voltage_rms_sum_c`这三个全局变量没有被初始化。当您在DMA中断内回调AD值计算函数时,这些变量可能会被意外赋值。这是因为在C语言中,全局变量默认会被初始化为0,但在某些编译器或硬件平台上,这个行为可能并不总是发生。因此,当您在中断服务例程(ISR)中使用这些变量时,它们可能已经被其他代码段意外地修改了。 2. 解决方案: 要解决这个问题,您可以采取以下几种方法: a. 初始化全局变量: 在您的代码中,确保在声明全局变量时对它们进行初始化。例如: ```c int32_t voltage_rms_sum_a = 0; int32_t voltage_rms_sum_b = 0; int32_t voltage_rms_sum_c = 0; ``` 这样可以确保在中断服务例程中使用这些变量时,它们已经被正确初始化。 b. 使用`static`修饰符: 您已经发现使用`static`修饰符可以解决问题。这是因为`static`修饰符会将变量的作用域限制在声明它的文件内,从而避免了其他代码段对这些变量的意外访问。例如: ```c static int32_t voltage_rms_sum_a; static int32_t voltage_rms_sum_b; static int32_t voltage_rms_sum_c; ``` c. 使用局部变量: 另一种方法是在中断服务例程中使用局部变量,而不是全局变量。这样可以确保变量的作用域仅限于中断服务例程,从而避免了其他代码段对这些变量的意外访问。例如: ```c void DMA_IRQHandler(void) { int32_t voltage_rms_sum_a; int32_t voltage_rms_sum_b; int32_t voltage_rms_sum_c; // 滑动平均值滤波 if (adc_convert_full == 1) { // ... } } ``` 3. 总结: 在您的代码中,未初始化的全局变量在第二次进入中断时被意外赋值,导致了计算结果的不正确。为了解决这个问题,您可以采取以下措施: - 初始化全局变量 - 使用`static`修饰符 - 使用局部变量 通过采取这些措施,您可以确保在中断服务例程中正确地使用这些变量,从而避免意外的赋值和计算错误。 |
|
|
|
只有小组成员才能发言,加入小组>>
156个成员聚集在这个小组
加入小组【Vision Board创客营连载体验】基于RA8D1-Vision Board的自动路径规划小车
901 浏览 0 评论
【Vision Board创客营连载体验】基于Vision Board的垃圾分类
1305 浏览 0 评论
【Vision Board创客营连载体验】使用 Vision Board 做一个 UVC Camera
935 浏览 0 评论
【Vision Board创客营连载体验】TinyMaix进行手写数字识别
1198 浏览 0 评论
【Vision Board创客营连载体验】RA8D1-Vision Board使用7寸屏设置为RGB666大端模式模式成功显示摄像头图案
1206 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 12:23 , Processed in 0.714073 second(s), Total 80, Slave 63 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号