问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

PCF8591详解(蓝桥杯单片机模块(IIC总线))

创作时间:
作者:
@小白创作中心

PCF8591详解(蓝桥杯单片机模块(IIC总线))

引用
CSDN
1.
https://blog.csdn.net/qq_37429313/article/details/115285842

PCF8591是一款单芯片、单电源、低功耗8位CMOS数据采集设备,具有四个模拟输入、一个模拟输出和一个串行I2C总线接口。三个地址引脚A0、A1和A2用于编程硬件地址,允许使用多达8个设备连接到I2C总线而不需要额外的硬件。地址、控制和数据通过两路双向I2C总线串行地传送到和从设备。该装置的功能包括模拟输入多路复用、片上跟踪和保持功能、8位模数转换和8位数模转换。最大转换速率由I2C总线的最大速度给出。

特性

  • 单电源
  • 工作电源电压2.5 V ~ 6V
  • 低待机电流
  • 通过I2C总线串行输入/输出
  • 地址由3个硬件地址引脚决定
  • 采样率由I2C总线速度决定
  • 给出4个模拟输入,可编程为单端或差分输入
  • 可选择自动递增通道
  • 模拟电压范围从Vss到Vdd
  • 片上跟踪和保持电路
  • 8位逐次逼近A/D转换
  • 一个DAC模拟输出

引脚功能

标志
引脚
描述
AIN0
1
模拟输入通道1(A/D转换器)
AIN1
2
模拟输入通道2(A/D转换器)
AIN2
3
模拟输入通道3(A/D转换器)
AIN3
4
模拟输入通道4(A/D转换器)
A0
5
硬件地址
A1
6
硬件地址
A2
7
硬件地址
Vss
8
负电源电压
SDA
9
IIC数据输入/输出
SCL
10
IIC时钟
OSC
11
振荡器inputioutput
EXT
12
振荡器输入的外部和内部开关
AGND
13
模拟地
Vref
14
参考电压输入
AOUT
15
模拟输出(D/A转换器)
Vdd
16
正极

功能描述

寻址

I2C总线系统中的每个PCF8591设备通过发送一个有效的地址来寻址。地址由固定部分和可编程部分组成。可编程部分必须根据地址引脚A0、A1和A2进行设置。地址总是必须作为I2C总线协议中的开始条件之后的第一个字节被发送。地址字节的最后一位是读写位,它设定了接下来数据传输的方向(见下图)。- 注:最后一位为0是写,最后一位为1是读

控制字节

发送到PCF8591设备的第二个字节将存储在其控制寄存器中,并需要控制设备的功能。控制寄存器的高4位用于使能模拟输出,并将模拟输入编程为单端或差分输入。低4位选择由高4位所定义的模拟输入通道之一。如果设置了自动增量标志,在每次A/D转换后,通道号会自动增加。如果在使用内部振荡器的应用中需要自动增量模式,则应该设置控制字节(第6位)中的模拟输出使能标志。这允许内部振荡器连续运行,从而防止由振荡器启动延迟导致的转换错误。上电复位后,控制寄存器的所有位都复位为逻辑0。为了省电,D/A转换器和振荡器被禁用。模拟输出被切换到高阻抗状态。

D/A转换

发送到PCF8591设备的第三个字节存储在DAC数据请求器中,并使用片上D/ A转换器转换为相应的模拟电压。这个D/A转换器由一个电阻分频链组成,该分频链连接到具有256个分频点和选择开关的外部参考电压。tap-decoder将其中一个tap切换到DAC输出线(见下图)。模拟输出电压由一个自动归零的放大器缓冲。这个缓冲放大器可以通过设置模拟输出使能标志来打开或关闭控制寄存器。在使能状态下,输出电压被保持直到进一步的数据字节被发送。片上D/A转换器也用于逐次逼近A/D转换。为了释放DAC进行A/D转换循环,单位增益放大器配备了跟踪和保持电路。这个电路在执行A/D转换时保持输出电压。

D/A转换过程

注意:S为IIC开始信号,P为IIC停止信号

要使用D/A转换,必须使能模拟输出,然后根据流程,首先

IIC开始信号->PCF8591地址写->等待PCF8591回应->控制字节->等待PCF8591回应->DAC的值->等待PCF8591回应->DAC的值…

这个DAC的值可以一直改变,只要没有重新IIC开始信号,或者结束信号,DAC输出就一直是最后一个输出的值!!

A/D转换

A/D转换器采用逐次逼近转换技术。在A/D转换周期内临时使用片上D/A转换器和高增益比较器。A/D转换周期总是在发送一个有效的读模式地址到PCF8591设备后开始。A/D转换周期在应答时钟脉冲的后缘触发。一旦转换周期被触发,所选通道的输入电压样本被存储在芯片上转换成相应的8位二进制码。从差分输入中提取的样本被转换成一个8位的转换结果存储在ADC数据寄存器并等待传输。如果设置了自动增量,则选择下一个通道。在一个读周期中传输的第一个字节包含前一个读周期的转换结果代码。在上电复位条件后,第一个字节读取为十六进制80。最大A/D转换速率是由I2C总线的实际速度给出的。

A/D转换过程

意思就是说,在开始读后,读的是上一次转换的结果!

流程为:IIC开始信号->地址读->等待PCF8591回应

->读PCF8591->主机回应->继续读->主机回应…->直到想停止AD转换了->不回应了->直接停止信号

蓝桥杯部分

原理图部分

从原理图可以看出,因为A0.A1.A2都连接到的是地,因此蓝桥杯板子上面PCF8591的地址为

写地址为:0x90

读地址为:0x91

然后

蓝桥杯板子上面PCF8591的4个ad通道分别连接到了4个不同的部分,其中省赛中考得最多的就是通道1和通道3,通道1连接到了光敏电阻,通道3连接到了滑动变阻器,而DA输出连接到的是板子上最右边的排针的19号引脚,这个在省赛也经常考到。下面就对这部分做说明了。

AD部分

首先是对模式进行初始化,因此必须先写入控制直接

比如我们这里

这里为了方便使用了delay的形式,注意,平常不要使用这种方式

初始化函数为

#define ADCW 0x90
#define ADCR 0x91
bit b_AdcStart(uchar addr)
{
    bit OK = 0;
    IIC_Start();
    IIC_SendByte(ADCW);
    if(!IIC_WaitAck());
    {
        IIC_SendByte(addr);    
        if(!IIC_WaitAck());
        {
            IIC_Stop();
            IIC_Start();
            IIC_SendByte(ADCR);
            if(!IIC_WaitAck())
            {
                OK = 1;
            }
        }
    }
    return OK;
}

读取函数为

uchar c_AdcRead()
{
    uchar _data;
    _data = IIC_RecByte();
    IIC_SendAck(0);
    return _data;
}

这里的步骤是严格按照步骤来的,必须首先写入控制字节才能够让pcf8591处于ad模式,并且在处于ad模式后,就可以一直开始读取数据,只要不停止,转换一次后,接收数据了,要主动回应pcf8591,让它进行下一次的ad转换!

注意:第一次读取到的值一定是0x80,也就是十进制的128,这个数据是为了后面如果要用到自动递增通道,而给你一个起始值,让你在收到这个起始值后,你就能够知道当前数据开始从0通道开始了。

下面是应用程序

void main()
{
    EA = 1;
    UartInit();
    b_AdcStart(0x03);
    v_SL(LED, 0x1f);
    while(1)
    {
        adcData = c_AdcRead();
        Delay1000ms();
        TI = 1;
        printf("%bu\r\n", adcData);
    }
}

输出

如果我用递增通道:(可以实现4组通道都读取)

void main()
{
    EA = 1;
    UartInit();
    b_AdcStart(0x04);
    v_SL(LED, 0x1f);
    while(1)
    {
        adcData = c_AdcRead();
        Delay1000ms();
        TI = 1;
        printf("channel %bu data is %bu\r\n", channel, adcData);
    }
}
//channel是一个全局变量
uchar c_AdcRead()
{
    uchar _data;
    _data = IIC_RecByte();
    IIC_SendAck(0);
    if(_data == 128)
    channel = -1;
    else
    channel = (channel + 1)%4;
    return _data;
}

DA部分

DA部分按照流程就是,首先写入控制字节将da功能开启,然后后面就是将需要的电压值,按照映射0对应0V,255对应5V来将值不断输入进去就是了。一般比赛不是单独只考da,而是将ad和da连起来一起,因此这里给出两个一起用的写法

void AdcStart(uchar _addr, uchar _data)
{
    uchar tmp;
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    IIC_SendByte(_addr);
    IIC_WaitAck();
    IIC_SendByte(_data);
    IIC_WaitAck();
    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();
    tmp = IIC_RecByte();
}
void AdcStartRead()
{
    IIC_SendAck(0);
    val = IIC_RecByte()*100.0/51;
}

每次需要改变da的值的时候,就调用

b_AdcStart(0x43, 127);

其中后面的值就是da输出的值,而读取adc的值还是使用

adcData = c_AdcRead();

不用变。

结束

其实pcf8591的部分并没有多难,就只是在iic的基础上面加了一定的控制而已,因此必须要看懂英文手册,这样在进行比赛的时候,才能够游刃有余,这种东西也不需要背的。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号