一、原理分析
1、基本概念
PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
I²C总线接口 知识参考:
(46条消息) 【蓝桥杯单片机进阶强化-01】IIC总线接口技术基础_小蜜蜂老师的干货铺-CSDN博客_蓝桥杯iichttps://blog.csdn.net/ohy3686/article/details/86716456?spm=1001.2014.3001.5502
2、特点
【1】通过I2C总线串行输入/输出
【2】PCF8591通过3个硬件地址引脚寻址
【3】PCF8591的模拟电压范围从VSS到VDD
【4】8-bit逐次逼近A/D转换器
【5】通过1路模拟输出实现DAC增益
【6】PCF8591内置跟踪保持电路
3、引脚
AIN0~AIN3:模拟信号输入端。A0~A2:引脚地址端。
AIN0
:接到右边排针上,可以用杜邦线连外部模拟电压信号AIN1
:接到光敏电阻上AIN2
:放大器的输出端AIN3
:接到滑动变阻器Rb2上
省赛中考得最多的是通道1和通道3:
光敏传感器接到AIN1,通道1;控制寄存器应写入:0x01。
电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03。
VDD、VSS:电源端。(2.5~6V)
SDA、SCL:I2C 总线的数据线、时钟线。
OSC:外部时钟输入端,内部时钟输出端。
EXT:内部、外部时钟选择线,使用内部时钟时 EXT 接地。
AGND:模拟信号地。
AOUT:D/A 转换输出端。
VREF:基准电源端。
4、设备地址
在i2c总线系统中的每个PCF8591设备通过发送一个有效的地址来激活。该地址由一个固定部分和一个可编程部分组成。可编程部分必须根据地址引脚A0、A1和A2进行设置。由原理图知A0、A1和A2都接地。在I2c总线协议中,该地址总是必须作为启动条件后的第一个字节发送。地址字节的最后一位是读/写位,它设置了以下数据传输的方向。写地址为:0x90 读地址为:0x91
5、控制字节
发送到PCF8591设备的第二个字节将存储在其控制寄存器中,并需要控制设备的功能。
二、程序编写
功能要求:采样可变电阻电压和光敏电阻电压
1.光敏电阻Rd1接到PCF8591的AIN1引脚;可调电阻Rb2接到PCF8591的AIN3引脚;
2.独立按键S4为通道切换选择,系统上电的时候,采样通道1光敏电阻的数据并显示在数据管上。按下S4松开后,切换到通道3采样可调电阻的数据并显示;再次按下S4松开后,又切换回通道1采样光敏电阻数据,如此循环往复。
3.数码管的显示格式:前3 位数码管显示通道号(CH通道号),后3位显示PCF8591相应通道读取的数据。如下图所示:
先将官方提供的iic.c和iic.h两个文件复制到工程路径下
iic.c
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
iic.h文章来源:https://www.toymoban.com/news/detail-412655.html
#ifndef _IIC_H
#define _IIC_H
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
#endif
main.c文章来源地址https://www.toymoban.com/news/detail-412655.html
#include "reg52.h"
#include "iic.h"
sbit S4 = P3^3;
unsigned char dat_Rd1;
unsigned char dat_Rb2;
unsigned char flag = 0;
unsigned char code SMG_duanma[18]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//数码管显示模块
void DelaySMG(unsigned int t)
{
while(t--);
}
void DisplaySMG_Bit(unsigned char pos, unsigned char value)
{
P2=0XE0;P0=0XFF;
P2=0XC0;P0=0X01<< pos;
P2=0XE0;P0=value;
}
void DisplaySMG_ADC(unsigned char channel, unsigned char dat)
{
DisplaySMG_Bit(0, SMG_duanma[12]);//显示C
DelaySMG(100);
DisplaySMG_Bit(1,0x89);//显示H
DelaySMG(100);
DisplaySMG_Bit(2, SMG_duanma[channel]);//显示通道号
DelaySMG(100);
DisplaySMG_Bit(3, 0xFF);
DisplaySMG_Bit(4, 0xFF);
DisplaySMG_Bit(5, SMG_duanma[dat / 100]);//百位
DelaySMG(100);
DisplaySMG_Bit(6, SMG_duanma[(dat /10 ) % 10]);//十位
DelaySMG(100);
DisplaySMG_Bit(7, SMG_duanma[dat % 10]);//个位
DelaySMG(100);
P2=0XC0;P0=0Xff;//避免最后一位数码管过亮
P2=0XE0;P0=0xff;
}
//光敏电阻A/D转化函数
void Read_RD1()
{
IIC_Start();//IIC总线起始信号
IIC_SendByte(0x90);//PCF8591的写设备地址
IIC_WaitAck();//等待从机应答
IIC_SendByte(0x01);//发送PCF8591的控制字节;选择选择模拟量输入通道;光敏传感器相应的控制寄存器应写入0x01
IIC_WaitAck();//等待从机应答
IIC_Stop(); //IIC总线停止信号
DisplaySMG_ADC(1,dat_Rd1);//光敏电阻通道号:1,数值
IIC_Start();//IIC总线起始信号
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck(); //等待从机应答
dat_Rd1 = IIC_RecByte();//读取PCF8591通道1的数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop(); //IIC总线停止信号
DisplaySMG_ADC(1,dat_Rd1);
}
//可调电阻A/D转化函数
void Read_RB2()
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
DisplaySMG_ADC(3,dat_Rb2);
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat_Rb2 = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
DisplaySMG_ADC(3,dat_Rb2);
}
//按键切换模块
void Scan_Keys()
{
if(S4 == 0)
{
DelaySMG(100);
if(S4 == 0)
{
if(flag == 0)
{
flag = 1;
while(S4 == 0)
{
DisplaySMG_ADC(1,dat_Rd1);
}
}
else if(flag == 1)
{
flag = 0;
while(S4 == 0)
{
DisplaySMG_ADC(3,dat_Rb2);
}
}
}
}
}
void main()
{
P2=0X80;P0= 0xff;
P2=0XA0;P0= 0x00;
while(1)
{
Scan_Keys();
if(flag == 0)
{
Read_RD1();
}
else if(flag == 1)
{
Read_RB2();
}
}
}
到了这里,关于蓝桥杯单片机—— PCF8591的基本原理及A/D转换应用(14)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!