can-loopback.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //! Showcases advanced CAN filter capabilities.
  2. //! Does not require additional transceiver hardware.
  3. #![no_main]
  4. #![no_std]
  5. use bxcan::{
  6. filter::{ListEntry16, ListEntry32, Mask16},
  7. ExtendedId, Frame, StandardId,
  8. };
  9. use panic_halt as _;
  10. use cortex_m_rt::entry;
  11. use embedded_hal::digital::v2::OutputPin;
  12. use nb::block;
  13. use stm32f1xx_hal::{can::Can, pac, prelude::*};
  14. #[entry]
  15. fn main() -> ! {
  16. let dp = pac::Peripherals::take().unwrap();
  17. let mut flash = dp.FLASH.constrain();
  18. let mut rcc = dp.RCC.constrain();
  19. // To meet CAN clock accuracy requirements, an external crystal or ceramic
  20. // resonator must be used.
  21. rcc.cfgr.use_hse(8.mhz()).freeze(&mut flash.acr);
  22. #[cfg(not(feature = "connectivity"))]
  23. let can = Can::new(dp.CAN1, &mut rcc.apb1, dp.USB);
  24. #[cfg(feature = "connectivity")]
  25. let can = Can::new(dp.CAN1, &mut rcc.apb1);
  26. let mut can = bxcan::Can::new(can);
  27. // Use loopback mode: No pins need to be assigned to peripheral.
  28. // APB1 (PCLK1): 8MHz, Bit rate: 500Bit/s, Sample Point 87.5%
  29. // Value was calculated with http://www.bittiming.can-wiki.info/
  30. can.modify_config()
  31. .set_bit_timing(0x001c_0000)
  32. .set_loopback(true)
  33. .set_silent(true);
  34. let mut filters = can.modify_filters();
  35. assert!(filters.num_banks() > 3);
  36. // The order of the added filters is important: it must match configuration
  37. // of the `split_filters_advanced()` method.
  38. // 2x 11bit id + mask filter bank: Matches 0, 1, 2
  39. // TODO: Make this accept also ID 2
  40. filters.enable_bank(
  41. 0,
  42. [
  43. // accepts 0 and 1
  44. Mask16::frames_with_std_id(StandardId::new(0).unwrap(), StandardId::new(1).unwrap()),
  45. // accepts 0 and 2
  46. Mask16::frames_with_std_id(StandardId::new(0).unwrap(), StandardId::new(2).unwrap()),
  47. ],
  48. );
  49. // 2x 29bit id filter bank: Matches 4, 5
  50. filters.enable_bank(
  51. 1,
  52. [
  53. ListEntry32::data_frames_with_id(ExtendedId::new(4).unwrap()),
  54. ListEntry32::data_frames_with_id(ExtendedId::new(5).unwrap()),
  55. ],
  56. );
  57. // 4x 11bit id filter bank: Matches 8, 9, 10, 11
  58. filters.enable_bank(
  59. 2,
  60. [
  61. ListEntry16::data_frames_with_id(StandardId::new(8).unwrap()),
  62. ListEntry16::data_frames_with_id(StandardId::new(9).unwrap()),
  63. ListEntry16::data_frames_with_id(StandardId::new(10).unwrap()),
  64. ListEntry16::data_frames_with_id(StandardId::new(11).unwrap()),
  65. ],
  66. );
  67. // Enable filters.
  68. drop(filters);
  69. // Sync to the bus and start normal operation.
  70. block!(can.enable()).ok();
  71. // Some messages shall pass the filters.
  72. for &id in &[0, 1, 2, 8, 9, 10, 11] {
  73. let frame_tx = Frame::new_data(StandardId::new(id).unwrap(), [id as u8]);
  74. block!(can.transmit(&frame_tx)).unwrap();
  75. let frame_rx = block!(can.receive()).unwrap();
  76. assert_eq!(frame_tx, frame_rx);
  77. }
  78. for &id in &[4, 5] {
  79. let frame_tx = Frame::new_data(ExtendedId::new(id).unwrap(), [id as u8]);
  80. block!(can.transmit(&frame_tx)).unwrap();
  81. let frame_rx = block!(can.receive()).unwrap();
  82. assert_eq!(frame_tx, frame_rx);
  83. }
  84. // Some messages shall not be received.
  85. for &id in &[3, 6, 7, 12] {
  86. let frame_tx = Frame::new_data(ExtendedId::new(id).unwrap(), [id as u8]);
  87. block!(can.transmit(&frame_tx)).unwrap();
  88. while !can.is_transmitter_idle() {}
  89. assert!(can.receive().is_err());
  90. }
  91. let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
  92. let mut led = gpiob.pb9.into_push_pull_output(&mut gpiob.crh);
  93. led.set_high().unwrap();
  94. loop {}
  95. }