//LCD1602驱动程序
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_RS P2_5 //定义引脚
#define LCD1602_RW P2_6
#define LCD1602_E P2_7
#define LCD1602_IO P0
#define Busy 0x80 //用于检测LCD1602状态字中的Busy标识
const uchar num[]="0123456789.-+";
void WriteData(uchar DAT);
void WriteCommand(uchar command,BuysC);
uchar ReadData(void);
void Readbusy(void);
void LCD1602_Init(void);
void DisplayOneChar(uchar X, uchar Y, uchar DData);
void Displaystring(uchar X, uchar Y, uchar code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void delayms(uchar);
uchar code a[] = {"WENDUCONGZHI"};
uchar code b[]={"LMT:2"};
uchar code c[]={"MAX:9"};
uchar a0,a1,a2,a3;
uint aa;
float wendu;//得到的十进制温度值
uchar temp[2]={0,0}; //存放DS18B20的温度寄存器值
uint value = 0; //读字节变量
sbit FM=P2^2; //超温 控制 引脚
sbit DQ=P2^0; //数据线
void ReadSerialNumber(void);
void ow_reset(void);
void tmstart (void);
void ReadSerialNumber(void);
void Read_Temperature(void);
void write_byte(char);
uint read_byte(void);
void delay_18B20(uint);
void baojing();
void zhuanhuan();
void delay_led(uint z);
/******转换************/
void zhuanhuan()
{
aa=wendu;
a1=aa/100; //百位
a2=aa%100/10; //十位
a3=aa%10; //个位
}
//========18b20延时程序=================*/
void delay_18B20(uint seconds) //12us延时
{
for(;seconds>0;seconds--);
}
/******************************************
18b20程序
******************************************/
//===============复位 ===========
void ow_reset(void)
{
uchar x;
DQ = 0; //pull DQ line low
delay_18B20(88); //至少480微秒,
DQ = 1;
delay_18B20(12); // wait for presence18b20 36us
x = DQ; // X=0,则 初始化成功 ,X=1,则 失败 。
delay_18B20(22);
}
//=========从总线上读取一个字节========
uint read_byte(void)
{
uchar i;
for (i=8;i>0;i--)
{
value>>=1;
DQ = 0;
_nop_();_nop_();_nop_();_nop_();
DQ = 1;
if(DQ)
{
value|=0x80; //取出高位数据
}
delay_18B20(8);
}
return(value); //返回 value值
}
//===========向18B20写一个字节=================
void write_byte(char val)
{
uchar i,j;
for (i=8; i>0; i--) // writes byte, one bit at a time
{
DQ = 0; // pull DQ low to start timeslot
j++; /*延时4us*/
DQ = val&0x01; //从低位开始写
delay_18B20(12);
DQ = 1;
j++;
val>>=1; //写完一位 ,移除它
}
}
//============读取温度============
void Read_Temperature(void)
{
uint k,i,t;
float temple; /*存放读取的温度值 将其除以16即为得到的值*/
ow_reset(); //复位
k++; //延时4us
k++;
k++;
k++;
write_byte(0xCC); //直访ROM
k++; //延时4us
write_byte(0xBE); // 写入读命令
k++;k++; //延时8us
temp[0]=read_byte(); //读取低字节
temp[1]=read_byte(); //读取高字节
i=temp[1];
t=temp[0];
i=i<<8;
i=i|t;
if((temp[1]&0x80)) //符号位判断
{
temple=(~i+1); //如果为负温则去除其补码 ,先将 补码转换成 原码
a0=num[11]; /*表示温度为负数 */
}
else
{
temple=i;
a0=num[12]; //*表示温度为正数
}
k=0;
wendu=temple*0.0625;
wendu=wendu*10+0.5;
}
//=======初始化============
void tmstart (void)
{
ow_reset(); //复位
delay_18B20(3); //延时
write_byte(0xCC); //跳过序列号命令,对所有器件有效
write_byte(0x44); //发转换命令 44H,
}
//========报警===========//
void baojing()
{
if(aa>=34)
FM=0;
else if( aa<=31)
FM=1;
}
//
void delayms(uchar i)
{
uchar j;
for(;i>0;i--)
for(j=0;j<125;j++)
{;}
}
void delays(uint m)
{
uint i,j;
for(i=0;i
for(j=0;j<1000;j++)
{;}
}
}
//
void main(void)
{
uchar shuju;
delayms(2);
Delay400Ms(); //启动等待,等LCM讲入工作状态
delays(1);
LCD1602_Init(); //LCM初始化
Delay5Ms(); //延时片刻(可不要)
shuju=ReadData();
Displaystring(2, 0, a);
tmstart (); //18B20初始化
delay_18B20(58);
while(1)
{
Read_Temperature(); //读温度
delay_18B20(59);
tmstart(); //初始化
delay_18B20(59); //*等待转换结束
zhuanhuan(); // 显示数值转换
DisplayOneChar(0,1,a0);
DisplayOneChar(1,1,num[a1]);
DisplayOneChar(2,1,num[a2]);
DisplayOneChar(3,1,num[10]);
DisplayOneChar(4,1,num[a3]);
Displaystring(6,1,b);
Displaystring(11,1,c);
baojing(); //报警扫描
//shuju=ReadData();//测试用句无意义
}
}
//写数据
void WriteData(uchar DAT)
{
Readbusy();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_IO = DAT;
LCD1602_E = 0; //若晶振速度太高可以在这后加小的延时
LCD1602_E = 0; //延时
LCD1602_E = 1;
LCD1602_E=1;
LCD1602_E=0;
}
//写指令
void WriteCommand(uchar command,BuysC) //BuysC为0时忽略忙检测
{
LCD1602_IO=0x00;
if (BuysC)
Readbusy(); //根据需要检测忙
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_IO = command;
LCD1602_E = 0;
LCD1602_E = 0;
LCD1602_E = 1;
LCD1602_E = 1;
LCD1602_E=0;
}
//读数据
uchar ReadData(void)
{
Readbusy();
LCD1602_RS = 1;
LCD1602_RW = 1;
LCD1602_E = 0;
LCD1602_E = 0;
LCD1602_E = 1;
delayms(1);
LCD1602_E = 0;
return(LCD1602_IO);
}
//读忙
void Readbusy(void)
{
LCD1602_IO = 0xff;
LCD1602_RS = 0;
LCD1602_RW = 1;
LCD1602_E = 0;
LCD1602_E = 0;
LCD1602_E = 1;
delayms(2);
while (LCD1602_IO&0x80); //检测忙信号
LCD1602_E = 0;
}
//初始化
void LCD1602_Init(void) //LCM初始化
{
Delay400Ms();
LCD1602_E = 0;
LCD1602_IO=0x00;
WriteCommand(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommand(0x38,0);
Delay5Ms();
WriteCommand(0x38,0);
Delay5Ms();
WriteCommand(0x38,1); //显示模式设置,开始要求每次检测忙信号
Delay5Ms();
WriteCommand(0x08,1); //关闭显示 ]
Delay5Ms();
WriteCommand(0x01,1); //显示清屏
Delay5Ms();
WriteCommand(0x06,1); // 显示光标移动设置
Delay5Ms();
WriteCommand(0x0f,1); // 显示开及光标设置
Delay5Ms();
}
//按指定位置显示一个字符
void DisplayOneChar(uchar X, uchar Y, uchar DData)
{
Y &= 0x01;
X &= 0x0f; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; // 算出指令码
WriteCommand(X, 0); //这里不检测忙信号,发送地址码
WriteData(DData);
}
//按指定位置显示一串字符
void Displaystring(uchar X, uchar Y, uchar code *DData)
{
uchar ListLength;
ListLength = 0;
Y &= 0x01;
X &= 0x0f; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x20) //若到达字串尾则退出
{
if (X <= 0x0f) //X坐标应小于0x0f
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}
//5ms延时
void Delay5Ms(void)
{
unsigned int t = 5552;
while(t--);
}
//400ms延时
void Delay400Ms(void)
{
uchar i = 5;
uint j;
while(i--)
{
j=7269;
while(j--);
}
}
上一篇:单片机做的简单逆变器(DC12-AC220)
下一篇:关于单片机I/0口置低的引脚不能拉高的问题
推荐阅读最新更新时间:2024-03-16 15:21