程序如下
main.c
/*********************************************************************/
/* 超声波测距数码管显示 */
/*********************************************************************/
/* 温度补偿 */
/* 用定时器0计数测量超声波发送接收时间 */
/* 用定时器1给ds18b20定时发收温度信号 */
/* 用外部中断0接收超声波返回的第一个脉冲 */
/*********************************************************************/
#include<reg52.H>
#include<intrins.h>
#include<wen.h>
#include<chao.h>
/*********************************************************************/
extern uint dis;
/*********************************************************************/
/***********************************/
/* 主函数
*/
/***********************************/
void main(void)
{
init();
//
display(1234);
//
delayms(100);
while(1) //循环测量并显示
{
tran(); //发送超声波信号测距
display(dis); //显示距离
delayms(100);
//
wen();
//显示温度
}
}
chao.c文件
#include<reg52.H>
#include<intrins.h>
#include<wen.h>
#include<chao.h>
/*********************************************************************/
uint dis;
uint H=100;
uint L=20;
uchar flag=0;
//中断标志
uchar high_time; //时间高位
uchar low_time;
//时间低位
uchar i,s1num;
/***************************
数码管为共阴数码管
***************************/
#define seg P0 //数码管的数据口为P0口
sbit s3=P2^0;
sbit s0=P2^1;
sbit s1=P2^2;
sbit s2=P2^3;
sbit dp=P0^7; //小数点
uchar shuzu[]={
0x3F, //”0″
0x06, //”1″
0x5B, //”2″
0x4F, //”3″
0x66, //”4″
0x6D, //”5″
0x7D, //”6″
0x07, //”7″
0x7F, //”8″
0x6F, //”9″
/*0x77, //”A”
0x7C, //”B”
0x39, //”C”
0x5E, //”D”
0x79, //”E”
0x71, //”F”
0x76, //”H”
0x38, //”L”
0x37, //”n”
0x3E, //”u”
0x73, //”P”
0x5C, //”o”
0x40, //”-” */
0x00, //熄灭
0x00 //自定义
};
/*********************************************************************/
/***********************************/
/* 初始化函数
*/
/***********************************/
void init(void)
{
TMOD=0x11; //定时器0方式1用于计时
TH0=0;
TL0=0;
TH1=(65536-60000)/256; //温度计时初值
TL1=(65536-60000)%256;
ET1=1; //开定时器1中断
TR1=1; //启动定时器1
EA=1;
IT0=1; //下降沿有效
}
/***********************************/
/* 显示函数
*/
/***********************************/
void display(uint dat)
{
uchar i,j,k,l; //分别为百十个位的缓存
dat=dat-70;
i=dat/1000; //百位
j=dat/100%10; //十位
k=dat/10%10; //个位
l=dat%10; //十分位
//
write_12864com(0x8b);
//
write_12864dat(table[i]);
//
delay_50us(1);
//
write_12864dat(table[j]);
//
delay_50us(1);
//
write_12864dat(table[k]);
//
delay_50us(1);
//
write_12864dat(table[10]);
//
delay_50us(1);
//
write_12864dat(table[l]);
//
delay_50us(1);
s3=1;
s2=0;
s1=1;
s0=1;
seg=~shuzu[i];
//
dp=0;
delayms(2);
//
dp=1;
s2=1;
s3=1;
s2=1;
s1=0;
s0=1;
seg=~shuzu[j];
delayms(2);
s1=1;
s3=1;
s2=1;
s1=1;
s0=0;
seg=~shuzu[k];
dp=0;
delayms(2);
dp=1;
s0=1;
s3=0;
s2=1;
s1=1;
s0=1;
seg=~shuzu[l];
//
dp=0;
delayms(2);
//
dp=1;
s3=1;
}
/***********************************/
/* 超声波测量函数
*/
/***********************************/
void tran(void)
{
uchar i;
float temp;
TH0=0;
TL0=0; //清定时0
TR0=1; //开定时0
flag=0;
for(i=8;i>0;i–)
{
csb=!csb;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
}
csb=1;
delayms(50);
EX0=1; //开中断
//
if(flag!=1)
//
{
//
dis=55;
//
}
if(flag==1) //中断标志位置1,说明有回波
{ //以下为路程计算
temp=high_time*256+low_time;
temp=(temp/100.0)/2.0;
temp*=331.45+0.607*30;
//温度补偿V=331.45+0.607*T(温度)
//
temp*=350+0.607*(gett()/100.0);
temp=temp/10.0;
dis=temp;
flag=0;
}
}
/***********************************/
/* 中断函数
*/
/***********************************/
void TT() interrupt 0
{
float tmp;
TR0=0; //关定时器0
ET0=0; //关外部中断
flag=1; //置位标志位
tmp=TH0*256+TL0; //读取定时器的值
//
if((tmp>0)&&(tmp<30000)) //判断是否超出范围,此设置的范围为0到5米
if((tmp>0)&&(tmp<=60000))
{
high_time=TH0; //把计时值放入缓冲
low_time=TL0;
}
else //超出范围则重新测量
{
high_time=0;
low_time=0;
}
}
wen.c文件
#include <reg52.h>
#include <wen.h>
#include”chao.h”
/***********************************************************************************/
uchar8 dis1[6] = { 0, 0, 0, 0, 0, 0 }; //数据暂存
uchar8 code wendu[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //0到9的代码
uchar8 flag1,sig,temp1;
//flag用于判定是否有中断,sig判定温度符号
/***********************************************************************************/
/********************************/
/* 延时函数 */
/********************************/
void delay(int us)
//DELAY-11.0592MHZ 调用程序大约为24us,每次循环为16us
{
int s;
for(s=0;s<us;s++);
}
/********************************/
/* 毫秒延时 */
/********************************/
void delayms(int z)
{
int x,y;
for(x=z;x>0;x–)
for(y=125;y>0;y–);
}
/********************************/
/* 复位程序 */
/********************************/
unsigned char reset(void)
{
uchar8 presence;
DQ=0;
//拉低总线。当总线停留在低电平480us-960us ,总线上所以器件都将被复位
delay(30);
//保持低电平504us
DQ=1;
//释放总线,让其恢复高电平
delay(3);
//等待芯片应答信号
presence=DQ;
//获取应答信号
delay(25);
//延时以完成整个时序
return(presence);
//返回应答信号。有芯片应答返回0,否则返回1。
}
/********************************/
/* 写一位数据 */
/********************************/
void write_bit(char bitval)
{
DQ=0;
//拉低DQ总线,开始时序
if(bitval==1) //如果写入的为1,则返回高电平
DQ=1;
delay(5); //延时104us,以完成整个时序
DQ=1;
}
/********************************/
/* 写一字节数据 */
/********************************/
void write_byte(char val)
{
uchar8 i,commend;
for (i=0;i<8;i++)
//写入一个字节的数据,一个时序中写一次
{
commend=val>>i;
//右移i位
commend&=0x01;
//复制那位数据到temp
write_bit(commend); //调用write_bit()
}
delay(5);
//延时104us以完成此次时序,之后再写下一数据
}
/********************************/
/* 读一位数据 */
/********************************/
unsigned char read_bit(void)
{
uchar8 i;
DQ=0;
//拉低DQ,开始读时序
DQ=1;
//释放DQ总线
for(i=0;i<3;i++);
//从时序开始延时15us
return(DQ);
//返回DQ值
}
/********************************/
/* 读一字节数据 */
/********************************/
unsigned char read_byte(void)
{
uchar8 i,value=0;
for(i=0;i<8;i++)
{
if(read_bit()) //读一字节数据,一个时序中读一次,并作移位处理
value|=0x01<<i;
delay(6);
//延时以完成此次读时序,之后再读下一数据
}
return(value);
}
/********************************/
/* 温度转化 */
/********************************/
void tmconvert(void)
{
reset();
//复位
delay(1);
write_byte(0xcc);
//仅一个DS18b20 ,跳过ROM
write_byte(0x44);
//温度变换
}
/********************************/
/* 读取温度 */
/********************************/
unsigned int gett()
{
uchar8 LSB=0,MSB=0;
//用于存储读取的温度
long temp;
reset();
//复位
write_byte(0xcc);
//写指令,跳过ROM,仅一个DS18b20
write_byte(0xbe);
//写指令,读暂存存储器
LSB = read_byte();
//读LSB
MSB = read_byte();
//读MSB
sig=(MSB>>4==0X0F);
if(sig) //判断符号位是否为负值,是负值了,转去处理
{
LSB=~LSB; //温度处理
MSB=~MSB;
LSB=LSB+1;
}
temp=MSB*256+LSB;
//十六进制转换为10进制
temp=temp*100/16;
//12位精度,最小分辨率为0.0625°C
return temp;
//获得0.01°C 的精度并返回
}
/********************************/
/* 温度处理 */
/********************************/
void display1(unsigned int m)
{
uchar8 i;
//分离各数位
dis1[1] = m/10000;
//百位
dis1[2] = (m%10000)/1000; //十位
dis1[3] = (m%1000)/100;
//个位
dis1[4] = (m%100)/10;
//小数第一位
dis1[5] = m%10;
//小数第二位
delayms(30);
//
write_12864com(0x9b);
//0x80+地址码,设置数据地址指针(显示 第一行:0-0fH,第二行:40-4fH;)
//
if(sig) write_12864dat(table[11]);
//如果sig=1,显示负号;否则显示正号
//
else write_12864dat(table[12]);
//
for(i=1; i<6; i++)
//
{
write_12864dat(table[dis1[i]]);
//显示温度
if(i==3) write_12864dat(table[10]);
//显示小数点
//
}
}
/********************************/
/* 温度显示函数 */
/********************************/
void wen(void)
{
char i;
if(flag1==1)
//是否有中断产生
{
flag1=0;
//中断标志位清零
tmconvert();
//开始温度转化
gett();
//读取温度
for(i=0;i<30;i++)
display(gett());
//显示温度
}
}
void timer0() interrupt 3
//定时器0 中断
{
TH1 =(65536-60000)/256;
TL1 =(65536-60000)%256;
flag1=1;
}
这是我们大三时候的课程设计,现在拿出来和大家分享,希望对各位朋友有帮助!