Skip to content
Snippets Groups Projects

Add basic SPI support

4 files
+ 301
37
Compare changes
  • Side-by-side
  • Inline

Files

+ 123
0
 
//! Read WHO_AM_I registers from LSM9DS1 3D accelerometer, gyroscope, magnetometer.
 
//!
 
//! Using the SparkFun LSM9DS1 breakout board, connect:
 
//! PA_8 -> CS_AG (Chip Select for accelerometer/gyro)
 
//! PA_9 -> CS_M (Chip Select for magnetometer)
 
//! PB_3 -> SCL (SPI clock)
 
//! PB_4 -> SDO_M and SDO_AG (Combined SPI MISO)
 
//! PB_5 -> SDA (SPI MOSI)
 
 
#![deny(unsafe_code)]
 
#![deny(warnings)]
 
#![no_std]
 
 
extern crate cortex_m;
 
extern crate embedded_hal as hal;
 
#[macro_use(block)]
 
extern crate nb;
 
extern crate stm32f4x_hal as f4;
 
 
use hal::spi::{Mode, Phase, Polarity};
 
use f4::prelude::*;
 
use f4::spi::{Spi, SpiConfig};
 
use f4::stm32f4x;
 
use f4::gpio::{Input, OpenDrain, Output, OutputSpeed, PushPull};
 
use f4::gpio::gpioa::{PA8, PA9};
 
use f4::gpio::gpiob::{PB3, PB4, PB5};
 
 
fn main() {
 
let p = stm32f4x::Peripherals::take().unwrap();
 
 
let mut flash = p.FLASH.constrain();
 
let mut rcc = p.RCC.constrain();
 
let mut gpioa = p.GPIOA.split(&mut rcc.ahb1);
 
let mut gpiob = p.GPIOB.split(&mut rcc.ahb1);
 
 
let clocks = rcc.cfgr.freeze(&mut flash.acr);
 
 
// Software CS for accelerometer/gyro
 
let mut cs_ag: PA8<Output<PushPull>> = gpioa
 
.pa8
 
.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
 
.into();
 
cs_ag.internal_pull_up(&mut gpioa.pupdr, true);
 
cs_ag.set_speed(&mut gpioa.ospeedr, OutputSpeed::HIGH);
 
cs_ag.set_high();
 
 
// Software CS for magnetometer
 
let mut cs_m: PA9<Output<PushPull>> = gpioa
 
.pa9
 
.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
 
.into();
 
cs_m.internal_pull_up(&mut gpioa.pupdr, true);
 
cs_m.set_speed(&mut gpioa.ospeedr, OutputSpeed::HIGH);
 
cs_m.set_high();
 
 
// SPI SCK
 
let mut sck: PB3<Output<PushPull>> = gpiob
 
.pb3
 
.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper)
 
.into();
 
sck.set_speed(&mut gpiob.ospeedr, OutputSpeed::HIGH);
 
let sck = sck.into_af6(&mut gpiob.moder, &mut gpiob.afrl);
 
 
// SPI MISO
 
let mut miso: PB4<Input<OpenDrain>> = gpiob
 
.pb4
 
.into_open_drain_input(&mut gpiob.moder, &mut gpiob.otyper)
 
.into();
 
miso.set_speed(&mut gpiob.ospeedr, OutputSpeed::HIGH);
 
miso.internal_pull_up(&mut gpiob.pupdr, true);
 
let miso = miso.into_af6(&mut gpiob.moder, &mut gpiob.afrl);
 
 
// SPI MOSI
 
let mut mosi: PB5<Output<PushPull>> = gpiob
 
.pb5
 
.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper)
 
.into();
 
mosi.set_speed(&mut gpiob.ospeedr, OutputSpeed::HIGH);
 
let mosi = mosi.into_af6(&mut gpiob.moder, &mut gpiob.afrl);
 
 
// SPI MASTER
 
let mut spi = Spi::spi3(
 
p.SPI3,
 
(sck, miso, mosi),
 
Mode {
 
polarity: Polarity::IdleHigh,
 
phase: Phase::CaptureOnSecondTransition,
 
},
 
SpiConfig::Master,
 
1.mhz(),
 
clocks,
 
&mut rcc.apb1,
 
);
 
 
// Read mode
 
const R: u8 = 0x80;
 
 
// Registers to read
 
const WHO_AM_I_AG: u8 = 0x0F;
 
const WHO_AM_I_M: u8 = 0x0F;
 
 
// Expected answers
 
const ANS_AG: u8 = 0x68;
 
const ANS_M: u8 = 0x3D;
 
 
loop {
 
cs_ag.set_low();
 
block!(spi.send(WHO_AM_I_AG | R)).ok();
 
block!(spi.read()).unwrap();
 
block!(spi.send(0)).ok();
 
let byte_ag = block!(spi.read()).unwrap();
 
assert_eq!(byte_ag, ANS_AG);
 
cs_ag.set_high();
 
 
cs_m.set_low();
 
block!(spi.send(WHO_AM_I_M | R)).ok();
 
block!(spi.read()).unwrap();
 
block!(spi.send(0)).ok();
 
let byte_m = block!(spi.read()).unwrap();
 
assert_eq!(byte_m, ANS_M);
 
cs_m.set_high();
 
}
 
}
Loading