Skip to content

Commit e5d0d6a

Browse files
authored
Support for I2C (#26)
* Add support for I2C. Most of this code is taken from stm32g0xx-hal, with only minor changes to the way pins are initialized and to the interaction with RCC. * Improve the I2C documentation. * Fix compiler error for devices without I2C4. * Add an I2C/MPU6050 example (the timing is still broken). * Fix the I2C bit rate. The std::max() meant that scll was always set to 255, resulting in bit rates that were far too slow. Also, the documentation states that the clock is divided by PRESC+1, not by 2^(PRESC+1).
1 parent a785c2a commit e5d0d6a

File tree

6 files changed

+596
-2
lines changed

6 files changed

+596
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ cortex-m-log = { version = "0.7", features = ["log-integration"] }
5353
cfg-if = "0.1.10"
5454
rtt-target = { version = "0.3.0", features = ["cortex-m"] }
5555
panic-rtt-target = { version = "0.1.1", features = ["cortex-m"] }
56+
mpu6050 = "0.1.4"
5657

5758
[features]
5859
default = ["rt"]

examples/i2c-mpu6050.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![deny(warnings)]
2+
#![deny(unsafe_code)]
3+
#![no_main]
4+
#![no_std]
5+
6+
use hal::i2c::Config;
7+
use hal::prelude::*;
8+
use hal::stm32;
9+
use stm32g4xx_hal as hal;
10+
11+
use cortex_m_rt::entry;
12+
use log::info;
13+
use mpu6050::*;
14+
15+
#[macro_use]
16+
mod utils;
17+
18+
#[entry]
19+
fn main() -> ! {
20+
utils::logger::init();
21+
22+
let dp = stm32::Peripherals::take().expect("cannot take peripherals");
23+
let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals");
24+
25+
let mut rcc = dp.RCC.constrain();
26+
let gpiob = dp.GPIOB.split(&mut rcc);
27+
28+
let sda = gpiob.pb9.into_alternate_open_drain();
29+
let scl = gpiob.pb8.into_alternate_open_drain();
30+
31+
let i2c = dp.I2C1.i2c(sda, scl, Config::new(100.khz()), &mut rcc);
32+
33+
let mut mpu = Mpu6050::new(i2c);
34+
let mut delay = cp.SYST.delay(&rcc.clocks);
35+
mpu.init(&mut delay).expect("cannot initialize the MPU6050");
36+
37+
loop {
38+
let acc = mpu.get_acc().expect("cannot read accelerometer");
39+
let gyro = mpu.get_gyro().expect("cannot read gyro");
40+
let temp = mpu.get_temp().expect("cannot read temperature");
41+
info!("acc: {:?}, gyro: {:?}, temp: {:?}C", acc, gyro, temp);
42+
delay.delay(250.ms());
43+
}
44+
}

examples/i2c.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#![deny(warnings)]
2+
#![deny(unsafe_code)]
3+
#![no_main]
4+
#![no_std]
5+
6+
use hal::i2c::Config;
7+
use hal::prelude::*;
8+
use hal::stm32;
9+
use stm32g4xx_hal as hal;
10+
11+
use cortex_m_rt::entry;
12+
use log::info;
13+
14+
#[macro_use]
15+
mod utils;
16+
17+
#[entry]
18+
fn main() -> ! {
19+
utils::logger::init();
20+
21+
let dp = stm32::Peripherals::take().expect("cannot take peripherals");
22+
let mut rcc = dp.RCC.constrain();
23+
let gpiob = dp.GPIOB.split(&mut rcc);
24+
25+
let sda = gpiob.pb9.into_alternate_open_drain();
26+
let scl = gpiob.pb8.into_alternate_open_drain();
27+
28+
let mut i2c = dp.I2C1.i2c(sda, scl, Config::new(40.khz()), &mut rcc);
29+
// Alternatively, it is possible to specify the exact timing as follows (see the documentation
30+
// of with_timing() for an explanation of the constant):
31+
//let mut i2c = dp
32+
// .I2C1
33+
// .i2c(sda, scl, Config::with_timing(0x3042_0f13), &mut rcc);
34+
35+
let buf: [u8; 1] = [0];
36+
loop {
37+
match i2c.write(0x3c, &buf) {
38+
Ok(_) => info!("ok"),
39+
Err(err) => info!("error: {:?}", err),
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)