I2C總線 簡介
I2C(Inter-IC Communication. IIC), 也是使用非常廣泛的同步串行總線, 支持多控制器,多從設(shè)備的總線,只需要 SCL 和 CLK兩根線即可,與 UART 串口不同的是, I2C 總線支持總線仲裁,解決多主設(shè)備同時發(fā)送時數(shù)據(jù)沖突問題,同時主從設(shè)備通信更穩(wěn)定,因為使用時鐘線 CLK 用于同步收發(fā)雙方的速度。
I2C 總線支持一個主機(jī)并聯(lián)多個從設(shè)備。通常使用拓?fù)淙缦拢?/span>
I2C 總線常用于板內(nèi)設(shè)備通信,如M應(yīng)用與CU與傳感器、控制電路、屏幕等設(shè)備之間的通信。 各從設(shè)備都具備一個 I2C 地址,且同一并聯(lián)的總線不能有相同的地址。I2C 的時鐘與數(shù)據(jù)線有著嚴(yán)格的時序要求。
I2C 時序
- 起始信號:SCL保持高,SDA下降沿
- 停止信號:SCL保持高,SDA上升沿
- 采集數(shù)據(jù):SDA穩(wěn)定,SCL上升沿
- ACK信號:接收方拉低SDA后,主機(jī)在SCL上升沿接收到低電平
- NACK信號:
示例:examples/i2c_master_block.rs
#![no_std]
#![no_main]
use defmt::Debug2Format;
// use embedded_io::Write;
use embedded_hal::digital::v2::OutputPin;
use hal::delay;
use hal::i2c::{AnyI2c, Config};
use py32f030_hal::delay::delay_ms;
use py32f030_hal::gpio::{Output, PinIoType, PinSpeed};
use py32f030_hal::{selfas hal, mode::Blocking};
use {defmt_rtt as _, panic_probe as _};
#[cortex_m_rt::entry]
fn main() -> ! {
defmt::info!("i2c start...");
let p = hal::init(Default::default());
let gpioa = p.GPIOA.split();
letmut lcd_rst = Output::new(gpioa.PA4, PinIoType::PullUp, PinSpeed::Low);
let _ = lcd_rst.set_low();
delay_ms(200);
let _ = lcd_rst.set_high();
let sda = gpioa.PA2;
let scl = gpioa.PA3;
let config = Config::default().speed(200_000);
// 配置 200K的速度
let i2c1 = AnyI2c::<_, Blocking>::new(p.I2C, scl, sda, config).unwrap();
let master = i2c1.as_master();
let buf: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
letmut r_buf: [u8; 2] = [0; 2];
letmut cnt = 0;
const SLAVE_DEVICE_ADDRESS: u8 = 0x3c;
loop {
// write from i2c
let rst = master.write_block(SLAVE_DEVICE_ADDRESS, &buf);
defmt::info!("write rst: {:?} ", Debug2Format(&rst));
if rst.is_err() {
// master.clear_errors()
}
// read from i2c
let rst = master.read_block(SLAVE_DEVICE_ADDRESS, &mut r_buf);
defmt::info!("read rst: {:?} ", Debug2Format(&rst));
delay::delay_ms(1000);
defmt::info!("{}", cnt);
cnt += 1;
}
}