/***********************lcd1602.c文件程序源代碼*************************/
#include <reg52.h>
#define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;
void LcdWaitReady() //等待液晶準備好
{
unsigned char sta;
LCD1602_DB = 0xFF;
LCD1602_RS = 0;
LCD1602_RW = 1;
do
{
LCD1602_E = 1;
sta = LCD1602_DB; //讀取狀態字
LCD1602_E = 0;
} while (sta & 0x80); //bit7等于1表示液晶正忙,重復檢測直到其等于0為止
}
void LcdWriteCmd(unsigned char cmd) //寫入命令函數
{
LcdWaitReady();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_E = 1;
LCD1602_E = 0;
}
void LcdWriteDat(unsigned char dat) //寫入數據函數
{
LcdWaitReady();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_E = 1;
LCD1602_E = 0;
}
void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str) //顯示字符串,屏幕起始坐標(x,y),字符串指針str
{
unsigned char addr;
//由輸入的顯示坐標計算顯示RAM的地址
if (y == 0)
addr = 0x00 + x; //第一行字符地址從0x00起始
else
addr = 0x40 + x; //第二行字符地址從0x40起始
//由起始顯示RAM地址連續寫入字符串
LcdWriteCmd(addr | 0x80); //寫入起始地址
while (*str != '\0') //連續寫入字符串數據,直到檢測到結束符
{
LcdWriteDat(*str);
str++;
}
}
void LcdInit() //液晶初始化函數
{
LcdWriteCmd(0x38); //16*2顯示,5*7點陣,8位數據接口
LcdWriteCmd(0x0C); //顯示器開,光標關閉
LcdWriteCmd(0x06); //文字不動,地址自動+1
LcdWriteCmd(0x01); //清屏
}
/*************************main.c文件程序源代碼**************************/
#include <reg52.h>
#include <intrins.h>
#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;
bit I2CAddressing(unsigned char addr);
extern void LcdInit();
extern void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str);
void main ()
{
bit ack;
unsigned char str[10];
LcdInit(); //初始化液晶
ack = I2CAddressing(0x50); //查詢地址為0x50的器件
str[0] = '5'; //將地址和應答值轉換為字符串
str[1] = '0';
str[2] = ':';
str[3] = (unsigned char)ack + '0';
str[4] = '\0';
LcdShowStr(0, 0, str); //顯示到液晶上
ack = I2CAddressing(0x62); //查詢地址為0x62的器件
str[0] = '6'; //將地址和應答值轉換為字符串
str[1] = '2';
str[2] = ':';
str[3] = (unsigned char)ack + '0';
str[4] = '\0';
LcdShowStr(8, 0, str); //顯示到液晶上
while(1)
{}
}
void I2CStart() //產生總線起始信號
{
I2C_SDA = 1; //首先確保SDA、SCL都是高電平
I2C_SCL = 1;
I2CDelay();
I2C_SDA = 0; //先拉低SDA
I2CDelay();
I2C_SCL = 0; //再拉低SCL
}
void I2CStop() //產生總線停止信號
{
I2C_SCL = 0; //首先確保SDA、SCL都是低電平
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 1; //先拉高SCL
I2CDelay();
I2C_SDA = 1; //再拉高SDA
I2CDelay();
}
bit I2CWrite(unsigned char dat) //I2C總線寫操作,待寫入字節dat,返回值為從機應答位的值
{
bit ack; //用于暫存應答位的值
unsigned char mask; //用于探測字節內某一位值的掩碼變量
for (mask=0x80; mask!=0; mask>>=1) //從高位到低位依次進行
{
if ((mask&dat) == 0) //該位的值輸出到SDA上
I2C_SDA = 0;
else
I2C_SDA = 1;
I2CDelay();
I2C_SCL = 1; //拉高SCL
I2CDelay();
I2C_SCL = 0; //再拉低SCL,完成一個位周期
}
I2C_SDA = 1; //8位數據發送完后,主機釋放SDA,以檢測從機應答
I2CDelay();
I2C_SCL = 1; //拉高SCL
I2CDelay();
ack = I2C_SDA; //讀取此時的SDA值,即為從機的應答值
I2C_SCL = 0; //再拉低SCL完成應答位,并保持住總線
return ack; //返回從機應答值
}
bit I2CAddressing(unsigned char addr) //I2C尋址函數,即檢查地址為addr的器件是否存在,返回值為其應答值,即應答則表示存在,非應答則表示不存在
{
bit ack;
I2CStart(); //產生起始位,即啟動一次總線操作
ack = I2CWrite(addr<<1); //器件地址需左移一位,因尋址命令的最低位為讀寫位,用于表示之后的操作是讀或寫
I2CStop(); //不需進行后續讀寫,而直接停止本次總線操作
return ack;
}