实验目的
1. 利用所学知识,解决实际问题。培养发现问题解决、问题的能力。
2. 学会如何利用误差理论处理测得的数据。
实验器材
HC6800单片机开发仪,KENKO牌KK-82MS型科学计算器
实验原理
1.HC6800中的18B20模块以及18B20电路图
18B20驱动程序
#include
#include
sbit D18B20=P3^7;
#define NOP() _nop_() /* 定义空指令*/
#define _Nop() _nop_() /*定义空指令*/
voidTempDelay (unsigned char idata us);
voidInit18b20 (void);
voidWriteByte (unsigned char idata wr); //单字节写入
voidread_bytes (unsigned char idata j);
unsignedchar CRC (unsigned char j);
voidGemTemp (void);
voidConfig18b20 (void);
voidReadID (void);
voidTemperatuerResult(void);
bit flag;
unsignedint idata Temperature;
unsignedchar idata temp_buff[9]; //存储读取的字节,read scratchpad为字节,read rom ID为字节
unsignedchar idata id_buff[8];
unsignedchar idata *p;
externunsigned int xdata TIM;
unsignedchar idata crc_data;
unsignedchar code CrcTable [256]={
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
//
/************************************************************
*Function:延时处理
*parameter:
*Return:
*Modify:
*************************************************************/
voidTempDelay (unsigned char idata us)
{
while(us--);
}
/************************************************************
*Function:18B20初始化
*parameter:
*Return:
*Modify:
*************************************************************/
voidInit18b20 (void)
{
D18B20=1;
_nop_();
D18B20=0;
TempDelay(80); //delay 530 uS//80
_nop_();
D18B20=1;
TempDelay(14); //delay 100 uS//14
_nop_();
_nop_();
_nop_();
if(D18B20==0)
flag = 1; //detect 1820 success!
else
flag = 0; //detect 1820 fail!
TempDelay(20); //20
_nop_();
_nop_();
D18B20 = 1;
}
/************************************************************
*Function:向B20写入一个字节
*parameter:
*Return:
*Modify:
*************************************************************/
voidWriteByte (unsigned char idata wr) //单字节写入
{
unsigned char idata i;
for (i=0;i<8;i++)
{
D18B20 = 0;
_nop_();
D18B20=wr&0x01;
TempDelay(3); //delay 45 uS //5
_nop_();
_nop_();
D18B20=1;
wr >>= 1;
}
}
/************************************************************
*Function:读B20的一个字节
*parameter:
*Return:
*Modify:
*************************************************************/
unsignedchar ReadByte (void) //读取单字节
{
unsigned char idata i,u=0;
for(i=0;i<8;i++)
{
D18B20 = 0;
u >>= 1;
D18B20 = 1;
if(D18B20==1)
u |= 0x80;
TempDelay (2);
_nop_();
}
return(u);
}
/************************************************************
*Function:读B20
*parameter:
*Return:
*Modify:
*************************************************************/
voidread_bytes (unsigned char idata j)
{
unsigned char idata i;
for(i=0;i { *p = ReadByte(); p++; } } /************************************************************ *Function:CRC校验 *parameter: *Return: *Modify: *************************************************************/ unsignedchar CRC (unsigned char j) { unsignedchar idata i,crc_data=0; for(i=0;i crc_data= CrcTable[crc_data^temp_buff[i]]; return (crc_data); } /************************************************************ *Function:读取温度 *parameter: *Return: *Modify: *************************************************************/ voidGemTemp (void) { read_bytes (9); if (CRC(9)==0) //校验正确 { Temperature = temp_buff[1]*0x100 + temp_buff[0]; // Temperature *= 0.625; Temperature /= 16; TempDelay(1); } } /************************************************************ *Function:内部配置 *parameter: *Return: *Modify: *************************************************************/ voidConfig18b20 (void) //重新配置报警限定值和分辨率 { Init18b20(); WriteByte(0xcc); //skip rom WriteByte(0x4e); //write scratchpad WriteByte(0x19); //上限 WriteByte(0x1a); //下限 WriteByte(0x7f); //set 12 bit (0.125) Init18b20(); WriteByte(0xcc); //skip rom WriteByte(0x48); //保存设定值 Init18b20(); WriteByte(0xcc); //skip rom WriteByte(0xb8); //回调设定值 } /************************************************************ *Function:读B20ID *parameter: *Return: *Modify: *************************************************************/ voidReadID (void)//读取器件id { Init18b20(); WriteByte(0x33); //read rom read_bytes(8); } /************************************************************ *Function:18B20ID全处理 *parameter: *Return: *Modify: *************************************************************/ voidTemperatuerResult(void) { p =id_buff; ReadID(); Config18b20(); Init18b20 (); WriteByte(0xcc); //skip rom WriteByte(0x44); //Temperature convert Init18b20 (); WriteByte(0xcc); //skip rom WriteByte(0xbe); //read Temperature p = temp_buff; GemTemp(); } voidGetTemp() { if(TIM >=500) //每隔500ms 读取温度 { TIM=0; TemperatuerResult(); } } 18B20采集温度数据,送至单片机处理,最终结果显示在12864上。 2.数据处理 任何测量都不可避免地存在误差,为了提高测量精度,必须尽可能地消除或减小误差,因此有必要对各种误差的性质、出现规律、产生原因、发现与消除或减小它们的主要方法以及测量结果的评定等方面,作进一步分析。 实验步骤 1. 根据电路原理图连接电路。并对电路进行多次调校,使其工作在较理想的状态。 2.编写适当的程序,并编译。在确定程序无误之后,烧录至单片机。 实验程序如下 #include #include #include "lcd.h" unsigned char Tempera_Val[3] ,temp; //温度 unsigned char RTC_Val[15]; //时钟数组 unsigned int xdata TIM,TIM1; //用于间隔读取温度和时钟 extern unsigned int idataTemperature; //温度 extern unsigned charxdata D[8]; //读取时钟放到D数组中 extern void Read_RTC(void); extern void GetTemp (void); extern void Set_RTC(void); //set RTC /********************************************************** 配置定时器参数 **********************************************************/ void Timer_Ini() { TMOD|= 0x11; TH1 = 0xD8; //10 TL1 = 0xF0; IE = 0x8A; TR1 = 1; } /********************************************************** 主函数 **********************************************************/ void main(void) { P2 = 0xff; P0 = 0xff; Timer_Ini(); //初始化 LCD_init(); //初始化 LCD_clear(5); //清屏 ChineseChar(14,10,2,colors[2],colors[7],1); ChineseChar(38,10,2,colors[2],colors[7],2); ChineseChar(62,10,2,colors[2],colors[7],3); ChineseChar(86,10,2,colors[2],colors[7],4); ChineseChar(24,50,1,colors[2],colors[7],10); ChineseChar(40,50,1,colors[2],colors[7],11); ChineseChar(80,50,1,colors[2],colors[7],12); ChineseChar(30,80,1,colors[2],colors[7],13); ChineseChar(46,80,1,colors[2],colors[7],14); ChineseChar(62,80,1,colors[2],colors[7],14); ChineseChar(76,80,1,colors[2],colors[7],15); Set_RTC(); while(1) { if( TIM1 >=10) //每隔10ms 读取ds1302 { TIM1 = 0; Read_RTC(); //读取DS1302 } GetTemp(); //*****温度*********************** Tempera_Val[0] =Temperature%100/10 + 0x30; //Temperature; Tempera_Val[1] =Temperature%10 + 0x30; //******月*********************** temp = ((D[4]&0x70)>>4)*10 +(D[4]&0x0f); RTC_Val[0] = temp/10 +0x30; //将位转成ASCII码 RTC_Val[1] = temp%10 +0x30; //将个位转成ASCII码 RTC_Val[2] = '-' ; //短横线 //*****日*********************** temp = ((D[3]&0x70)>>4)*10 +(D[3]&0x0f); RTC_Val[3] = temp/10 + 0x30; RTC_Val[4] = temp%10 + 0x30; RTC_Val[5] = ' ' ; //******时*********************** temp = ((D[2]&0x70)>>4)*10 +(D[2]&0x0f); RTC_Val[6] = temp/10 +0x30; RTC_Val[7] = temp%10 +0x30; RTC_Val[8] = ':' ; //冒号 //******分*********************** temp = ((D[1]&0x70)>>4)*10 +(D[1]&0x0f); RTC_Val[9] = temp/10 + 0x30; RTC_Val[10] = temp%10+ 0x30; RTC_Val[11] = ':'; //******秒*********************** temp = ((D[0]&0x70)>>4)*10 + (D[0]&0x0f); RTC_Val[12] = temp/10+ 0x30; RTC_Val[13] = temp%10+ 0x30; LCD_ShowString(60,50,colors[7],colors[2],Tempera_Val); //将字符送到彩屏中显示 LCD_ShowString(10,100,colors[7],colors[2],RTC_Val); //将字符送到彩屏中显示 } } /************************************* [ t1 (10ms)中断] 中断 *************************************/ void T1zd(void) interrupt 3 { TH1 = 0xD8; //10 TL1 = 0xF0; TIM++; TIM1++; } 3. 开始记录数据。(温度单位:℃) 在连续的八天记录数据期间,单片机持续供电。每隔十分钟记录数据。每天都在11:50开始记录数据。 时间 11:50 ℃ 31 32 32 32 32 32 32 33 33 33 ℃ 29 29 29 30 30 30 30 31 31 32 ℃ 30 30 30 31 31 31 32 32 32 33 ℃ 30 30 30 31 31 31 32 32 33 33 ℃ 31 31 31 32 32 32 33 33 34 34 ℃ 29 29 30 30 31 31 32 32 33 33 ℃ 30 30 31 31 32 32 32 33 33 33 ℃ 32 32 32 33 33 33 34 34 34 35 计算每天获取数值的算术平均值,记录如下: 测量天数 1 32.2 0.575 0.3306 2 30.1 -1.525 2.3256 3 31.2 -0.425 0.1806 4 31.3 -0.325 0.1056 5 32.3 0.675 0.4556 6 31 -0.625 0.4556 7 31.7 0.075 0.0056 8 33.2 1.575 2.4806 注: =31.625℃, = /8, 在测量过程中,遇到明显的降温天气,使得测的数据的粗大误差偏大。 测量结果的数据处理 1、 算术平均值的计算校核 根据残余误差代数和校核规则,现用规则2进行校核,因 A=0.001,n=8 =0 故 计算正确。 2、由Bessal = = =0.33647 按Peters公式 1.253 / =0.1214 =1+u, =1- =0.5965, =0.5965 =0.75593. 故测量列中不存在系统误差. 3、 n=8, 由狄克松准则得 = = =0.4091 不含粗大误差 = =0.4091 不含粗大误差. 4、 求算数平均值的标准差 0.3364 =0.2563 5、 求算术平均值的极限误差 已知 则 = 2.36x0.2563=0.6049 6、 写出最后测量结果 T=(31.625 ) 心得体会 此次实验综合了单片机的应用,误差理论与数据处理的知识。 在测量温度时,会受到很多因素的影响,比如室内开启电风扇的数目及风扇的转速,单片机持续工作时内部电路产生的误差。在数据采集期间,武汉当地气温比较恒定,数据采集条件比较理想。 参考资料: http://www.wpxap.com/智机网 http://www.mcuol.com/嵌入式在线 http://www.eepw.com.cn/电子产品世界网 http://www.eaw.com.cn/电子设计应用网 《数字电子技术》 康华光主编 高等教育出版社 《单片机原理及应用》 李建忠主编 西安电子科技大学出版社 《单片机应用系统设计实例与分析》 沈红卫主编 北京航空航天大学出版社 《误差理论与数据处理》(第五版) 费业泰主编 合肥工业大学出版社
实验数据分析