你的位置:
首页
>
IT圈
>
I2C总线8位远程IO扩展口芯片PCF8574的驱动程序
2024年6月10日发(作者:黄含莲)
//......................................
//名称: PCF8574(A).c I2C扩展8位I/O芯片的接口程序
//编程: 不详
//日期: 20111025
//
//发现问题请指点,谢谢!
//......................................
//CPU: 89C55 11.0592MHz
//环境: Keil C51 V8.01
//引脚定义:
// CPU_P2.0 --- PCF8574X_SCL 时钟
// CPU_P2.1 --- PCF8574X_SDA 数据
// CPU_P2.2 --- PCF8574X_INT 中断
//......................................
#include
#include
#include "delay_s.h"
#include "pcf8574.h"
//PCF8574(A)芯片指令的定义
#define PCF8574_WRITE 0x40 //器件地址= 0111 A2 A1 A0 r/w
#define PCF8574_READ 0x41 //器件地址= 0111 A2 A1 A0 r/w
#define PCF8574A_WRITE 0x70 //器件地址= 0111 A2 A1 A0 r/w
#define PCF8574A_READ 0x71 //器件地址= 0111 A2 A1 A0 r/w
#definePCF8574X_REGISTER_ADDR_MAX 7 //器件内部寄存器地址的最大值
//内部函数
static void i2c_start_cond(void);
static void i2c_stop_cond(void);
static uchar i2c_read_byte(void);
static uchar i2c_read_byte_nack(void);
static void i2c_write_byte(uchar da);
//==============================================================
===============
//接口调用函数部分
//*******************************************************
//序号:
// HD_PCF8574X_S01
//功能:
// 读出芯片的复位状态
//输入:
// is_pcf8574a =1 是A芯片
// add_of_part 器件的子地址 0~3
//输出:
// 端口的数据
//********************************************************
uchar PCF8574X_read_io(uchar is_pcf8574a, uchar add_of_part)
{
uchar i;
i2c_start_cond();
if(is_pcf8574a !=0)
{
i2c_write_byte(PCF8574A_READ |((add_of_part <<1) &0x0E));//器件地
址=0111 A2 A1 A0 r/w
}
else
{
i2c_write_byte(PCF8574_READ |((add_of_part <<1) &0x0E));//器件地
址=0100 A2 A1 A0 r/w
}
i =i2c_read_byte_nack(); //顺序读的方式读出一个字节
i2c_stop_cond();
return(i);
}
//*******************************************************
//序号:
// HD_PCF8574X_S02
//功能:
// 写数据到I/O端口
//输入:
// is_pcf8574a =1 是A芯片
// add_of_part: 器件的子地址 0~7
// dat: 写入的字节
//输出:
// 无
//********************************************************
void PCF8574X_write_io(uchar is_pcf8574a, uchar add_of_part, uchar dat)
{
i2c_start_cond();
if(is_pcf8574a !=0)
{
i2c_write_byte(PCF8574A_WRITE |((add_of_part <<1) &0x0E)); //器件
地址=0111 A2 A1 A0 r/w
}
else
{
i2c_write_byte(PCF8574_WRITE |((add_of_part <<1) &0x0E)); //器件
地址=0100 A2 A1 A0 r/w
}
i2c_write_byte(dat);
i2c_stop_cond();
}
//==============
//内部调用函数部分
//==============
//----------------------------------------------
//I2C 发启始条件:时钟线为高时数据线发生下降沿跳变
//----------------------------------------------
static void i2c_start_cond(void)
{
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SDA_LOW;
_DELAY_NOP3;
}
//----------------------------------------
//I2C 发结束条件:时钟线为高时数据线发生上升沿跳变
//----------------------------------------
static void i2c_stop_cond(void)
{
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_LOW;
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
}
//----------------------------------------
// I2C 读取一个中间字节的数据
//----------------------------------------
/*
static uchar i2c_read_byte(void)
{
uchar i;
uchar da=0;
for(i =0; i<8; i++)
{
da <<=1; //传输的数据高位在前
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SCL_HIGH; //时钟为高时读数据
//NOP3;
if (JUDGE_PCF8574X_SDA) da++;
}
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_LOW; //发送应答位
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_HIGH;
return(da);
}
*/
//----------------------------------------
// I2C 读取一个结尾字节的数据
//----------------------------------------
static uchar i2c_read_byte_nack(void)
{
uchar i;
uchar da =0;
for (i =0; i<8; i++)
{
da <<=1;
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SCL_HIGH;
//NOP3;
if(JUDGE_PCF8574X_SDA) da++;
}
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SCL_LOW;
return( da );
}
//----------------------------------------
// I2C 写入一个字节的数据
//----------------------------------------
static void i2c_write_byte(uchar da )
{
uchar i;
for(i =0; i<8; i++)
{
CODE_SCL_LOW;
if(da&0x80)
{
CODE_SDA_HIGH;
}
else
{
CODE_SDA_LOW;
}
CODE_SCL_HIGH;
da <<=1;
}
CODE_SCL_LOW; //第8个SCL下降沿,写入8位数据
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
CODE_SCL_HIGH;
}
//==============================================================
===============
//End Of File
2024年6月10日发(作者:黄含莲)
//......................................
//名称: PCF8574(A).c I2C扩展8位I/O芯片的接口程序
//编程: 不详
//日期: 20111025
//
//发现问题请指点,谢谢!
//......................................
//CPU: 89C55 11.0592MHz
//环境: Keil C51 V8.01
//引脚定义:
// CPU_P2.0 --- PCF8574X_SCL 时钟
// CPU_P2.1 --- PCF8574X_SDA 数据
// CPU_P2.2 --- PCF8574X_INT 中断
//......................................
#include
#include
#include "delay_s.h"
#include "pcf8574.h"
//PCF8574(A)芯片指令的定义
#define PCF8574_WRITE 0x40 //器件地址= 0111 A2 A1 A0 r/w
#define PCF8574_READ 0x41 //器件地址= 0111 A2 A1 A0 r/w
#define PCF8574A_WRITE 0x70 //器件地址= 0111 A2 A1 A0 r/w
#define PCF8574A_READ 0x71 //器件地址= 0111 A2 A1 A0 r/w
#definePCF8574X_REGISTER_ADDR_MAX 7 //器件内部寄存器地址的最大值
//内部函数
static void i2c_start_cond(void);
static void i2c_stop_cond(void);
static uchar i2c_read_byte(void);
static uchar i2c_read_byte_nack(void);
static void i2c_write_byte(uchar da);
//==============================================================
===============
//接口调用函数部分
//*******************************************************
//序号:
// HD_PCF8574X_S01
//功能:
// 读出芯片的复位状态
//输入:
// is_pcf8574a =1 是A芯片
// add_of_part 器件的子地址 0~3
//输出:
// 端口的数据
//********************************************************
uchar PCF8574X_read_io(uchar is_pcf8574a, uchar add_of_part)
{
uchar i;
i2c_start_cond();
if(is_pcf8574a !=0)
{
i2c_write_byte(PCF8574A_READ |((add_of_part <<1) &0x0E));//器件地
址=0111 A2 A1 A0 r/w
}
else
{
i2c_write_byte(PCF8574_READ |((add_of_part <<1) &0x0E));//器件地
址=0100 A2 A1 A0 r/w
}
i =i2c_read_byte_nack(); //顺序读的方式读出一个字节
i2c_stop_cond();
return(i);
}
//*******************************************************
//序号:
// HD_PCF8574X_S02
//功能:
// 写数据到I/O端口
//输入:
// is_pcf8574a =1 是A芯片
// add_of_part: 器件的子地址 0~7
// dat: 写入的字节
//输出:
// 无
//********************************************************
void PCF8574X_write_io(uchar is_pcf8574a, uchar add_of_part, uchar dat)
{
i2c_start_cond();
if(is_pcf8574a !=0)
{
i2c_write_byte(PCF8574A_WRITE |((add_of_part <<1) &0x0E)); //器件
地址=0111 A2 A1 A0 r/w
}
else
{
i2c_write_byte(PCF8574_WRITE |((add_of_part <<1) &0x0E)); //器件
地址=0100 A2 A1 A0 r/w
}
i2c_write_byte(dat);
i2c_stop_cond();
}
//==============
//内部调用函数部分
//==============
//----------------------------------------------
//I2C 发启始条件:时钟线为高时数据线发生下降沿跳变
//----------------------------------------------
static void i2c_start_cond(void)
{
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SDA_LOW;
_DELAY_NOP3;
}
//----------------------------------------
//I2C 发结束条件:时钟线为高时数据线发生上升沿跳变
//----------------------------------------
static void i2c_stop_cond(void)
{
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_LOW;
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
}
//----------------------------------------
// I2C 读取一个中间字节的数据
//----------------------------------------
/*
static uchar i2c_read_byte(void)
{
uchar i;
uchar da=0;
for(i =0; i<8; i++)
{
da <<=1; //传输的数据高位在前
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SCL_HIGH; //时钟为高时读数据
//NOP3;
if (JUDGE_PCF8574X_SDA) da++;
}
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_LOW; //发送应答位
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_HIGH;
return(da);
}
*/
//----------------------------------------
// I2C 读取一个结尾字节的数据
//----------------------------------------
static uchar i2c_read_byte_nack(void)
{
uchar i;
uchar da =0;
for (i =0; i<8; i++)
{
da <<=1;
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SCL_HIGH;
//NOP3;
if(JUDGE_PCF8574X_SDA) da++;
}
CODE_SCL_LOW;
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
CODE_SCL_HIGH;
_DELAY_NOP3;
CODE_SCL_LOW;
return( da );
}
//----------------------------------------
// I2C 写入一个字节的数据
//----------------------------------------
static void i2c_write_byte(uchar da )
{
uchar i;
for(i =0; i<8; i++)
{
CODE_SCL_LOW;
if(da&0x80)
{
CODE_SDA_HIGH;
}
else
{
CODE_SDA_LOW;
}
CODE_SCL_HIGH;
da <<=1;
}
CODE_SCL_LOW; //第8个SCL下降沿,写入8位数据
_DELAY_NOP3;
CODE_SDA_HIGH;
_DELAY_NOP3;
CODE_SCL_HIGH;
}
//==============================================================
===============
//End Of File