【芯片使用】PCF8591

实验平台:普中A2开发板,STC89C51RC芯片,11.0592M晶振。


前言


本文就介绍PCF8591模块的使用。

PCF8591使用IIC通信协议,模块上自带“可调电阻输入、光敏电阻输入、热敏电阻输入”。


一、模块图

在这里插入图片描述

引脚说明

  • INPUT0:与可调电阻相连
  • INPUT1:与光敏电阻相连
  • INPUT3:与热敏电阻相连
  • AIN0:芯片的模拟量输入口0,地址0x40
  • AIN1:芯片的模拟量输入口1,地址0x41
  • AIN2:芯片的模拟量输入口2,地址0x42
  • AIN3:芯片的模拟量输入口3,地址0x43

使用模块上模拟量作为输入

  • 当选择用数码管显示可调电阻的模拟电压值时,需要用跳线帽将AIN0与INPUT0短接;

使用外部模拟量作为输入

  • 若4个通道都使用外部模拟量输入,则将4个外部模拟量接在AIN0—AIN3上即可。

二、代码

1.main.c

代码如下:

/**************************************************************************************
实验平台:普中A2开发板(STC89C51RC芯片)
					PCF8591模块
试验现象:数码管显示采集到的模拟量(范围0-255)
***************************************************************************************/

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include <SelfDef.h>
#include <PCF8591.h>	
#include <LedDisplay.h>

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	u8 dat=0;
	u8 disp[8];
	while(1)
	{ 
		//0x40、0x41、0x42、0x43,分别为四个模拟量通道地址
		dat=ReadPCF8591(0x43);
		datapros(disp,dat);
		DigDisplay(disp);
	}		
}


2.PCF8591.c

代码如下:

/***************************************************************************************/
/**此部分为I2C总线的驱动程序*********************************/
/**适用平台:普中A2开发板,STC89CXX芯片,晶振11.0592M*********/
/**模块使用说明:INPUT0、INPUT1、INPUT2分别为可调电阻、光敏、热敏电阻
			AIN0、AIN1、AIN2、AIN3分别为地址0x40-0x43的地址输入
			当使用可调电阻作为模拟量输入时,需将AIN0与INPUT0用跳线帽短接即可*/

#include <PCF8591.h>


bit ack;             /*应答标志位*/ 
u8 disp[8];

/*******************************************************************************
* 函数名         : Delay6us()
* 函数功能		   : 软件延时
*******************************************************************************/
void Delay6us()		  //@11.0592MHz
{
	_nop_();
}

/*******************************************************************************
* 函数名         : Start_I2c()
* 函数功能		   : 启动I2C总线,即发送I2C起始条件.
* 备注           : 起始之后SDA和SCL都为0
*******************************************************************************/
void Start_I2c()
{
  SDA=1;         /*发送起始条件的数据信号*/	
	Delay6us();
  SCL=1;
  Delay6us();	   /*起始条件建立时间大于4.7us,延时*/
  SDA=0;         /*发送起始信号*/
	Delay6us();
	SCL=0;				 /*钳住SCL总线,准备发送或接收数据 */
	Delay6us();
}

/*******************************************************************************
* 函数名         : Stop_I2c()
* 函数功能		   : 结束总线函数 
*******************************************************************************/
void Stop_I2c()
{
  SDA=0;      	/*发送结束条件的数据信号*/
	Delay6us();
  SCL=1;      	/*结束条件建立时间>4μs*/
  Delay6us();
  SDA=1;      	/*发送I2C总线结束信号*/
  Delay6us(); 	/*保持时间>4.7μs*/
}

/*******************************************************************************
* 函数名         : SendByte(u8 c)
* 函数功能		   : 字节数据发送函数 
* 输入           : 要发送的字节chr
* 注意           :将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
									此状态位进行操作(不应答或非应答都使ack=0,发送数据正常,ack=1)
									注意此函数对延时精度要求较高,多检查此处
*******************************************************************************/
void SendByte(u8 chr)
{
	u8 i;
	for(i=0;i<8;i++)  		/*要传送的数据长度为8位*/
	{
		if((chr<<i)&0x80)
			SDA=1;   					/*判断发送位*/
		else
			SDA=0;                
		Delay6us();
		SCL=1;              /*置时钟线为高,通知被控器开始接收数据位*/
		Delay6us(); 				/*保证时钟高电平周期大于4μs*/         
		SCL=0; 
	}
	Delay6us();
	SDA=1;                /*8位发送完后释放数据线,准备接收应答位*/
	Delay6us();   
	SCL=1;
	Delay6us();
	if(SDA==1)
		ack=0;     
	else
		ack=1;        			/*判断是否接收到应答信号,1表示收到应答*/
	SCL=0;
	Delay6us();
}
 
/*******************************************************************************
* 函数名         : RcvByte()
* 函数功能		   : 字节数据接收函数 
*******************************************************************************/
u8 RcvByte()
{
  u8 retc;
  u8 i;
  retc=0; 
  SDA=1;                    /*置数据线为输入方式*/
  for(i=0;i<8;i++)
	{          
		SCL=0;                  /*置时钟线为低,准备接收数据位*/
		Delay6us();                 /*时钟低电平周期大于4.7μs*/
		SCL=1;                  /*置时钟线为高使数据线上数据有效*/
		Delay6us();
		retc=retc<<1;
		if(SDA==1)
			retc=retc+1;          /*读数据位,接收的数据位放入retc中 */
		Delay6us();   
	}
  SCL=0;    
  Delay6us();  
  return retc;
}

/********************************************************************                     
*函数名        : void Ack_I2c(bit a);
*函数功能      : 应答子函数,主控器进行应答信号
								(可以是应答或非应答信号,由位参数a决定)
********************************************************************/
void Ack_I2c(bit a)
{
  if(a==0)
		SDA=0;              		 /*在此发出应答或非应答信号 */
  else
		SDA=1;
  Delay6us();      
  SCL=1;
  Delay6us();                /*时钟低电平周期大于4μs*/  
  SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/
  Delay6us();    
}

/*******************************************************************************
* 函数名         : ISendByte(u8 sla,u8 c)
* 函数功能		   : ADC发送字节[命令]数据函数 
*******************************************************************************/
bit ISendByte(u8 sla,u8 c)
{
	 Start_I2c();              //启动总线
	 SendByte(sla);            //发送器件地址
	 if(ack==0)
		 return 0;
	 SendByte(c);              //发送数据
	 if(ack==0)
		 return 0;
	 Stop_I2c();               //结束总线
	 return 1;
}

/*******************************************************************************
* 函数名         : IRcvByte(u8 sla)
* 函数功能		   : ADC读字节数据函数  
*******************************************************************************/
u8 IRcvByte(u8 sla)
{  
	u8 c;
  Start_I2c();          //启动总线
  SendByte(sla+1);      //发送器件地址
  if(ack==0)
		return 0;
  c=RcvByte();          //读取数据0
  Ack_I2c(1);           //发送非就答位
  Stop_I2c();           //结束总线
	return c;
}
/*******************************************************************************
* 函数名         : ReadPCF8591(u8 address)
* 函数功能		   : 读取PCF8591数据 ,address为要读取的地址
* 注意           :0x40、0x41、0x42、0x43分别为可调电阻、光敏电阻、热敏电阻、悬空
*******************************************************************************/
u8 ReadPCF8591(u8 address)
{
	ISendByte(PCF8591,address);
	return IRcvByte(PCF8591);
}


/***********************************驱动程序结束****************************************/

3.PCF8591.h

代码如下:

#ifndef __PCF8591_H_
#define __PCF8591_H_

#include <reg52.h>
#include <SelfDef.h>
#include <intrins.h>

#define  PCF8591 0x90    //PCF8591 地址

sbit SCL=P2^0;           //I2C  时钟 
sbit SDA=P2^1;           //I2C  数据 
 
void Start_I2c();
void Stop_I2c();
void Ack_I2c(bit a);
void SendByte(u8 c);
bit ISendByte(u8 sla,u8 c);
u8 RcvByte();
u8 IRcvByte(u8 sla);
u8 ReadPCF8591(u8 address);

#endif


该处使用的url网络请求的数据。


总结

提示:这里对文章进行总结:

//******************************************************************//

承接stm32单片机、STC系列单片机设计、嵌入式问题咨询

联系QQ:2424644692

//******************************************************************//

在这里插入图片描述

版权声明:本文为CSDN博主「傅里叶也头大」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43625266/article/details/122508593

实验平台:普中A2开发板,STC89C51RC芯片,11.0592M晶振。


前言


本文就介绍PCF8591模块的使用。

PCF8591使用IIC通信协议,模块上自带“可调电阻输入、光敏电阻输入、热敏电阻输入”。


一、模块图

在这里插入图片描述

引脚说明

  • INPUT0:与可调电阻相连
  • INPUT1:与光敏电阻相连
  • INPUT3:与热敏电阻相连
  • AIN0:芯片的模拟量输入口0,地址0x40
  • AIN1:芯片的模拟量输入口1,地址0x41
  • AIN2:芯片的模拟量输入口2,地址0x42
  • AIN3:芯片的模拟量输入口3,地址0x43

使用模块上模拟量作为输入

  • 当选择用数码管显示可调电阻的模拟电压值时,需要用跳线帽将AIN0与INPUT0短接;

使用外部模拟量作为输入

  • 若4个通道都使用外部模拟量输入,则将4个外部模拟量接在AIN0—AIN3上即可。

二、代码

1.main.c

代码如下:

/**************************************************************************************
实验平台:普中A2开发板(STC89C51RC芯片)
					PCF8591模块
试验现象:数码管显示采集到的模拟量(范围0-255)
***************************************************************************************/

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include <SelfDef.h>
#include <PCF8591.h>	
#include <LedDisplay.h>

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	u8 dat=0;
	u8 disp[8];
	while(1)
	{ 
		//0x40、0x41、0x42、0x43,分别为四个模拟量通道地址
		dat=ReadPCF8591(0x43);
		datapros(disp,dat);
		DigDisplay(disp);
	}		
}


2.PCF8591.c

代码如下:

/***************************************************************************************/
/**此部分为I2C总线的驱动程序*********************************/
/**适用平台:普中A2开发板,STC89CXX芯片,晶振11.0592M*********/
/**模块使用说明:INPUT0、INPUT1、INPUT2分别为可调电阻、光敏、热敏电阻
			AIN0、AIN1、AIN2、AIN3分别为地址0x40-0x43的地址输入
			当使用可调电阻作为模拟量输入时,需将AIN0与INPUT0用跳线帽短接即可*/

#include <PCF8591.h>


bit ack;             /*应答标志位*/ 
u8 disp[8];

/*******************************************************************************
* 函数名         : Delay6us()
* 函数功能		   : 软件延时
*******************************************************************************/
void Delay6us()		  //@11.0592MHz
{
	_nop_();
}

/*******************************************************************************
* 函数名         : Start_I2c()
* 函数功能		   : 启动I2C总线,即发送I2C起始条件.
* 备注           : 起始之后SDA和SCL都为0
*******************************************************************************/
void Start_I2c()
{
  SDA=1;         /*发送起始条件的数据信号*/	
	Delay6us();
  SCL=1;
  Delay6us();	   /*起始条件建立时间大于4.7us,延时*/
  SDA=0;         /*发送起始信号*/
	Delay6us();
	SCL=0;				 /*钳住SCL总线,准备发送或接收数据 */
	Delay6us();
}

/*******************************************************************************
* 函数名         : Stop_I2c()
* 函数功能		   : 结束总线函数 
*******************************************************************************/
void Stop_I2c()
{
  SDA=0;      	/*发送结束条件的数据信号*/
	Delay6us();
  SCL=1;      	/*结束条件建立时间>4μs*/
  Delay6us();
  SDA=1;      	/*发送I2C总线结束信号*/
  Delay6us(); 	/*保持时间>4.7μs*/
}

/*******************************************************************************
* 函数名         : SendByte(u8 c)
* 函数功能		   : 字节数据发送函数 
* 输入           : 要发送的字节chr
* 注意           :将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
									此状态位进行操作(不应答或非应答都使ack=0,发送数据正常,ack=1)
									注意此函数对延时精度要求较高,多检查此处
*******************************************************************************/
void SendByte(u8 chr)
{
	u8 i;
	for(i=0;i<8;i++)  		/*要传送的数据长度为8位*/
	{
		if((chr<<i)&0x80)
			SDA=1;   					/*判断发送位*/
		else
			SDA=0;                
		Delay6us();
		SCL=1;              /*置时钟线为高,通知被控器开始接收数据位*/
		Delay6us(); 				/*保证时钟高电平周期大于4μs*/         
		SCL=0; 
	}
	Delay6us();
	SDA=1;                /*8位发送完后释放数据线,准备接收应答位*/
	Delay6us();   
	SCL=1;
	Delay6us();
	if(SDA==1)
		ack=0;     
	else
		ack=1;        			/*判断是否接收到应答信号,1表示收到应答*/
	SCL=0;
	Delay6us();
}
 
/*******************************************************************************
* 函数名         : RcvByte()
* 函数功能		   : 字节数据接收函数 
*******************************************************************************/
u8 RcvByte()
{
  u8 retc;
  u8 i;
  retc=0; 
  SDA=1;                    /*置数据线为输入方式*/
  for(i=0;i<8;i++)
	{          
		SCL=0;                  /*置时钟线为低,准备接收数据位*/
		Delay6us();                 /*时钟低电平周期大于4.7μs*/
		SCL=1;                  /*置时钟线为高使数据线上数据有效*/
		Delay6us();
		retc=retc<<1;
		if(SDA==1)
			retc=retc+1;          /*读数据位,接收的数据位放入retc中 */
		Delay6us();   
	}
  SCL=0;    
  Delay6us();  
  return retc;
}

/********************************************************************                     
*函数名        : void Ack_I2c(bit a);
*函数功能      : 应答子函数,主控器进行应答信号
								(可以是应答或非应答信号,由位参数a决定)
********************************************************************/
void Ack_I2c(bit a)
{
  if(a==0)
		SDA=0;              		 /*在此发出应答或非应答信号 */
  else
		SDA=1;
  Delay6us();      
  SCL=1;
  Delay6us();                /*时钟低电平周期大于4μs*/  
  SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/
  Delay6us();    
}

/*******************************************************************************
* 函数名         : ISendByte(u8 sla,u8 c)
* 函数功能		   : ADC发送字节[命令]数据函数 
*******************************************************************************/
bit ISendByte(u8 sla,u8 c)
{
	 Start_I2c();              //启动总线
	 SendByte(sla);            //发送器件地址
	 if(ack==0)
		 return 0;
	 SendByte(c);              //发送数据
	 if(ack==0)
		 return 0;
	 Stop_I2c();               //结束总线
	 return 1;
}

/*******************************************************************************
* 函数名         : IRcvByte(u8 sla)
* 函数功能		   : ADC读字节数据函数  
*******************************************************************************/
u8 IRcvByte(u8 sla)
{  
	u8 c;
  Start_I2c();          //启动总线
  SendByte(sla+1);      //发送器件地址
  if(ack==0)
		return 0;
  c=RcvByte();          //读取数据0
  Ack_I2c(1);           //发送非就答位
  Stop_I2c();           //结束总线
	return c;
}
/*******************************************************************************
* 函数名         : ReadPCF8591(u8 address)
* 函数功能		   : 读取PCF8591数据 ,address为要读取的地址
* 注意           :0x40、0x41、0x42、0x43分别为可调电阻、光敏电阻、热敏电阻、悬空
*******************************************************************************/
u8 ReadPCF8591(u8 address)
{
	ISendByte(PCF8591,address);
	return IRcvByte(PCF8591);
}


/***********************************驱动程序结束****************************************/

3.PCF8591.h

代码如下:

#ifndef __PCF8591_H_
#define __PCF8591_H_

#include <reg52.h>
#include <SelfDef.h>
#include <intrins.h>

#define  PCF8591 0x90    //PCF8591 地址

sbit SCL=P2^0;           //I2C  时钟 
sbit SDA=P2^1;           //I2C  数据 
 
void Start_I2c();
void Stop_I2c();
void Ack_I2c(bit a);
void SendByte(u8 c);
bit ISendByte(u8 sla,u8 c);
u8 RcvByte();
u8 IRcvByte(u8 sla);
u8 ReadPCF8591(u8 address);

#endif


该处使用的url网络请求的数据。


总结

提示:这里对文章进行总结:

//******************************************************************//

承接stm32单片机、STC系列单片机设计、嵌入式问题咨询

联系QQ:2424644692

//******************************************************************//

在这里插入图片描述

版权声明:本文为CSDN博主「傅里叶也头大」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43625266/article/details/122508593

生成海报
点赞 0

傅里叶也头大

我还没有学会写个人说明!

暂无评论

相关推荐

STM32CubeMX系列|DHT11温湿度传感器

DHT11温湿度传感器 1. DHT11简介 DHT11是一款温湿度一体化的数字传感器,该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机连接。通过单片机微处理器简单的电路连接就能够实时

GD32F103基础教程—外部中断实验(八)

一、教程简介 本章主要是讲解GPIO输入实验,通过按键触发外部中断,控制LED2闪烁。 二、实验流程 1、工程配置 外部中断触发实验工程配置方法与第五章的配置方法一致,具体请查看第五章教程&#xff0c

MCU串行通讯和并行通讯的区别以及UART的理解

假如我们需要从一个MCU发送一段数据到另一个MCU,我们可以选择两种通信方式,串行通信或者并行通信。 假如我们要发送的数据是数字198转化为二进制,就是11000110,如果使用串行通信