Skip to content

Commit 575b7fc

Browse files
committed
Added small CAN loopback example
1 parent 8702fa7 commit 575b7fc

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ lto = true
100100
name = "adc"
101101
required-features = ["rt", "stm32l4x3"]
102102

103+
[[example]]
104+
name = "can-loopback"
105+
required-features = ["rt", "stm32l4x1"]
106+
103107
[[example]]
104108
name = "irq_button"
105109
required-features = ["rt"]

examples/can-loopback.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//! Run the bxCAN peripheral in loopback mode.
2+
3+
#![deny(unsafe_code)]
4+
#![deny(warnings)]
5+
#![no_main]
6+
#![no_std]
7+
8+
use bxcan::{
9+
filter::Mask32,
10+
{Frame, StandardId},
11+
};
12+
use panic_halt as _;
13+
use rtic::app;
14+
use rtt_target::{rprintln, rtt_init_print};
15+
use stm32l4xx_hal::{can::Can, prelude::*};
16+
17+
#[app(device = stm32l4xx_hal::stm32, peripherals = true)]
18+
const APP: () = {
19+
#[init]
20+
fn init(cx: init::Context) {
21+
rtt_init_print!();
22+
23+
let dp = cx.device;
24+
25+
let mut flash = dp.FLASH.constrain();
26+
let mut rcc = dp.RCC.constrain();
27+
let mut pwr = dp.PWR.constrain(&mut rcc.apb1r1);
28+
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2);
29+
30+
// Set the clocks to 80 MHz
31+
let _clocks = rcc.cfgr.sysclk(80.mhz()).freeze(&mut flash.acr, &mut pwr);
32+
33+
rprintln!(" - CAN init");
34+
35+
let mut can = {
36+
let rx = gpioa.pa11.into_af9(&mut gpioa.moder, &mut gpioa.afrh);
37+
let tx = gpioa.pa12.into_af9(&mut gpioa.moder, &mut gpioa.afrh);
38+
39+
let can = Can::new(dp.CAN1, (tx, rx));
40+
41+
bxcan::Can::new(can)
42+
};
43+
can.configure(|config| {
44+
// APB1 (PCLK1): 80 MHz, Bit rate: 100kBit/s, Sample Point 87.5%
45+
// Value was calculated with http://www.bittiming.can-wiki.info/
46+
config.set_bit_timing(0x001c_0031);
47+
config.set_loopback(true);
48+
});
49+
50+
// Configure filters so that can frames can be received.
51+
let mut filters = can.modify_filters();
52+
filters.enable_bank(0, Mask32::accept_all());
53+
54+
// Drop filters to leave filter configuraiton mode.
55+
drop(filters);
56+
57+
// Enable and wait for bxCAN sync to bus
58+
while let Err(_) = can.enable() {}
59+
60+
// Send a frame
61+
let mut test: [u8; 8] = [0; 8];
62+
let id: u16 = 0x500;
63+
64+
test[0] = 72;
65+
test[1] = 1;
66+
test[2] = 2;
67+
test[3] = 3;
68+
test[4] = 4;
69+
test[5] = 5;
70+
test[6] = 6;
71+
test[7] = 7;
72+
let test_frame = Frame::new_data(StandardId::new(id).unwrap(), test);
73+
can.transmit(&test_frame).unwrap();
74+
75+
// Wait for TX to finish
76+
while !can.is_transmitter_idle() {}
77+
78+
rprintln!(" - CAN tx complete: {:?}", test_frame);
79+
80+
// Receive the packet back
81+
let r = can.receive();
82+
83+
rprintln!(" - CAN rx {:?}", r);
84+
85+
assert_eq!(Ok(test_frame), r);
86+
}
87+
88+
#[idle]
89+
fn idle(_: idle::Context) -> ! {
90+
loop {
91+
continue;
92+
}
93+
}
94+
};

0 commit comments

Comments
 (0)