DS1820 LCD屏显的问题~
时间:10-02
整理:3721RD
点击:
#include <reg52.h> //51芯片管脚定义头文件
#include <intrins.h> //内部包含延时函数 _nop_();
#define uchar unsigned char
#define uint unsigned int
sbit BEEP = P3^6; //蜂鸣器
sbit DS1820_DQ= P3^3; //单总线引脚
sbit LCD_CS =P2^0; //LCD片选端
sbit LCD_SID=P2^1; //LCD串行数据输入/输出端
sbit LCD_CLK=P2^2; //LCD串行同步时钟,上升沿时读取SID数据.
sbit LCD_BC=P2^3;
//函数声明:
void LCD_SEND(unsigned char send_data);
unsigned char LCD_RECEIVE();
unsigned char LCD_READ_BF();
void LCD_WRITE_IR(unsigned char LCD_COMMAND);
void LCD_WRITE_DR(unsigned char LCD_DATA);
void LCD_INIT();
//函数声明
bit DS1820_Reset();
void DS1820_WriteData(unsigned char wData);
unsigned char DS1820_ReadData();
void read_temp();
void delay100us();
void DispCode();
void display();
//函数声明:
void LCD_SEND(unsigned char sData);
unsigned char LCD_RECEIVE();
unsigned char LCD_READ_BF();
void LCD_WRITE_IR(unsigned char LCD_COMMAND);
void LCD_WRITE_DR(unsigned char LCD_DATA);
/**********************************************************/
//声明外部温度读数数组
extern unsigned char data temperature[2];
//存放分解的7个ASCII码温度数据
unsigned char temp[7];
unsigned char code string[6]={"温度:"};
unsigned char code DispStr[7]={"系列号"};
unsigned char fCode[8]; //存放序列号,CRC
/***************主函数*******************/
void main()
{
unsigned char i;
delay100us();//等待电源稳定,液晶复位完成
delay100us();
LCD_INIT(); //液晶初始化
DS1820_Reset();//DS1820复位
DS1820_WriteData(0x33);//读ROM指令
for (i=0;i<8;i++)
{//读取64位系列号
fCode[i] = DS1820_ReadData();
}
DS1820_Reset();//DS1820复位
LCD_WRITE_IR(0x80);//在第一行显示
for (i=0;i<5;i++)
{
LCD_WRITE_DR(string[i]);//显示"温度:"
}
LCD_WRITE_IR(0x88);//在第3行显示
for (i=0;i<6;i++)
{
LCD_WRITE_DR(DispStr[i]);//显示"系列号"
}
DispCode();//在第4行显示序列号
do{
read_temp(); //读取温度值
delay100us();
display(); //显示温度值
delay100us();
}while (1); //无限循环
}
/**********************************************************
*系列号显示子程序
*显示顺序(从左到右)8位CRC编码->48位序列号->8位产品系列编码
**********************************************************/
void DispCode()
{
unsigned char i,temp;
LCD_WRITE_IR(0x98); //在第4行显示
for (i=8;i>0;i--)
{
//显示高4位
temp = fCode[i-1]>>4;
if (temp<10) //ASCII码转换
LCD_WRITE_DR(temp += 0x30);
else
LCD_WRITE_DR(temp += 0x37);
//显示低4位
temp = fCode[i-1]&0x0f;
if (temp<10) //ASCII码转换
LCD_WRITE_DR(temp += 0x30);
else
LCD_WRITE_DR(temp += 0x37);
}
}
/**********************************************************
*延时子程序
**********************************************************/
void delay100us()
{
unsigned char i;
for (i=49;i>0;i--);
}
/**********************************************************
*转换显示子程序
**********************************************************/
void display()
{
unsigned char temp_data,temp_data_2;
unsigned int TempDec; //用来存放4位小数
temp_data = temperature[1];
temp_data &= 0xf0; //取高4位
if (temp_data==0xf0) //判断是正温度还是负温度读数
{
//负温度读数求补,取反加1,判断低8位是否有进位
if (temperature[0]==0)
{ //有进位,高8位取反加1
temperature[0]=~temperature[0]+1;
temperature[1]=~temperature[1]+1;
}
else
{ //没进位,高8位不加1
temperature[0]=~temperature[0]+1;
temperature[1]=~temperature[1];
}
}
temp_data = temperature[1]<<4; //取高字节低4位(温度读数高4位)
temp_data_2 = temperature[0]>>4; //取低字节高4位(温度读数低4位)
temp_data = temp_data|temp_data_2; //组合成完整数据
temp[0] = temp_data/100+0x30; //取百位转换为ASCII码
temp[1] = (temp_data%100)/10+0x30; //取十位转换为ASCII码
temp[2] = (temp_data%100)%10+0x30; //取个位转换为ASCII码
temperature[0]&=0x0f; //取小数位转换为ASCII码
TempDec = ((temperature[0]&0x0f)*0.0625)*10000;//小数部分,扩大1万倍
temp[3] = TempDec/1000+0x30; //取小数个位转换为ASCII码
temp[4] = (TempDec%1000)/100+0x30; //取小数十位转换为ASCII码
temp[5] = ((TempDec%1000)%100)/10+0x30;//取小数百位转换为ASCII码
temp[6] = ((TempDec%1000)%100)%10+0x30;//取小数千位转换为ASCII码
LCD_WRITE_IR(0x91);//在LCD第2行显示
LCD_WRITE_DR(temp[0]); //显示百位
LCD_WRITE_DR(temp[1]); //显示十位
LCD_WRITE_DR(temp[2]); //显示个位
LCD_WRITE_DR(0x2e); //显示"."
LCD_WRITE_DR(temp[3]); //显示小数位
LCD_WRITE_DR(temp[4]); //显示小数位
LCD_WRITE_DR(temp[5]); //显示小数位
LCD_WRITE_DR(temp[6]); //显示小数位
LCD_WRITE_DR(0xa1); //显示"℃"
LCD_WRITE_DR(0xe6);
}
/**********************************************************
*读温度数据函数
**********************************************************/
void read_temp()
{
unsigned char i;
DS1820_Reset(); //复位
DS1820_WriteData(0xcc); //跳过ROM命令
DS1820_WriteData(0x44); //温度转换命令
DS1820_Reset(); //复位
DS1820_WriteData(0xcc); //跳过ROM命令
DS1820_WriteData(0xbe); //读DS1820温度暂存器命令
for (i=0;i<2;i++)
{
temperature[i]=DS1820_ReadData();
}
DS1820_Reset(); //复位,结束读数据
}
/**********************************************************
*DS1820复位及存在检测(通过存在脉冲可以判断DS1820是否损坏)
*函数名称:DS1820_Reset()
*说明:函数返回一个位标量(0或1)flag=0存在,反之flag=1不存在
**********************************************************/
bit DS1820_Reset()
{
unsigned char i;
bit flag; //DS1820存在标志位
DS1820_DQ = 0; //拉低总线
for (i=240;i>0;i--);//延时480微秒,产生复位脉冲
DS1820_DQ = 1; //释放总线
for (i=40;i>0;i--); //延时80微秒对总线采样
flag = DS1820_DQ;
for (i=200;i>0;i--); //延时400微秒等待总线恢复
return (flag); //根据flag的值可以知道DS1820是否存在或损坏
} //可以加声音告警提示DS1820故障
/**********************************************************
*写数据到DS1820
*函数名称:DS1820_WriteData()
*
**********************************************************/
void DS1820_WriteData(unsigned char wData)
{
unsigned char i,j;
for (i=8;i>0;i--)
{
DS1820_DQ = 0; //拉低总线,产生写信号
for (j=2;j>0;j--); //延时4us
DS1820_DQ = wData&0x01; //发送1位
for (j=30;j>0;j--); //延时60us,写时序至少要60us
DS1820_DQ = 1; //释放总线,等待总线恢复
wData>>=1; //准备下一位数据的传送
}
}
/**********************************************************
*从DS1820中读出数据
*函数名称:DS1820_ReadData()
*
**********************************************************/
unsigned char DS1820_ReadData()
{
unsigned char i,j,TmepData;
for (i=8;i>0;i--)
{
TmepData>>=1;
DS1820_DQ = 0; //拉低总线,产生读信号
for (j=2;j>0;j--); //延时4us
DS1820_DQ = 1; //释放总线,准备读数据
for (j=4;j>0;j--); //延时8微秒读数据
if (DS1820_DQ == 1)
TmepData |= 0x80;
for (j=30;j>0;j--); //延时60us
DS1820_DQ = 1; //拉高总线,准备下一位数据的读取.
}
return (TmepData);//返回读到的数据
}
/**********************************************************
*LCD初始化函数
**********************************************************/
void LCD_INIT()
{
LCD_BC=0;
LCD_WRITE_IR(0x30); //功能设置-基本指令集
LCD_WRITE_IR(0x0c); //显示打开,光标关,反白显示关
LCD_WRITE_IR(0x01); //清屏
LCD_WRITE_IR(0x06); //进入点设定,光标向右移动,AC+1
}
/**********************************************************
*写指令到LCD函数
*名称:LCD_WRITE_IR
*入口参数:LCD_COMMAND (字符型--8位数据)
**********************************************************/
void LCD_WRITE_IR(unsigned char LCD_COMMAND)
{
unsigned char tData;
LCD_CS = 0; //拉低片选终止所有数据传送
//判忙
do{tData = LCD_READ_BF();}
while(tData&0x80==0x80);
LCD_CS = 1; //拉高片选准备传送数据
LCD_SEND(0xf8); //发送写指令
tData = LCD_COMMAND;
tData = tData&0xf0;//屏蔽低4位(取出高4位)
LCD_SEND(tData); //发送高4位
tData = LCD_COMMAND;
tData = tData<<4; //取低4位
LCD_SEND(tData); //发送低4位
LCD_CS = 0; //拉低片选终止所有数据传送
}
/**********************************************************
*写数据到LCD函数
*名称:LCD_WRITE_DR
*入口参数:LCD_DATA (字符型-8位)
**********************************************************/
void LCD_WRITE_DR(unsigned char LCD_DATA)
{
unsigned char tData=0;
LCD_CS = 0; //拉低片选终止所有数据传送
//判忙
do{tData = LCD_READ_BF();}
while(tData&0x80==0x80);
LCD_CS = 1; //拉高片选准备传送数据
LCD_SEND(0xfa); //发送写数据指令
tData = LCD_DATA;
tData = tData&0xf0;//屏蔽低4位(取出高4位)
LCD_SEND(tData); //发送高4位
tData = LCD_DATA;
tData = tData<<4; //取低4位
LCD_SEND(tData); //发送低4位
LCD_CS = 0; //拉低片选终止所有数据传送
}
/**********************************************************
*读取LCD忙碌标志(BF)和地址计数器(AC)的状态
*名称:LCD_READ_BF
**********************************************************/
unsigned char LCD_READ_BF()
{
unsigned char i,tData=0;
LCD_CS = 1; //拉高片选准备传送数据
LCD_SEND(0xfc); //发送读数据指令
i = LCD_RECEIVE(); //读取数据高4位
tData = LCD_RECEIVE(); //读取数据低4位
LCD_CS = 0; //拉低片选终止所有数据传送
i = i&0xf0; //屏蔽低4位
tData = tData>>4;
tData = tData&0x0f;//屏蔽高4位
tData = tData|i; //组合成完整数据
return (tData);
}
/**********************************************************
*LCD发送8BIT的数据(1个字节)
*名称:LCD_SEND
*入口:
**********************************************************/
void LCD_SEND(unsigned char sData)
{
unsigned char i;
for (i=8;i>0;i--)
{
LCD_CLK = 0;
LCD_SID = sData&0x80;//发送一位数据
LCD_CLK = 1; //拉高串行时钟端,锁存数据
sData <<= 1;
}
}
/**********************************************************
*LCD接收8BIT数据(1个字节)
*名称:LCD_RECEIVE
*出口:rData
**********************************************************/
unsigned char LCD_RECEIVE()
{
unsigned char i,rData=0;
for (i=8;i>0;i--)
{
LCD_CLK = 0;
rData <<=1;
LCD_CLK = 1;
rData |= LCD_SID;
}
return(rData);
}
以上为实验范例程序~~但是不能实现功能~~显屏是1602LCD液晶~~目测只能有两行吧~~主函数处注释有四行。是这个问题么?把那些多余的行的程序给去掉了貌似也不行吖~~~还是本人太小白。实在不明白~~求指导!求引路~~需要更详细信息请直接@我~~
QQQ!
#include <intrins.h> //内部包含延时函数 _nop_();
#define uchar unsigned char
#define uint unsigned int
sbit BEEP = P3^6; //蜂鸣器
sbit DS1820_DQ= P3^3; //单总线引脚
sbit LCD_CS =P2^0; //LCD片选端
sbit LCD_SID=P2^1; //LCD串行数据输入/输出端
sbit LCD_CLK=P2^2; //LCD串行同步时钟,上升沿时读取SID数据.
sbit LCD_BC=P2^3;
//函数声明:
void LCD_SEND(unsigned char send_data);
unsigned char LCD_RECEIVE();
unsigned char LCD_READ_BF();
void LCD_WRITE_IR(unsigned char LCD_COMMAND);
void LCD_WRITE_DR(unsigned char LCD_DATA);
void LCD_INIT();
//函数声明
bit DS1820_Reset();
void DS1820_WriteData(unsigned char wData);
unsigned char DS1820_ReadData();
void read_temp();
void delay100us();
void DispCode();
void display();
//函数声明:
void LCD_SEND(unsigned char sData);
unsigned char LCD_RECEIVE();
unsigned char LCD_READ_BF();
void LCD_WRITE_IR(unsigned char LCD_COMMAND);
void LCD_WRITE_DR(unsigned char LCD_DATA);
/**********************************************************/
//声明外部温度读数数组
extern unsigned char data temperature[2];
//存放分解的7个ASCII码温度数据
unsigned char temp[7];
unsigned char code string[6]={"温度:"};
unsigned char code DispStr[7]={"系列号"};
unsigned char fCode[8]; //存放序列号,CRC
/***************主函数*******************/
void main()
{
unsigned char i;
delay100us();//等待电源稳定,液晶复位完成
delay100us();
LCD_INIT(); //液晶初始化
DS1820_Reset();//DS1820复位
DS1820_WriteData(0x33);//读ROM指令
for (i=0;i<8;i++)
{//读取64位系列号
fCode[i] = DS1820_ReadData();
}
DS1820_Reset();//DS1820复位
LCD_WRITE_IR(0x80);//在第一行显示
for (i=0;i<5;i++)
{
LCD_WRITE_DR(string[i]);//显示"温度:"
}
LCD_WRITE_IR(0x88);//在第3行显示
for (i=0;i<6;i++)
{
LCD_WRITE_DR(DispStr[i]);//显示"系列号"
}
DispCode();//在第4行显示序列号
do{
read_temp(); //读取温度值
delay100us();
display(); //显示温度值
delay100us();
}while (1); //无限循环
}
/**********************************************************
*系列号显示子程序
*显示顺序(从左到右)8位CRC编码->48位序列号->8位产品系列编码
**********************************************************/
void DispCode()
{
unsigned char i,temp;
LCD_WRITE_IR(0x98); //在第4行显示
for (i=8;i>0;i--)
{
//显示高4位
temp = fCode[i-1]>>4;
if (temp<10) //ASCII码转换
LCD_WRITE_DR(temp += 0x30);
else
LCD_WRITE_DR(temp += 0x37);
//显示低4位
temp = fCode[i-1]&0x0f;
if (temp<10) //ASCII码转换
LCD_WRITE_DR(temp += 0x30);
else
LCD_WRITE_DR(temp += 0x37);
}
}
/**********************************************************
*延时子程序
**********************************************************/
void delay100us()
{
unsigned char i;
for (i=49;i>0;i--);
}
/**********************************************************
*转换显示子程序
**********************************************************/
void display()
{
unsigned char temp_data,temp_data_2;
unsigned int TempDec; //用来存放4位小数
temp_data = temperature[1];
temp_data &= 0xf0; //取高4位
if (temp_data==0xf0) //判断是正温度还是负温度读数
{
//负温度读数求补,取反加1,判断低8位是否有进位
if (temperature[0]==0)
{ //有进位,高8位取反加1
temperature[0]=~temperature[0]+1;
temperature[1]=~temperature[1]+1;
}
else
{ //没进位,高8位不加1
temperature[0]=~temperature[0]+1;
temperature[1]=~temperature[1];
}
}
temp_data = temperature[1]<<4; //取高字节低4位(温度读数高4位)
temp_data_2 = temperature[0]>>4; //取低字节高4位(温度读数低4位)
temp_data = temp_data|temp_data_2; //组合成完整数据
temp[0] = temp_data/100+0x30; //取百位转换为ASCII码
temp[1] = (temp_data%100)/10+0x30; //取十位转换为ASCII码
temp[2] = (temp_data%100)%10+0x30; //取个位转换为ASCII码
temperature[0]&=0x0f; //取小数位转换为ASCII码
TempDec = ((temperature[0]&0x0f)*0.0625)*10000;//小数部分,扩大1万倍
temp[3] = TempDec/1000+0x30; //取小数个位转换为ASCII码
temp[4] = (TempDec%1000)/100+0x30; //取小数十位转换为ASCII码
temp[5] = ((TempDec%1000)%100)/10+0x30;//取小数百位转换为ASCII码
temp[6] = ((TempDec%1000)%100)%10+0x30;//取小数千位转换为ASCII码
LCD_WRITE_IR(0x91);//在LCD第2行显示
LCD_WRITE_DR(temp[0]); //显示百位
LCD_WRITE_DR(temp[1]); //显示十位
LCD_WRITE_DR(temp[2]); //显示个位
LCD_WRITE_DR(0x2e); //显示"."
LCD_WRITE_DR(temp[3]); //显示小数位
LCD_WRITE_DR(temp[4]); //显示小数位
LCD_WRITE_DR(temp[5]); //显示小数位
LCD_WRITE_DR(temp[6]); //显示小数位
LCD_WRITE_DR(0xa1); //显示"℃"
LCD_WRITE_DR(0xe6);
}
/**********************************************************
*读温度数据函数
**********************************************************/
void read_temp()
{
unsigned char i;
DS1820_Reset(); //复位
DS1820_WriteData(0xcc); //跳过ROM命令
DS1820_WriteData(0x44); //温度转换命令
DS1820_Reset(); //复位
DS1820_WriteData(0xcc); //跳过ROM命令
DS1820_WriteData(0xbe); //读DS1820温度暂存器命令
for (i=0;i<2;i++)
{
temperature[i]=DS1820_ReadData();
}
DS1820_Reset(); //复位,结束读数据
}
/**********************************************************
*DS1820复位及存在检测(通过存在脉冲可以判断DS1820是否损坏)
*函数名称:DS1820_Reset()
*说明:函数返回一个位标量(0或1)flag=0存在,反之flag=1不存在
**********************************************************/
bit DS1820_Reset()
{
unsigned char i;
bit flag; //DS1820存在标志位
DS1820_DQ = 0; //拉低总线
for (i=240;i>0;i--);//延时480微秒,产生复位脉冲
DS1820_DQ = 1; //释放总线
for (i=40;i>0;i--); //延时80微秒对总线采样
flag = DS1820_DQ;
for (i=200;i>0;i--); //延时400微秒等待总线恢复
return (flag); //根据flag的值可以知道DS1820是否存在或损坏
} //可以加声音告警提示DS1820故障
/**********************************************************
*写数据到DS1820
*函数名称:DS1820_WriteData()
*
**********************************************************/
void DS1820_WriteData(unsigned char wData)
{
unsigned char i,j;
for (i=8;i>0;i--)
{
DS1820_DQ = 0; //拉低总线,产生写信号
for (j=2;j>0;j--); //延时4us
DS1820_DQ = wData&0x01; //发送1位
for (j=30;j>0;j--); //延时60us,写时序至少要60us
DS1820_DQ = 1; //释放总线,等待总线恢复
wData>>=1; //准备下一位数据的传送
}
}
/**********************************************************
*从DS1820中读出数据
*函数名称:DS1820_ReadData()
*
**********************************************************/
unsigned char DS1820_ReadData()
{
unsigned char i,j,TmepData;
for (i=8;i>0;i--)
{
TmepData>>=1;
DS1820_DQ = 0; //拉低总线,产生读信号
for (j=2;j>0;j--); //延时4us
DS1820_DQ = 1; //释放总线,准备读数据
for (j=4;j>0;j--); //延时8微秒读数据
if (DS1820_DQ == 1)
TmepData |= 0x80;
for (j=30;j>0;j--); //延时60us
DS1820_DQ = 1; //拉高总线,准备下一位数据的读取.
}
return (TmepData);//返回读到的数据
}
/**********************************************************
*LCD初始化函数
**********************************************************/
void LCD_INIT()
{
LCD_BC=0;
LCD_WRITE_IR(0x30); //功能设置-基本指令集
LCD_WRITE_IR(0x0c); //显示打开,光标关,反白显示关
LCD_WRITE_IR(0x01); //清屏
LCD_WRITE_IR(0x06); //进入点设定,光标向右移动,AC+1
}
/**********************************************************
*写指令到LCD函数
*名称:LCD_WRITE_IR
*入口参数:LCD_COMMAND (字符型--8位数据)
**********************************************************/
void LCD_WRITE_IR(unsigned char LCD_COMMAND)
{
unsigned char tData;
LCD_CS = 0; //拉低片选终止所有数据传送
//判忙
do{tData = LCD_READ_BF();}
while(tData&0x80==0x80);
LCD_CS = 1; //拉高片选准备传送数据
LCD_SEND(0xf8); //发送写指令
tData = LCD_COMMAND;
tData = tData&0xf0;//屏蔽低4位(取出高4位)
LCD_SEND(tData); //发送高4位
tData = LCD_COMMAND;
tData = tData<<4; //取低4位
LCD_SEND(tData); //发送低4位
LCD_CS = 0; //拉低片选终止所有数据传送
}
/**********************************************************
*写数据到LCD函数
*名称:LCD_WRITE_DR
*入口参数:LCD_DATA (字符型-8位)
**********************************************************/
void LCD_WRITE_DR(unsigned char LCD_DATA)
{
unsigned char tData=0;
LCD_CS = 0; //拉低片选终止所有数据传送
//判忙
do{tData = LCD_READ_BF();}
while(tData&0x80==0x80);
LCD_CS = 1; //拉高片选准备传送数据
LCD_SEND(0xfa); //发送写数据指令
tData = LCD_DATA;
tData = tData&0xf0;//屏蔽低4位(取出高4位)
LCD_SEND(tData); //发送高4位
tData = LCD_DATA;
tData = tData<<4; //取低4位
LCD_SEND(tData); //发送低4位
LCD_CS = 0; //拉低片选终止所有数据传送
}
/**********************************************************
*读取LCD忙碌标志(BF)和地址计数器(AC)的状态
*名称:LCD_READ_BF
**********************************************************/
unsigned char LCD_READ_BF()
{
unsigned char i,tData=0;
LCD_CS = 1; //拉高片选准备传送数据
LCD_SEND(0xfc); //发送读数据指令
i = LCD_RECEIVE(); //读取数据高4位
tData = LCD_RECEIVE(); //读取数据低4位
LCD_CS = 0; //拉低片选终止所有数据传送
i = i&0xf0; //屏蔽低4位
tData = tData>>4;
tData = tData&0x0f;//屏蔽高4位
tData = tData|i; //组合成完整数据
return (tData);
}
/**********************************************************
*LCD发送8BIT的数据(1个字节)
*名称:LCD_SEND
*入口:
**********************************************************/
void LCD_SEND(unsigned char sData)
{
unsigned char i;
for (i=8;i>0;i--)
{
LCD_CLK = 0;
LCD_SID = sData&0x80;//发送一位数据
LCD_CLK = 1; //拉高串行时钟端,锁存数据
sData <<= 1;
}
}
/**********************************************************
*LCD接收8BIT数据(1个字节)
*名称:LCD_RECEIVE
*出口:rData
**********************************************************/
unsigned char LCD_RECEIVE()
{
unsigned char i,rData=0;
for (i=8;i>0;i--)
{
LCD_CLK = 0;
rData <<=1;
LCD_CLK = 1;
rData |= LCD_SID;
}
return(rData);
}
以上为实验范例程序~~但是不能实现功能~~显屏是1602LCD液晶~~目测只能有两行吧~~主函数处注释有四行。是这个问题么?把那些多余的行的程序给去掉了貌似也不行吖~~~还是本人太小白。实在不明白~~求指导!求引路~~需要更详细信息请直接@我~~
QQQ!