ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

RaspberryPi 4B 使用 PCF8591 8位AD和DA转换器

2021-06-20 15:58:57  阅读:374  来源: 互联网

标签:AD read bus smbus2 DA RaspberryPi PCF8591 byte data


模数/数模转换在实际应用中非常有用。如何使用树莓派操作挂载到 PCF8591 I²C 线路上的设备?实际上和其他 I²C 设备操作并无差异。首先来学习 PCF8591 的使用方法,然后通过树莓派控制 PCF8591 芯片。

一、 PCF8591 预备知识

PCF8591 是一个单片集成、单独供电、低功耗、8-bit CMOS 数据获取器件。PCF8591 具有 4 个模拟输入、1 个模拟输出和 1 个串行 I²C 总线接口。PCF8591 的 3 个地址引脚 A0, A1 和 A2 可用于硬件地址编程,允许在同个 I²C 总线上接入 8 个器件,而无需额外的硬件。在 PCF8591 器件上输入输出的地址、控制和数据信号都是通过两线双向 I²C 总线以串行的方式进行传输。

特征

  1. 单独供电

  2. 工作电压范围 2.5V~6V

  3. 低待机电流

  4. 通过 I²C 总线串行输入/输出

  5. 通过 3 个硬件地址引脚编址

  6. 采样率由 I²C 总线速率决定

  7. 4 个模拟输入可编程为单端型或差分输入

  8. 自动增量通道选择

  9. 模拟电压范围:VSS~VDD

  10. 片上跟踪保持电路

  11. 8-bit 逐次逼近 A/D 转换器

  12. 带一个模拟输出的乘法 DAC

以下为 PCF8591 的引脚信息

在这里插入图片描述

引脚名称含义
AIN0~AIN3模拟信号输入端。
A0~A2引脚地址端。
VDD、Vss电源端。(2.5~6V)
SDA、SCLI²C 总线的数据线、时钟线。
OSC外部时钟输入端,内部时钟输出端。
EXT内部、外部时钟选择线,使用内部时钟时 EXT 接地。
AGND模拟信号地。
AOUTD/A 转换输出端。
VREF基准电源端。

PCF8591 芯片所能接收的地址包含固定部分和可编程部分。可编程部分必须根据地址引脚 A0,A1 和 A2 来设置,在 I²C 总线协议中地址必须是起始条件后作为第一个字节发送,地址字节的最后一位用来设置对目标地址的读或写。地址字节格式如下所示:

在这里插入图片描述

发送到 PCF8591 的第二个字节将被存储在控制寄存器,用于控制器件功能。控制寄存器的高半字节用于允许模拟输出,和将模拟输入编程为单端或差分输入。低半字节选择一个由高半字节定义的模拟输入通道。如果自动增量(auto-increment)标志置 1,每次 A/D 转换后通道号将自动增加。

如果自动增量(auto-increment)模式是使用内部振荡器的应用中所需要的,那么控制字中模拟输出允许标志应置 1。这要求内部振荡器持续运行,因此要防止振荡器启动延时的转换错误结果。模拟输出允许标志可以在其他时候复位以减少静态功耗。

选择一个不存在的输入通道将导致分配最高可用的通道号。所以,如果自动增量(auto-increment)被置 1,下一个被选择的通道将总是通道 0。两个半字节的最高有效位(即 bit 7 和 bit 3)是留给未来的功能,必须设置为逻辑 0。控制寄存器的所有位在上电复位后被复位为逻辑 0。D/A 转换器和振荡器在节能时被禁止。模拟输出被切换到高阻态。

在这里插入图片描述

二、PCF8591 模块

原理图如下
在这里插入图片描述

从原理图不难看出模块集成了电位计(INPUT0)、光敏电阻(INPUT1)和热敏电阻(INPUT2)作为输入端,同时将 A0、A1 和 A2 都接地,也就是置位 0。另外 INPUT 和 AIN 是通过跳线帽连接的,可以根据需要设置。D3 LED 在上电以后就会发光,作为电源指示灯。D4 LED 是由 AOUT 控制,也就是通过 D4 LED 的明暗程度来反映模拟输出。SCL 和 SDA 用来挂载 I²C。电阻 R7 和 R8 是典型的 I²C 设备上拉电阻。芯片参考电路设计建议在电源和参考电压输入端加上去耦电容(10μF),这反映在了原理图上的 C1 和 C2。这是为了防止额外的地线和电源噪声,以及减小数字信号对模拟信号路径的串扰。

不看最后的读写位,不难得出 PCF8591 模块的 I²C 地址为 0x1001 000,也就是 0x48。

三、smbus2

先给树莓派安装 smbus2 模块,方便接下来通过 smbus2 来读写 I²C 设备(PCF8591 模块)。

pip install smbus2

根据 Putty 的终端输出不难看到 smbus2-0.4.1 已经安装,接下来就可以在 python 中导入该模块使用了。

pi@raspberrypi:~/test $ pip install smbus2
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting smbus2
  Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0xb54bc490>: Failed to establish a new connection: [Errno 101] \xe7\xbd\x91\xe7\xbb\x9c\xe4\xb8\x8d\xe5\x8f\xaf\xe8\xbe\xbe',)': /packages/c8/bf/62ef029fb7077fc87c3539f7365859bccc6cedb2bb20796b737b788c8d09/smbus2-0.4.1-py2.py3-none-any.whl
  Downloading https://files.pythonhosted.org/packages/c8/bf/62ef029fb7077fc87c3539f7365859bccc6cedb2bb20796b737b788c8d09/smbus2-0.4.1-py2.py3-none-any.whl
Installing collected packages: smbus2
Successfully installed smbus2-0.4.1

使用之前先来学习一番 smbus2 提供的 API,可以直接去网站查看英文资料:https://pypi.org/project/smbus2/

这个库是为了在纯 Python 中替换 smbus-cffi/smbus-python。smbus2 是(另一个)Python -smbus 包的纯 Python 实现。

设计一开始就有两个目标:

  1. smbus 的替代品,语法必须相同;
  2. 与 pysmbus 等其他纯 Python 实现相比,更广泛地使用固有的 I²C 结构体和联合。通过这样做,获得更完整的特性和更容易扩展。

目前支持的特性有:

获得 I²C 功能(I2C_FUNCS)

SMBus报文错误检查 (PEC)支持

read_byte

write_byte

read_byte_data

write_byte_data

read_word_data

write_word_data

read_i2c_block_data

write_i2c_block_data

write_quick

process_call

read_block_data

write_block_data

block_process_call

I2c_rdwr 组合写/读事务,重复启动

它是在 Python 2.7 上开发的,但在 Python 3 中无需任何修改即可工作 3.X。

例一 读一个字节

from smbus2 import SMBus

# 打开 i2c 总线 1,从地址 80 读取一个字节,偏移量为 0
bus = SMBus(1)
b = bus.read_byte_data(80, 0)
print(b)
bus.close()

例二 使用 with 读一个字节

from smbus2 import SMBus

with SMBus(1) as bus:
    b = bus.read_byte_data(80, 0)
    print(b)

例三 写一个字节

from smbus2 import SMBus

with SMBus(1) as bus:
    # 写一个字节到地址 80,偏移量为0
    data = 45
    bus.write_byte_data(80, 0, data)

四、操作 PCF8591 模块

使用下面的 demo 前先要将树莓派 4B 的 I²C 支持打开。

将 PCF8591 模块接入树莓派 4B。

树莓派PCF8591 模块
SCLSCL
SDASDA
GNDGND
3.3VVCC
双色 LED 模块PCF8591 模块
SAOUT
GNDGND

程序首先读取通道 0、1 和 2 上的输入,然后将 0 通道的输入值作为输出写出。也就是将电位计的输入值写入到 AOUT,控制绿灯的明暗程度。

#!/usr/bin/env python3

import time
from smbus2 import SMBus

def do(addr):
    while True:
        vcc_in = read(addr, 0x40)
        print('AIN0 = ' + str(vcc_in)) 
        print('AIN1 = ' + str(read(addr, 0x41))) 
        print('AIN2 = ' + str(read(addr, 0x42))) 
        with SMBus(1) as bus:
            bus.write_byte_data(addr, 0, vcc_in)
        time.sleep(0.01)

def read(addr, ctl_byte): 
    with SMBus(1) as bus:
        bus.write_byte(addr, ctl_byte)
        return bus.read_byte_data(addr, 0)

if __name__ == "__main__":
    try:
        do(0x48)
    except KeyboardInterrupt:
        print("KeyboardInterrupt") 

标签:AD,read,bus,smbus2,DA,RaspberryPi,PCF8591,byte,data
来源: https://blog.csdn.net/tyyj90/article/details/118070818

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有