Skip to content

Commit de23a67

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

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-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

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

0 commit comments

Comments
 (0)