(代码里已经注释许多的注释)想必能找到这,必定对上面三个电子器件已经有所了解,然后来到处寻找代码来打开自己的头绪。所以我就不多介绍直接上代码;理解这些需要一点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);
}
}
拜了拜,祝学运昌隆