第51节:利用ADC0832采集电压信号进行滤波处理
unsigned long ulTempFilterV=0; //参与换算的中间变量
unsigned long ulBackupFilterV=5000; //备份最新采样数据的中间变量
unsigned char ucSamplingCnt=0; //记录连续N次采样的计数器
unsigned long ulV=0; //未经滤波处理的实时电压值
unsigned long ulFilterV=0; //经过滤波后的实时电压值
//根据原理图得出的共阴数码管字模表
code unsigned char dig_table[]=
{
0x3f, //0 序号0
0x06, //1 序号1
0x5b, //2 序号2
0x4f, //3 序号3
0x66, //4 序号4
0x6d, //5 序号5
0x7d, //6 序号6
0x07, //7 序号7
0x7f, //8 序号8
0x6f, //9 序号9
0x00, //无 序号10
0x40, //- 序号11
0x73, //P 序号12
};
void main()
{
initial_myself();
delay_long(100);
initial_peripheral();
while(1)
{
ad_sampling_service(); //AD采样与处理的服务程序
display_service(); //显示的窗口菜单服务程序
}
}
void ad_sampling_service(void) //AD采样与处理的服务程序
{
unsigned char i;
ucAD=0; //AD值
ucCheckAD=0; //用来做校验对比的AD值
/* 片选信号置为低电平 */
adc0832_cs_dr = 0;
/* 第一个脉冲,开始位 */
adc0832_data_sr_dr = 1;
adc0832_clk_dr = 0;
delay_short(1);
adc0832_clk_dr = 1;
/* 第二个脉冲,选择通道 */
adc0832_data_sr_dr = 1;
adc0832_clk_dr = 0;
adc0832_clk_dr = 1;
/* 第三个脉冲,选择通道 */
adc0832_data_sr_dr = 0;
adc0832_clk_dr = 0;
adc0832_clk_dr = 1;
/* 数据线输出高电平 */
adc0832_data_sr_dr = 1;
delay_short(2);
/* 第一个下降沿 */
adc0832_clk_dr = 1;
adc0832_clk_dr = 0;
delay_short(1);
/* AD值开始送出 */
for (i = 0; i < 8; i++)
{
ucAD <= 1;
adc0832_clk_dr = 1;
adc0832_clk_dr = 0;
if (adc0832_data_sr_dr==1)
{
ucAD |= 0x01;
}
}
/* 用于校验的AD值开始送出 */
for (i = 0; i < 8; i++)
{
ucCheckAD >>= 1;
if (adc0832_data_sr_dr==1)
{
ucCheckAD |= 0x80;
}
adc0832_clk_dr = 1;
adc0832_clk_dr = 0;
}
/* 片选信号置为高电平 */
adc0832_cs_dr = 1;
if(ucCheckAD==ucAD) //检验相等
{
ulTemp=0; //把char类型数据赋值给long类型数据之前,必须先清零
ulTemp=ucAD; //把char类型数据赋值给long类型数据,参与乘除法运算的数据,为了避免运算结果溢出,我都用long类型
/* 注释一:
* 因为保留3为小数点,这里的5000代表5.000V。ulTemp/255代表分辨率.
* 有些书上说8位AD最高分辩可达到256级(0xff+1),我认为这种说法是错误的。
* 8位AD最高分辩应该是255级(0xff),所以这里除以255,而不是256.
*/
ulTemp=5000*ulTemp/255; //进行电压换算
ulV=ulTemp; //得到未经滤波处理的实时电压值
ucWd1Part1Update=1; //局部更新显示未经滤波处理的电压
/* 注释二:
* 以下连续判断N次一致性的滤波法,为了避免末尾小数点的数据偶尔跳动。
* 这种滤波方法的原理跟我在按键扫描中的去抖动原理是一模一样的,被我频繁
* 地应用在大量的工控项目中。
* 具体原理:当某个采样变量发生变化时,有两种可能,一种可能是外界的一个瞬间干扰。
* 另一种可能是变量确实发生变化。为了有效去除干扰,当发现变量有变化时,
* 我会连续采集N次,如果连续N次都是一致的结果,我才认为不是干扰。如果中间
* 只要出现一次不一致,我会马上把计数器清零,这一步是精华,很关键。
*
*/
if(ulTempFilterV!=ulTemp) //发现变量有变化
{
ucSamplingCnt++; //计数器累加
if(ucSamplingCnt>const_N) //如果连续N次都是一致的,则认为不是干扰。确实有数据需要更新显示。这里的const_N取值是8
{
ucSamplingCnt=0;
ulTempFilterV=ulTemp; //及时保存更新了的数据,方便下一次有新数据对比做准备
ulFilterV=ulTempFilterV; //得到经过滤波处理的实时电压值
ucWd1Part2Update=1; //局部更新显示经过滤波处理的电压
}
}
else
{
ucSamplingCnt=0; //只要出现一次不一致,我会马上把计数器清零,这一步是精华,很关键。
}
}
}
void display_service(void) //显示的窗口菜单服务程序
{
if(ucWd1Part1Update==1)//未经滤波处理的实时电压更新显示
{
ucWd1Part1Update=0;
ucTemp8=ulV%10000/1000; //显示电压值个位
ucTemp7=ulV%1000/100; //显示电压值小数点后第1位
ucTemp6=ulV%100/10; //显示电压值小数点后第2位
ucTemp5=ulV%10; //显示电压值小数点后第3位
ucDigShow8=ucTemp8; //数码管显示实际内容
ucDigShow7=ucTemp7;
ucDigShow6=ucTemp6;
ucDigShow5=ucTemp5;
}
if(ucWd1Part2Update==1)//经过滤波处理后的实时电压更新显示
{
ucWd1Part2Update=0;
ucTemp4=ulFilterV%10000/1000; //显示电压值个位
ucTemp3
ADC0832电压信号滤波处 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)