Skip to content

Commit 33c84a6

Browse files
authored
Merge pull request #100 from zklapow/canbus-with-crate
CAN Support
2 parents 8486da1 + 3a22595 commit 33c84a6

File tree

5 files changed

+625
-0
lines changed

5 files changed

+625
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1414
- Support for `stm32f302x6` and `stm32f302x8` devices ([#132](https://github.com/stm32-rs/stm32f3xx-hal/pull/132))
1515
- Support for the onboard real-time clock (RTC) ([#136](https://github.com/stm32-rs/stm32f3xx-hal/pull/136))
1616
- Enable DMA for USART on `stm32f302` devices ([#139](https://github.com/stm32-rs/stm32f3xx-hal/pull/139))
17+
- Basic CAN bus support ([#100](https://github.com/stm32-rs/stm32f3xx-hal/pull/100))
1718

1819
### Changed
1920

Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ paste = "1"
2626
rtcc = "0.2"
2727
stm32f3 = "0.12"
2828

29+
[dependencies.embedded-hal-can]
30+
version = "0.1.0"
31+
optional = true
32+
33+
[dependencies.heapless]
34+
version = "0.5.5"
35+
optional = true
36+
2937
[dependencies.bare-metal]
3038
version = "0.2"
3139
features = ["const-fn"]
@@ -54,6 +62,7 @@ unproven = ["embedded-hal/unproven"]
5462
device-selected = []
5563
direct-call-deprecated = []
5664
rt = ["stm32f3/rt"]
65+
can = ["embedded-hal-can", "heapless"]
5766

5867
gpio-f302 = []
5968
gpio-f303 = []
@@ -111,6 +120,10 @@ required-features = ["rt", "stm32f303xc", "stm32-usbd"]
111120
name = "spi"
112121
required-features = ["stm32f303"]
113122

123+
[[example]]
124+
name = "can"
125+
required-features = ["rt", "can", "stm32f303"]
126+
114127
[[example]]
115128
name = "serial_dma"
116129
required-features = ["stm32f303"]

examples/can.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//! Example of using CAN.
2+
#![no_std]
3+
#![no_main]
4+
5+
use panic_semihosting as _;
6+
7+
use stm32f3xx_hal as hal;
8+
9+
use cortex_m_rt::entry;
10+
11+
use cortex_m::asm;
12+
use hal::prelude::*;
13+
use hal::stm32;
14+
use hal::watchdog::IndependentWatchDog;
15+
16+
use hal::can::{Can, CanFilter, CanFrame, CanId, Filter, Frame, Receiver, Transmitter};
17+
use nb::block;
18+
19+
// Each "node" needs a different ID, we set up a filter too look for messages to this ID
20+
// Max value is 8 because we use a 3 bit mask in the filter
21+
const ID: u16 = 0b100;
22+
23+
#[entry]
24+
fn main() -> ! {
25+
let dp = stm32::Peripherals::take().unwrap();
26+
27+
let mut flash = dp.FLASH.constrain();
28+
let mut rcc = dp.RCC.constrain();
29+
let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
30+
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
31+
32+
let _clocks = rcc
33+
.cfgr
34+
.use_hse(32.mhz())
35+
.sysclk(32.mhz())
36+
.pclk1(16.mhz())
37+
.pclk2(16.mhz())
38+
.freeze(&mut flash.acr);
39+
40+
// Configure CAN RX and TX pins (AF9)
41+
let can_rx = gpioa.pa11.into_af9(&mut gpioa.moder, &mut gpioa.afrh);
42+
let can_tx = gpioa.pa12.into_af9(&mut gpioa.moder, &mut gpioa.afrh);
43+
44+
// Initialize the CAN peripheral
45+
let can = Can::can(dp.CAN, can_rx, can_tx, &mut rcc.apb1);
46+
47+
// Uncomment the following line to enable CAN interrupts
48+
// can.listen(Event::Fifo0Fmp);
49+
50+
let (mut can_tx, mut rx0, _rx1) = can.split();
51+
52+
let mut led0 = gpiob
53+
.pb15
54+
.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper);
55+
led0.set_high().unwrap();
56+
57+
let filter = CanFilter::from_mask(0b100, ID as u32);
58+
rx0.set_filter(filter);
59+
60+
// Watchdog makes sure this gets restarted periodically if nothing happens
61+
let mut iwdg = IndependentWatchDog::new(dp.IWDG);
62+
iwdg.stop_on_debug(&dp.DBGMCU, true);
63+
iwdg.start(100.ms());
64+
65+
// Send an initial message!
66+
asm::delay(100_000);
67+
let data: [u8; 1] = [0];
68+
69+
let frame = CanFrame::data_frame(CanId::BaseId(ID), &data);
70+
71+
block!(can_tx.transmit(&frame)).expect("Cannot send first CAN frame");
72+
73+
loop {
74+
let rcv_frame = block!(rx0.receive()).expect("Cannot receive CAN frame");
75+
76+
if let Some(d) = rcv_frame.data() {
77+
let counter = d[0].wrapping_add(1);
78+
79+
if counter % 3 == 0 {
80+
led0.toggle().unwrap();
81+
}
82+
83+
let data: [u8; 1] = [counter];
84+
let frame = CanFrame::data_frame(CanId::BaseId(ID.into()), &data);
85+
86+
block!(can_tx.transmit(&frame)).expect("Cannot send CAN frame");
87+
}
88+
89+
iwdg.feed();
90+
91+
asm::delay(1_000_000);
92+
}
93+
}

0 commit comments

Comments
 (0)