forked from stm32-rs/stm32f1xx-hal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
can-echo.rs
90 lines (71 loc) · 2.95 KB
/
can-echo.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
//! Simple CAN example.
//! Requires a transceiver connected to PA11, PA12 (CAN1) or PB5 PB6 (CAN2).
#![no_main]
#![no_std]
use panic_halt as _;
use bxcan::filter::Mask32;
use cortex_m_rt::entry;
use nb::block;
use stm32f1xx_hal::{can::Can, pac, prelude::*};
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut flash = dp.FLASH.constrain();
let rcc = dp.RCC.constrain();
// To meet CAN clock accuracy requirements an external crystal or ceramic
// resonator must be used. The blue pill has a 8MHz external crystal.
// Other boards might have a crystal with another frequency or none at all.
rcc.cfgr.use_hse(8.mhz()).freeze(&mut flash.acr);
let mut afio = dp.AFIO.constrain();
let mut can1 = {
#[cfg(not(feature = "connectivity"))]
let can = Can::new(dp.CAN1, dp.USB);
#[cfg(feature = "connectivity")]
let can = Can::new(dp.CAN1);
let mut gpioa = dp.GPIOA.split();
let rx = gpioa.pa11.into_floating_input(&mut gpioa.crh);
let tx = gpioa.pa12.into_alternate_push_pull(&mut gpioa.crh);
can.assign_pins((tx, rx), &mut afio.mapr);
// APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5%
// Value was calculated with http://www.bittiming.can-wiki.info/
bxcan::Can::builder(can)
.set_bit_timing(0x001c_0003)
.leave_disabled()
};
// Configure filters so that can frames can be received.
let mut filters = can1.modify_filters();
filters.enable_bank(0, Mask32::accept_all());
#[cfg(feature = "connectivity")]
let _can2 = {
let can = Can::new(dp.CAN2);
let mut gpiob = dp.GPIOB.split();
let rx = gpiob.pb5.into_floating_input(&mut gpiob.crl);
let tx = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
can.assign_pins((tx, rx), &mut afio.mapr);
// APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5%
// Value was calculated with http://www.bittiming.can-wiki.info/
let mut can2 = bxcan::Can::builder(can)
.set_bit_timing(0x001c_0003)
.leave_disabled();
// A total of 28 filters are shared between the two CAN instances.
// Split them equally between CAN1 and CAN2.
let mut slave_filters = filters.set_split(14).slave_filters();
slave_filters.enable_bank(14, Mask32::accept_all());
can2
};
// Drop filters to leave filter configuraiton mode.
drop(filters);
// Select the interface.
let mut can = can1;
//let mut can = _can2;
// Split the peripheral into transmitter and receiver parts.
block!(can.enable_non_blocking()).unwrap();
// Echo back received packages in sequence.
// See the `can-rtfm` example for an echo implementation that adheres to
// correct frame ordering based on the transfer id.
loop {
if let Ok(frame) = block!(can.receive()) {
block!(can.transmit(&frame)).unwrap();
}
}
}