一、系统方案
本设计采用52单片机作为主控器,液晶1602显示,DS18B20检测温度,电流检测。
二、硬件设计
原理图如下:
三、单片机软件设计
1、首先是系统初始化
void lcd_init() //lcd 初始化设置子函数,不带参数 ,0x38 是显示模式设置 , 其余是显示开 / 关及光标设置,无顺序
{
delay1ms(15);
wr_com(0x38); // 调用写控制指令子函数,并用实参 “0011 1000” 代替形参 com
//0x38 表示设置为 162 显示,每个块为 57 点阵, 8 位数据接口
delay1ms(5);
wr_com(0x08); // 调用写控制指令子函数,并用实参 “0000 1000” 代替形参 com
//0x08 表示设置为关显示、不显示光标、光标不闪烁
delay1ms(5);
wr_com(0x01); // 调用写控制指令子函数,并用实参 “0000 0001” 代替形参 com
//0x01 表示显示数据清屏(数据指针清 0,所有显示清 0)
delay1ms(5);
wr_com(0x06);// 调用写控制指令子函数,并用实参 “0000 0110” 代替形参 com
//0x06 表示当读或写一个字符后地址指针加 1,且光标加 1; 当写一个字符时,整屏显示不移动
delay1ms(5);
wr_com(0x0c);// 调用写控制指令子函数,并用实参 “0000 1100” 代替形参 com
//0x0c 打开显示、不显示光标、光标不闪烁
delay1ms(5);
}
2、液晶显示程序
void wr_com(uchar com) //lcd 写控制指令子函数,形参为 com
{
delay1ms(1); // 调用延时子函数,并用实参 1 代替延时子函数中的形参 ms
RS=0; //RS=0 进入写命令状态,即一些 LCD设置命令
RW=0; //RW=0 为写模式
EN=0; //EN=0 时不能完成写操作
P2=com; // 把要设置的指令码 com送给 P2 口
delay1ms(1);
EN=1; // 给 EN一个高脉冲,将数据送入液晶控制器,完成写操作
delay1ms(1);
EN=0; }//EN=0 时不能完成写操作
/检测忙标志函数*********/
void check_busy(void)
{
uchar dt;
do
{
dt=0xff;
EN=0;
RS=0;
RW=1;
EN=1;
dt=P2;
}while(dt&0x80);
EN=0;
}
//写数据**************/
void wr_dat(uchar dat) //lcd 写显示数据子函数,形参为 dat
{
/* check_busy();/
delay1ms(1);
RS=1; //RS=1 进入写数据状态,即要显示的内容
RW=0; //RW=0 为写模式
EN=0; //EN=0 时不能完成写操作
P2=dat; // 把要显示的数据 dat 送给 P2 口
delay1ms(1);
EN=1; // 给 EN一个高脉冲,将数据送入液晶控制器,完成写操作
delay1ms(1);
EN=0; //EN=0 时不能完成写操作
}
3、DS18B20程序
/********************************************************/
/********************ds18b20 程序 **********************/
void delay_18b20(uint i) // 延时 1 微秒
{
while(i–);
}
void ds18b20rst() //ds18b20 初始化子函数
// 要求"数据线拉高 - 延时 - 数据线拉低 - 延时大于 480 微妙 -数据线拉高 - 延时等待 "
{
uchar x=0;
DQ = 1; // 信号线 DQ复位
delay_18b20(4); // 延时
DQ = 0; //DQ 拉低
delay_18b20(100); // 精确延时大于 480us
DQ = 1; // 拉高
delay_18b20(40);
}
void ds18b20wr(uchar wdata) / 写数据子函数 , 无返回值,含参数 /
{
uchar i=0;
for (i=8; i>0; i–)// 要写完一个字节,故需要重复 8 次以下操作
{
DQ = 0; // 数据线拉低
DQ = wdata&0x01;//wdata 是一个形参,将其与 0000 0001 进行按位与
// 按从低到高的顺序发送数据(一次发送一位 )
delay_18b20(10);
DQ = 1; // 最后将数据线拉高
wdata>>=1; // 将 wdata 右移 1 位
}
}
uchar ds18b20rd() // 读数据子函数 , 是有返回值 dat
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i–)// 要读完一个字节,故需要重复 8 次以下操作
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18b20(10);
}
return(dat); // 返回 dat
}
read_temp() // 读取温度值并转换的子函数,有返回值温度值 tvalue
{
uchar a,b;
ds18b20rst(); // 调用 ds18b20 初始化子函数
ds18b20wr(0xcc);// 调用写数据子函数,向 ds18b20 写命令 0xcc
//ccH 表示跳过 ROM读序列号,适用于单机工作,直接向 18b20 发送温度变换命令
ds18b20wr(0x44);// 调用写数据子函数,向 ds18b20 写命令 0x44
//44H 表示启动 ds18b20 温度转换 , 结果自行存入 9 字节的 RAM中
ds18b20rst(); // 调用 ds18b20 初始化子函数
ds18b20wr(0xcc);// 同上
ds18b20wr(0xbe);// 调用写数据子函数,向 ds18b20 写命令 0xbe
//beH 表示读取 RAM中 9 字节的温度数据
a=ds18b20rd(); // 调用读数据子函数,并将所得数据给 a
b=ds18b20rd(); //
tvalue=b; // 把 b 的值给 tvalue
tvalue<<=8; //tvalue 左移 8 位
tvalue=tvalue|a;//tvalue 与 a 进行按位或
if(tvalue<0x0fff)//
tflag=0; // 前五位为 0 时,读取的温度为正,标志位为 0,此时只要
// 将测得数值乘以 0.0625 即可得到实际温度
else // 前五位为 1 时,读取的温度为负,标志位为 1,此时需要
{ // 将测得数值取反后再加 1,再乘以 0.0625 即可得到实际温度
tflag=1; // 此时表示负温度
tvalue=~tvalue+1;
}
tvalue=tvalue(0.625);// 温度值扩大 10 倍,精确到 1 位小数
return(tvalue); // 返回温度值
}
/*********************************/
/ 温度值显示 *******************/
void ds18b20disp() // 温度值显示
{
uchar flagdat;
disdata[0]=tvalue/1000+0x30; // 百位数
disdata[1]=tvalue%1000/100+0x30;// 十位数
disdata[2]=tvalue%100/10+0x30; // 个位数
disdata[3]=tvalue%10+0x30; // 小数位
if(tflag==0)
flagdat=0x2b; // 正温度显示符号 :+
else
flagdat=0x2d; // 负温度显示负号 :-
if(disdata[0]==0x30)
{
disdata[0]=0x20; // 如果百位为 0,不显示
if(disdata[1]==0x30)
{
disdata[1]=0x20; // 如果百位为 0,十位为 0 也不显示
}
}
wr_com(0x80+0x46); // 定位数据指针的位置:第二行第五个字符处
wr_dat(flagdat); // 显示符号位
wr_com(0x80+0x47); // 定位数据指针的位置:第二行第六个字符处
wr_dat(disdata[0]); // 显示百位
wr_com(0x80+0x48); // 定位数据指针的位置:第二行第七个字符处
wr_dat(disdata[1]); // 显示十位
wr_com(0x80+0x49); // 定位数据指针的位置:第二行第八个字符处
wr_dat(disdata[2]); // 显示个位
wr_com(0x80+0x4A); // 定位数据指针的位置:第二行第九个字符处
wr_dat(0x2e); // 显示小数点
wr_com(0x80+0x4B); // 定位数据指针的位置:第二行第十个字符处
wr_dat(disdata[3]); // 显示小数位
/显示摄氏度/
wr_com(0x80+0x4C); // 定位数据指针的位置:第二行第十一个字符处
wr_dat(0XDF);
wr_com(0x80+0x4D); // 定位数据指针的位置:第二行第十二个字符处
wr_dat(0X43);
}
4、核心算法程序
uint ReadADC_TLC1543(uchar ain)
{
uchar t;
uint adc_value = 0;
ain <<= 4;
CS_1543 = 0;
for (t = 0; t < 10; t++) // 将判断语句改为 temp<12
{ // 程序可移殖至 TLC2543.
adc_value <<= 1;
ain <<= 1;
ADDR_1543 = CY;
if (DOUT_1543) adc_value += 1;
SCLK_1543 = 1;
delayus(1);
SCLK_1543 = 0;
}
CS_1543 = 1;
return adc_value;
}
四、 proteus仿真设计
Proteus软件是一款应用比较广泛的工具,它可以在没有硬件平台的基础上通过自身的软件仿真出硬件平台的运行情况,这样就可以通过软件仿真来验证我们设计的方案有没有问题,如果有问题,可以重新选择器件,连接器件,直到达到我们设定的目的,避免我们搭建实物的时候,如果当初选择的方案有问题,我们器件都已经焊接好了,再去卸载下去,再去焊接新的方案的器件,测试,这样会浪费人力和物力,也给开发者带来一定困惑,Proteus仿真软件就很好的解决这个问题,我们在设计之初,就使用该软件进行模拟仿真,测试,选择满足我们设计的最优方案。最后根据测试没问题的仿真图纸,焊接实物,调试,最终完成本设计的作品。