hal_can.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "hal_can.h"
  2. #include "stm32f4xx.h"
  3. #include "stm32f4xx_gpio.h"
  4. #include <string.h>
  5. CanTxMsg tx_message;
  6. CanRxMsg rx_message;
  7. pcan_rx pcan_rx_back = NULL;
  8. pcan_tx pcan_tx_back = NULL;
  9. // CAN初始化
  10. // tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
  11. // tbs2:时间段2的时间单元. 范围:CAN_BS2_1tq~CAN_BS2_8tq;
  12. // tbs1:时间段1的时间单元. 范围:CAN_BS1_1tq ~CAN_BS1_16tq
  13. // brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
  14. // 波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
  15. // mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
  16. // Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
  17. // 则波特率为:42M/((6+7+1)*6)=500Kbps
  18. u8 hal_can1_mode_init(uint8_t tsjw, uint8_t tbs2, uint8_t tbs1, uint16_t brp, uint8_t mode)
  19. {
  20. GPIO_InitTypeDef GPIO_InitStructure;
  21. CAN_InitTypeDef CAN_InitStructure;
  22. CAN_FilterInitTypeDef CAN_FilterInitStructure;
  23. NVIC_InitTypeDef NVIC_InitStructure;
  24. CAN_DeInit(CAN1);
  25. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能PORTA时钟
  26. RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); // 使能CAN1时钟
  27. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  28. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  29. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  30. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  31. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
  32. GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化IO
  33. GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1);
  34. GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1);
  35. // CAN单元设置
  36. CAN_InitStructure.CAN_TTCM = DISABLE; // 非时间触发通信模式
  37. CAN_InitStructure.CAN_ABOM = ENABLE; // 软件自动离线管理
  38. CAN_InitStructure.CAN_AWUM = DISABLE; // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
  39. CAN_InitStructure.CAN_NART = DISABLE; // 禁止报文自动传送
  40. CAN_InitStructure.CAN_RFLM = DISABLE; // 报文不锁定,新的覆盖旧的
  41. CAN_InitStructure.CAN_TXFP = DISABLE; // 优先级由报文标识符决定
  42. CAN_InitStructure.CAN_Mode = mode; // 模式设置
  43. CAN_InitStructure.CAN_SJW = tsjw; // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
  44. CAN_InitStructure.CAN_BS1 = tbs1; // Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
  45. CAN_InitStructure.CAN_BS2 = tbs2; // Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
  46. CAN_InitStructure.CAN_Prescaler = brp; // 分频系数(Fdiv)为brp+1
  47. CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1
  48. // 配置过滤器0
  49. CAN_FilterInitStructure.CAN_FilterNumber = 0; // 过滤器0
  50. CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
  51. CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; // 32位
  52. // 只接收标识符位0x0666报文 注意:RTR IDE SRR也参与构成标识符
  53. CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; //(((u32)0x0666<<3)&0xFFFF0000)>>16; //要过滤的ID高位
  54. CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000; //(((u32)0x0666<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位
  55. CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; // 32位MASK
  56. // CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfff8; // 最后3位不管
  57. CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; // 最后3位不管
  58. CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; // 过滤器0关联到FIFO0
  59. CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; // 激活过滤器0
  60. CAN_FilterInit(&CAN_FilterInitStructure); // 滤波器初始化
  61. CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // FIFO0消息挂号中断允许.
  62. NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  63. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为
  64. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
  65. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  66. NVIC_Init(&NVIC_InitStructure);
  67. // CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); // FIFO0消息挂号中断允许.
  68. NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn;
  69. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
  70. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
  71. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  72. NVIC_Init(&NVIC_InitStructure);
  73. ////////////////////////////////////////////////
  74. return 0;
  75. }
  76. /**********************************************************************************************************
  77. * 函 数 名: CAN1_Init
  78. * 功能说明: CAN1初始化
  79. * 形 参: 无
  80. * 返 回 值: 无
  81. **********************************************************************************************************/
  82. void hal_can_init(void)
  83. {
  84. #if defined(__CAN_BAUD_500K)
  85. hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 6, CAN_Mode_Normal); // CAN1初始化环回模式,波特率500Kbps
  86. #elif defined(__CAN_BAUD_250K)
  87. hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 12, CAN_Mode_Normal); // CAN1初始化环回模式,波特率250Kbps
  88. #else
  89. #error no can baud macro!;
  90. #endif
  91. }
  92. uint8_t hal_can_msg_tx(uint32_t id, uint8_t id_type, uint8_t *p_data, uint8_t len)
  93. {
  94. uint8_t flg = 0;
  95. if (id_type)
  96. {
  97. tx_message.ExtId = id; // 设置扩展标示符(29位)
  98. }
  99. else
  100. {
  101. tx_message.StdId = id_type; // 标准标识符为0
  102. }
  103. tx_message.IDE = id_type; // 使用扩展标识符
  104. tx_message.RTR = CAN_RTR_Data; // 消息类型为数据帧
  105. tx_message.DLC = len; // 发送两帧信息
  106. memcpy(tx_message.Data, p_data, len);
  107. flg = CAN_Transmit(CAN1, &tx_message);
  108. return flg;
  109. }
  110. void hal_can_rx_back_init(pcan_rx p_fun)
  111. {
  112. pcan_rx_back = p_fun;
  113. }
  114. void hal_can_tx_back_init(pcan_tx p_fun)
  115. {
  116. pcan_tx_back = p_fun;
  117. }
  118. void CAN1_TX_IRQHandler(void)
  119. {
  120. if (pcan_tx_back != NULL)
  121. {
  122. pcan_tx_back();
  123. }
  124. }
  125. void CAN1_RX0_IRQHandler(void)
  126. {
  127. CAN_Receive(CAN1, CAN_FIFO0, &rx_message);
  128. if (pcan_rx_back != NULL)
  129. {
  130. pcan_rx_back(rx_message);
  131. }
  132. }