这几天在做SMT32F407 ADC转换功能,遇到一些个人觉得比较诡异的问题,抛出给大家看看,不知道哪位遇到过,盼指导。
用STM32F407的ADC采样触摸屏信号。
MDK 2级优化
在单独做ADC功能的时候,完全正常。
后面加入了其他功能,例如文件系统,SD卡驱动。
现象1
加入这些后,ADC读到的数据全部不对,理论上ADC最大就是4095,现在确能读出几万的值(ADC读回来的是U16)。
这时如果屏蔽一些代码,例如WM8978的代码,ADC又正常了。
就算不屏蔽代码,将优化等级改为0,也正常。
当时没有再深入处理。
现象2
到今天,决定解决这个问题。优化等级保留2。
多次调试后发现,只要把nvic配置直接放到adc初始化里面,从ADC读出来的数值就不对。只要单独封一个函数,在ADC初始化里面调用,就正常。
- s32 mcu_adc_config_nvic(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
-
- NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /**
- *@brief: mcu_adc_init
- *@details: adc初始化,用于电阻触摸屏检测
- *@param[in] void
- *@param[out] 无
- *@retval: static
- */
- void mcu_adc_init(void)
- {
- ADC_InitTypeDef ADC_InitStructure;
- ADC_CommonInitTypeDef ADC_CommonInitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);//使能ADC 时钟
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使用GPIOB时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//---模拟模式
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//---不上下拉
- GPIO_Init(GPIOB, &GPIO_InitStructure);//---初始化 GPIO
- ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
- ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;//两个采样阶段之间的延迟 5 个时钟
- ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA 失能
- ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;//预分频 6分频。
- ADC_CommonInit(&ADC_CommonInitStructure);//初始化
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12 位模式
- ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式
- ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//非连续转换
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
- ADC_InitStructure.ADC_NbrOfConversion = 1;//1 个转换在规则序列中, 也就是说一次转换一个通道
- ADC_Init(ADC2, &ADC_InitStructure);//ADC 初始化
- mcu_adc_config_nvic();
- ADC_ITConfig(ADC2, ADC_IT_EOC, ENABLE);
- ADC_ClearFlag(ADC2, ADC_FLAG_EOC);
- ADC_Cmd(ADC2, ENABLE);
-
- }
复制代码 用CMSIS DAP看了一下汇编,如果不封成函数的情况如下,出现两次重复(实际是不是重复,不确定,看不太懂),如果封成函数,就只有一次。
- 0x0800BC4C 9402 STR r4,[sp,#0x08]
- 58: ADC_InitStructure.ADC_NbrOfConversion = 1;//1 ¸öת»»ÔÚ¹æÔòÐòÁÐÖÐ, Ò²¾ÍÊÇ˵һ´Îת»»Ò»¸öͨµÀ
- 0x0800BC4E 9404 STR r4,[sp,#0x10]
- 59: ADC_Init(ADC2, &ADC_InitStructure);//ADC ³õʼ»¯
- 60:
- 0x0800BC50 4C09 LDR r4,[pc,#36] ; @0x0800BC78
- 58: ADC_InitStructure.ADC_NbrOfConversion = 1;//1 ¸öת»»ÔÚ¹æÔòÐòÁÐÖÐ, Ò²¾ÍÊÇ˵һ´Îת»»Ò»¸öͨµÀ
- 0x0800BC52 F88D5014 STRB r5,[sp,#0x14]
- 59: ADC_Init(ADC2, &ADC_InitStructure);//ADC ³õʼ»¯
复制代码
现象3
请教下面两种写法对代码编译优化有什么影响?
代码1,功能正常
- s32 dev_touchscreen_init(void)
- {
- return dev_ts_adc_init();
- }
复制代码 代码2,功能不正常
- s32 dev_touchscreen_init(void)
- {
- dev_ts_adc_init();
- return 0;
- }
复制代码
通常我们要的优化问题,都是变量被优化,只要加上volatile就解决问题了。
这些几个问题比较困惑。
不知是否有对优化比较熟悉的朋友指点一二。
先谢!
|
adc,同步触发采样,采集电机的电流,我不接电机的情况下,采集底噪在设置不同的优化等级下不一样,比较诡异的是:
比如我现在设置的0级优化,底噪感觉正常的,但是我加了一些代码之后,还是0级优化就不正常了,
然后我就不断的改优化等级,可能是3级优化正常,然后我又改点和这个adc无关的代码,可能这时候原来正常的优化等级又不正常了,
这时候又要试一遍,可能遇到优化等级2又是正常的,
adc的底噪是正常的时候大约在10lsb以内,不正常的就是有很大的跳变,如图:
底噪正常的:试到优化等级1正常
åºåªæ£å¸¸ ä¼åç级1
底噪异常的:优化等级0,2,3异常
åºåªå¼å¸¸ ä¼åç级0ï¼2ï¼3
意思就是说每次我增加了一点代码,或者删除了一点代码,当然是和adc无关的代码,我需要不断的调优化等级,可能找到一种优化等级保证adc的噪声是正常的
理由:1)去掉某部分,相当于排除了部分内存,造成内存有多余。
2)加 volatile 定义 的变量不会被优化掉。有客观保护该变量的意思,
3) ADC单独封一个函数,也相当于 ADC 结果变量 被保护了。
内存泄漏或分配乱指向 都比较像造成某个值异常。
多谢指点,警告确实是个问题。我的代码确实有些警告没清理,回头清理完了在研究研究这个问题。
点评
评分
查看全部评分
KEIL-MDKä¼åç级设置
评分
查看全部评分
里面讲的很清楚。
评分
查看全部评分
所以,一般,我使用 局部优化
#pragma OPTIMIZE(x)
来指定对某段代码的优化级别。
不同的代码,使用不同的优化级别。
使用方法,见付件第4页。
评分
查看全部评分
请指教,特别现象3,实在想不明白。
感谢
评分
查看全部评分
评分
查看全部评分