实验一 滤波器多次滤波求平均值
实验目的
1、学习和掌握A/D转换的几种方法
2、学会运用数字滤波和设计滤波器
实验步骤
1、通过调节电路电阻等效进行温度输入
2、利用A/D转换将模拟量转化为数字量、通过0809芯片显示
3、在基于A/D转换的基础上,实现滤波器多次采样后求取平均值
实验原理
A/D转换器
它是用来通过一定的电路将模拟量转变为数字量。
模拟量可以是电压、电流等电信号,也可以是压力、温度、湿度、位移、声音等非电信号。但在A/D转换前,输入到A/D转换器的输入信号必须经各种传感器把各种物理量转换成电压信号。
A/D转换后,输出的数字信号可以有8位、10位、12位和16位等。
A/D转换器的工作原理 主要介绍以下三种方法:逐次逼近法 双积分法 电压频率转换法
A/D转换四步骤:采样、保持、量化、编码。
数字滤波器
与模拟滤波器相对应,在离散系统中广泛应用数字滤波器。它的作用是利用离散时间系统的特性对输入信号波形或频率进行加工处理。或者说,把输入信号变成一定的输出信号,从而达到改变信号频谱的目的。数字滤波器一般可以用两种方法来实现:一种方法是用数字硬件装配成一台专门的设备,这种设备称为数字信号处理机;另一种方法就是直接利用通用计算机,将所需要的运算编成程序让通用计算机来完成,即利用计算机软件来实现。
本实验采用算术平均值滤波。
方法:
连续取N个采样值进行算术平均运算
N值较大时:信号平滑度较高,但灵敏度较低
N值较小时:信号平滑度较低,但灵敏度较高
N值的选取:一般流量,N=12;压力:N=4
优点:
适用于对一般具有随机干扰的信号进行滤波
这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动
缺点:
对于测量速度较慢或要求数据计算速度较快的实时控制不适用
比较浪费RAM
实验源程序
/* “验证式” 温度测量与数字滤波*/
#include #define LEDLen 6 #define MODE 0x03 #define N 12 ;取十二次求得平均值 #define CS0809 XBYTE[0xa000] #define CAddr XBYTE[0xe100] /* 命令控制口 */ #define OUTBIT XBYTE[0xe101] /* 位控制口 */ #define CLK164 XBYTE[0xe102] /* 段控制口(接164时钟位) */ #define DAT164 XBYTE[0xe102] /* 段控制口(接164数据位) */ #define IN XBYTE[0xe103] /* 键盘读入口 */ unsigned char LEDBuf[LEDLen]; /* 显示缓冲 */ code unsigned char LEDMAP[] = { /* 八段管显示码 */ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 }; void Delay(unsigned char CNT) { unsigned char i; while (CNT-- !=0) for (i=100; i !=0; i--); } void DisplayLED() { unsigned char i, j; unsigned char Pos; unsigned char LED; Pos = 0x20; /* 从左边开始显示 */ for (i = 0; i < LEDLen; i++) { OUTBIT = 0; /* 关所有八段管 */ LED = LEDBuf[i]; for (j = 0; j < 8; j++) { /* 送164 */ if (LED & 0x80) DAT164 = 1 ; else DAT164 = 0 ; CLK164 = CLK164| 0X02; CLK164 = CLK164& 0Xfd; LED <<= 1; } OUTBIT = Pos; /* 显示一位八段管 */ Delay(1); Pos >>= 1; /* 显示下一位 */ } OUTBIT = 0; /* 关所有八段管 */ } unsigned char Read0809() { unsigned char i; CS0809 = 0; /* 起动 A/D */ for (i=0; i<0x20; i++) ; return(CS0809); } void main() { unsigned char j; unsigned char b; CAddr= MODE; while(1) { LEDBuf[0] = 0Xb8; /* 延时 > 100us */ /* 读入结果 */ LEDBuf[1] = 0X40; LEDBuf[2] = 0X40; LEDBuf[3] = 0X40; LEDBuf[4] = 0X00; LEDBuf[5] = 0X00; //b = Read0809(); char filter() { unsigned int sum = 0; unsigned char i; for (i=0;i sum + = Read0809(); ;平均值滤波程序 delay(); } return(char)(sum/N); } LEDBuf[5] = LEDMAP[filter() & 0x0f] ; LEDBuf[4] = LEDMAP[filter()>>4 & 0x0f] ; for(j=0; j<5; j++) DisplayLED(); /* 延时 */ } } 实验总结: 通过本次试验,让我知道了实验的重要性,在实验过程中,调试很关键,程序能否按照预期的运行以及怎么修改,都得通过调试之后才能知道,而且我认为调试是一个比较难的环节,自己找自己的问题不是一件容易的事情。 实验二 智能温度控制系统 实验目的 1. 学习和熟练运用keil usion软件 2. 学习了解A/D采样 3. 学习矩阵键盘输入的规律和编程思路了解,并掌握利用行列扫描法读取按键信息及软件消抖的方法。 实验步骤 利用AD采样测温度 键盘驶入给定值,同时显示设定值和温度 通过LED灯控制 实验原理 A/D转换器 它是用来通过一定的电路将模拟量转变为数字量。 模拟量可以是电压、电流等电信号,也可以是压力、温度、湿度、位移、声音等非电 信号。但在A/D转换前,输入到A/D转换器的输入信号必须经各种传感器把各种物理量转换成电压信号。 A/D转换后,输出的数字信号可以有8位、10位、12位和16位等。 A/D转换器的工作原理 主要介绍以下三种方法:逐次逼近法 双积分法 电压频率转换法 A/D转换四步骤:采样、保持、量化、编码。 矩阵式键盘的结构与工作原理 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。 矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输入端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。 实验源程序如下 /* \"验证式? 键盘扫描显示和智能温控 */ #include #define LEDLen 6 #define mode 0x03; #define CAddr XBYTE[0xe100]/* 控制字地址 */ #define OUTBIT XBYTE[0xe101]/* 位控制口 */ #define CLK164 XBYTE[0xe102]/* 段控制口(接164时钟位) */ #define DAT164 XBYTE[0xe102] /* 段控制口(接164数据位) */ #define IN XBYTE[0xe103] /* 键盘读入口 */ unsigned char LEDBuf[LEDLen]; /* 显示缓冲 */ code unsigned char LEDMAP[] = { /* 八段管显示码 */ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 }; /* A/D转换 */ unsigned char Read0809() { unsigned char i; CS0809 = 0; /* 起动 A/D */ for (i=0; i<0x20; i++) ; /* 延时 > 100us */ return(CS0809); /* 读入结果 */ } void Delay(unsigned char CNT) { unsigned char i; while (CNT-- !=0) for (i=100; i !=0; i--); } void DisplayLED() { unsigned char i, j; unsigned char Pos; unsigned char LED; Pos = 0x20; /* 从左边开始显示 */ for (i = 0; i < LEDLen; i++) { OUTBIT = 0; /* 关所有八段管 */ LED = LEDBuf[i]; for (j = 0; j < 8; j++) { /* 送164 */ if (LED & 0x80) DAT164 = 1; else DAT164 = 0; CLK164 = CLK164|0x02; CLK164 = CLK164&0xfd; LED <<= 1; } OUTBIT = Pos; /* 显示一位八段管 */ Delay(1); Pos >>= 1; /* 显示下一位 */ } } code unsigned char KeyTable[] = { /* 键码定义 */ 0x00, 0x01, 0x04, 0x07 , 0x0f, 0x02, 0x05, 0x08, 0x0e, 0x03, 0x06, 0x09 , 0x0d, 0x0c, 0x0b, 0x0a , 0x10,0x11,0x12,0x13,0x14, 0x15,0x16, }; unsigned char TestKey() { OUTBIT = 0; /* 输出线置为0 */ return (~IN & 0x0f); /* 读入键状态 (高四位不用) */ } unsigned char GetKey() { unsigned char Pos; unsigned char i; unsigned char k; i = 6; Pos = 0x20; /* 找出键所在列 */ do { OUTBIT = ~ Pos; Pos >>= 1; k = ~IN & 0x0f; } while ((--i != 0) && (k == 0)); /* 键值 = 列 X 4 + 行 */ if (k != 0) { i *= 4; if (k & 2) i += 1; else if (k & 4) i += 2; else if (k & 8) i += 3; OUTBIT = 0; do Delay(10); while (TestKey()); /* 等键释放 */ return(KeyTable[i]); /* 取出键码 */ } else return(0xff); } void main() { CAddr = mode; LEDBuf[0] = 0xff; LEDBuf[1] = 0xff; LEDBuf[2] = 0xff; LEDBuf[3] = 0xff; LEDBuf[4] = 0x00; LEDBuf[5] = 0x00; while (1) { LEDBuf[5] = LEDMAP[Read0809() & 0x0f] ; LEDBuf[4] = LEDMAP[Read0809()>>4 & 0x0f] ; DisplayLED(); if(Read0809()>wendu) kongzhideng=0; //*控制灯明灭*// else kongzhideng=1; } } 实验总结: 此次实验做得不是很成功,最开始的时候忘记了怎么建工程,怎么载入程序,而且所编的程序和出来的现象不一致,但是还是学得到了不少知识,至少很清晰的了解到了矩阵键盘的工作原理和编程思路,也复习了一遍keil usion软件的操作。 因篇幅问题不能全部显示,请点此查看更多更全内容