程序如下
main.c
/*********************************************************************/
/* 超声波测距数码管显示 */
/*********************************************************************/
/* 温度补偿 */
/* 用定时器0计数测量超声波发送接收时间 */
/* 用定时器1给ds18b20定时发收温度信号 */
/* 用外部中断0接收超声波返回的第一个脉冲 */
/*********************************************************************/
#include
#include
#include
#include
/*********************************************************************/
extern uint dis;
/*********************************************************************/
/***********************************/
/* 主函数 */
/***********************************/
void main(void)
{
init();
// display(1234);
// delayms(100);
while(1) //循环测量并显示
{
tran(); //发送超声波信号测距
display(dis); //显示距离
delayms(100);
// wen(); //显示温度
}
}
chao.c文件
#include
#include
#include
#include
/*********************************************************************/
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
#include
#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
/********************************/
/* 毫秒延时 */
/********************************/
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<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;
}
这是我们大三时候的课程设计,现在拿出来和大家分享,希望对各位朋友有帮助!