Skip to content

Commit b2682bd

Browse files
authored
Example of using i2c with the bme280 air sensor (#313)
* Example of useing i2c with the bme280 air sensor
1 parent adc4e8c commit b2682bd

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

.cargo/config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[target.thumbv7m-none-eabi]
2-
runner = 'gdb-multiarch'
2+
runner = 'arm-none-eabi-gdb'
33
rustflags = [
44
"-C", "link-arg=-Tlink.x",
55
]

examples/i2c-bme280/Cargo.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[package]
2+
name = "i2c-bme280"
3+
version = "0.1.0"
4+
license = "Apache-2.0"
5+
description = "I2C example for real peripheral"
6+
repository = "https://github.com/stm32-rs/stm32f1xx-hal"
7+
edition = "2018"
8+
publish = false
9+
10+
[dependencies]
11+
bme280 = "0.2.1"
12+
cortex-m-semihosting = "0.3.3"
13+
panic-semihosting = "0.5.2"
14+
cortex-m-rt = "0.6.8"
15+
cortex-m = "0.6.0"
16+
17+
[dependencies.stm32f1xx-hal]
18+
path = "../.."
19+
version = "0.7.0"
20+
features = ["stm32f103", "rt", "stm32-usbd"]
21+
22+
[profile.dev]
23+
incremental = false
24+
codegen-units = 1
25+
26+
[profile.release]
27+
codegen-units = 1
28+
debug = true
29+
lto = true

examples/i2c-bme280/memory.x

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* Linker script for the STM32F103C8T6 */
2+
MEMORY
3+
{
4+
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
5+
RAM : ORIGIN = 0x20000000, LENGTH = 20K
6+
}

examples/i2c-bme280/src/main.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! Reads data from a BME280 over i2c
2+
//!
3+
//! This assumes that a BME280 is connected with clk on PB6 and data on PB7.
4+
//!
5+
//! For the Adafruit breakout boards PB6 should be connected to SCK and PB7 to SDI
6+
//!
7+
//! This program writes the sensor values to the debug output provided by semihosting
8+
//! you must enable semihosting in gdb with `monitor arm semihosting enable` I have it
9+
//! added to my `.gdbinit`. Then the debug infomation will be printed in your openocd
10+
//! terminal.
11+
//!
12+
//! This program dose not fit on my blue pill unless compiled in release mode
13+
//! eg. `cargo run --example i2c-bme280 --features "stm32f103 bme280 rt" --release`
14+
//! However as noted above the debug output with the read values will be in the openocd
15+
//! terminal.
16+
17+
#![deny(unsafe_code)]
18+
#![no_std]
19+
#![no_main]
20+
21+
use cortex_m_semihosting::hprintln;
22+
use panic_semihosting as _;
23+
24+
use bme280::BME280;
25+
use cortex_m_rt::entry;
26+
use stm32f1xx_hal::{
27+
delay::Delay,
28+
i2c::{BlockingI2c, DutyCycle, Mode},
29+
pac,
30+
prelude::*,
31+
};
32+
33+
#[entry]
34+
fn main() -> ! {
35+
// Get access to the core peripherals from the cortex-m crate
36+
let cp = cortex_m::Peripherals::take().unwrap();
37+
// Get access to the device specific peripherals from the peripheral access crate
38+
let dp = pac::Peripherals::take().unwrap();
39+
40+
// Take ownership over the raw flash and rcc devices and convert them into the corresponding
41+
// HAL structs
42+
let mut flash = dp.FLASH.constrain();
43+
let mut rcc = dp.RCC.constrain();
44+
let mut afio = dp.AFIO.constrain();
45+
// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
46+
// `clocks`
47+
let clocks = if 1 == 1 {
48+
rcc.cfgr.use_hse(8.mhz()).freeze(&mut flash.acr)
49+
} else {
50+
// My blue pill with a stm32f103 clone dose not seem to respect rcc so will not compensate its pulse legths
51+
// with a faster clock like this. And so the sensor dose not have time to respond to the START pulse.
52+
// I would be interested if others with real stm32f103's can use this program with the faster clocks.
53+
rcc.cfgr
54+
.use_hse(8.mhz())
55+
.sysclk(48.mhz())
56+
.pclk1(6.mhz())
57+
.freeze(&mut flash.acr)
58+
};
59+
60+
// Acquire the GPIOB peripheral
61+
let mut gpiob = dp.GPIOB.split();
62+
63+
let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl);
64+
let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl);
65+
66+
let i2c = BlockingI2c::i2c1(
67+
dp.I2C1,
68+
(scl, sda),
69+
&mut afio.mapr,
70+
Mode::Fast {
71+
frequency: 400_000.hz(),
72+
duty_cycle: DutyCycle::Ratio16to9,
73+
},
74+
clocks,
75+
1000,
76+
10,
77+
1000,
78+
1000,
79+
);
80+
81+
// The Adafruit boards have address 0x77 without closing the jumper on the back, the BME280 lib connects to 0x77 with `new_secondary`, use
82+
// `new_primary` for 0x76 if you close the jumper/solder bridge.
83+
let mut bme280 = BME280::new_secondary(i2c, Delay::new(cp.SYST, clocks));
84+
bme280
85+
.init()
86+
.map_err(|error| {
87+
hprintln!("Could not initialize bme280, Error: {:?}", error).unwrap();
88+
panic!();
89+
})
90+
.unwrap();
91+
loop {
92+
match bme280.measure() {
93+
Ok(measurements) => {
94+
hprintln!("Relative Humidity = {}%", measurements.humidity).unwrap();
95+
hprintln!("Temperature = {} deg C", measurements.temperature).unwrap();
96+
hprintln!("Pressure = {} pascals", measurements.pressure).unwrap();
97+
}
98+
Err(error) => {
99+
hprintln!("Could not read bme280 due to error: {:?}", error).unwrap();
100+
}
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)