stm32f4xx-hal 0.14.0

Peripheral access API for STM32F4 series microcontrollers
Documentation
//! Simple CAN example.
//! Requires a transceiver connected to PB8, 9 (CAN1) or PB5 PB6 (CAN2).

#![no_main]
#![no_std]

use panic_halt as _;

use bxcan::filter::Mask32;
use bxcan::{Fifo, Frame, StandardId};
use cortex_m_rt::entry;
use nb::block;
use stm32f4xx_hal::{pac, prelude::*};

#[entry]
fn main() -> ! {
    let dp = pac::Peripherals::take().unwrap();

    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();

    let gpiob = dp.GPIOB.split();
    let mut can1 = {
        let rx = gpiob.pb8.into_alternate::<9>();
        let tx = gpiob.pb9.into_alternate();

        // let can = Can::new(dp.CAN1, (tx, rx));
        // or
        let can = dp.CAN1.can((tx, rx));

        bxcan::Can::builder(can)
            // APB1 (PCLK1): 8MHz, Bit rate: 500kBit/s, Sample Point 87.5%
            // Value was calculated with http://www.bittiming.can-wiki.info/
            .set_bit_timing(0x001c_0000)
            .enable()
    };

    // Configure filters so that can frames can be received.
    let mut filters = can1.modify_filters();
    filters.enable_bank(0, Fifo::Fifo0, Mask32::accept_all());

    let _can2 = {
        let tx = gpiob.pb13.into_alternate();
        let rx = gpiob.pb12.into_alternate();

        let can = dp.CAN2.can((tx, rx));

        let can2 = bxcan::Can::builder(can)
            // APB1 (PCLK1): 8MHz, Bit rate: 500kBit/s, Sample Point 87.5%
            // Value was calculated with http://www.bittiming.can-wiki.info/
            .set_bit_timing(0x001c_0000)
            .enable();

        // A total of 28 filters are shared between the two CAN instances.
        // Split them equally between CAN1 and CAN2.
        filters.set_split(14);
        let mut slave_filters = filters.slave_filters();
        slave_filters.enable_bank(14, Fifo::Fifo0, Mask32::accept_all());
        can2
    };

    // Drop filters to leave filter configuraiton mode.
    drop(filters);

    // Select the interface.
    let mut can = can1;
    //let mut can = can2;

    // 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.
    let mut test: [u8; 8] = [0; 8];
    let mut count: u8 = 0;
    let id: u16 = 0x500;

    test[1] = 1;
    test[2] = 2;
    test[3] = 3;
    test[4] = 4;
    test[5] = 5;
    test[6] = 6;
    test[7] = 7;
    loop {
        test[0] = count;
        let test_frame = Frame::new_data(StandardId::new(id).unwrap(), test);
        block!(can.transmit(&test_frame)).unwrap();
        if count < 255 {
            count += 1;
        } else {
            count = 0;
        }
    }
}