思路大概就是先定义一个get_adc_average的函数,在函数里用
for(t=0;t<times;t++)
{
temp_val+=Get_Adc();
}
实现求平均值。然后Get_Adc()程序如下:
u16 Get_adc()
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_56Cycles);; //ADC1,ADC通道,采样时间为239.5周期
ADC_Cmd(RHEOSTAT_ADC, ENABLE);
ADC_SoftwareStartConv(RHEOSTAT_ADC); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
编译正常。然后运行的时候发现屏幕显示一次数后就不跳变了。
然后用野火的仿真器硬件仿真。发现程序卡死在while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));一直出不来。
参考官方库,发现对ADC_GetFlagStatus就是:
if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET)
{
/* ADC_FLAG is set */
bitstatus = SET;
}
else
{
/* ADC_FLAG is reset */
bitstatus = RESET;
}
return bitstatus;
然后在看while内的内容,就是要求执行else后的程序段, 就是要求(ADCx->SR & ADC_FLAG)=0
其中根据我设置好的ADC_FLAG_EOC是0x02,即二进制的10.而sr寄存器对应的该位的确是EOC.
还有在f429的参考手册中EOC置位表示转化已完成。所以这样配置应该没有错啊。
然后吊诡的事情是当我把while里面的!去掉的时候再次硬件调试,发现程序依旧卡死在while里面。
然后分析到这里就分析不下去了,所以就在这里问如下三个问题:
1. 为什么会卡在这里并且怎么解决?
2.为什么我将!去掉之后仍然是这种情况。
3.对于sr的相关位我发现都是硬件配置,我可以通过软件来配置吗?
我把这个问题放在论坛上好几天,但是没有人来回答我。于是我开始自己想办法。
既然程序是卡在while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));,那么我能不能不调用这个语句而实现连续读取adc值得功能呢?
答案是肯定的。
我们可以将adc的读取函数写在adc转化中断里。因为每次adc读取完毕都可以触发中断,也就是触发中断的时候一定是完成adc转化的时候,所以就自然不用用while来判断adc是否转化完毕。具体的配置就是adc使能转化完毕中断,adc采用连续转化模式。
中断里的代码如下:
if(ADC_GetITStatus(RHEOSTAT_ADC,ADC_IT_EOC)==SET)
{
if(i!=10)
{
// 读取ADC的转换值
V+= ADC_GetConversionValue(RHEOSTAT_ADC);
i++;
}
else
{
ADC_ConvertedValue=V/(float)(10.0);
i=0;
V=0;
}
}
ADC_ClearITPendingBit(RHEOSTAT_ADC,ADC_IT_EOC);
}
这里在函数里定义char i和float V;i用来实现计算转化次数的功能,然后V用来实现存储每次数据的功能。而ADC_ConvertedValue则是在main.c里定义的一个外部变量。这里就用中断实现了求平均值来求adc的精确值。
然后这回其实最大的收获是以后在移植程序出现问题的时候,会不在纠结问题出在那里,而是试图去尝试自己写一段代码来解决问题。