打印
[MCU]

真诚求助,求建议,奇怪的问题

[复制链接]
楼主: haohaodee
手机看帖
扫描二维码
随时随地手机跟帖
21
linqing171| | 2018-3-28 21:57 | 只看该作者 回帖奖励 |倒序浏览
printf的堆栈可能比你后面的函数的堆栈用的深,你用pc-lint报一下,看看是不是有没有初值的变量?
crt中的printf还有几个全局变量,比如stdin这个FILE*,如果你不用printf,它就不链接了,你用了,系统的ram就会变大这个结构体大小。

使用特权

评论回复
22
泰山特曲123| | 2018-3-28 22:58 | 只看该作者
把printf换成同样时间的delay,也会吗?如果会,可能是算法出问题了。监测算法里面的数据,看是在算法那一步出现异常。总而言之,逐步缩小范围,将无关代码暂时屏蔽。

使用特权

评论回复
23
haohaodee|  楼主 | 2018-3-29 00:34 | 只看该作者
linqing171 发表于 2018-3-28 21:57
printf的堆栈可能比你后面的函数的堆栈用的深,你用pc-lint报一下,看看是不是有没有初值的变量?
crt中的p ...

只是在进主程序前printf,控制的时候printf延时肯定会抖的。我说printf的意思是向表达,不管在程序哪里加一些无关代码,就会引起截然不同的效果。

pc-lint已经过了。

使用特权

评论回复
24
haohaodee|  楼主 | 2018-3-29 19:55 | 只看该作者
linqing171 发表于 2018-3-28 21:57
printf的堆栈可能比你后面的函数的堆栈用的深,你用pc-lint报一下,看看是不是有没有初值的变量?
crt中的p ...

现在我在主程序之前加296个nop指令,飞机就飞稳了,如果295个就很抖。多于296个就稳,少于296个就抖动。

比较295和296的汇编可以得到有用信息吗?
@ayb_ice

使用特权

评论回复
25
linqing171| | 2018-3-29 23:03 | 只看该作者
haohaodee 发表于 2018-3-29 19:55
现在我在主程序之前加296个nop指令,飞机就飞稳了,如果295个就很抖。多于296个就稳,少于296个就抖动。
...

上电之前的AD或者DA的参考源不稳定? 电源不稳定?
单看nop,应该看不出来。

使用特权

评论回复
26
haohaodee|  楼主 | 2018-3-30 11:16 | 只看该作者
本帖最后由 haohaodee 于 2018-3-30 11:25 编辑


现在我在主程序之前加296个nop指令,飞机就飞稳了,如果295个就很抖。多于296个就稳,少于296个就抖动。

比较295和296的.map文件,nop所在的main()函数size增大了4个字节,其后的函数地址都后推了4个字节。


另外,同一个代码,在这台电脑上编译,飞机抖动;换到另一台电脑的另一个版本keil编译,飞机就很稳。
比较两个编译出来的.map文件,也是有一个函数的地址比另一个版本后移了4个字节。

我现在严重怀疑真的是编译器或者arm系的一个缺陷。

@苏山人家

使用特权

评论回复
27
runningwzf| | 2018-3-30 14:52 | 只看该作者
直觉是printf意外帮你初始化了一些变量,建议你检查一下变量是否赋初值。另外使用printf造成了一定的延时,刚好帮助传感器稳定,也是有可能的,只是可能性很小
至于你说的不同版本的keil编译出来的有差异,其实这个不奇怪,不同编译器的优化程度不一样。比如你用了空转的循环延时,或者你使用了keil自带的库

使用特权

评论回复
28
ta1ent| | 2018-3-30 15:25 | 只看该作者
haohaodee 发表于 2018-3-28 17:03
明白,但不是这个问题。有printf时,只是启动的时候printf,以后就没有了。 ...

感觉是上电启动的时候传感器需要稳定一段时间呢。
你把printf()换成delay()试试。

使用特权

评论回复
29
科技猎人| | 2018-3-30 19:33 | 只看该作者
可能是进入主循环前,某个初始化需要延时一定时间才完成。

使用特权

评论回复
30
苏山人家| | 2018-3-30 21:58 | 只看该作者
haohaodee 发表于 2018-3-30 11:16
现在我在主程序之前加296个nop指令,飞机就飞稳了,如果295个就很抖。多于296个就稳,少于296 ...

加nop就好,我很怀疑是不是你的陀螺仪初始化还没有完全你就读数造成你初始对准姿态错误,或者是别的什么传感器初始化没有完全,你就读取了,比如加速度等

使用特权

评论回复
评论
simonliu009 2018-3-30 23:41 回复TA
同意,可以考虑把nop改为delay()看看 
31
haohaodee|  楼主 | 2018-3-31 00:06 | 只看该作者
linqing171 发表于 2018-3-28 21:51
你用pc-lint检查你的代码了吗?
printf除了慢,还有就是耗内存也大。
看你的描述,还是像有其它函数的局 ...

不只是printf,别的没用的if(float a = 0.0f; float b = a + 3.0f;)这句都会引起。
“局部变量被你用指针传出来”是指什么情况啊?能不能举个例子,很可能是这种问题。
我程序中有下面例子的代码,总不会是你说的指针传出了局部变量吧。
void f(float * a, float *b){
  float tmp[2] = {2,3};
  *a = tmp[0];
  *b = tmp[1]+1.0f;
}
main(){
  float data, beta;
f(&data,&beta)
}
中断里尽量避免多写代码,这个设计时注意到了。
没有浮点运算单元的。

是可以记录抖动,用无线透传把数据发回来,我已经记录分析了,可惜真心没找到哪里出问题了,本来我们做飞控的对这个很在行的,原谅我没找出来。

有这么牛叉的视频方案啊。

使用特权

评论回复
32
haohaodee|  楼主 | 2018-3-31 00:08 | 只看该作者
runningwzf 发表于 2018-3-30 14:52
直觉是printf意外帮你初始化了一些变量,建议你检查一下变量是否赋初值。另外使用printf造成了一定的延时, ...

你说的初始化了一些变量是指全局变量,局部变量还是。。。
不是传感器稳定的问题,传感器都delay了;关键是在别的地方加也会引起变化的

使用特权

评论回复
33
haohaodee|  楼主 | 2018-3-31 00:10 | 只看该作者
苏山人家 发表于 2018-3-30 21:58
加nop就好,我很怀疑是不是你的陀螺仪初始化还没有完全你就读数造成你初始对准姿态错误,或者是别的什么 ...

在nop之前都有delay的,关键是即使while(1)之前不加,在while以内别的不会影响姿态的地方加也会引起变抖或者变稳的

使用特权

评论回复
34
619888476| | 2018-3-31 10:52 | 只看该作者
增加延时试试,可能需要时间稳定

使用特权

评论回复
35
liunian00| | 2018-3-31 10:53 | 只看该作者
可以看看源代码吗?

使用特权

评论回复
36
haohaodee|  楼主 | 2018-3-31 11:25 | 只看该作者
本帖最后由 haohaodee 于 2018-3-31 11:48 编辑
liunian00 发表于 2018-3-31 10:53
可以看看源代码吗?

可以啊,你有什么思路吗

使用特权

评论回复
37
haohaodee|  楼主 | 2018-3-31 11:27 | 只看该作者
可不可以排除了野指针的问题?野指针会不会可能造成这种现象?

使用特权

评论回复
38
苏山人家| | 2018-3-31 12:18 | 只看该作者
haohaodee 发表于 2018-3-31 00:10
在nop之前都有delay的,关键是即使while(1)之前不加,在while以内别的不会影响姿态的地方加也会引起变抖 ...

没有代码看不出来了,建议你这样
1.局部变量必须给初值
2.一般单片机里的堆申请不可重入所以检查中断里面有没有内存申请或者加全局中断做临界区
3.自己写的函数是否存在重入的可能
4.指针释放必须赋NULL
正如楼上各位大佬说的,编译器一般都不会出错的,C语言很成熟了,MDK也是佼佼者,所以软件的坑一般人是没有机会踩的。只要编程者有良好的编写规范就好。
另外,您说在while里面加也会出现这样的问题,个人觉得问题可能就是两个方面
1.内存问题(指针,堆,全局等)
2.时间(比如本来姿态积分是等间隔,因为某些原因时间间隔不稳定造成积分误差太大等,或者某些频繁中断的地方执行时间过长造成cpu负载过大等等)
希望你可以从这两方面排查一下

使用特权

评论回复
39
苏山人家| | 2018-3-31 12:25 | 只看该作者
如果使用动态申请强烈建议自己封装一下,保证不可重入还有内存释放后NULL
下面已经给你写好代码了,一定要用,也非常建议各位使用动态申请的工程师这样用,除非使用rtos等接管内存管理的。
void* MALLOC(size_t size)
{
void* p = NULL;
__disable_irq()
p = malloc(size);
__enable_irq()
return p;
}

void FREE(void* p)
{
__disable_irq();
free(p)
p = NULL;
__enable_irq();
}

使用特权

评论回复
评论
linqing171 2018-3-31 23:09 回复TA
__disable_irq 这个内置函数,在有些情况下有使用范围,具体见keil帮助。 
40
haohaodee|  楼主 | 2018-3-31 14:38 | 只看该作者
本帖最后由 haohaodee 于 2018-3-31 14:46 编辑
苏山人家 发表于 2018-3-31 12:18
没有代码看不出来了,建议你这样
1.局部变量必须给初值
2.一般单片机里的堆申请不可重入所以检查中断里面 ...

1. 我先保证局部变量都赋初值。
2. 中断里面确认没有内存申请,但有memcpy,把中断接收到的数据copy出来,应该没问题吧。
3. 使用好多全局变量。
4. 只用了一组malloc,free后都赋值NULL了。并且malloc只有特定情况才用,而现在我可以保证malloc没执行的情况下也会变抖或变稳。

我也怀疑是内存的问题,是不是指针用错了。
但我全程序没有主动申请指针,都是申请一个变量或者结构体,然后&取地址给函数做实参。
另外有一个
typedef structure{
  int a;
  float b;
  uint8_t *p;
} data_s;
data_s data: // 申请全局变量
uint8_t addr_tmp = 0;  // 全局变量
然后初始化data.p=&addr_tmp;
以后使用就是data.p=&array_globle_{i};  // 全局数组,为方括号,方括号打不上用大括号代替

另外,全局有什么注意的,就是要初始化了吧。

时间间隔没问题,专门测过了,排查过了,不会引起时间间隔的变化。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则