#include "dev_can.h" #include "dev_iap.h" #include "queue.h" #include #include #include queue_entry(pdu_tag, 30) can_tx_queue; queue_entry(pdu_tag, 30) can_rx_queue; double pow_branch(double x, long long N) { double ans = 1.0; // 贡献的初始值为 x double x_contribute = x; // 在对 N 进行二进制拆分的同时计算答案 while (N > 0) { if (N % 2 == 1) { // 如果 N 二进制表示的最低位为 1,那么需要计入贡献 ans *= x_contribute; } // 将贡献不断地平方 x_contribute *= x_contribute; // 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可 N = N >> 1; } return ans; } double pow(double x, double N) { return N >= 0 ? pow_branch(x, N) : 1.0 / pow_branch(x, -N); } uint8_t recv_can_id = 0; static uint64_t base_data; void data_bit_move(uint8_t start_bit, uint8_t bit_len, uint64_t data) { uint64_t mask = 0; uint64_t source_data = (uint64_t)data; mask = pow(2, bit_len) - 1; base_data |= (mask & source_data) << start_bit; } void product_array(uint8_t send_array[8]) { send_array[0] = (uint8_t)base_data; send_array[1] = (uint8_t)(base_data >> 8); send_array[2] = (uint8_t)(base_data >> 16); send_array[3] = (uint8_t)(base_data >> 24); send_array[4] = (uint8_t)(base_data >> 32); send_array[5] = (uint8_t)(base_data >> 40); send_array[6] = (uint8_t)(base_data >> 48); send_array[7] = (uint8_t)(base_data >> 56); base_data = 0; } uint8_t push_can_message_to_queue(uint32_t id, uint8_t len, uint8_t *p_data) { pdu_tag response_msg; QUEUE_STATUS result_status; response_msg.id.r = id; response_msg.reg.dlc = len; memcpy(&response_msg.data.u8_buf[0], p_data, len); if (id > 0x7FF) { response_msg.reg.ide = CAN_Id_Extended; } else { response_msg.reg.ide = CAN_Id_Standard; } __disable_irq(); en_queue(&can_tx_queue, response_msg, result_status); __enable_irq(); if (result_status != Q_OK) { return 0; } return 1; } static uint8_t can_tx_frame(pdu_tag can_message) { uint8_t result = CAN_TxStatus_NoMailBox; result = drv_can_msg_tx(can_message.id.r, can_message.reg.ide, can_message.data.u8_buf, can_message.reg.dlc); return result; } void can_tx_callback(void) { pdu_tag tx_data; QUEUE_STATUS result_status; de_queue(&can_tx_queue, tx_data, result_status); if (result_status == Q_OK) // 返回值为1代表读取成功 { can_tx_frame(tx_data); CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); } else { CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE); } } void can_rx_callback(CanRxMsg rx_message) { pdu_tag data; QUEUE_STATUS result; switch (rx_message.ExtId) { case 0x18DFF4E1: data.id.r = 0x18DFF4E1; data.reg.dlc = rx_message.DLC; memcpy(&data.data.u8_buf[0], rx_message.Data, rx_message.DLC); en_queue(&can_rx_queue, data, result); break; default: return; } } can_rx_tab can_tab[] = { 0x18DFF4E1, iap_rec_handler, }; void can_start_send(void) { pdu_tag tx_msg; QUEUE_STATUS result_status; if (0 == ((CAN1->IER) & 0x1)) { de_queue(&can_tx_queue, tx_msg, result_status); if (result_status == Q_OK) // 返回值为1代表读取成功 { can_tx_frame(tx_msg); CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); } } } static uint8_t can_rx_process(void) { uint8_t i; uint8_t flg = 0; pdu_tag rec_msg; QUEUE_STATUS result; for (uint8_t j = 0; j < 15; j++) { __disable_irq(); de_queue(&can_rx_queue, rec_msg, result); __enable_irq(); if (Q_OK == result) { for (i = 0; i < ARR_SIZE(can_tab); i++) { if (can_tab[i].id == rec_msg.id.r) { can_tab[i].p_func(rec_msg); break; } } } } } void dev_can_network_init(void) { drv_can_init(); queue_init(&can_rx_queue); queue_init(&can_tx_queue); drv_can_rx_back_init(can_rx_callback); drv_can_tx_back_init(can_tx_callback); } void can_process(void) { can_rx_process(); can_start_send(); }