第50节:利用ADC0832采集电压信号,用平均法和区间法进行软件滤
标志
unsigned char ucTemp1=0; //中间过渡变量
unsigned char ucTemp2=0; //中间过渡变量
unsigned char ucTemp3=0; //中间过渡变量
unsigned char ucTemp4=0; //中间过渡变量
unsigned char ucTemp5=0; //中间过渡变量
unsigned char ucTemp6=0; //中间过渡变量
unsigned char ucTemp7=0; //中间过渡变量
unsigned char ucTemp8=0; //中间过渡变量
unsigned char ucAD=0; //AD值
unsigned char ucCheckAD=0; //用来做校验对比的AD值
unsigned long ulTemp=0; //参与换算的中间变量
unsigned long ulTempFilterV=0; //参与换算的中间变量
unsigned long ulBackupFilterV=5000; //备份最新采样数据的中间变量
unsigned char ucSamplingCnt=0; //统计采样的次数 本程序采样8次后求平均值
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; //局部更新显示未经滤波处理的电压
ulTempFilterV=ulTempFilterV+ulTemp; //累加8次后求平均值
ucSamplingCnt++; //统计已经采样累计的次数
if(ucSamplingCnt>=8)
{
/* 注释二:
* 求平均值滤波法,为了得到的数据更加圆滑,去除小毛刺。
* 向右边移动3位相当于除以8。
*/
ulTempFilterV=ulTempFilterV>>3; //求平均值滤波法
/* 注释三:
* 以下区间滤波法,为了避免末尾小数点的数据频繁跳动。
* 这里的20用于区间滤波法的正负偏差,这里的20代表0.020V。
* 意思是只要最近采集到的数据在正负0.020V偏差范围内,就不更新。
*/
if(ulBackupFilterV>=20) //最近备份的上一次数据大于等于0.02V的情况下
{
if(ulTempFilterV<(ulBackupFilterV-20)||ulTempFilterV>(ulBackupFilterV+20)) //在正负0.020V偏差范围外,更新
{
ulBackupFilterV=ulTempFilterV; //备份最新采样的数据,方便下一次对比判断
ulFilterV=ulTempFilterV; //得到经过滤波处理的实时电压值
ucWd1Part2Update=1; //局部更新显示经过滤波处理的电压
}
}
else //最近备份的上一次数据小于0.02V的情况下
{
if(ulTempFilterV>(ulBackupFilterV+20)) //在正0.020V偏差范围外,更新
{
ulBackupFilterV=ulTempFilterV; //备份最新采样的数据,方便下一次对比判断
ulFilterV=ulTempFilterV; //得到经过滤波处理的实时电压值
ucWd1Part2Update=1;
ADC0832电压信号软件滤 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)