以前课设做的小温度传感系统,分享一下!
想要直接用的可以去我资源界面下载,传送门。
老规矩先上效果
本系统以AT89C52、DS18B20温度传感器、DS1302实时时钟、LCD1602液晶显示屏模块、蜂鸣器、固态继电器模块等元件构成一个自动恒温加热装置。
温度控制的利用在许多的地方都有比较大的发展空间。随着现代电子信息技术的发展,许多质量好而且便宜的温度传感器被设计开发,在温度的检测控制得到了较大的利用。
在此背景条件下,我们选择AT89C52最小系统为总控芯片设计出一个带声光报警系统的恒温箱系统,以DS18B20温度传感器和两个独立按键作为系统与外界的交互模块,可以通过独立按键模块对恒温系统的温度变化范围进行设置,当外界温度传感器的温度过低时,单片机将对其控制下的加热“热得快”进行一定占空比的供电,可以调节加热的速率,当温度过高时,会开启降温模块下的温控小风扇进行模拟降温,从而在一定程度上降低恒温箱的温度,迫使它回归正常的温度范围。
用到的元器件
本系统以AT89C52、DS18B20温度传感器、DS1302实时时钟、LCD1602液晶显示屏模块、蜂鸣器、固态继电器模块等元件构成一个自动恒温加热装置。
- AT89C52做本设计的主控芯片,主要处理来自外部信号检测,采集以及控制。
AT89C52芯片的CPU的内核是8051,内含8K字节的的可反复擦写1000次的Flash存储器,片内含256字节的随机存取数据存储器(RAM), 相当于计算机的内存。STC89C52 是由宏晶科技公司生产的与工业标准 MCS-51 指令集和输出管脚相兼容的单片机。
(1)中央处理器(CPU)
中央处理器是单片机的核心,完成运算和控制功能。8051 的 CPU 能处理 8 位二进制数或代码。
(2)内部数据存储器(内部 RAM)
8051 芯片中共有 256 个 RAM 单元,但其中后 128 单元被专用寄存器占用,能作为寄存器供用户使用的只是前 128 单元,用于存放可读写的数据。因此通常所说的内部数据存储器就是指前 128 单元,简称内部 RAM。
(3)内部程序存储器(内部 ROM)
8051 共有 4KB 掩膜 ROM,用于存放程序、原始数据或表格,因此,称之为程序存储器,简称内部 ROM。
(4)定时/计数器
8051 共有两个 16 位的定时/计数器,以实现定时或计数功能,并以其定时或计数结果对计算机进行控制。
(5)并行 I/O 口
MCS-51 共有 4 个 8 位的 I/O 口(P0、P1、P2、P3),以实现数据的并行输入/输出。
(6)串行口
8051 单片机有一个全双工的串行口,以实现单片机和其它设备之间的串行数据传送。该串行口功能较强,既可作为全双工异步通信收发器使用,也可作为同步移位器使用。
(7)中断控制系统
8051 单片机的中断功能较强,以满足控制应用的需要。8051 共有 5 个中断源,即外中断两个,定时/计数中断两个,串行中断一个。全部中断分为高级和低级共两个优先级别。
(8) 时钟电路8051 芯片
内部有时钟电路,但石英晶体和微调电容需外接。时钟电路为单片机产生时钟脉冲序列。系统允许的晶振频率一般为 6 MHz 和 12 MHz。
从上述内容可以看出,MCS-51 虽然是一个单片机芯片,但作为计算机应该具有的基本部件它都包括,因此,实际上它已是一个简单的微型计算机系统了。
- DS18B20温度传感器主要检测加热的实时温度,经单片机处理后显示在12864LCD液晶显示屏上。
液晶(Liquid Crystal)是一种高分子材料,因为其特殊的物理、化学、光学特性,20 世纪中叶开始广泛应用在轻薄型显示器上。
液晶显示器(Liquid Crystal Display, LCD)的主要原理是以电流刺激液晶分子产生点、线、面并配合背部灯管构成画面。为叙述简便,通常把各种液晶显示器都直接叫做液晶。
各种型号的液晶通常是按照显示字符的行数或液晶点阵的行、列数来命名的。比如:1602 的意思是每行显示 16 个字符,一共可以显示两行;类似的命名还有 0801, 0802, 1601 等,这类液晶通常都是字符型液晶,即只能显示 ASCII 码字符,如数字、大小写字母、各种符号等。12232 液晶属于图形型液晶,她的意思是液晶由 122 列、32 行组成,即共有 122 X 32 个点来显示各种图形,我们可以通过程序控制这 122 X 32 个点中的任一个点显示或不显示。类似的命名还有12864, 19264, 192128, 320240 等,根据客户需要,厂家可以设计出任意数组合的点阵液晶。
DDRAM地址与现实位置的对应关系:
读操作时序
写操作时序
时序参数
-
DS1302为实时钟芯片,做为系统显示时间用。电源电路经变压器变压后,再经7805稳压后为系统提供稳定的5V工作电压。
DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单、体积小的特点。18B20 芯片形状同普通小功率三极管极为相似,因此用它来组成一个测温系统,线路简单,在一根通信线上,可以挂很多这样的数字温度计,十分方便。DS18B20是美国DALLAS公司新推出的一种可组网数字式温度传感器,与DS1820相似,DS18B20也能够直接读取被测物体的温度值。但是与DS1820相比,DS18B20的功能更强大些。它体积小,电压适用范围宽(35V),用户还可以通过编程实现912位的温度读数,即具有可调的温度分辨率,因此它的实用性和可靠性比同类产品更高。另外,DS18B20有多种封装可选,如TO-92, SOIC及CSP封装。
DS18B20的内部测温电路中低温度系数振荡器的振荡频率受温度的影响很小,用于产生固定频率的脉冲信号送给减法计数器1,高温度系数振荡器随温度变化其振荡频率明显改变,所产生的信号作为减法计数器2的脉冲输入。它的内部还隐含着计数门,当计数门打开时,DS18B20就对低温度系数振荡器产生的时钟脉冲进行计数,进而完成温度测量。计数门的开启时间由高温度系数振荡器来决定,每次测量前,首先将-55℃所对应的基数分别置人减法计数器1和温度寄存器中,减法计数器1和温度寄存器被预置在-55℃所对应的一个基数值。减法计数器1对低温度系数振荡器产生的脉冲信号进行减法计数,当减法计数器1的预置值减到。时温度寄存器的值将加1,减法计数器1的预置将重新被装人,减法计数器1重新开始对低温度系数振荡器产生的脉冲信号进行计数,如此循环直到减法计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。图5-11中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正减法计数器的预置值,只要计数门仍未关闭就重复上述过程,直至温度寄存器值达到被测温度值,这就是DS18B20的测温原理。
它的特点如下:
(1)18b20 是单线温度传感器,广泛用于多点温度检测,因为他是数字信号,可直接将温度转化为串行数字信号供单片机处理,所以可以避免长距离误差;
(2)电压范围在3.0-5.5V;测量温度在 -55°C+125°C,在10°C+85°C精度为±0.5°C
(3)其中一种封装外形如同普通三极管,2 个电源引脚,一个信号接口,硬件 连接只需要一个10K电阻;
(4)主要是程序部分,由于是单线采集,精度较高是采样时间比较长,接近 1S,所以重复采样的频率不能太高,不然会造成数据紊乱。 -
固态继电器
固态继电器(亦称固体继电器)英文名称为SolidState Relay,简称SSR。它是用半导体器件代替传统电接点作为切换装置的具有继电器特性的无触点开关器件,单相SSR为四端有源器件,其中两个输入控制端,两个输出端,输入输出间为光隔离,输入端加上直流或脉冲信号到一定电流值后,输出端就能从断态转变成通态。
固态继电器使用场合:固态继电器目前已广泛应用于计算机外围接口装置,电炉加热恒温系统,照明舞台灯光控制系统,自动消防、保安系统等等。另外,在化工、煤矿等需防爆、防潮、防腐蚀场合中均有大量使用。
固态继电器优缺点:固态继电器工作可靠,寿命长,无噪声,无火花,无电磁干扰,开关速度快,抗干扰能力强,且体积小,耐冲击,耐振荡,防爆、防潮、防腐蚀、能与TTL、DTL、HTL等逻辑电路兼容,以微小的控制信号达到直接驱动大电流负载。
主要不足是存在通态压降(需相应散热措施),有断态漏电流,交直流不能通用,触点组数少。 另外,过电流、过电压及电压上升率、电流上升率等指标差。
固态继电器按负载类型可分为交流型(AC-SSR)和直流型(DC-SSR)两类,两者不能混用。
-
蜂鸣器报警,用于系统温度超高报警用,超温指示灯当温度超出时闪烁。
-
按键控制设置上下限温度的设置。启动/停止按键为开始启动加热和停止加热按键,每按一次可在开和关之间转换。
硬件总体设计
软件设计
主程序设计,当系统上电后。系统首先进行系统初始化,完成对系统定时器的配置以及,液晶显示屏的初始化工作。然后进入循环检测控制程序,其中包括对温度的检测,以及对温度的控制,并且有LCD1602液晶实时显示当前系统信息。
按键控制软件部分,是对温度上下限设置的操作。系统分为3个控制按键,分别为设置按键、加按键、减按键。“设置按键”是对当前系统状态以及当前设置项的切换。并且根据当前设置项的不同,通过“加按键”、“减按键”设置温度上、下限的值,从而控制系统温度的范围。
系统温度控制,是根据当前系统温度对比温度的上、下限值。从而控制系统加温及降温的控制操作,如图所示。并且通过蜂鸣器做报警提示处理,当温度超出温度上、下限时,蜂鸣器开始报警。
单片机对DS18B20的访问流程是:先对DS18B20初始化,再进行ROM操作命令,最后才能对存储器操作,数据操作。
DS18B20每一步操作都要遵循严格的工作时序和通信协议。如主机控制DS18B20完成温度转换这一过程,根据DS18B20的通讯协议,须经三个步骤:每一次读写之前都要对DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作。
代码实现
#include<reg52.h>
#include<LCD1602.h> //引用1602头文件
#include<DS18B20.h> // 引用18B20头文件
#include<EEPROM.h> //引用掉电存储头文件
sbit KEY1=P3^1; //定义按键
sbit KEY2=P3^2;
sbit KEY3=P3^3;
sbit beep=P1^4; //定义蜂鸣器
sbit jdq1=P1^0; //定义继电器1
sbit jdq2=P1^1; //定义继电器2
bit key2_flag=0;
bit key3_flag=0;
bit key4_flag=0;
bit key5_flag=0;
uchar xdata rec[36];
uchar sec1=0,sec2=0; //定义按键长按延时变量
int DS;
char RH;
char RL;
uchar xdata rec_dat[16];
uchar i,j,nu;
uchar w=0;
uint tt,yy;
bit l=0; //按键连按标志位
bit beep1=0;
void key(void);
//-------------------延时函数--------------------------
void delay(uint z) //延时
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//---------------------------------------------------
void Timer0_Init() //初始化定时器
{
tt=0;
yy=0;
TMOD=0x11;//设置定时器0为工作方式1
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
EA= 1;//开总中断
ET0=1;//开定时器0中断
ET1=1;//开定时器1中断
TR0=1;//启动定时器0
TR1=1;//启动定时器1
}
//--------------掉电存储-------------------------
void write()
{
SectorErase(0x2000); //扇区擦除
byte_write (0x2001,RH);
byte_write (0x2002,RL);
}
void read()
{
RH=byte_read(0x2001);
RL=byte_read(0x2002);
}
//---------------------------------------------------
//--------------温度显示界面-----------------------
void show1()
{
LCD1602_write(0,0x80);
LCD1602_writebyte("Temper:");
if(DS>=0)
{
if((DS/1000%10)>0)
LCD1602_write(1,0x30+DS/1000%10);
else
LCD1602_writebyte(" ");
if((DS/100%10)>=0&&(DS/1000%10)>0)
LCD1602_write(1,0x30+DS/100%10);
else if((DS/100%10)>0&&(DS/1000%10)<=0)
LCD1602_write(1,0x30+DS/100%10);
else
LCD1602_writebyte(" ");
if((DS/10%10)>=0)
LCD1602_write(1,0x30+DS/10%10);
LCD1602_writebyte(".");
LCD1602_write(1,0x30+DS%10);
LCD1602_write(1,0xdf);
LCD1602_writebyte("C");
}
else if(DS*-1>=100)
{
LCD1602_write(0,0x87); //从lcd1602第一行第八个位置开始显示
LCD1602_writebyte("-");
if((DS*-1)/100%10>0)
LCD1602_write(1,0x30+(DS*-1)/100%10);
else
LCD1602_writebyte(" ");
if(((DS*-1)/10%10)>=0&&((DS*-1)/100%10>0))
LCD1602_write(1,0x30+(DS*-1)/10%10);
else if(((DS*-1)/10%10)>0&&(DS*-1)/100%10<0)
LCD1602_write(1,0x30+(DS*-1)/10%10);
else
LCD1602_writebyte(" ");
LCD1602_writebyte(".");
LCD1602_write(1,0x30+(DS*-1)%10);
LCD1602_write(1,0xdf);
LCD1602_writebyte("C");
}
else
{
LCD1602_write(0,0x87); //从lcd1602第一行第八个位置开始显示
LCD1602_writebyte(" ");
LCD1602_writebyte("-");
LCD1602_write(1,0x30+(DS*-1)/10%10);
LCD1602_writebyte(".");
LCD1602_write(1,0x30+(DS*-1)%10);
LCD1602_write(1,0xdf);
LCD1602_writebyte("C");
}
LCD1602_write(0,0x80+0x40);
LCD1602_writebyte("H:");
LCD1602_write(0,0x80+0x49);
LCD1602_writebyte("L:");
if(RH>=0)
{
LCD1602_write(0,0x80+0x42);
if((RH/100%10)>0)
LCD1602_write(1,0x30+RH/100%10);
else
LCD1602_writebyte(" ");
if((RH/10%10)>=0&&(RH/100%10)>0)
LCD1602_write(1,0x30+RH/10%10);
else if((RH/10%10)>0)
LCD1602_write(1,0x30+RH/10%10);
else
LCD1602_writebyte(" ");
if((RH%10)>=0)
LCD1602_write(1,0x30+RH%10);
}
if(RH<0)
{
LCD1602_write(0,0x80+0x42);
LCD1602_writebyte("-");
if(((RH*-1)/10%10)>0)
LCD1602_write(1,0x30+(RH*-1)/10%10);
else
LCD1602_writebyte(" ");
if(((RH*-1)/10%10)>=0&&((RH*-1)/10%10)>0)
LCD1602_write(1,0x30+(RH*-1)%10);
else
LCD1602_write(1,0x30+(RH*-1)%10);
}
if(RL>=0)
{
LCD1602_write(0,0x80+0x4b);
if((RL/100%10)>0)
LCD1602_write(1,0x30+RL/100%10);
else
LCD1602_writebyte(" ");
if((RL/10%10)>=0&&(RL/100%10)>0)
LCD1602_write(1,0x30+RL/10%10);
else if((RL/10%10)>0)
LCD1602_write(1,0x30+RL/10%10);
else
LCD1602_writebyte(" ");
if((RL%10)>=0)
LCD1602_write(1,0x30+RL%10);
}
if(RL<0)
{
LCD1602_write(0,0x80+0x4b);
LCD1602_writebyte("-");
if(((RL*-1)/10%10)>0)
LCD1602_write(1,0x30+(RL*-1)/10%10);
else
LCD1602_writebyte(" ");
if(((RL*-1)/10%10)>=0&&((RL*-1)/10%10)>0)
LCD1602_write(1,0x30+(RL*-1)%10);
else
LCD1602_write(1,0x30+(RL*-1)%10);
}
}
//---------------------------------------------------
//-----------------温度上下限调整------------------
void KEY() //温度上下限调整
{
//--------------------------------RH+-
w=0;
w++; //W:是设置按键KEY1按下次数,KEY1按下一次W加一,按下三次后退出设置功能,退出KEY()函数,返回main()函数,执行主函数内的流程//
while(1)
{
show1(); //显示温度界面
if(nu==1&&w==1)
{
LCD1602_write(0,0x80+0x42);
LCD1602_writebyte(" ");
LCD1602_write(0,0x80+0x43);
LCD1602_writebyte(" ");
LCD1602_write(0,0x80+0x44);
LCD1602_writebyte(" ");
}
if(!KEY2) //按键KEY2按下(数字加功能键)
{
if(key2_flag) //按键按下标志位,只有按键松开才会置一
{
key2_flag=0; //清零,这样,就算按键一直按下,由于只有按键松开才会置一,所以这个函数只会执行一次
if( RH<125) {RH++;} //数据加一
}
if(sec1==0) //这个变量只有在按键松开,才会一直是2,按键按下后会每隔1S减一
{ //当等于0的时候,判断为长按,需要连加减
if( RH<125) {RH++;} //连加设定
}
key4_flag=1; //按键按下才会置一 //温度上限RH加一
}
else
{
key2_flag=1; sec1=2; //赋值
if(key4_flag==1) //当确定按下键按下过,就执行这个函数
{
key4_flag=0;
write(); //存储数据
}
}
if(!KEY3) //与上述KEY2相同,不在阐述
{
if(key3_flag)
{
key3_flag=0;
if( RH>(RL+1)) {RH--;}
}
if(sec2==0)
{
if( RH>(RL+1)) {RH--;}
}
key5_flag=1;
}
else
{
key3_flag=1; sec2=2;
if(key5_flag==1)
{
key5_flag=0;
write();
}
}
if(KEY1==0)
{
while(!KEY1);
delay(10);
while(!KEY1);
w++;
while(1)
{
show1();
if(nu==1&&w==2)
{
LCD1602_write(0,0x80+0x4b);
LCD1602_writebyte(" ");
LCD1602_write(0,0x80+0x4c);
LCD1602_writebyte(" ");
LCD1602_write(0,0x80+0x4d);
LCD1602_writebyte(" ");
}
if(!KEY2) //按键KEY2按下(数字加功能键)
{
if(key2_flag) //按键按下标志位,只有按键松开才会置一
{
key2_flag=0; //清零,这样,就算按键一直按下,由于只有按键松开才会置一,所以这个函数只会执行一次
if( RL<(RH+1)) {RL++;} //数据加一
if(RL==RH) {RL--;}
}
if(sec1==0) //这个变量只有在按键松开,才会一直是2,按键按下后会每隔1S减一
{ //当等于0的时候,判断为长按,需要连加减
if( RL<(RH+1)) {RL++;} //连加设定
if(RL==RH) {RL--;}
}
key4_flag=1; //按键按下才会置一 //温度上限RH加一
}
else
{
key2_flag=1; sec1=2; //赋值
if(key4_flag==1) //当确定按下键按下过,就执行这个函数
{
key4_flag=0;
write(); //存储数据
}
}
if(!KEY3)
{
if(key3_flag)
{
key3_flag=0;
if( RL>(-55)) {RL--;}
}
if(sec2==0)
{
if( RL>(-55)) {RL--;}
}
key5_flag=1;
}
else
{
key3_flag=1; sec2=2;
if(key5_flag==1)
{
key5_flag=0;
write();
}
}
if(KEY1==0)
{
while(!KEY1);
delay(10);
while(!KEY1);
w++;
}
if(w>=3)
break;
}
}
if(w>=3)
break;
}
write();
}
//--------------------------------RL+-
//---------------------------------------------------
//-----------------------报警函数--------------------
void alert()
{
if(DS<RH*10&&DS>RL*10) //如果当前温度高于设置最高温度RH,发光二极管点亮,蜂鸣器报警
beep1=1;
else //否则 发光二极管、蜂鸣器关闭
beep1=0;
if(DS<RL*10) // 当前温度低于设置最低温度RL,继电打开
jdq1=0;
if(DS>=RH*10) // 当前温度高于设置最高温度RH,继电器关闭
{
jdq1=1;
jdq2=0;
}
if(DS<RH*10)
jdq2=1;
}
//---------------------------------------------------
//---------------------主界面------------------------
void main()
{
LCD1602_cls(); //lcd1602初始化
Initial(); //初始化DS18B20函数
do
{ //调用读温度函数,这里是一个判断,因为温度传感器,第一次读数据会出来一个850,不是温度数据,所以滤掉这一个数据
DS=Temper();
}
while(DS==850);
Timer0_Init(); //初始化定时器
read(); //读单片机内部EEPROM内存储的温度上下限的值
show1(); //界面显示
// cc=0;
// dd=0;
// l=0;
if(RH<(-50)||RH>130||RL<(-50)||RL>130||RH<=RL) //如果从存储区读取的温度上下限RH、RL的值不对,就对它们从新赋值
{
RH=40;
RL=10;
}
while(1)
{
show1(); //打印界面
alert(); //进入报警程序,判断是否有触发状态
if(KEY1==0) //按键一按下,进入上下限设置功能
{
while(!KEY1); //等待按键起来
delay(10); //延时消抖,可不要
key(); //进入按键设置
}
}
}
void time_0() interrupt 1 //定时器0
{
TH0=(65536-10000)/256; //
TL0=(65536-10000)%256; //重装载值100ms
tt++;
if(tt>=5) //每500ms读取一次DS18B20的值
{
DS=Temper();
}
if(tt>=50)
{
tt=0;
if(beep1==0) beep=~beep;
else beep=1;
if(w==1||w==2) //闪烁标志位
{
nu=!nu;
}
}
}
void time1() interrupt 3 //定时器1的服务函数
{
TH1=0x3C;
TL1=0xb0;
yy++;
if(yy>=20) //如果ms大于等于20,说明ms自加了20次,20*50=1000,也就是1S
{
yy=0; //清零
if(sec1!=0) sec1--; //只要这两个数据不为零,都是每隔1S减一
if(sec2!=0) sec2--;
}
}
#ifndef _DS18B20_H_
#define _DS18B20_H_
#define uchar unsigned char
#define uint unsigned int
//温度IO
sbit DS1820_dat=P3^4;
void DS18B20_delay(uint T) //短延时
{
while(T--);
}
//初始化DS18B20函数
void Initial()
{
DS1820_dat=1;
DS18B20_delay(8);
DS1820_dat=0;
DS18B20_delay(80);
DS1820_dat=1;
DS18B20_delay(15);
}
void Input(uchar f) //往DS18B20里面写数据,写一个字节
{
uchar j;
for (j=0;j<8;j++)
{
DS1820_dat=0;
DS1820_dat=f&0x01;
DS18B20_delay(10);
DS1820_dat=1;
f>>=1;
}
}
uchar Output() //读取DS18B20数据,读一个字节
{
uchar j,b;
for (j=0;j<8;j++)
{
DS1820_dat=0;
b>>=1;
DS1820_dat=1;
if (DS1820_dat)
{
b=b|0x80;
}
DS18B20_delay(10);
}
return(b);
}
int Temper() //读取温度数据
{
int Store;
int Store_2,Store_1;
Initial(); //对 DS18B20 复位
Input(0xcc); //跳过 ROM
Input(0x44); //启动温度转换
Initial(); //对 DS18B20 复位
Input(0xcc); //跳过 ROM
Input(0xbe); //读 RAM 命令
Store_1=Output(); //读温度的低字节
Store_2=Output(); //读温度的高字节
Store_2=(Store_2*256)+Store_1; //合起来为温度的整数部分
Store=(int) Store_2*0.625;
return Store;
}
#endif
//1602使用上比较简单,三步走,首先初始化,然后送要显示的地址,然后送显示数据即可
#ifndef _LCD1602_H_
#define _LCD1602_H_
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_dat P0 //数据并行口宏定义
sbit LCD1602_rs=P2^5;//IO 定义
sbit LCD1602_rw=P2^6;
sbit LCD1602_e=P2^7;
void LCD1602_delay(uint T) //延时函数
{
while(T--);
}
/********************************************************************
* 名称 : LCD1602_write(uchar order,dat)
* 功能 : 1602写如数据函数
* 输入 : order为数据/命令切换变量 //0是命令 1是数据
* : dat为数据/命令的发送数据
* 输出 : 无
***********************************************************************/
void LCD1602_write(uchar order,dat) //1602 一个字节 处理
{
LCD1602_e=0;
LCD1602_rs=order;
LCD1602_dat=dat;
LCD1602_rw=0;
LCD1602_e=1;
LCD1602_delay(1);
LCD1602_e=0;
}
/********************************************************************
* 名称 : LCD1602_writebye(uchar *prointer)
* 功能 : 1602写入数据函数 指针式
* 输入 : 输入需要显示的内容
* 输出 : 无
***********************************************************************/
void LCD1602_writebyte(uchar *prointer) //1602 字符串 处理
{
while(*prointer!='\0')
{
LCD1602_write(1,*prointer);
prointer++;
}
}
/********************************************************************
* 名称 : LCD1602_cls()
* 功能 : 初始化1602液晶
* 输入 : 无
* 输出 : 无
***********************************************************************/
void LCD1602_cls() //1602 初始化
{
LCD1602_write(0,0x01); //1602 清屏 指令
LCD1602_delay(1500);
LCD1602_write(0,0x38); // 功能设置 8位、5*7点阵
LCD1602_delay(1500);
LCD1602_write(0,0x0c); //设置 光标 不显示开关、不显示光标、字符不闪烁
LCD1602_write(0,0x06);
LCD1602_write(0,0xd0);
LCD1602_delay(1500);
}
#endif
#ifndef _EEPROM52_H_
#define _EEPROM52_H_
#include <intrins.h>
//存储数据,我们用的是单片机里面自带的EEPROM,这个区域使用的流程就是
//确定使用那个扇区,然后把那个扇区数据擦除,然后写数据就行了
//读数据,直接读扇区地址
//存储区域是8位的,也就是说能够存下的最大数据是 255,而我们存的数据最大是9999,所以
//把数据拆开存 /256得到高位 %256得到低位
/*
例如
void memory()
{
SectorErase(0x2000);
byte_write (0x2002,pm_density_h/256);
byte_write (0x2003,pm_density_h%256);
}
void read_memory()
{
pm_density_h=byte_read(0x2002)*256+byte_read(0x2003);
if(pm_density_h>9999)
{
pm_density_h=200;
}
}
*/
/********STC89C51扇区分布*******
第一扇区:1000H--11FF
第二扇区:1200H--13FF
第三扇区:1400H--15FF
第四扇区:1600H--17FF
第五扇区:1800H--19FF
第六扇区:1A00H--1BFF
第七扇区:1C00H--1DFF
第八扇区:1E00H--1FFF
*****************/
/********STC89C52扇区分布*******
第一扇区:2000H--21FF
第二扇区:2200H--23FF
第三扇区:2400H--25FF
第四扇区:2600H--27FF
第五扇区:2800H--29FF
第六扇区:2A00H--2BFF
第七扇区:2C00H--2DFF
第八扇区:2E00H--2FFF
*****************/
/********STC89C54扇区分布*******
第一扇区:08000H
*****************/
#define RdCommand 0x01 //定义ISP的操作命令
#define PrgCommand 0x02
#define EraseCommand 0x03
#define Error 1
#define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间
sfr ISP_DATA=0xe2; //寄存器申明
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0xe5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;
/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
EA = 0; /* 关中断 */
ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable(void)
{
ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
ISP_TRIG = 0x00;
EA = 1; /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon(void)
{
ISP_IAP_enable(); /* 打开 ISP,IAP 功能 */
ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */
ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */
_nop_();
}
/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
EA = 0;
ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
ISP_CMD = ISP_CMD | RdCommand; /* 写入读命令 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
EA = 1;
return (ISP_DATA); /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(unsigned int sector_addr)
{
unsigned int iSectorAddr;
iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
ISP_ADDRL = 0x00;
ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */
ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
EA = 0;
// SectorErase(byte_addr);
ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */
ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */
ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */
ISP_DATA = original_data; /* 写入数据准备 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭IAP功能 */
EA =1;
}
#endif
编写不易,求个点赞!!!!!!!
“你是谁?”
“一个看帖子的人。”
“看帖子不点赞啊?”
“你点赞吗?”
“当然点了。”
“我也会点。”
“谁会把经验写在帖子里。”
“写在帖子里的那能叫经验贴?”
“上流!”
cheer!!!