#include "app_main.h" #include #include // 地址 ID高3位 0x0-0x7 #define CAN_ADDRESS_HOST 0x7 #define CAN_ADDRESS_DEVICE 0x1 #define CAN_ADDRESS_MASK 0x7 // 指令 ID低8位 0x00-0xFF #define CAN_COMMAND_LED_CONTROL 0x01 #define CAN_COMMAND_LED_STATUS 0x02 #define CAN_COMMAND_MASK 0xFF static volatile uint8_t led_status[2] = { 0 }; static volatile uint8_t led_status_changed = 0; void can_configure(void) { /** * BYTE3 | BYTE2 | BYTE1 | BYTE0 * STID[10:3] | STID[2:0] EXID[17:13] | EXID[12:5] | EXID[4:0] IDE RTR 0 * * STID[10:4] 标准ID,此处用作地址,Id置CAN_ADDRESS_HOST的值,MaskId置0x7F * EXID[17:15] 扩展ID,未使用,Id置全0,Mask置全0 * RTR 1为遥控帧,0为数据帧,此处均接收,不需要过滤,Id任意,MaskId置0 * IDE 1为扩展ID格式,0为标准ID格式,此处只接收标准格式,需要过滤,Id置0,MaskId置1 */ uint32_t filter_id = ((uint32_t)CAN_ADDRESS_DEVICE << 8) << 21; uint32_t filter_id_mask = (((uint32_t)CAN_ADDRESS_MASK << 8) << 21) | ((uint32_t)0x01 << 3); CAN_FilterTypeDef filter; filter.FilterBank = 0; filter.FilterMode = CAN_FILTERMODE_IDMASK; //过滤除主机发送的所有帧 filter.FilterScale = CAN_FILTERSCALE_32BIT; //标准ID格式,Id与Mask的High与Low分别代表两个过滤器 filter.FilterIdHigh = filter_id >> 16; filter.FilterIdLow = (uint16_t)filter_id; filter.FilterMaskIdHigh = filter_id_mask >> 16; filter.FilterMaskIdLow = (uint16_t)filter_id_mask; filter.FilterFIFOAssignment = CAN_RX_FIFO0; filter.FilterActivation = ENABLE; HAL_CAN_ConfigFilter(&hcan, &filter); //配置接收过滤器 HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_ERROR); //使能接收与发送中断 HAL_CAN_ActivateNotification(&hcan, CAN_IT_ERROR | CAN_IT_RX_FIFO0_OVERRUN | CAN_IT_RX_FIFO0_FULL | CAN_IT_LAST_ERROR_CODE); //使能错误中断 HAL_CAN_Start(&hcan); //使能CAN外设 } HAL_StatusTypeDef can_transmit(uint16_t id, const uint8_t *data, uint8_t length) { CAN_TxHeaderTypeDef header = { .IDE = CAN_ID_STD, //标准ID格式 .RTR = CAN_RTR_DATA, //数据帧 .StdId = id, .DLC = length }; uint32_t mailbox; return HAL_CAN_AddTxMessage(&hcan, &header, data, &mailbox); } void app_led_update(void) { if (led_status[0]) { LED1_ON(); } else { LED1_OFF(); } if (led_status[1]) { LED2_ON(); } else { LED2_OFF(); } } void app_key_process(void) { if (KEY1_PRESSED()) { led_status[0] = !led_status[0]; led_status_changed = 1; HAL_Delay(100); while (KEY1_PRESSED()); HAL_Delay(100); } if (KEY2_PRESSED()) { led_status[1] = !led_status[1]; led_status_changed = 1; HAL_Delay(100); while (KEY2_PRESSED()); HAL_Delay(100); } } void app_can_update(void) { if (led_status_changed) { can_transmit((CAN_ADDRESS_HOST << 8) | CAN_COMMAND_LED_STATUS, (uint8_t*)led_status, sizeof(led_status)); led_status_changed = 0; } } void app_main(void) { can_configure(); while (1) { app_key_process(); app_led_update(); app_can_update(); } } void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { CAN_RxHeaderTypeDef header; uint8_t data[8]; if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header, data) != HAL_OK || header.DLC < 2) { printf("wrong can message\r\n"); return; } if ((header.StdId & 0xFF) == CAN_COMMAND_LED_CONTROL) { if (data[0] == 1) { //点亮 led_status[0] = 1; } else if (data[0] == 2) { //熄灭 led_status[0] = 0; } else if (data[0] == 3) { //切换 led_status[0] = !led_status[0]; } if (data[1] == 1) { //点亮 led_status[1] = 1; } else if (data[1] == 2) { //熄灭 led_status[1] = 0; } else if (data[1] == 3) { //切换 led_status[1] = !led_status[1]; } led_status_changed = 1; } else { printf("unhandled command: 0x%02X\r\n", (int)header.StdId & 0xFF); } } void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { printf("rx fifo full!\r\n"); } void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { printf("tx mailbox0 send ok\r\n"); } void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { printf("tx mailbox1 send ok\r\n"); } void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { printf("tx mailbox2 send ok\r\n"); } void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { uint32_t error_code = HAL_CAN_GetError(hcan); if (error_code & (HAL_CAN_ERROR_RX_FOV0 | HAL_CAN_ERROR_RX_FOV1)) { printf("rx fifo overrun error"); } if (error_code & (HAL_CAN_ERROR_TX_ALST0 | HAL_CAN_ERROR_TX_ALST1 | HAL_CAN_ERROR_TX_ALST2)) { printf("tx mailbox arbitration failure"); //仲裁失败导致的发送错误 } else if (error_code & (HAL_CAN_ERROR_TX_TERR0 | HAL_CAN_ERROR_TX_TERR1 | HAL_CAN_ERROR_TX_TERR2)) { printf("tx mailbox transmit error"); //发送失败导致的发送错误 } if (error_code & HAL_CAN_ERROR_STF) { printf(", reason: stuff error"); //位填充错误 } else if (error_code & HAL_CAN_ERROR_FOR) { printf(", reason: form error"); //格式错误 } else if (error_code & HAL_CAN_ERROR_ACK) { printf(", reason: acknowledgment error"); //ACK错误 } else if (error_code & HAL_CAN_ERROR_BR) { printf(", reason: bit recessive error"); //显性位错误 } else if (error_code & HAL_CAN_ERROR_BD) { printf(", reason: bit dominant error"); //隐性位错误 } else if (error_code & HAL_CAN_ERROR_CRC) { printf(", reason: crc error"); //CRC校验错误 } printf("\r\n"); }