#i2c #driver #嵌入式-io #嵌入式-hal-driver #analog #读写

无std mcp23017-tp

MCP23017 16位I2C串行接口I/O扩展器的Rust驱动程序

2个版本

0.1.1 2024年7月20日
0.1.0 2024年7月19日

#293 in 嵌入式开发

Download history 64/week @ 2024-07-13 158/week @ 2024-07-20 27/week @ 2024-07-27

每月249次下载

MIT/Apache

95KB
2K SLoC

mcp23017

带串行接口的16位I/O扩展器

mcp23017 数据手册

描述

此crate是为Microchip的MCP23017设计的,并在该crate上进行了测试,它基于嵌入式-hal crate的I2C。此crate的实现基于#![no_std],但经过一些小的调整,它也可以在std环境中使用。

此驱动程序允许您

  • 选择操作模式:(1x16位)、(2x8位)或(16x1位)
  • 配置中断
  • 启用或禁用中断
  • 设置内部上拉电阻
  • 根据选择的模式读取或写入引脚/端口/芯片

注意:在16位模式下操作时,使用LittleEndian格式化(0xbbaa)。

版本修订

0.1.0 - 第一个版本

0.1.1 - 修复了文档生成,修复了特性中的异步支持,改进了预导入以用于特性使用,修复了中断函数的端序

特性

特性 = ["async"] - 启用对异步Rust的支持(目前嵌入式_hal_bus没有实现I2C的异步,因此如果使用多个引脚/端口,请禁用异步特性)

特性 = ["chipmode"] - 驱动程序作为1x 16位设备运行,完全设置为输出或输入

特性 = ["portmode"] - 驱动程序作为2x 8位端口设备运行,每个端口单独配置

特性 = ["pinmode"] - 驱动程序作为16x 1位引脚设备运行,每个引脚单独配置

注意:只能启用一种模式,否则将面临后果……异步可以在任何模式下使用

示例

要使用驱动程序,您必须具有embedded-hal特性的具体实现。此示例使用stm32f4xx-hal

当使用chipmode时,驱动程序将在16位模式下运行,以下代码将设置所有引脚为输出

use core::cell::RefCell;
use embedded_hal_bus::i2c;
use mcp23017_tp::prelude::*;

    let mut i2c = dp.I2C1.i2c(
        (scl, sda),
        Mode::Standard {
            frequency: 100.kHz(),
        },
        &clocks,
    );

    let i2c_ref_cell = RefCell::new(i2c);

    let mut mcp = mcp23017_tp::MCP23017::new(i2c::RefCellDevice::new(&i2c_ref_cell), address)
        .set_as_output()
        .unwrap();

    loop {
          mcp.write(0xbbaa).unwrap();
          delay.delay_ms(2000);

          // u16: 0xbbaa - u8[]: [0]aa [1]bb (LittleEndian)
          mcp.write(0x0000).unwrap();
          delay.delay_ms(2000);
        }

当使用portmode时,驱动程序将在2x8位模式下运行,以下代码将端口A设置为输出,端口B设置为输入

use core::cell::RefCell;
use embedded_hal_bus::i2c;
use mcp23017_tp::prelude::*;

    let mut i2c = dp.I2C1.i2c(
        (scl, sda),
        Mode::Standard {
            frequency: 100.kHz(),
        },
        &clocks,
    );

    let i2c_ref_cell = RefCell::new(i2c);

    let mut porta = mcp23017_tp::PortA::new(i2c::RefCellDevice::new(&i2c_ref_cell), address)
         .set_as_output()
         .unwrap();
    
    let mut portb = mcp23017_tp::PortB::new(i2c::RefCellDevice::new(&i2c_ref_cell), address)
        .set_as_input()
        .unwrap()
        .set_pull(PinSet::High)
        .unwrap()
        .ready();

    loop {
          porta.write(0xff).unwrap();
          delay.delay_ms(2000);
          porta.write(0x00).unwrap();
          delay.delay_ms(2000);

          rprintln!("{:#02x}", portb.read().unwrap());
        }

当使用pinmode时,驱动程序将在16x1位模式下运行,以下代码将引脚A1和引脚B3设置为输入

use core::cell::RefCell;
use embedded_hal_bus::i2c;
use mcp23017_tp::prelude::*;

    let mut i2c = dp.I2C1.i2c(
        (scl, sda),
        Mode::Standard {
            frequency: 100.kHz(),
        },
        &clocks,
    );

    let i2c_ref_cell = RefCell::new(i2c);

    let mut pina1 = mcp23017_tp::Pina1::new(i2c::RefCellDevice::new(&i2c_ref_cell), address)
        .set_as_input()
        .unwrap()
        .set_pull(PinSet::High)
        .unwrap()
        .ready();

    let mut pinb3 = mcp23017_tp::Pinb3::new(i2c::RefCellDevice::new(&i2c_ref_cell), address)
        .set_as_input()
        .unwrap()
        .set_pull(PinSet::High)
        .unwrap()
        .ready();

    loop {
          delay.delay_ms(2000);
          rprintln!(
              "{:#02x} {:#02x}",
              pina1.read().unwrap(),
              pinb3.read().unwrap()
          );
        }

许可证

许可如下:

由您选择。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义,您有意提交的任何贡献,包括在作品中的包含,将如上双许可,没有任何额外的条款或条件。

依赖关系

~2MB
~39K SLoC