文章目录[隐藏]
实验平台:普中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
暂无评论