栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

STC12驱动PCF8575

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

STC12驱动PCF8575

一、简介

PCF8575是一个I/O扩展芯片,德州仪器的芯片。有3个硬件地址引脚寻址,也就是说这个芯片可以设置8个IIC器件地址;芯片工作电压2.5V~5.5V,具有16位准双向输入/输出(I/O)端口(P07-P00、P17-P10)。当我们在做嵌入式开发时,MCU接口不够用可以考虑使用这一款芯片扩展,详细查看相关芯片手册。

淘宝有这一款模块售卖,我使用的经验总结是:使用IO扩展模块当输出时,必须加上拉电阻。上拉电阻选择是1K-10K之间就行了。不然驱动的电压很低!

二、例程

备注:使用例程编译的时候会出现警告,已经检查过警告原因是没有调用函数,不影响功能运行。不用理会即可。
例程1:使用STC12使端口持续高低电平切换

//
//PCF8575控制电平和读取电平
//作者:小途
//时间:2022年2月17日
//

#include 
#include 

#define uchar unsigned char
#define uint unsigned int

//常用数据宏定义
#define MAIN_Fosc		11059200L	//宏定义主时钟HZ
//#define MAIN_Fosc		12000000L

//当A0 A1 A2 为000时
#define PCF8575_READ_ADDRESS 0x41		//IIC总线从机8位读地址
#define PCF8575_WRITEADDRESS 0x40		//IIC总线从机8位写地址


sbit SCL = P3^2;		//I2C时钟总线
sbit SDA = P3^3;		//I2C数据总线


#define I2cRead 		1			//I2C读方向位
#define I2cWrite 		0			//I2C写方向


bit AckFlag;	//应答标志位
uchar PCF8575_LVal,PCF8575_HVal;

//基于STC12单片机1ms延时函数
//函数说明:内部调用
static void Delay1ms()
{
	# if MAIN_Fosc == 11059200L
	//晶振11.0592MHz
	unsigned char i, j;

	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	
	#elif MAIN_Fosc == 12000000L
	//晶振12.000000MHZ
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 12;
	j = 168;
	do
	{
		while (--j);
	} while (--i);
	
	#endif
	
}

//基于STC12单片机1us延时函数
//函数说明:内部调用
static void Delaym1us()
{
	# if MAIN_Fosc == 11059200L
	//晶振11.0592MHz
	_nop_();
	
	#elif MAIN_Fosc == 12000000L
	//晶振12.000000MHZ
	_nop_();
	_nop_();
	
	#endif
}



//基于STC12单片机ms延时函数
//函数说明:外部调用
void Delay_ms(uint time)
{
	int i;
	for(i=0; i
		Delay1ms();
	}
}

//基于STC12单片机us延时函数
//函数说明:外部调用
void Delay_us(uint time)
{
	int i;
	for(i=0; i
		Delaym1us();
	}
}

//I2C延时5us函数
void I2cDelay_5us(void)
{
	Delay_us(5);
}

//I2C总线起始信号
void I2cStart(void)
{
	SCL = 1;
	SDA = 1;
	I2cDelay_5us();//状态保持5us
	SDA = 0;
	I2cDelay_5us();//状态保持5us
}

//I2C总线停止信号
void I2cStop(void)
{
	SCL = 0;
	SDA = 0;
	SCL = 1;
	I2cDelay_5us();//状态保持5us
	SDA = 1;
	I2cDelay_5us();//状态保持5us
}


bit ReadACK(void)
{
	uint i;
	
	SCL = 0;//拉低时钟总线,允许从机控制SDA
	SCL = 1;//拉高,读SDA
	I2cDelay_5us();
	while((SDA==1) && (i<250))//等待SDA应答,或者超过时间默认应答
		i++;
	SCL = 0;
	I2cDelay_5us();
	return(0);//返回0应答
}


void SendACK(bit i)
{
	SCL = 0;	//拉低时钟总线,允许主机控制SDA
	if(i)		//发送非应答
		SDA = 1;
	else
		SDA = 0;
	SCL = 1;	//拉高总线,让从机读SDA
	I2cDelay_5us();
	SCL = 0;	//拉低时钟总线,允许SDA释放
	SDA = 1;	//释放数据总线
}


void I2cSendByte(uchar DAT)
{
	uchar i;
	for(i=0; i<8; i++)	//分别写8次,每次写1位
	{
		SCL = 0;		//拉低时钟总线,允许SDA变化
		if(DAT & 0x80)	//先写数据最高位
			SDA = 1;  	//写1
		else
			SDA = 0;  	//写0
		SCL = 1;	  	//拉高时钟,让从机读SDA
		DAT <<= 1;	  	//为发送下一位左移1位
	}
	SCL = 0;			//拉低时钟总线,允许SDA释放
	SDA = 1;			//释放数据总线
}



uchar I2cReadByte(void)
{
	uchar i, DAT;
	for(i=0; i<8; i++)//分别读8次,每次读一位
	{
		DAT <<= 1; //数据左移1位,准备接收一位
		SCL = 0;   //拉低时钟总线,允许从机控制SDA变化
		SCL = 1;   //拉高时钟总线,读取SDA上的数据
		if(SDA)
			DAT |= 0x01;//为1则写1,否则不行执行写1,通过左移补0
	}
	return(DAT); //返回读出的数据
}


void PCF8575Read(uchar dat1, uchar dat2)
{
	bit AckTemp=1;
	
	I2cStart();//发送启动位
	I2cSendByte(PCF8575_WRITEADDRESS);//发送地址
	AckTemp=ReadACK();//接收应答
	I2cSendByte(dat1);//控制P0.0-P0.7
	AckTemp=ReadACK();//接收应答
	I2cSendByte(dat2);//控制P1.0-P1.7
	AckTemp=ReadACK();//接收应答
	I2cStop();
}


void PCF8575_Read()
{
	bit AckTemp = 1;
	
	I2cStart();//发送启动位
	I2cSendByte(PCF8575_READ_ADDRESS);//发送地址位
	AckTemp=ReadACK();//接收应答
	PCF8575_LVal = I2cReadByte();//接收1个字节(P0.0-P0.7)
	SendACK(0);//发送应答位
	PCF8575_HVal = I2cReadByte();//接收1个字节(P1.0-P1.7)
	SendACK(1);//发送非应答位
	I2cStop();
}

void main()
{
	PCF8575Read(0xff,0xff);//上电复位将PCF8575的电平拉高
	while(1)
	{
		
		//使控制的led闪烁
		Delay_ms(1000);
		PCF8575Read(0xff,0xff);
		Delay_ms(1000);
		PCF8575Read(0x00,0x00);
		
		
	}
}

例程2:使用STC12读取PCF8575端口电平,通过串口发送当前电平状态

#include 
#include 

//数据类型重定义
#define uchar unsigned char
#define uint unsigned int

//常用数据宏定义
#define MAIN_Fosc		11059200L	//宏定义主时钟HZ
//#define MAIN_Fosc		12000000L

//当A0 A1 A2 为000时
//IIC总线从机8位读地址
//IIC总线从机8位写地址
//#define PCF8575_READ_ADDRESS 0x41
//#define PCF8575_WRITEADDRESS 0x40


#define I2cRead 		1			//I2C读方向位
#define I2cWrite 		0			//I2C写方向


//IO管脚定义
sbit SDA = P0^7;//I2C时钟总线
sbit SCL = P0^6;//I2C数据总线
sbit INT0 = P3^2;//按键中断引脚


//全局变量定义
uchar PCF8575_LVal;
uchar PCF8575_HVal;

//基于STC12单片机1ms延时函数
//函数说明:内部调用
static void Delay1ms()
{
	# if MAIN_Fosc == 11059200L
	//晶振11.0592MHz
	unsigned char i, j;

	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	
	#elif MAIN_Fosc == 12000000L
	//晶振12.000000MHZ
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 12;
	j = 168;
	do
	{
		while (--j);
	} while (--i);
	
	#endif
	
}

//基于STC12单片机1us延时函数
//函数说明:内部调用
static void Delaym1us()
{
	# if MAIN_Fosc == 11059200L
	//晶振11.0592MHz
	_nop_();
	
	#elif MAIN_Fosc == 12000000L
	//晶振12.000000MHZ
	_nop_();
	_nop_();
	
	#endif
}



//基于STC12单片机ms延时函数
//函数说明:外部调用
void Delay_ms(uint time)
{
	int i;
	for(i=0; i
		Delay1ms();
	}
}

//基于STC12单片机us延时函数
//函数说明:外部调用
void Delay_us(uint time)
{
	int i;
	for(i=0; i
		Delaym1us();
	}
}

// 发送I2C启动位
void I2C_Start(void)
{
	SDA=1; 
	SCL=1; 
	Delay_us(2);
	SDA=0; 
	Delay_us(2);
	SCL=0;
	Delay_us(2);
}

// 发送I2C停止位
void I2C_Stop(void)
{
	SDA=0;
	SCL=1;
	Delay_us(2);
	SDA=1;
	Delay_us(2);
	SCL=0;
	Delay_us(2);
}

// 发送BIT0  
void I2C_Send_Bit_0(void)
{
	SDA=0;
	SCL=1;
	Delay_us(2);
	SCL=0;
	Delay_us(2);
}

// 发送BIT1 
void I2C_Send_Bit_1(void)
{
	SDA=1;
	SCL=1;
	Delay_us(2);
	SCL=0;
	Delay_us(2);
}

// 接收应答信号
bit I2C_Check_Ack(void)
{
	SDA=1;
	SCL=1;
	Delay_us(2);
	F0=SDA;
	Delay_us(2);
	SCL=0;
	Delay_us(2);
	if(F0==1) return 1;

	return 0;
}

// 发送应答信号
void I2C_Ack()
{
	SDA=0;
	SCL=1;
	Delay_us(2);
	SDA=0;
	Delay_us(2);
	SCL=0;
	Delay_us(2);
}

void I2C_NoAck()
{
	SDA=1;
	SCL=1;
	Delay_us(2);
	SDA=1;
	Delay_us(2);
	SCL=0;
	Delay_us(2);
}

// 写一个字节
void I2C_Write8Bit(unsigned char I2C_data)
{
	unsigned char i;

	for(i=0;i<8;i++)
	{
		if((I2C_data<
	unsigned char I2C_data=0,i;

	for(i=0;i<8;i++)
	{
		SDA=1;    
		SCL=1;    
		Delay_us(2);
		F0=SDA;
		Delay_us(2);
		SCL=0;
		if(F0==1)
		{
			I2C_data=I2C_data<<1;
			I2C_data=I2C_data|0x01;
		}
		else
			I2C_data=I2C_data<<1;
	}
	return I2C_data;
}

// 控制PCF8575引脚电平
void PCF8575_Wirte(unsigned char addr, unsigned int val)
{
  	bit AckTemp=1;
  
  	I2C_Start();
  	I2C_Write8Bit(0x40|(addr<<1));
  	I2C_Check_Ack();
  	I2C_Write8Bit(val);                   
  	I2C_Check_Ack();
  	I2C_Write8Bit(val>>8);                 
  	I2C_Check_Ack();
  	I2C_Stop();
}

// 读出PCF8575引脚电平
void PCF8575_Read(unsigned char addr)
{    
	bit AckTemp=1;

	I2C_Start();
	I2C_Write8Bit(0x41|(addr<<1));
	AckTemp=I2C_Check_Ack();
	PCF8575_LVal=I2C_Read8Bit();
	I2C_Ack();
	PCF8575_HVal=I2C_Read8Bit();
	I2C_NoAck();
	I2C_Stop();
}


//串口初始化,晶振11.0592,波特率9600
void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x04;		//独立波特率发生器时钟为Fosc,即1T
	BRT = 0xDC;		//设定独立波特率发生器重装值
	AUXR |= 0x01;		//串口1选择独立波特率发生器为波特率发生器
	AUXR |= 0x10;		//启动独立波特率发生器
	
	EA = 1;//开总中断
	ES = 1;//开串口中断
}

//向串口发送一个字符
void putchar(char ch)
{
	SBUF = ch;
	while(!TI);TI = 0;
}

void main()
{
	UartInit();//串口初始化
	
	PCF8575_Wirte(0,0xffff); // 让PCF8575的所有IO口输出高电平
	
	while(1)
	{
		Delay_ms(100);
		PCF8575_Read(0); // 读PCF8575引脚电平 
		putchar(PCF8575_LVal); // 把P0.0~P0.7的电平字节发送到串口
		putchar(PCF8575_HVal); // 把P1.0~P1.7的电平字节发送到串口
	}
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/974954.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号