-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathcan.rs
109 lines (82 loc) · 2.95 KB
/
can.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
103
104
105
106
107
108
109
//! Example of using CAN.
#![no_std]
#![no_main]
use panic_semihosting as _;
use stm32f3xx_hal as hal;
use cortex_m::asm;
use cortex_m_rt::entry;
use hal::pac;
use hal::prelude::*;
use hal::watchdog::IndependentWatchDog;
use bxcan::filter::Mask32;
use bxcan::{Frame, StandardId};
use hal::can::Can;
use nb::block;
// Each "node" needs a different ID, we set up a filter too look for messages to this ID
// Max value is 8 because we use a 3 bit mask in the filter
const ID: u16 = 0b100;
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.constrain();
let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
let _clocks = rcc
.cfgr
.use_hse(32.MHz())
.hclk(64.MHz())
.sysclk(64.MHz())
.pclk1(32.MHz())
.pclk2(64.MHz())
.freeze(&mut flash.acr);
// Configure CAN RX and TX pins (AF9)
let rx = gpioa
.pa11
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);
let tx = gpioa
.pa12
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);
// Initialize the CAN peripheral
// Use loopback mode: No pins need to be assigned to peripheral.
// APB1 (PCLK1): 64MHz, Bit rate: 500kBit/s, Sample Point 87.5%
// Value was calculated with http://www.bittiming.can-wiki.info/
let mut can = bxcan::Can::builder(Can::new(dp.CAN, tx, rx, &mut rcc.apb1))
.set_bit_timing(0x001c_0003)
.set_loopback(false)
.set_silent(false)
.leave_disabled();
let mut filters = can.modify_filters();
filters.enable_bank(0, Mask32::accept_all());
// Enable filters.
drop(filters);
// Sync to the bus and start normal operation.
block!(can.enable_non_blocking()).ok();
let mut led0 = gpiob
.pb15
.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper);
led0.set_high().unwrap();
// Watchdog makes sure this gets restarted periodically if nothing happens
let mut iwdg = IndependentWatchDog::new(dp.IWDG);
iwdg.stop_on_debug(&dp.DBGMCU, true);
iwdg.start(100.milliseconds());
// Send an initial message!
asm::delay(100_000);
let data: [u8; 1] = [1];
let frame = Frame::new_data(StandardId::new(ID).unwrap(), data);
block!(can.transmit(&frame)).expect("Cannot send first CAN frame");
loop {
let rcv_frame = block!(can.receive()).expect("Cannot receive CAN frame");
if let Some(d) = rcv_frame.data() {
let counter = d[0].wrapping_add(1);
if counter % 3 == 0 {
led0.toggle().unwrap();
}
let data: [u8; 1] = [counter];
let frame = Frame::new_data(StandardId::new(ID).unwrap(), data);
block!(can.transmit(&frame)).expect("Cannot send CAN frame");
}
iwdg.feed();
asm::delay(1_000_000);
}
}