-
Notifications
You must be signed in to change notification settings - Fork 184
Controller Area Network (CAN) #215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
8319e5d
can: Add basic types
timokroeger 0974b15
can: API constructors
timokroeger 80ae548
can: Basic configuration to enable the peripheral
timokroeger 8ddd345
can: Basic transmission
timokroeger e2861e8
can: More sophisticated transmit logic
timokroeger 2a121bc
can: Use UAVCAN transmit approach
timokroeger e937ed8
can: Document `Tx::transmit()`
timokroeger 77e66b1
can: clippy suggestions
timokroeger d6fb675
can: Implement `Ord` for ids
timokroeger c0869f4
can: Impl `Ord` trait for frames
timokroeger a178097
can: TX interrupt support
timokroeger a1e6c61
can: Interrupt based CAN tx example
timokroeger 2b585cc
can: Split pin assigment from constructor
timokroeger 26a7b5f
can: Basic RX code
timokroeger 33e680f
can: Combine both FIFOs in one receiver
timokroeger ae2e3f6
can: Improve interrupt enableding/disabling
timokroeger 4cd5caa
can: Update the examples
timokroeger c5d9766
can: Fix priority ordering
timokroeger 0365b81
can: Update doc comments
timokroeger 7d15ec7
can: Make `set_bit_timing()` safe
timokroeger d83a034
can: Refactor transmitter code
timokroeger c77b837
can: Make automatic wake-up configurable
timokroeger 28dc2ec
can: Configurable filters
timokroeger 6dff5c2
can: Fix stm32f103 build
timokroeger a3d6295
can: Silent and Loop-back-mode
timokroeger 901faa8
can: Detect RX overrun errors
timokroeger c9ac19e
can: Remove `RxError` enum
timokroeger 59dfee7
can: Consistent naming for rtr bit methods
timokroeger 626dc40
can: Fix the `PartialEq` trait for frames
timokroeger 3128139
can: Filter bank split index for stm32f105/107
timokroeger 6e6f138
can: Fix and improve filter configuration
timokroeger 510daaf
can: Add advanced filter configuration
timokroeger baf7f0f
can: Documentation and example cleanup
timokroeger e3a17fe
can: RTR frames can have a DLC > 0
timokroeger ee348df
Do not build `can-loopback` when unsupported
timokroeger e86efb0
can: Improve advanced filter configuration
timokroeger a2e8f0d
can: Improve feature usage for examples
timokroeger cb801eb
can: Make `can-rtfm` example work with stm32f103
timokroeger f5b6d73
can: Fix PB8 PB9 pin remapping
timokroeger 916b96c
can: Use `unsafe` for bit-banding
timokroeger e1b217d
Fix typos and review comments
timokroeger 8d1732a
can: Add `Id` enum
timokroeger c6a095e
can: Improve RTFM example
timokroeger File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//! Simple CAN example. Requires a transceiver connected to PB5 and PB6. | ||
|
||
#![no_main] | ||
#![no_std] | ||
|
||
use panic_halt as _; | ||
|
||
use cortex_m_rt::entry; | ||
use nb::block; | ||
use stm32f1xx_hal::{ | ||
can::{Can, Filter, NUM_FILTER_BANKS}, | ||
pac, | ||
prelude::*, | ||
}; | ||
|
||
#[entry] | ||
fn main() -> ! { | ||
let dp = pac::Peripherals::take().unwrap(); | ||
|
||
let mut flash = dp.FLASH.constrain(); | ||
let mut 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 can2 = Can::new(dp.CAN2, &mut rcc.apb1); | ||
|
||
// Select pins for CAN2. | ||
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); | ||
let can_rx_pin = gpiob.pb5.into_floating_input(&mut gpiob.crl); | ||
let can_tx_pin = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl); | ||
let mut afio = dp.AFIO.constrain(&mut rcc.apb2); | ||
can2.assign_pins((can_tx_pin, can_rx_pin), &mut afio.mapr); | ||
|
||
can2.configure(|config| { | ||
// APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5% | ||
// Value was calculated with http://www.bittiming.can-wiki.info/ | ||
config.set_bit_timing(0x001c_0003); | ||
}); | ||
|
||
// Filters are required to use the receiver part of CAN2. | ||
// Because the filter banks are part of CAN1 we first need to enable CAN1 | ||
// and split the filters between the peripherals to use them for CAN2. | ||
let mut can1 = Can::new(dp.CAN1, &mut rcc.apb1); | ||
|
||
// Split the filters at index 0: No filters for CAN1 (unused), 28 filters | ||
// for CAN2. | ||
let (_filters1, mut filters2) = can1.split_filters(0).unwrap(); | ||
assert_eq!(filters2.num_available(), NUM_FILTER_BANKS); | ||
filters2.add(&Filter::accept_all()).unwrap(); // Receive all messages. | ||
|
||
// Split the peripheral into transmitter and receiver parts. | ||
let mut rx = can2.take_rx(filters2).unwrap(); | ||
let mut tx = can2.take_tx().unwrap(); | ||
|
||
// Sync to the bus and start normal operation. | ||
block!(can2.enable()).ok(); | ||
|
||
// 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!(rx.receive()) { | ||
block!(tx.transmit(&frame)).unwrap(); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
//! Showcases advanced CAN filter capabilities. | ||
//! Does not require additional transceiver hardware. | ||
|
||
#![no_main] | ||
#![no_std] | ||
|
||
use panic_halt as _; | ||
|
||
use cortex_m_rt::entry; | ||
use embedded_hal::digital::v2::OutputPin; | ||
use nb::block; | ||
use stm32f1xx_hal::{ | ||
can::{Can, Filter, Frame, Id}, | ||
pac, | ||
prelude::*, | ||
}; | ||
|
||
#[entry] | ||
fn main() -> ! { | ||
let dp = pac::Peripherals::take().unwrap(); | ||
|
||
let mut flash = dp.FLASH.constrain(); | ||
let mut rcc = dp.RCC.constrain(); | ||
|
||
// To meet CAN clock accuracy requirements, an external crystal or ceramic | ||
// resonator must be used. | ||
rcc.cfgr.use_hse(8.mhz()).freeze(&mut flash.acr); | ||
|
||
#[cfg(not(feature = "connectivity"))] | ||
let mut can = Can::new(dp.CAN1, &mut rcc.apb1, dp.USB); | ||
|
||
#[cfg(feature = "connectivity")] | ||
let mut can = Can::new(dp.CAN1, &mut rcc.apb1); | ||
|
||
// Use loopback mode: No pins need to be assigned to peripheral. | ||
can.configure(|config| { | ||
// APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5% | ||
// Value was calculated with http://www.bittiming.can-wiki.info/ | ||
config.set_bit_timing(0x001c_0003); | ||
config.set_loopback(true); | ||
config.set_silent(true); | ||
}); | ||
|
||
// Use advanced configurations for the first three filter banks. | ||
// More details can be found in the reference manual of the device. | ||
#[cfg(not(feature = "connectivity"))] | ||
let mut filters = can | ||
.split_filters_advanced(0x0000_0006, 0xFFFF_FFFA, 0x0000_0007) | ||
.unwrap(); | ||
#[cfg(feature = "connectivity")] | ||
let (mut filters, _) = can | ||
.split_filters_advanced(0x0000_0006, 0xFFFF_FFFA, 0x0000_0007, 3) | ||
.unwrap(); | ||
|
||
assert_eq!(filters.num_available(), 8); | ||
|
||
// The order of the added filters is important: it must match configuration | ||
// of the `split_filters_advanced()` method. | ||
|
||
// 2x 11bit id + mask filter bank: Matches 0, 1, 2 | ||
filters | ||
.add(&Filter::new(Id::Standard(0)).with_mask(!0b1)) | ||
.unwrap(); | ||
filters | ||
.add(&Filter::new(Id::Standard(0)).with_mask(!0b10)) | ||
.unwrap(); | ||
|
||
// 2x 29bit id filter bank: Matches 4, 5 | ||
filters.add(&Filter::new(Id::Standard(4))).unwrap(); | ||
filters.add(&Filter::new(Id::Standard(5))).unwrap(); | ||
|
||
// 4x 11bit id filter bank: Matches 8, 9, 10, 11 | ||
filters.add(&Filter::new(Id::Standard(8))).unwrap(); | ||
filters.add(&Filter::new(Id::Standard(9))).unwrap(); | ||
filters.add(&Filter::new(Id::Standard(10))).unwrap(); | ||
filters.add(&Filter::new(Id::Standard(11))).unwrap(); | ||
|
||
// Split the peripheral into transmitter and receiver parts. | ||
let mut rx = can.take_rx(filters).unwrap(); | ||
let mut tx = can.take_tx().unwrap(); | ||
|
||
// Sync to the bus and start normal operation. | ||
block!(can.enable()).ok(); | ||
|
||
// Some messages shall pass the filters. | ||
for &id in &[0, 1, 2, 4, 5, 8, 9, 10, 11] { | ||
let frame_tx = Frame::new(Id::Standard(id), &[id as u8]).unwrap(); | ||
block!(tx.transmit(&frame_tx)).unwrap(); | ||
let frame_rx = block!(rx.receive()).unwrap(); | ||
assert_eq!(frame_tx, frame_rx); | ||
} | ||
|
||
// Others must be filtered out. | ||
for &id in &[3, 6, 7, 12] { | ||
let frame_tx = Frame::new(Id::Standard(id), &[id as u8]).unwrap(); | ||
block!(tx.transmit(&frame_tx)).unwrap(); | ||
assert!(rx.receive().is_err()); | ||
} | ||
|
||
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); | ||
let mut led = gpiob.pb9.into_push_pull_output(&mut gpiob.crh); | ||
led.set_high().unwrap(); | ||
|
||
loop {} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.