大学本科生毕业设计(论文)
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); TX=0; } }
超声波接收中断程序:
超声测距系统主程序利用外中断0检测返回超声波信号,一旦接收到返回超声波信号(即INTO引脚出现低电平),立即进入中断程序。进入该中断后就立即关闭计时器TO停止计时,并将测距成功标志字赋值1。如果当计时器溢出时还未检测到超声波返回信号,则定时器刊溢出中断将外中断0关闭,并将测距成功标志字赋值2以表示本次测距不成功。
4.4 DS18B20温度采集程序
DS18B20的工作流程是,初始化?ROM操作指令?存储器操作指令?数据传输。其工作时序包括:初始化时序、写时序和读时序。
(1)DS18B20的初始化
DS18B20的初始化的实质是使DS18B20复位,主要是通过判断存在脉冲的形式来实现的。以延时等待,然后通过输入/输出线读存在脉冲,为低说明存在,复位成功;否则说明不存在,复位失败,必须对DS18B20重新初始化。
ow_reset(void) {char presence=1; while(presence) { while(presence)
{ DQ=1;_nop_();_nop_();//从高拉倒低 DQ=0; delay(50); //550 us DQ=1; delay(6); //66 us presence=DQ; //presence=0 复位成功,继续下一步 }
delay(45); //延时500 us presence=~DQ; }
DQ=1; //拉高电平 }
(2)字节写入DS18B20程序
27
大学本科生毕业设计(论文)
字节写入的时序是拉低输入/输出线至少15?S以作为起始信号,按从低位到高位的顺序取出欲写入字节中的1位数据,写入输入/输出线,延时等待15?S后将输入/输出线拉高作为停止信号,以等待下一位的写入。写入程序如下:
/****************DS18B20写命令函数************************/ //向1-WIRE 总线上写1个字节 void write_byte(uchar val) { uchar i; for(i=8;i>0;i--)
{ DQ=1;_nop_();_nop_(); //从高拉倒低 DQ=0;_nop_();_nop_();_nop_();_nop_(); //5 us
DQ=val&0x01; //最低位移出 delay(6); //66 us val=val/2; //右移1位 } DQ=1; delay(1); }
(3)字读DS18B20程序 读取过程结合下面函数说明
/****************DS18B20读1字节函数************************/ //从总线上取1个字节 uchar read_byte(void) {uchar i; uchar value=0; for(i=8;i>0;i--)
{ DQ=1;_nop_();_nop_(); value>>=1;
DQ=0;_nop_();_nop_();_nop_();_nop_(); //4 us DQ=1;_nop_();_nop_();_nop_();_nop_(); //4 us if(DQ)value|=0x80;
delay(6); //66 us } DQ=1; return(value);}
从上面可以看出,16位数据同样是从低位到高位被逐一读取的,而且读
28
大学本科生毕业设计(论文)
取的温度为补码的形式,使用前必须进行补码转换。
(4)DS18B20温度读取函数
/****************读出温度函数************************/ read_temp()
{ ow_reset(); //总线复位 delay(200);
write_byte(0xcc); //发命令 write_byte(0x44); //发转换命令 ow_reset(); delay(1);
write_byte(0xcc); //发命令 write_byte(0xbe);
temp_data[0]=read_byte(); //读温度值的低字节 temp_data[1]=read_byte(); //读温度值的高字节 temp=temp_data[1];
temp<<=8; temp=temp|temp_data[0]; // 两字节合成一个整型变量。 return temp; //返回温度值 }
(5)温度处理函数
/****************温度数据处理函数************************/ //二进制高字节的低半字节和低字节的高半字节组成一字节,这个 //字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩 //下的低字节的低半字节转化成十进制后,就是温度值的小数部分 /********************************************************/ work_temp(uint tem) {uchar n=0;
if(tem>6348) // 温度值正负判断 {tem=65536-tem;n=1;} // 负温度求补码,标志位置1 display[4]=tem&0x0f; // 取小数部分的值 display[0]=ditab[display[4]]; // 存入小数部分显示值
display[4]=tem>>4; // 取中间八位,即整数部分的值 display[3]=display[4]/100; // 取百位数据暂存 display[1]=display[4]0; // 取后两位数据暂存
29
大学本科生毕业设计(论文)
display[2]=display[1]/10; // 取十位数据暂存 display[1]=display[1];
/******************符号位显示判断**************************/ if(!display[3])
{ display[3]=0x0a; //最高位为0时不显示 if(!display[2])
{ display[2]=0x0a; //次高位为0时不显示 } }
if(n){display[3]=0x0b;} //负温度时最高位显示\}
4.5 距离计算程序
距离计算中,实行了温度补偿和报警功能。程序如下:
void Conut(void)
if((S>=700)||flag==1) //超出测量范围显示“-” { flag=0;
disbuff[0]=10; //“-” disbuff[1]=10; //“-” disbuff[2]=10; //“-” } else
{ disbuff[0]=S00/100; disbuff[1]=S000/10; disbuff[2]=S00 ;
30
{ int i;
time=TH0*256+TL0; TH0=0; TL0=0;
S=(time*1.75)/100; //算出来是CM
大学本科生毕业设计(论文)
间长短
if(S<=40)
{ for(i=0;i<200;i++)//喇叭发声的时间循环,改变大小可以改变发声时 {
delay(100); //参数决定发声的频率,估算值,可以自行更改参数
SPK=!SPK; }
SPK=1; //喇叭停止工作,间歇的时间,可更改 //delay(20000); } }
ow_reset(); //开机先转换一次 write_byte(0xcc); //Skip ROM write_byte(0x44);
work_temp(read_temp());
}
//处理温度数据
4.6 LCD显示程序
uchar code ditab[16]=
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
unsigned
char
const
discode[]
={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff/*-*/};
unsigned char const positon[7]={ 0x7f,0xbf,0xdf,0xfe,0xfd,0xfb,0xf7}; uchar data temp_data[2]={0x00,0x00}; unsigned char disbuff[8] ={ 0,0,0,0,0,0,0,0,};
/********************************************************/ void Display(void) {
if(posit==0)
{P0=(discode[disbuff[posit]]);} else
{P0=discode[disbuff[posit]];} P1=positon[posit]; if(++posit>=7)
31
//扫描数码管