Skip to content

Commit

Permalink
Example of using i2c with the bme280 air sensor (stm32-rs#313)
Browse files Browse the repository at this point in the history
* Example of useing i2c with the bme280 air sensor
  • Loading branch information
fishrockz authored Jul 29, 2021
1 parent adc4e8c commit b2682bd
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .cargo/config
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[target.thumbv7m-none-eabi]
runner = 'gdb-multiarch'
runner = 'arm-none-eabi-gdb'
rustflags = [
"-C", "link-arg=-Tlink.x",
]
Expand Down
29 changes: 29 additions & 0 deletions examples/i2c-bme280/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "i2c-bme280"
version = "0.1.0"
license = "Apache-2.0"
description = "I2C example for real peripheral"
repository = "https://github.com/stm32-rs/stm32f1xx-hal"
edition = "2018"
publish = false

[dependencies]
bme280 = "0.2.1"
cortex-m-semihosting = "0.3.3"
panic-semihosting = "0.5.2"
cortex-m-rt = "0.6.8"
cortex-m = "0.6.0"

[dependencies.stm32f1xx-hal]
path = "../.."
version = "0.7.0"
features = ["stm32f103", "rt", "stm32-usbd"]

[profile.dev]
incremental = false
codegen-units = 1

[profile.release]
codegen-units = 1
debug = true
lto = true
6 changes: 6 additions & 0 deletions examples/i2c-bme280/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* Linker script for the STM32F103C8T6 */
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
RAM : ORIGIN = 0x20000000, LENGTH = 20K
}
103 changes: 103 additions & 0 deletions examples/i2c-bme280/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//! Reads data from a BME280 over i2c
//!
//! This assumes that a BME280 is connected with clk on PB6 and data on PB7.
//!
//! For the Adafruit breakout boards PB6 should be connected to SCK and PB7 to SDI
//!
//! This program writes the sensor values to the debug output provided by semihosting
//! you must enable semihosting in gdb with `monitor arm semihosting enable` I have it
//! added to my `.gdbinit`. Then the debug infomation will be printed in your openocd
//! terminal.
//!
//! This program dose not fit on my blue pill unless compiled in release mode
//! eg. `cargo run --example i2c-bme280 --features "stm32f103 bme280 rt" --release`
//! However as noted above the debug output with the read values will be in the openocd
//! terminal.
#![deny(unsafe_code)]
#![no_std]
#![no_main]

use cortex_m_semihosting::hprintln;
use panic_semihosting as _;

use bme280::BME280;
use cortex_m_rt::entry;
use stm32f1xx_hal::{
delay::Delay,
i2c::{BlockingI2c, DutyCycle, Mode},
pac,
prelude::*,
};

#[entry]
fn main() -> ! {
// Get access to the core peripherals from the cortex-m crate
let cp = cortex_m::Peripherals::take().unwrap();
// Get access to the device specific peripherals from the peripheral access crate
let dp = pac::Peripherals::take().unwrap();

// Take ownership over the raw flash and rcc devices and convert them into the corresponding
// HAL structs
let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.constrain();
let mut afio = dp.AFIO.constrain();
// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
// `clocks`
let clocks = if 1 == 1 {
rcc.cfgr.use_hse(8.mhz()).freeze(&mut flash.acr)
} else {
// My blue pill with a stm32f103 clone dose not seem to respect rcc so will not compensate its pulse legths
// with a faster clock like this. And so the sensor dose not have time to respond to the START pulse.
// I would be interested if others with real stm32f103's can use this program with the faster clocks.
rcc.cfgr
.use_hse(8.mhz())
.sysclk(48.mhz())
.pclk1(6.mhz())
.freeze(&mut flash.acr)
};

// Acquire the GPIOB peripheral
let mut gpiob = dp.GPIOB.split();

let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl);
let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl);

let i2c = BlockingI2c::i2c1(
dp.I2C1,
(scl, sda),
&mut afio.mapr,
Mode::Fast {
frequency: 400_000.hz(),
duty_cycle: DutyCycle::Ratio16to9,
},
clocks,
1000,
10,
1000,
1000,
);

// The Adafruit boards have address 0x77 without closing the jumper on the back, the BME280 lib connects to 0x77 with `new_secondary`, use
// `new_primary` for 0x76 if you close the jumper/solder bridge.
let mut bme280 = BME280::new_secondary(i2c, Delay::new(cp.SYST, clocks));
bme280
.init()
.map_err(|error| {
hprintln!("Could not initialize bme280, Error: {:?}", error).unwrap();
panic!();
})
.unwrap();
loop {
match bme280.measure() {
Ok(measurements) => {
hprintln!("Relative Humidity = {}%", measurements.humidity).unwrap();
hprintln!("Temperature = {} deg C", measurements.temperature).unwrap();
hprintln!("Pressure = {} pascals", measurements.pressure).unwrap();
}
Err(error) => {
hprintln!("Could not read bme280 due to error: {:?}", error).unwrap();
}
}
}
}

0 comments on commit b2682bd

Please sign in to comment.