forked from stm32-rs/stm32h7xx-hal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spi_send_frames.rs
102 lines (85 loc) · 3.45 KB
/
spi_send_frames.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! This example shows off the FrameTransaction mode of hardware chip select functionality.
//!
//! For more docs, see https://docs.rs/stm32h7xx-hal/latest/stm32h7xx_hal/spi/index.html
//!
#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_rt::entry;
#[macro_use]
mod utilities;
use core::num::NonZeroU16;
use spi::Spi;
use stm32h7xx_hal::{pac, prelude::*, spi};
use log::info;
use nb::block;
#[entry]
fn main() -> ! {
utilities::logger::init();
let dp = pac::Peripherals::take().unwrap();
// Constrain and Freeze power
info!("Setup PWR... ");
let pwr = dp.PWR.constrain();
let pwrcfg = example_power!(pwr).freeze();
// Constrain and Freeze clock
info!("Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc
.sys_ck(96.MHz())
.pll1_q_ck(48.MHz())
.freeze(pwrcfg, &dp.SYSCFG);
// Acquire the GPIOA peripheral. This also enables the clock for
// GPIOA in the RCC register.
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
let sck = gpioa.pa5.into_alternate();
let miso = gpioa.pa6.into_alternate();
let mosi = gpioa.pa7.into_alternate();
// Because we want to use the hardware chip select, we need to provide that too
let hcs = gpioa.pa4.into_alternate();
info!("");
info!("stm32h7xx-hal example - SPI Frame Transactions");
info!("");
// Initialise the SPI peripheral.
let mut spi: Spi<_, _, u8> = dp.SPI1.spi(
// Give ownership of the pins
(sck, miso, mosi, hcs),
// Create a config with the hardware chip select given
spi::Config::new(spi::MODE_0)
// Put 1 us idle time between every word sent
.inter_word_delay(0.000001)
// Specify that we use the hardware cs
.hardware_cs(spi::HardwareCS {
// See the docs of the HardwareCSMode to see what the different modes do
mode: spi::HardwareCSMode::FrameTransaction,
// Put 1 us between the CS being asserted and the first clock
assertion_delay: 0.000001,
// Our CS should be high when not active and low when asserted
polarity: spi::Polarity::IdleHigh,
}),
3.MHz(),
ccdr.peripheral.SPI1,
&ccdr.clocks,
);
// We want to send a frame of three bytes.
// This means that the CS should be asserted, three words should be sent and the CS should be de-asserted.
// To do this, it takes a bit more management.
// Prepare sending the frame
spi.setup_transaction(NonZeroU16::new(3).unwrap()).unwrap();
// Write fixed data.
// The CS will automatically be pulled low before the data is sent and de-assert after the sending is done.
for word in &[0x11u8, 0x22, 0x33] {
block!(spi.send(*word)).unwrap();
}
// The way that the silicon works, we also need to clean up some flags.
// If we don't, then the SPI will silently swallow any data you want to send.
// So in this example that would have meant that if we also called send with a fourth byte,
// that byte would've simply not been sent
spi.end_transaction().unwrap();
// When in this mode, the blocking embedded-hal interface already does this for us.
// For example if we want to send two separate frames of different lengths, we can do this:
spi.write(&[0, 1, 2]).unwrap();
spi.write(&[0, 1, 2, 3, 4, 5, 6]).unwrap();
loop {
cortex_m::asm::nop();
}
}