智能仪器实验999999.docx
《智能仪器实验999999.docx》由会员分享,可在线阅读,更多相关《智能仪器实验999999.docx(26页珍藏版)》请在冰豆网上搜索。
智能仪器实验999999
智能仪器课程设计
实验室所用实验箱已经作了重新设计,故下面的设计仅供参考,实际应用必须作相应的修改!
!
!
一.带温度计的电子钟设计
1.设计任务
用温度传感器和4个按键、4个数码管设计带温度计的电子时钟程序,要求:
(1)用单线数字温度传感器DS18B20按键检测当前环境温度,温度精度0.1。
(2)用定时器/计数器显示电子走时(时、分),用2个按键(k1、k2)调整修改时钟,用4位数码管显示时钟。
(3)用2个按键(k3、k4)控制显示:
按下k3选择电子时钟显示;按下k4选择温度测量显示。
2.电路设计
根据设计要求,温度检测选用DS18B20,显示采用4位串行静态数码显示,数码管是共阳极,电路如图16-1所示。
图16-1带温度计的电子时钟电路原理图
3.算法思路和程序流程图
DS18B20是11位数字温度传感器,最小分辨率为0.125℃,采用单总线方式访问,时钟和数据共用一根线,这种单总线方式对读写时序有非常严格的要求,一旦时序上有偏差就会得不到正确的结果。
DS18B20进行温度转换时需要500ms~800ms的转换时间,主程序负责温度测量,每秒调用一次温度测量子程序。
按键检测与处理放在10ms定时器0中断程序中,这样时钟显示、修改和温度测量就会互不影响。
硬件配置:
CPU选择AT89C51,晶振时钟为12MHz;SW1、SW2用于调整修改时钟;SW3、SW4选择时钟、温度显示切换;RXD、TXD用作串行静态显示。
程序流程如图16-2所示。
程序规划:
1、功能规划
本设计软件的功能函数模块包括:
定时器0中断函数、串行静态数码管显示函数、DS18B20操作函数、延时函数。
其中定时器0中断函数主要用于按键检测与处理,判读是显示时钟还是显示温度,判读是否要修改时钟等功能。
串行静态数码管显示函数主要用来显示温度和时钟信息,根据显示缓冲区的内容来查笔形码表后显示相对应的信息。
DS18B20操作函数主要包括DS18B20的复位、初始化、读取转换温度等操作。
由于DS18B20对读写时序有非常严格的要求,因此对DS18B20的时序延时操作采用汇编程序编写,以达到精确的时序控制要求。
2、层次规划
软件的层次规划也即是通常所说的软件架构,即软件设计的总体思想、功能模块的划分、各模块间的通讯方式定义等。
一般如果采用自顶向下的软件设计方法都要先确定软件的架构,分配好任务后再进行编程。
本软件的层次规划为:
主程序主要完成系统各项状态、信息等的初始化,包括串行口初始化、定时器初始化、DS18B20初始化等。
然后控制每秒采集1次温度,并将采集的数字量标度变换成温度值。
同时等待定时器0中断程序中通过按键的操作来判断是显示时钟还是温度、是否要修改时钟、是修改时还是修改分等。
图16-2带温度计的电子时钟程序流程图
4.参考程序(资源分配、加注释的程序清单)
(1)常数定义与资源分配
#include
#include
#defineucharunsignedchar
sbitKEY1=P1^7;//时钟修改选择键
sbitKEY2=P1^6;//时钟修改加1键
sbitKEY3=P1^5;//按下此键显示时钟
sbitKEY4=P1^4;//按下此键显示温度
sbitDQ=P1^3;//数字温度传感器DS18B20接口
ucharHour;//小时存放单元
ucharMin;//分钟存放单元
ucharSec;//秒钟存放单元
intTempValue;//存放温度值
ucharTempH;//温度高值存放单元
ucharTempL;//温度低值存放单元
ucharTimCnt05S;//0.5秒计数单元,用于修改时闪烁显示
ucharTimCnt1S;//1秒计数单元,用于秒加1
ucharModifyBuf[2];//小时,分钟修改缓冲区
ucharDispBuf[4];//显示缓冲区存放单元首址
ucharModifyStat;//时钟修改状态,1,修改时;2,修改分
bitTim1SFlag;//1秒时间到标志位
bitKey1Old;//按键SW1旧值,用于延时去抖
bitKey2Old;//按键SW2旧值,用于延时去抖
bitKey3Old;//按键SW3旧值,用于延时去抖
bitKey4Old;//按键SW3旧值,用于延时去抖
bitKeyOK;//按键响应标志,防止连击
bitModifyFlag;//时钟是否处于修改状态(1为修改状态)
bitFlashFlag;//时钟修改闪烁单元
bitDispClk_T;//是处于时钟显示还是温度显示状态(1为时钟显示,0为温度显示)
bitSign;//温度正负标志位,正为0,负为1
//***温度传感器DS18B20
#defineCONFIG0x5f//11位温度转换(此时传感器最小分辨率为0.125摄氏度)
#defineTHIGH30
#defineTLOW10
//***数码管显示笔形码表
ucharcodeDispTab[18]={
//0123456789ABCDEF-(16)17
0x09,0x7D,0x07,0x15,0x71,0x91,0x81,0x3D,0x01,0x11,0x21,0xC1,0x8B,0x45,0x83,0xA3,0xF7,0xFF};
//***自定义函数
voidDS18B20Init(void);//DS18B20初始化函数
voidRdTemp(void);//启动温度测量,读取转换的温度值(数字量)
voidDispClock(void);//时钟计数值分离成显示格式函数
voidDispTemp(void);//温度变换,温度值分离成显示格式函数
voidDisp(void);//送显示单元的数据到数码管显示函数
externvoiddelayus(uchar);//us延时函数
externvoiddelayms(uchar);//ms延时函数
(2)主程序
主要完成系统初始化,控制每秒采集1次温度,并将采集的数字量标度变换成温度值,实现带温度计的电子钟设计。
main()
{SCON=0x00;
TMOD=0x01;//定时器0工作于方式1,10ms定时方式
TH0=55536/256;
TL0=55536%256;
ET0=1;
EA=1;
DS18B20Init();
TR0=1;
KeyOK=0;
Tim1SFlag=0;
ModifyFlag=0;
Key1Old=1;
Key2Old=1;
Key3Old=1;
Key4Old=1;
DispClk_T=1;
while
(1)
{while(!
Tim1SFlag);
Tim1SFlag=0;
RdTemp();
if(DispClk_T)continue;
DispTemp();
}
}
(3)定时中断函数
使用T0作定时器,定时10ms,完成时钟走时、按键扫描、时钟校准、数值显示和控制显示状态指示等。
voidTimer0(void)interrupt1
{TL0=55536%256;//重置定时器初值
TH0=55536/256;
if((++TimCnt1S)==100)
{TimCnt1S=0;
Tim1SFlag=1;//1s定时时间到
if((++Sec)==60)
{Sec=0;
if((++Min)==60)
{Min=0;
if((++Hour)==24)Hour=0;
}
}
if((!
ModifyFlag)&&(DispClk_T))DispClock();//判断是否要调用时钟显示
}//在时钟修改中和温度测量显示中,不需调用时钟显示
else
{//时钟修改中,需闪烁显示修改单元
if(ModifyFlag)
{if((++TimCnt05S)==50)
{FlashFlag=~FlashFlag;
if(FlashFlag)//熄灭
{DispBuf[(ModifyStat-1)*2]=17;
DispBuf[(ModifyStat-1)*2+1]=17;
}
else//点亮
{DispBuf[(ModifyStat-1)*2]=ModifyBuf[ModifyStat-1]/10;
DispBuf[(ModifyStat-1)*2+1]=ModifyBuf[ModifyStat-1]%10;
}
Disp();//显示显示缓冲区中的内容
}
}
}
if(!
KEY1)//是否有SW1(时钟修改选择键按下)
{if(!
Key1Old)//10ms之前此键也是按下,中断延时去抖
{if(!
KeyOK)//此按键是否已经响应
{if((++ModifyStat)==3)//是否完成修改
{ModifyStat=0;
Hour=ModifyBuf[0];
Min=ModifyBuf[1];
ModifyFlag=0;
}
KeyOK=1;//设置按键已响应标志,防止连击
}
}
Key1Old=KEY1;//10ms之前此键未按,还需要延时去抖
}
elseif(!
KEY2)//是否有SW2(修改加1键按下)
{if(!
Key2Old)//10ms之前此键也是按下,中断延时去抖
{if(!
KeyOK)//此按键是否已经响应
{if(ModifyStat==1)//修改时
{if((++ModifyBuf[0])==24)
{ModifyBuf[0]=0;
}
}
elseif(ModifyStat==2)//修改分
{if((++ModifyBuf[1])==60)
{ModifyBuf[1]=0;
}
}
KeyOK=1;//设置按键已响应标志,防止连击
}
}
Key2Old=KEY2;//10ms之前此键未按,还需要延时去抖
}
elseif(!
KEY3)//是否有SW3(时钟显示选择键按下)
{if(!
Key3Old)//10ms之前此键也是按下,中断延时去抖
{if(!
KeyOK)//此按键是否已经响应
{DispClk_T=1;
//DispClock();
KeyOK=1;//设置按键已响应标志,防止连击
}
}
Key3Old=KEY3;//10ms之前此键未按,还需要延时去抖
}
elseif(!
KEY4)//是否有SW4(时钟显示选择键按下)
{if(!
Key4Old)//10ms之前此键也是按下,中断延时去抖
{if(!
KeyOK)//此按键是否已经响应
{DispClk_T=0;
//DispTemp();//应屏蔽,防止跟主程序的有冲突
KeyOK=1;//设置按键已响应标志,防止连击
}
}
Key4Old=KEY4;//10ms之前此键未按,还需要延时去抖
}
else
{Key1Old=1;
Key2Old=1;
Key3Old=1;
Key4Old=1;
}
}
(4)显示函数:
将显示缓冲区中的内容送数码管显示子程序
voidDisp(void)
{uchari,j;
for(i=0;i<4;i++)
{j=DispBuf[i];
j=DispTab[j];//查笔形码表
if(!
ModifyFlag&&!
DispClk_T)//确保当前不是处于时钟修改中且显示温度有效
{if(i==2)j=j&0xfe;//在倒数第二个数码管加上小数点
}
SBUF=j;
while(!
TI);
TI=0;
}
}
/*****时钟显示单元分离函数******/
voidDispClock(void)
{DispBuf[0]=Hour/10;
DispBuf[1]=Hour%10;
DispBuf[2]=Min/10;
DispBuf[3]=Min%10;
Disp();
}
/******温度变换和显示单元分离函数******
**11位温度转换分辨率为0.125,结果=Td×125/100,得到带1位小数的摄氏温度值*****/
voidDispTemp(void)
{TempValue=(TempValue*5)/4;//显示3位温度值,最高位作温度的正负,为负显示-
if(TempValue<0)//如果为负
{TempValue=0-TempValue;//取补码
Sign=1;
}
elseSign=0;
if(Sign)DispBuf[0]=16;//显示负号
elseDispBuf[0]=17;//为正,不显示
DispBuf[1]=(TempValue%1000)/100;
DispBuf[2]=(TempValue%100)/10;
DispBuf[3]=TempValue%10;
Disp();
}
(5)DS18B20操作函数
DS18B20是单总线访问的器件,使用改器件时,先应复位初始化,设置配置寄存器,应按照时序对器件进行读写,每次读写时先对其复位,然后读出当前转换的温度值。
/**************DS18B20初始化函数********************/
voidDS18B20Init(void)
{ow_reset();//复位
write_uchar(0xcc);//发SKIPROM命令
write_uchar(0x4e);//发写TH和TL
write_uchar(THIGH);//写高温报警点
write_uchar(TLOW);//写低温报警点
write_uchar(CONFIG);//写配置寄存器,11位
}
/************读取温度*****************/
voidRdTemp(void)
{uchari,j;
ow_reset();
write_uchar(0xcc);//SkipROM
write_uchar(0x44);//ReadScratchPad
for(i=0;i<8;i++)//延时800ms
{delayms(100);
}
ow_reset();
write_uchar(0xcc);//SkipROM
write_uchar(0xbe);//发读存储器命令
i=read_uchar();//读出温度的低字节
j=read_uchar();//读出温度的高字节
read_uchar();//读出TH
read_uchar();//读出TL
read_uchar();//读出CONFIG
TempValue=j*256+i;
}
/*******复位函数********************/
voidow_reset(void)//复位
{//bitpresence=1;
DQ=1;
do
{while(DQ)
{DQ=0;//pullDQlinelow
delayus(149);//低电平480-960us,取600us
delayus(149);
DQ=1;//电阻上拉15~60us,取50
delayus(29);//waitforpresence
}
delayus(119);//延时240us
}while(!
DQ);
delayus(249);//延时500us
}
/************从1-wire总线上读取一个字节****************/
ucharread_uchar(void)
{
uchari;
ucharvalue=0;
for(i=8;i>0;i--)
{value>>=1;
DQ=0;//pullDQlowtostarttimeslot
_nop_();
DQ=1;//thenreturnhigh
delayus(5);//延时12us
if(DQ)value|=0x80;
delayus(29);//延时60us
}
DQ=1;//thenreturnhigh
return(value);
}
/************向1-WIRE总线上写一个字节*****************/
voidwrite_uchar(ucharval)
{
uchari;
for(i=8;i>0;i--)//writesuchar,onebitatatime
{DQ=1;
_nop_();
DQ=0;//pullDQlowtostarttimeslot
delayus(7);//延时16us
DQ=val&0x01;
delayus(29);//延时60us
DQ=1;
val=val/2;
}
DQ=1;
}
(6)延时函数
使用汇编语言编写延时程序(DELAY.ASM),以混合编程的方式嵌入到C51程序中。
NAMEDELAY
?
PR?
_delayms?
DELAYSEGMENTCODE;申明代码段
?
PR?
_delayus?
DELAYSEGMENTCODE
PUBLIC_delayms,_delayus;输出函数名
RSEG?
PR?
_delayms?
DELAY;这个函数可被连接器放置在任何地方
_delayms:
;延时函数体
D1:
MOVR6,#10
D2:
MOVR5,#48
D3:
DJNZR5,D3
DJNZR6,D2;以上程序为延时1ms
DJNZR7,D1
RET
RSEG?
PR?
_delayus?
DELAY;必须为(2x+2)us
_delayus:
DJNZR7,$
RET
END
二.可控波形发生器
1.设计任务
用D/A转换器和键盘、显示设计可控波形发生器,要求:
(1)用单片机控制D/A转换器产生输出的波形,频率范围在0~1KHz。
(2)用按键选择输出方波、三角波、锯齿波或正弦波,输出波形频率能用步进可调,按键步进10Hz。
(3)通过键盘能预置波形输出频率,用数码显示当前输出波形的频率值。
2.电路设计
根据设计要求,采用D/A转换产生波形输出,由单片机控制波形的频率,扩展4位串行静态数码显示,数码管是共阳极;扩展4*4键盘选择输出波形,修改输出波形频率,实验电路如图16-1所示。
图16-3可控波形发生器电路原理图
3.算法思路和程序流程图
4*4键盘有16个键,其中0~9数字键用于预设输出波形频率,F键用于频率预置确认键,A键用于频率步进“+”键(步进为10Hz),B键用于频率步进“-”键,C键用于切换输出波形类型。
正弦波对应的50个波形点的数字量由TurboC2.0编程得出形成表格。
图16-4波形发生器主要程序流程图
波形发生器对打点的时间间隔要求比较严格,使用定时器T2控制定时打点。
因为波形输出频率的范围为10Hz~1KHz,相应的打点间隔时间为2000us~20us,考虑到20us的时间很短,应采用定时器的自动重装方式来实现定时打点。
由于T0、T1定时器只有8位定时重装方式,满足不了定时2000us的要求,故选用89C52系列单片机的定时器2来实现自动重装。
定时器0工作于10ms定时方式,用于按键检测和显示等功能。
系统监控程序采用汇编语言编写,程序流程如图16-4所示。
4.参考程序(资源分配、加注释的程序清单)
(1)资源分配常量定义
T2CONDATA0C8H;8052Extensions
RCAP2LDATA0CAH
RCAP2HDATA0CBH
TL2DATA0CCH
TH2DATA0CDH
ET2BIT0ADH
PT2BIT0BDH
TF2BIT0CFH
TR2BIT0CAH
KEYPORTEQUP1;4*4的矩阵键盘接在P1口
DA0832_ADDREQU00H;DAC0832地址
DA0832_CSBITP2.0
WAVE_TYPEDATA30H;存放波形类型,0:
正弦波,1:
方波,2:
三角波,3:
锯齿波
WAVE_FREQDATA31H;存放波形频率
WAVE_PTDATA32H;存放表格指针偏移量
KEYCODEDATA33H;按键扫描码存放单元
FREQ_BUFEQU34H;频率设置和显示值存放单元首址(占34H~37H)
T0_INT_FLAGBIT20H.0;T0定时器中断标志
KEYOKBIT20H.1;按键响应标志,防止连击