can-echo.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. //! Simple CAN example.
  2. //! Requires a transceiver connected to PA11, PA12 (CAN1) or PB5 PB6 (CAN2).
  3. #![no_main]
  4. #![no_std]
  5. use panic_halt as _;
  6. use bxcan::filter::Mask32;
  7. use cortex_m_rt::entry;
  8. use nb::block;
  9. use stm32f1xx_hal::{can::Can, pac, prelude::*};
  10. #[entry]
  11. fn main() -> ! {
  12. let dp = pac::Peripherals::take().unwrap();
  13. let mut flash = dp.FLASH.constrain();
  14. let mut rcc = dp.RCC.constrain();
  15. // To meet CAN clock accuracy requirements an external crystal or ceramic
  16. // resonator must be used. The blue pill has a 8MHz external crystal.
  17. // Other boards might have a crystal with another frequency or none at all.
  18. rcc.cfgr.use_hse(8.mhz()).freeze(&mut flash.acr);
  19. let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
  20. let mut can1 = {
  21. #[cfg(not(feature = "connectivity"))]
  22. let can = Can::new(dp.CAN1, &mut rcc.apb1, dp.USB);
  23. #[cfg(feature = "connectivity")]
  24. let can = Can::new(dp.CAN1, &mut rcc.apb1);
  25. let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
  26. let rx = gpioa.pa11.into_floating_input(&mut gpioa.crh);
  27. let tx = gpioa.pa12.into_alternate_push_pull(&mut gpioa.crh);
  28. can.assign_pins((tx, rx), &mut afio.mapr);
  29. bxcan::Can::new(can)
  30. };
  31. // APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5%
  32. // Value was calculated with http://www.bittiming.can-wiki.info/
  33. can1.modify_config().set_bit_timing(0x001c_0003);
  34. // Configure filters so that can frames can be received.
  35. let mut filters = can1.modify_filters();
  36. filters.enable_bank(0, Mask32::accept_all());
  37. #[cfg(feature = "connectivity")]
  38. let _can2 = {
  39. let can = Can::new(dp.CAN2, &mut rcc.apb1);
  40. let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
  41. let rx = gpiob.pb5.into_floating_input(&mut gpiob.crl);
  42. let tx = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
  43. can.assign_pins((tx, rx), &mut afio.mapr);
  44. let mut can2 = bxcan::Can::new(can);
  45. // APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5%
  46. // Value was calculated with http://www.bittiming.can-wiki.info/
  47. can2.modify_config().set_bit_timing(0x001c_0003);
  48. // A total of 28 filters are shared between the two CAN instances.
  49. // Split them equally between CAN1 and CAN2.
  50. let mut slave_filters = filters.set_split(14).slave_filters();
  51. slave_filters.enable_bank(14, Mask32::accept_all());
  52. can2
  53. };
  54. // Drop filters to leave filter configuraiton mode.
  55. drop(filters);
  56. // Select the interface.
  57. let mut can = can1;
  58. //let mut can = _can2;
  59. // Split the peripheral into transmitter and receiver parts.
  60. block!(can.enable()).unwrap();
  61. // Echo back received packages in sequence.
  62. // See the `can-rtfm` example for an echo implementation that adheres to
  63. // correct frame ordering based on the transfer id.
  64. loop {
  65. if let Ok(frame) = block!(can.receive()) {
  66. block!(can.transmit(&frame)).unwrap();
  67. }
  68. }
  69. }