PCF8574T+LCD1602+DS18B20(显示小数)完整显示代码;包括IIC的时序代码;KEIL5.27编译器;AT/STC89C52单片机

(代码里已经注释许多的注释)想必能找到这,必定对上面三个电子器件已经有所了解,然后来到处寻找代码来打开自己的头绪。所以我就不多介绍直接上代码;理解这些需要一点C基础


首先是IIC的时序(上面是头文件定义,下面是程序)

#ifndef __IIC_H_
#define __IIC_H_

#include <REG52.H>

sbit IIC_SDA=P3^7;//是所有的IIC器件IO口!!!!!!!!!!!!!!!!!!!
sbit IIC_SCL=P3^6;

void IIC_Delay6us();
void IIC_Start();//启始信号
void IIC_Stop();//停止信号
void IIC_WriteByte(unsigned char Byte);//写入1BYTE数据
unsigned char IIC_ReadByte();//读取数据1BYTE数据
void IIC_SendAck(unsigned char BitAck);//主机接受完了发送/0应答/1非应答
unsigned char IIC_ReceptionAck();//从机接受完了发送/0应答/1非应答

#endif

#include <IIC.H>
#include <intrins.H>
void IIC_Delay6us()        //@11.0592MHz
{
    _nop_();
} //此处是为了适应不同的单片机速度做的延时,所以统一延时6us


void IIC_Start()//启始信号
{
    IIC_SDA=1;//空闲状态
    IIC_SCL=1;    
    IIC_Delay6us();
    
    IIC_SDA=0;
    IIC_Delay6us();
    IIC_SCL=0;
}

void IIC_Stop()//停止信号
{
    IIC_SCL=0;
    IIC_SDA=0;
    IIC_Delay6us();
    
    IIC_SCL=1;
    IIC_Delay6us();    
    IIC_SDA=1;
}

//此处是高位先发送
void IIC_WriteByte(unsigned char Byte)//写入1BYTE数据
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        IIC_SDA=Byte&(0x80>>i);
        
        IIC_SCL=1;
        IIC_Delay6us();
        IIC_SCL=0;
    }
}

unsigned char IIC_ReadByte()//读取数据1BYTE数据
{
    unsigned char i,Byte=0x00;
    
    IIC_SDA=1;//释放数据线让从机操作
    for(i=0;i<8;i++)
    {
        IIC_SCL=1;
        if(IIC_SDA){Byte|=(0x80>>i);}
        IIC_Delay6us();
        IIC_SCL=0;        
    }    
    return Byte;
}

void IIC_SendAck(unsigned char BitAck)//主机接受完了发送/0应答/1非应答
{
    IIC_SDA=BitAck;
    
    IIC_SCL=1;
    IIC_Delay6us();
    IIC_SCL=0;
}

unsigned char IIC_ReceptionAck()//从机接受完了发送/0应答/1非应答
{
    unsigned char BitAck;
    IIC_SDA=1;//释放数据线让从机操作
    
    IIC_SCL=1;    
    BitAck=IIC_SDA;
    IIC_Delay6us();    
    IIC_SCL=0;
    
    return BitAck;
}


接着是PCF8574T的驱动,基于IIC(上面是头文件定义,下面是程序)

#ifndef __PCF8574T_H_
#define __PCF8574T_H_

#include <IIC.H>

#define PCF8574T_W_Address 0x4e//写入时的地址
#define PCF8574T_R_Address 0x4f//读取时的地址

void PCF8574T_Write_Byte(unsigned char dat);//写入一个字节
unsigned char PCF8574T_Read_Byte();//读取一个字节

#endif

#include "PCF8574T.H"
void PCF8574T_Write_Byte(unsigned char dat)//写入一个字节//高位对应着高位
{
    IIC_Start();//开始
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();//从机回应
    IIC_WriteByte(dat);
    IIC_ReceptionAck();//从机回应
    IIC_Stop();
}


unsigned char PCF8574T_Read_Byte()//读取一个字节
{
    unsigned char Data;
    
    IIC_Start();//开始
    IIC_WriteByte(PCF8574T_R_Address);//读取时的地址
    IIC_ReceptionAck();//从机回应
    Data=IIC_ReadByte();//读取到的数据暂存
//    IIC_SendAck(0);//主机应答
    IIC_SendAck(1);//非应答
    IIC_Stop();
    
    return Data;
}


接着是PCF8574T+LCD1602(四线驱动)的驱动,基于PCF8574T(上面是头文件定义,下面是程序)

#ifndef __LCDPCF8574T_H_
#define __LCDPCF8574T_H_

#include "PCF8574T.H"
#include <intrins.H>

#define PCFLCD_WriteCmd 0X00
#define PCFLCD_WriteDat 0X01

void LCDPCF_1ms();        //@11.0592MHz
void LCDPCF1602_Init();//初始化
void LCDPCF1602_WriteDat(unsigned char Dat);//写数据
void LCDPCF1602_WriteCmd(unsigned char Cmd);//写命令

void LCDPCF1602_ShowChar(unsigned char line,unsigned char column,unsigned char Char);//显示字符
void LCDPCF1602_ShowStrng(unsigned char line,unsigned char column,unsigned char *string);//显示字符串
void LCDPCF1602_ShowNum(unsigned char line,unsigned char column,unsigned char Number,unsigned char length);//显示数字
void LCDPCF1602_ShowSignedNum(unsigned char line,unsigned char column,int Number,unsigned char length);//显示有符号数字
void LCDPCF1602_ShowHexNum(unsigned char line,unsigned char column,unsigned int Number,unsigned char length);//显示16进制数字
void LCDPCF1602_ShowBinNum(unsigned char line,unsigned char column,unsigned int Number,unsigned char length);//显示2进制数字
void LCDPCF1602_ShowDecimals(unsigned char line,unsigned char column, float Number,unsigned char length,unsigned char lengthb);//显示正负小数
    
#endif

#include "LCDPCF8574T.H"
/*位置对应图

PCF8574T引脚与LCD1602对应
P0-RS 
P1-RW
P2-EN
P3
P4-D4
P5-D5
P6-D6
P7-D7
使用四线传输
*/
void LCDPCF_1ms()        //@11.0592MHz
{
    unsigned char i, j;

    _nop_();
    i = 2;
    j = 199;
    do
    {
        while (--j);
    } while (--i);
}

void LCDPCF1602_Init()//初始化
{
    PCF8574T_Write_Byte(0x00);
    
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    LCDPCF1602_WriteCmd(0x28);//四线初始化
    LCDPCF_1ms();
    
    PCF8574T_Write_Byte(0x04);//以下是至关重要的四句的代码,没有就会四线传输不成功
    LCDPCF_1ms()//;
    PCF8574T_Write_Byte(0x00);//
    LCDPCF_1ms();//
    
    LCDPCF1602_WriteCmd(0x0c);
    LCDPCF1602_WriteCmd(0x06);
    LCDPCF1602_WriteCmd(0x01);
    IIC_ReceptionAck();
    IIC_Stop();
}

void LCDPCF1602_WriteDat(unsigned char Dat)//写数据
{
    unsigned char da;
    da=(Dat/16)<<4;//取出高四位
    PCF8574T_Write_Byte(da|0x01);//将RS置一

    PCF8574T_Write_Byte(da|0x05);//将RS和RN置一
    LCDPCF_1ms();
    PCF8574T_Write_Byte(da|0x01);//将RS置一
    LCDPCF_1ms();
    
    
    da=(Dat%16)<<4;//取出低四位
    PCF8574T_Write_Byte(da|0x01);//将RS置一
    LCDPCF_1ms();
    
    PCF8574T_Write_Byte(da|0x05);//将RS和RN置一
    LCDPCF_1ms();
    PCF8574T_Write_Byte(da|0x01);//将RS置一
    LCDPCF_1ms();
}

void LCDPCF1602_WriteCmd(unsigned char Cmd)//写命令
{      
    unsigned char cd; 
    cd=(Cmd/16)<<4;//取出高四位
    PCF8574T_Write_Byte(cd);//RS,RW,EN是零
    
    PCF8574T_Write_Byte(cd|0x04);
    LCDPCF_1ms();
    PCF8574T_Write_Byte(cd);
    LCDPCF_1ms();
    
    
    cd=(Cmd%16)<<4;//取出低四位
    PCF8574T_Write_Byte(cd);
    LCDPCF_1ms();
    
    PCF8574T_Write_Byte(cd|0x04);
    LCDPCF_1ms();
    PCF8574T_Write_Byte(cd);
    LCDPCF_1ms();
}
//                                        行                    列
void LCDPCF1602_SetCursor(unsigned char line,unsigned char column)//行列选择
{
    if(line==1)
    {
        LCDPCF1602_WriteCmd(0x80|(column-1));//LCD1602数据手持说:要与上AC即0x80//发送命令选择行列位置
    }
    else
    {
        LCDPCF1602_WriteCmd(0x80|(column-1)+0x40);
    }
}

//                                        行                    列                   'a'就显示a
void LCDPCF1602_ShowChar(unsigned char line,unsigned char column,unsigned char Char)//显示字符
{
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();
    LCDPCF1602_SetCursor(line,column);
    LCDPCF1602_WriteDat(Char);
    IIC_Stop();
}
//                                        行                    列                   "Hellow"就显示Hellow
void LCDPCF1602_ShowStrng(unsigned char line,unsigned char column,unsigned char *string)//显示字符串
{
    unsigned char i;
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();
    LCDPCF1602_SetCursor(line,column);
    for(i=0;string[i]!=0;i++)
    {
        LCDPCF1602_WriteDat(string[i]);
    }
    IIC_Stop();
}

int LCDPCF_Pow(unsigned char X,unsigned char Y)//运算缓存函数
{
    unsigned char i;
    int num=1;
    for(i=0;i<Y;i++)
    {
        num*=X;
    }
    return num;
}
//                                                                           22                    2位    显示22   不显示负数
 //                                            行                    列             数值                    长度      
void LCDPCF1602_ShowNum(unsigned char line,unsigned char column,unsigned char Number,unsigned char length)//显示数字
{
    unsigned char i;
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();
    LCDPCF1602_SetCursor(line,column);
    for(i=length;i>0;i--)
    {
        LCDPCF1602_WriteDat(0x30+Number/LCDPCF_Pow(10,i-1)%10);//845/100%10
    }
    IIC_Stop();
}

//                                                                           22                    2位    显示+22 负数同理
 //                                            行                    列             数值                    长度              
void LCDPCF1602_ShowSignedNum(unsigned char line,unsigned char column,int Number,unsigned char length)//显示有符号数字
{
    //符号不算一位//int是一个有符号的
    unsigned char i;
    unsigned int Number1;//这是一个无符号
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();
    LCDPCF1602_SetCursor(line,column);
    if(Number>=0)
    {
        LCDPCF1602_WriteDat('+');//在数字前面显示一个符号
        Number1=Number;
    }
    else
    {
        LCDPCF1602_WriteDat('-');
        Number1=-Number;
    }
    
    for(i=length;i>0;i--)
    {
        LCDPCF1602_WriteDat(0x30+Number1/LCDPCF_Pow(10,i-1)%10);//例子 845/100%10
    }
    IIC_Stop();
}
//                                                                               0x66                    2位   显示66
 //                                            行                    列                 数值                    长度              
void LCDPCF1602_ShowHexNum(unsigned char line,unsigned char column,unsigned int Number,unsigned char length)//显示16进制数字
{
    unsigned char i,num;//判断缓存
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();
    LCDPCF1602_SetCursor(line,column);
    for(i=length;i>0;i--)
    {
        num=(Number/LCDPCF_Pow(16,i-1)%16);
        if(num<10)//正常显示
        {
            LCDPCF1602_WriteDat(0x30+num);
        }
        else//显示字符A~F
        {
            LCDPCF1602_WriteDat(0x41+num-10);//845/100%16    
        }        
    }
    IIC_Stop();
}
 //                                            行                    列                 数值                    长度            
void LCDPCF1602_ShowBinNum(unsigned char line,unsigned char column,unsigned int Number,unsigned char length)//显示2进制数字
{
    unsigned char i;
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();
    LCDPCF1602_SetCursor(line,column);
    for(i=length;i>0;i--)
    {
        LCDPCF1602_WriteDat(0x30+Number/LCDPCF_Pow(2,i-1)%2);//845/100%10
    }
    IIC_Stop();    
}
 //                                            行                    列            数值                整数长度            小数长度
void LCDPCF1602_ShowDecimals(unsigned char line,unsigned char column, float Number,unsigned char length,unsigned char lengthb)//显示正负小数
{
    //最高小数点4位
    unsigned char i;
    unsigned char Sgg[5];
    unsigned long mun;
    
    IIC_Start();
    IIC_WriteByte(PCF8574T_W_Address);//写入时的地址
    IIC_ReceptionAck();
    LCDPCF1602_SetCursor(line,column);
    
    if(lengthb>=1)
    {
        mun=Number*1000000;
        Sgg[1]=(mun%1000000)/100000;//从左往右取出第二位
        Sgg[2]=(mun%100000)/10000;//取出第三位
        Sgg[3]=(mun%10000)/1000;//取出第四位
        Sgg[4]=(mun%1000)/100;//取出第五位
        Sgg[5]=(mun%100)/10;//取出第六位
        
        LCDPCF1602_ShowSignedNum(line,column,Number,length);//显示最高位,即整数
        if(length>1)
        {
            LCDPCF1602_ShowChar(line,column+3,'.');
        }
        else
        {
            LCDPCF1602_ShowChar(line,column+2,'.');
        }
        
        if(length>1)
        {
            for(i=1;i<=lengthb;i++)
            {    
                LCDPCF1602_ShowNum(line,column+i+3,Sgg[i],1);
            }
        }
        else
        {
            for(i=1;i<=lengthb;i++)
            {    
                LCDPCF1602_ShowNum(line,column+i+2,Sgg[i],1);
            }

        }
        
        
    }
    else
    {
        LCDPCF1602_ShowSignedNum(line,column,Number,length);
    }    
    IIC_Stop();    
}


接着是DS18B20的OneWire(一根线)协议,(上面是头文件定义,下面是程序)

#ifndef __OneWire_H_
#define __OneWire_H_

#include <REG52.H>

sbit OneWire_Dat=P2^7;

unsigned char OneWire_Init();//初始化
void OneWire_SendBit(unsigned char Dat);//写入一个bit
unsigned char OneWire_ReadBit();//读取一个bit
void OneWire_SendByte(unsigned char Byte);//写入一个Byte
unsigned char OneWire_ReadByte();//读取一个Byte

#endif

#include "OneWire.H"

unsigned char OneWire_Init()//初始化
{
    unsigned char i;
    unsigned char ack;
    OneWire_Dat=1;           
    OneWire_Dat=0;    
    i = 227;while (--i);//delay 500us
    OneWire_Dat=1;
    i = 29;while (--i);//delay 70us
    ack=OneWire_Dat;//返回的标志位
    i = 227;while (--i);//delay 500us
    
    return ack;//0代表DS18B30已应答//1是非应答
}

void OneWire_SendBit(unsigned char Dat)//写入一个bit
{   
    unsigned char i;
    OneWire_Dat=0;    
    i = 4;while (--i);//delay 10us
    OneWire_Dat=Dat;//写入的值放在Bit中
    i = 22;while (--i);//delay 50us
    OneWire_Dat=1;
}

unsigned char OneWire_ReadBit()//读取一个bit
{
    unsigned char i;
    unsigned char Bit;
    OneWire_Dat=0;
    i = 2;while (--i);//delay 5us;
    OneWire_Dat=1;
    i = 2;while (--i);//delay 5us;
    
    Bit=OneWire_Dat;//采集到的值放在Bit中
    i = 22;while (--i);//delay 50us
    
    return Bit;
}

void OneWire_SendByte(unsigned char Byte)//写入一个Byte
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        OneWire_SendBit(Byte&(0x01<<i));//注意主机是低位先发送
    }
}

unsigned char OneWire_ReadByte()//读取一个Byte
{
    unsigned char i;
    unsigned char Byte=0x00;
    for(i=0;i<8;i++)
    {
        if(OneWire_ReadBit()){Byte|=(0x01<<i);}//注意从机是低位先发出
    }
    return Byte;
}
 


接着是DS18B20,基于OneWire(一根线)协议(上面是头文件定义,下面是程序)

#ifndef __DS18B20_H_
#define __DS18B20_H_

#include "OneWire.H"

#define Skip_ROM         0xcc     //跳过ROM指令
#define Read_ROM         0xbe    //查询ROM指令
#define Alarm_Search     0xec    //报警查找指令//一般不用
#define convert_T         0x44    //温度转换指令

void DS18B20_Convert_T();//转换温度指令
float DS18B20_ReadConvert_T();//读取温度


#endif

#include "DS18B20.H"

void DS18B20_Convert_T()//转换温度
{
    OneWire_Init();
    OneWire_SendByte(Skip_ROM);
    OneWire_SendByte(convert_T);
}

float DS18B20_ReadConvert_T()//读取温度
{
    unsigned char TMSB,TLSB;//数据暂存
    int num;//转换的中转数//在C51中int是16位的
    float T;//实际的数据是浮点型
    OneWire_Init();
    OneWire_SendByte(Skip_ROM);
    OneWire_SendByte(Read_ROM);
    TLSB=OneWire_ReadByte();//先读取的字节
    TMSB=OneWire_ReadByte();//后读取的字节
    num=(TMSB<<8)|TLSB;//两个字节合成一个字节
    T=num/16.0;
    
    return T;
}


到这就完了,最后主函数

void main()
{   
    float m;
    LCDPCF1602_Init();
    LCDPCF1602_ShowDecimals(1,1,17.9124,2,4);
    while(1)
    {
        DS18B20_Convert_T();//转换温度指令
        m=DS18B20_ReadConvert_T();//读出的温度储存
        LCDPCF1602_ShowDecimals(1,1,m,2,4);        
    }
}

 拜了拜,祝学运昌隆

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值