新手上路
积分 31
金钱 31
注册时间 2018-1-24
在线时间 12 小时
10 金钱
本帖最后由 garyfisher 于 2018-5-18 23:45 编辑
程序找别人写的,电路都连好了,插上送的单片机,大部分功能都正常,但是ds18b20温度补偿用不了,一直显示95度。我把他发来的程序烧录进我自己的单片机想找找问题,但烧录进我的单片机之后LCD屏只显示初始化之后的第一面,也就是write_string(1,0,"G:0.00m B:0.00m");
write_string(2,0,"L:0.00m R:0.00m ");
之后就不继续执行了,按键也没反应。
俩问题,第一个程序问什么不能继续执行,第二个为什么温度补偿用不了
另外我发现温度补偿用的I/O口和另一个I/O重复了,复用什么的现在我还不太会,也许是这里的问题?
完整程序贴下面了,能答出来的话别拦我,我要给红包
原理图
原理图
#include <reg52.h> //调用单片机头文件
#define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
#define uint unsigned int //无符号整型 宏定义 变量范围0~65535
#include <intrins.h>
sbit c_send_r = P2^0; //超声波发射
sbit c_recive_r = P2^1; //超声波接收
sbit c_send_z = P2^2; //超声波发射
sbit c_recive_z = P2^3; //超声波接收
sbit c_send_l = P2^4; //超声波发射
sbit c_recive_l = P2^5; //超声波接收
sbit c_recive_b = P2^6; //超声波接收
sbit c_send_b = P2^7; //超声波发射
sbit beep = P1^4; //蜂鸣器IO口定义
//这三个引脚参考资料
sbit rs=P1^0; //1602数据/命令选择引脚 H:数据 L:命令
sbit rw=P1^1; //1602读写引脚 H:数据寄存器 L:指令寄存器
sbit e =P1^2; //1602使能引脚 下降沿触发
uchar code table_num[]="0123456789abcdefg";
uint code wendu_buchang1[46] = { //温度补偿表格
331,332,333,333,334,334,335,336,336,337, // 0-9度
337,338,339,339,340,341,341,342,342,343, //10-19度
343,344,345,345,346,346,347,348,348,349, //20-29度
349,350,351,351,352,352,353,354,354,355, //30-39度
355,356,357,357,358,358 //40-45度
};
sbit dq = P3^1; //18b20 IO口的定义
uint temperature ; //
uchar flag_value;
uchar flag_value_l;
uchar flag_value_r;
uint flag_time0; //用来保存定时器0的时候的
uchar flag_hc_value; //超声波中间变量
long distance_z; //距离
long distance_l; //距离
long distance_r; //距离
long distance_b; //距离
long set_l; //距离
long set_r; //距离
long set_z; //距离
long set_b; //距离
bit flag_csb_juli_z; //超声波超出量程
bit flag_csb_juli_l; //超声波超出量程
bit flag_csb_juli_r; //超声波超出量程
bit flag_csb_juli_b; //超声波超出量程
/***********************语音模块控制IO口的定义************************/
sbit VBUSY= P3^4;
sbit VRST = P3^0;
sbit VSDA = P3^1;
sbit VCS = P3^2;
sbit VSCL = P3^3;
bit flag_300ms ;
uint flag_time0; //用来保存定时器0的时候的
// 按键的IO变量的定义
uchar key_can; //按键值的变量
uchar menu_1; //菜单设计的变量
uchar a_a;
sbit led_r = P1^7; //指示灯
sbit led_z = P1^6;
sbit led_l = P1^5;
sbit led_b = P1^3;
/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;i++)
for(j=0;j<120;j++);
}
/********************************************************************
* 名称 : delay_uint()
* 功能 : 小延时。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
while(q--);
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_data(*p);
p++;
}
}
/***********************lcd1602上显示两位十进制数************************/
void write_sfm3(uchar hang,uchar add,uint date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(0x30+date/100%10);
write_data('.');
write_data(0x30+date/10%10);
write_data(0x30+date%10);
}
/********************************************************************
* 名称 : init_1602()
* 功能 : 初始化1602液晶
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_1602() //1602初始化
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
delay_uint(1000);
write_string(1,0,"G:0.00m B:0.00m");
write_string(2,0,"L:0.00m R:0.00m ");
}
/***********************18b20初始化函数*****************************/
void init_18b20()
{
bit q;
dq = 1; //把总线拿高
delay_uint(1); //15us
dq = 0; //给复位脉冲
delay_uint(80); //750us
dq = 1; //把总线拿高 等待
delay_uint(10); //110us
q = dq; //读取18b20初始化信号
delay_uint(20); //200us
dq = 1; //把总线拿高 释放总线
}
/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{ //写数据是低位开始
dq = 0; //把总线拿低写时间隙开始
dq = dat & 0x01; //向18b20总线写数据了
delay_uint(5); // 60us
dq = 1; //释放总线
dat >>= 1;
}
}
/*************读取18b20内的数据***************/
uchar read_18b20()
{
uchar i,value;
for(i=0;i<8;i++)
{
dq = 0; //把总线拿低读时间隙开始
value >>= 1; //读数据是低位开始
dq = 1; //释放总线
if(dq == 1) //开始读写数据
value |= 0x80;
delay_uint(5); //60us 读一个时间隙最少要保持60us的时间
}
return value; //返回数据
}
/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
uint value;
uchar low; //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
init_18b20(); //初始化18b20
write_18b20(0xcc); //跳过64位ROM
write_18b20(0x44); //启动一次温度转换命令
delay_uint(50); //500us
init_18b20(); //初始化18b20
write_18b20(0xcc); //跳过64位ROM
write_18b20(0xbe); //发出读取暂存器命令
EA = 0;
low = read_18b20(); //读温度低字节
value = read_18b20(); //读温度高字节
EA = 1;
value <<= 8; //把温度的高位左移8位
value |= low; //把读出的温度低位放到value的低八位中
value *= 0.0625; //转换到温度值
return value; //返回读出的温度
}
/***********************小延时函数**************************/
void delay_us (unsigned int us)
{
while(us--)
{
_nop_();
}
}
/***********************语音子程序************************/
void Send_threelines(unsigned char addr)
{
unsigned char i;
VRST=0;
delay_1ms(5);
VRST=1;
delay_1ms(20); /* 复位拉高20ms*/
VCS=0;
delay_1ms(5); /* 片选拉低5ms */
for(i=0;i<8;i++)
{
VSCL=0;
if(addr&0x01)
{
VSDA=1;
}
else
VSDA=0;
addr>>=1;
delay_us(150); /* 150us */
VSCL=1;
delay_us(150); /* 150us */
}
VCS=1;
delay_1ms(200);
while(VBUSY == 0); //忙等待
}
/********************独立按键程序*****************/
uchar key_can; //按键值
void key() //独立按键程序
{
static uchar key_new;
key_can = 20; //按键值还原
P3 |= 0xf0;
if((P3 & 0xf0) != 0xf0) //按键按下
{
delay_1ms(1); //按键消抖动
if(((P3 & 0xf0) != 0xf0) && (key_new == 1))
{ //确认是按键按下
key_new = 0;
switch(P3 & 0xf0)
{
case 0x70: key_can = 3; break; //得到k2键值
case 0xA0: key_can = 2; break; //得到k3键值
case 0xE0: key_can = 1; break; //得到k4键值
}
}
}
else
key_new = 1;
}
/****************按键处理显示函数***************/
void key_with()
{
if(key_can == 1) //设置键
{
menu_1 ++;
if(menu_1 > 3)
{
menu_1 = 0;
init_1602() ; //1602初始化
}
}
if(menu_1 != 0)
{
if(menu_1 == 1) //设置距离报警
{
if(key_can == 2)
{
set_z ++ ; //加1
if(set_z > 450)
set_z = 450;
}
if(key_can == 3)
{
set_z -- ; //减1
if(set_z <= 1)
set_z = 1;
}
}
if(menu_1 == 2) //设置距离报警
{
if(key_can == 2)
{
set_l ++ ; //加1
if(set_l > 450)
set_l = 450;
}
if(key_can == 3)
{
set_l -- ; //减1
if(set_l <= 1)
set_l = 1;
}
}
if(menu_1 == 3) //设置距离报警
{
if(key_can == 2)
{
set_r ++ ; //加1
if(set_r > 450)
set_r = 450;
}
if(key_can == 3)
{
set_r -- ; //减1
if(set_r <= 1)
set_r = 1;
}
}
if(menu_1 == 3) //设置距离报警
{
if(key_can == 2)
{
set_b ++ ; //加1
if(set_b > 450)
set_b = 450;
}
if(key_can == 3)
{
set_b -- ; //减1
if(set_b <= 1)
set_b = 1;
}
}
write_sfm3(1,6,set_z); //显示左中间的距离
write_sfm3(1,10,set_b); //显示左中间的距离
write_sfm3(2,2,set_l); //显示左边的距离
write_sfm3(2,10,set_r); //显示右边的距离
}
}
/**************10us延时函数***************/
void delay()
{
_nop_(); //执行一条_nop_()指令就是1us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/*********************超声波测距程序*****************************/
void send_wave_z()
{
c_send_z = 1; //10us的高电平触发
delay();
c_send_z = 0;
TH0 = 0; //给定时器0清零
TL0 = 0;
TR0 = 0; //关定时器0定时
TR0=1; //开启计数
while(c_recive_z) //当c_recive为1计数并等待
{
flag_time0 = TH0 * 256 + TL0;
if((flag_time0 > 40000)) //当超声波超过测量范围时,显示3个888
{
TR0 = 0;
flag_csb_juli_z = 2;
distance_z = 888;
break ;
}
else
{
flag_csb_juli_z = 1;
}
}
if(flag_csb_juli_z == 1)
{
TR0=0; //关定时器0定时
distance_z =flag_time0; //读出定时器0的时间
distance_z *= wendu_buchang1[temperature] / 2.0 * 0.0001; // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
}
}
/*********************超声波测距程序*****************************/
void send_wave_l()
{
c_send_l = 1; //10us的高电平触发
delay();
c_send_l = 0;
TH0 = 0; //给定时器0清零
TL0 = 0;
TR0 = 0; //关定时器0定时
TR0=1; //开启计数
while(c_recive_l) //当c_recive为1计数并等待
{
flag_time0 = TH0 * 256 + TL0;
if((flag_time0 > 40000)) //当超声波超过测量范围时,显示3个888
{
TR0 = 0;
flag_csb_juli_l = 2;
distance_l = 888;
break ;
}
else
{
flag_csb_juli_l = 1;
}
}
if(flag_csb_juli_l == 1)
{
TR0=0; //关定时器0定时
distance_l=flag_time0; //读出定时器0的时间
distance_l *= wendu_buchang1[temperature] / 2.0 * 0.0001; // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
}
}
/*********************超声波测距程序*****************************/
void send_wave_r()
{
c_send_r = 1; //10us的高电平触发
delay();
c_send_r = 0;
TH0 = 0; //给定时器0清零
TL0 = 0;
TR0 = 0; //关定时器0定时
TR0=1; //开启计数
while(c_recive_r) //当c_recive为1计数并等待
{
flag_time0 = TH0 * 256 + TL0;
if((flag_time0 > 40000)) //当超声波超过测量范围时,显示3个888
{
TR0 = 0;
flag_csb_juli_r = 2;
distance_r = 888;
break ;
}
else
{
flag_csb_juli_r = 1;
}
}
if(flag_csb_juli_r == 1)
{
TR0=0; //关定时器0定时
TR0=0; //关定时器0定时
distance_r =flag_time0; //读出定时器0的时间
distance_r *= wendu_buchang1[temperature] / 2.0 * 0.0001; // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
}
}
/*********************超声波测距程序*****************************/
void send_wave_b()
{
c_send_b = 1; //10us的高电平触发
delay();
c_send_b = 0;
TH0 = 0; //给定时器0清零
TL0 = 0;
TR0 = 0; //关定时器0定时
while(!c_recive_b); //当c_recive为零时等待
TR0=1; //开启计数
while(c_recive_b) //当c_recive为1计数并等待
{
flag_time0 = TH0 * 256 + TL0;
if((flag_time0 > 40000)) //当超声波超过测量范围时,显示3个888
{
TR0 = 0;
flag_csb_juli_b = 2;
distance_b = 888;
break ;
}
else
{
flag_csb_juli_b = 1;
}
}
if(flag_csb_juli_b == 1)
{
TR0=0; //关定时器0定时
TR0=0; //关定时器0定时
distance_b =flag_time0; //读出定时器0的时间
distance_b *= wendu_buchang1[temperature] / 2.0 * 0.0001; // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
}
}
/****************报警函数***************/
void clock_h_l()
{
if(distance_l <= set_l)
led_l = 0; //打开指示灯
else
led_l = 1;
if(distance_z <= set_z)
led_z = 0; //打开指示灯
else
led_z = 1;
if(distance_r <= set_r)
led_r = 0; //打开指示灯
else
led_r = 1;
if(distance_b <= set_b)
led_b = 0; //打开指示灯
else
led_b = 1;
if((distance_l <= set_l) || (distance_z <= set_z) || (distance_r <= set_r) || (distance_b <= set_b))
{
beep = ~beep; //蜂鸣器报警
}
else
{
beep = 1; //取消报警
}
}
/*********************定时器0、定时器1初始化******************/
void time_init()
{
EA = 1; //开总中断
TMOD = 0X11; //定时器0、定时器1工作方式1
ET0 = 0; //关定时器0中断
TR0 = 0; //允许定时器0定时
ET1 = 0; //开定时器1中断
TR1 = 1; //允许定时器1定时
}
/***************主函数*****************/
void main()
{
static uchar value = 5;
init_1602(); //1602初始化
time_init();
while(1)
{
key(); //按键函数
if(key_can < 10)
{
key_with(); //按键处理函数
}
if(flag_300ms == 1)
{
flag_300ms = 0;
temperature = read_temp(); //先读出温度的值
send_wave_z(); //读出距离
send_wave_l(); //读出距离
send_wave_r(); //读出距离
send_wave_b(); //读出距离
if(menu_1 == 0)
{
value ++;
if(value > 10) //3秒钟自动播放一次
{
value = 0;
if(distance_z == 888)
{
Send_threelines(46); //前方
Send_threelines(0x0d); //语音播放已超出量程
}
else
{
Send_threelines(46); //前方
Send_threelines( distance_z / 100 % 10); //语音播放
Send_threelines(0x0b);
Send_threelines(distance_z / 10 % 10);
Send_threelines(distance_z % 10);
Send_threelines(0x0c);
Send_threelines(49); //米有障碍物
}
if(distance_l == 888)
{
Send_threelines(47); //左方
Send_threelines(0x0d); //语音播放已超出量程
}
else
{
Send_threelines(47); //左方
Send_threelines( distance_l / 100 % 10); //语音播放
Send_threelines(0x0b);
Send_threelines(distance_l / 10 % 10);
Send_threelines(distance_l % 10);
Send_threelines(0x0c);
Send_threelines(49); //米有障碍物
}
if(distance_r == 888)
{
Send_threelines(48); //右方
Send_threelines(0x0d); //语音播放已超出量程
}
else
{
Send_threelines(48); //右方
Send_threelines( distance_r / 100 % 10); //语音播放
Send_threelines(0x0b);
Send_threelines(distance_r / 10 % 10);
Send_threelines(distance_r % 10);
Send_threelines(0x0c);
Send_threelines(49); //米有障碍物
}
if(distance_b == 888)
{
Send_threelines(55); //后方
Send_threelines(0x0d); //语音播放已超出量程
}
else
{
Send_threelines(55); //后方
Send_threelines( distance_b / 100 % 10); //语音播放
Send_threelines(0x0b);
Send_threelines(distance_b / 10 % 10);
Send_threelines(distance_b % 10);
Send_threelines(0x0c);
Send_threelines(49); //米有障碍物
}
}
write_sfm3(1,6,distance_z); //显示左中间的距离
write_sfm3(1,10,distance_b); //显示右边的距离
write_sfm3(2,2,distance_l); //显示左边的距离
write_sfm3(2,10,distance_r); //显示右边的距离
}
}
}
}
/*********************定时器0中断服务程序************************/
void time1_int() interrupt 3
{
static uchar value; //定时10ms中断一次
TH1 = 0xf8;
TL1 = 0x30; //2ms
value++;
if(value >= 150)
{
value = 0;
flag_300ms = 1;
clock_h_l(); //*报警函数
}
}
我来回答