(二)CAN通信协议代码-升级版

CAN代码-升级版

  • (1)can.c
  • (2)can.h

(1)can.c

#define CAN_BUS_ENABLE  1
#define CAN_BUS_DISABLE 0
#define CAN2_FILTER_S   14

typedef struct __can_gpio_pin_t{
    uint32_t  pin_bit;
    uint32_t gpio_rcc;
    GPIO_TypeDef *gpio_port;
}can_gpio_pin_t;

typedef struct __send_status_t{
    uint8_t mbox_s;
}send_status_t;

typedef struct _can_cfg_t{
    uint8_t can_dev_id;
    uint8_t pin_map;
    uint8_t fifo_no;
    uint8_t filter_start;
    can_gpio_pin_t r_pin;
    can_gpio_pin_t t_pin;    
    uint32_t can_rcc;
    CAN_TypeDef* can_ch;
    send_status_t txs;
    uint8_t irq;
    uint8_t it_flag;
    uint8_t res[2];
}can_cfg_t;

/*--- 设置常用CAN波特率 ---*/
typedef struct __can_tq_t {
    uint16_t can_baudrate;
    uint16_t can_prescaler;
    uint8_t can_syn_jump_width;
    uint8_t can_time_bit_seg1;
    uint8_t can_time_bit_seg2;
    uint8_t can_res;
}can_tq_t;

static can_tq_t can_baud_array[] = {
    { 5, 400, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 10, 200, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 20, 100, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 40, 50, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 50, 40, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 80, 25, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 100, 20, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 125, 16, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 200, 10, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 250, 36, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
    { 400, 5, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 500, 4, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 666, 3, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 800, 11, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
    { 1000, 9, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
    { 0 },
};

static can_cfg_t can_cfg[CAN_DEV_CNT]={
    [CAN_DEV1] = {
        .can_dev_id = CAN_DEV1,
        .fifo_no = CAN_Filter_FIFO0,
        .t_pin = { GPIO_Pin_12, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_TX PA12
        .r_pin = { GPIO_Pin_11, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_RX PA11
        .pin_map = 0,
        .can_rcc = RCC_APB1Periph_CAN1,
        .can_ch = CAN1,
        .filter_start = 0,//0~13
        .irq = CAN1_RX0_IRQn,
        .it_flag = CAN_IT_FMP0,
    },
    [CAN_DEV2] = {
        .can_dev_id = CAN_DEV2,
        .fifo_no = CAN_Filter_FIFO1,
        .t_pin = { GPIO_Pin_13, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_TX PB13
        .r_pin = { GPIO_Pin_12, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_RX PB12
        .pin_map = 0,
        .can_rcc = RCC_APB1Periph_CAN2,
        .can_ch = CAN2,
        .filter_start = CAN2_FILTER_S,//14~27
        .irq = CAN2_RX1_IRQn,
        .it_flag = CAN_IT_FMP1,
    }
};

static can_tq_t *__get_tp(int br)
{
    int i = 0;
    while(can_baud_array[i].can_baudrate != 0){
        if(can_baud_array[i].can_baudrate == br){
            return &can_baud_array[i];
        }
        i++;
    }
    return NULL;
}

static void __can_enable(int can_dev, u32 val)
{
    if(can_dev == CAN_DEV1){
        if(val == CAN_BUS_ENABLE){
            _debug(SYS_INFO, "CAN_1 bus enable\n");
            pp_ctrl_set(PIN_CAN1_STB,0);/*0 enable*/
        }else{
            pp_ctrl_set(PIN_CAN1_STB,1);/*1 disable*/
        }
    }else if(can_dev == CAN_DEV2){
        if(val == CAN_BUS_ENABLE){
            _debug(SYS_INFO, "CAN_2 bus enable\n");
            pp_ctrl_set(PIN_CAN2_STB,0);/*0 enable*/
        }else{
            pp_ctrl_set(PIN_CAN2_STB,1);/*1 disable*/
        }
    }
}

int can_dev_init(int can_dev, int can_mode, int brp)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    can_cfg_t* pparam = &can_cfg[can_dev];

    _debug(SYS_INFO, "CAN%d Init start\n", pparam->can_dev_id + 1);

    CAN_DeInit(pparam->can_ch);

    /* 使能GPIO、CANx外设复用功能时钟使能 */
    RCC_APB1PeriphClockCmd(pparam->can_rcc, ENABLE);
    RCC_APB2PeriphClockCmd(pparam->r_pin.gpio_rcc | pparam->t_pin.gpio_rcc, ENABLE);
    // RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);

    /* GPIO 复用功能初始化:Rx */
    GPIO_InitStructure.GPIO_Pin = pparam->r_pin.pin_bit;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(pparam->r_pin.gpio_port, &GPIO_InitStructure);

    /* GPIO 复用功能初始化:Tx */
    GPIO_InitStructure.GPIO_Pin = pparam->t_pin.pin_bit;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
    GPIO_Init(pparam->t_pin.gpio_port, &GPIO_InitStructure);
    
    /* CAN 初始化 */
    u8 ret_can;
    can_tq_t* pcan_baud = __get_tp(brp);
    if (pcan_baud == NULL) {
        _debug(SYS_INFO, "Setting BaudRate param is unqualified %d\n",brp);
        return -1;
    }
    CAN_InitStructure.CAN_Prescaler = pcan_baud->can_prescaler;
    CAN_InitStructure.CAN_SJW = pcan_baud->can_syn_jump_width;
    CAN_InitStructure.CAN_BS1 = pcan_baud->can_time_bit_seg1;
    CAN_InitStructure.CAN_BS2 = pcan_baud->can_time_bit_seg2;
    _debug(SYS_INFO, "BaudRate = %dKHZ, can_prescaler = %d, CAN_SJW_%dtq, CAN_BS1_%dtq, CAN_BS2_%dtq \n",
        pcan_baud->can_baudrate,
        pcan_baud->can_prescaler,
        pcan_baud->can_syn_jump_width + 1,
        pcan_baud->can_time_bit_seg1 + 1,
        pcan_baud->can_time_bit_seg2 + 1);

    CAN_InitStructure.CAN_Mode = can_mode;
    CAN_InitStructure.CAN_TTCM = DISABLE; //can_time_trigger_communication;
    CAN_InitStructure.CAN_ABOM = DISABLE; //can_auto_bus_off;
    CAN_InitStructure.CAN_AWUM = DISABLE; //can_auto_wakeup;
    CAN_InitStructure.CAN_NART = ENABLE;  //can_no_auto_retransmit;(开启不自动重发)
    CAN_InitStructure.CAN_RFLM = DISABLE; //can_recv_fifo_lock;
    CAN_InitStructure.CAN_TXFP = DISABLE; //can_transmit_fifo_priority;
    ret_can = CAN_Init(pparam->can_ch, &CAN_InitStructure);
    if (ret_can == 0) {
        _debug(SYS_INFO, "CAN%d Initialize is failed \n", pparam->can_dev_id + 1);
        return -1; 
    }
#if 1
    /* 接收中断参数配置 */
    CAN_ITConfig(pparam->can_ch, pparam->it_flag, ENABLE); //FIFO0消息挂号中断允许
    NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //接收IRQ通道使能
    NVIC_Init(&NVIC_InitStructure); //初始化接收中断配置
#endif
   _debug(SYS_INFO, "CAN%d Init end\n", pparam->can_dev_id + 1);
    return 0;
}

int p_can_open(int can_dev,int bps)
{
  int ret = can_dev_init(can_dev,CAN_Mode_Normal,bps);
  if(ret == 0){
    __can_enable(can_dev,CAN_BUS_ENABLE);
  }
  return ret;
}

void p_can_close(int can_dev)
{
    NVIC_InitTypeDef NVIC_InitStructure = {0};
    can_cfg_t* pparam = &can_cfg[can_dev];
    __can_enable(can_dev,CAN_BUS_DISABLE);
    CAN_ITConfig(pparam->can_ch, pparam->it_flag, DISABLE);
    NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;
    NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; 
    NVIC_Init(&NVIC_InitStructure);
    CAN_DeInit(pparam->can_ch);
}

int p_can_read(int can_dev, can_msg_t* msg)
{
    can_cfg_t* pparam = &can_cfg[can_dev];
    CanRxMsg RxMessage;

    /* 判别是哪个接收邮箱有数据挂起 */
    if (CAN_MessagePending(pparam->can_ch, CAN_FIFO0)) {
        CAN_Receive(pparam->can_ch, CAN_FIFO0, &RxMessage);
    } else if (CAN_MessagePending(pparam->can_ch, CAN_FIFO1)) {
        CAN_Receive(pparam->can_ch, CAN_FIFO1, &RxMessage);
    } else {
        _error("read error can msg");
        return 0;
    }

    if(CAN_Id_Standard == RxMessage.IDE){
        msg->id_type = CAN_ID_ST;
        msg->id = RxMessage.StdId;
        _debug(SYS_INFO, "CAN%d FIFO0 receive msg Std_id = 0x%x ...\n", pparam->can_dev_id + 1, RxMessage.StdId);
    }else{
        msg->id_type = CAN_ID_EX;
        msg->id = RxMessage.ExtId;
        _debug(SYS_INFO, "CAN%d FIFO1 receive msg EXT_id = 0x%x ...\n", pparam->can_dev_id + 1, RxMessage.ExtId);
    }

    if(CAN_RTR_Data == RxMessage.RTR){
        msg->id_frame = CAN_FR_DATA;
    }else{
        msg->id_frame = CAN_FR_REMOTE;
    }
    msg->len = RxMessage.DLC;
    memcpy(msg->data,RxMessage.Data, RxMessage.DLC);
    return RxMessage.DLC;
}

int p_can_send(int can_dev, can_msg_t* msg)
{
    can_cfg_t* pparam = &can_cfg[can_dev];
    CanTxMsg TxMsg = {0};
    if(msg->id_type == CAN_ID_ST){
        TxMsg.IDE = CAN_Id_Standard;
        TxMsg.StdId = msg->id;
    }else{
        TxMsg.IDE = CAN_Id_Extended;
        TxMsg.ExtId = msg->id;
    }
    if(msg->id_frame == CAN_FR_DATA){
       TxMsg.RTR =  CAN_RTR_Data;
    }else{
       TxMsg.RTR =  CAN_RTR_Remote; 
    }
    TxMsg.DLC = msg->len;

    memcpy(TxMsg.Data,msg->data,TxMsg.DLC);

    pparam->txs.mbox_s = CAN_TxStatus_NoMailBox;
    uint8_t tx_mbox = CAN_Transmit(pparam->can_ch, &TxMsg);
    if (tx_mbox == CAN_TxStatus_NoMailBox) {
        _debug(SYS_INFO, "CAN Transmit Status is No MailBox\n");
        return -1;
    }
    pparam->txs.mbox_s = tx_mbox;
    return 0;
}

int p_can_send_ok(int can_dev)
{
    can_cfg_t* pparam = &can_cfg[can_dev];
    if(pparam->txs.mbox_s == CAN_TxStatus_NoMailBox){
        return -1;
    }

    if(CAN_TransmitStatus(pparam->can_ch, pparam->txs.mbox_s) == CAN_TxStatus_Failed){
        return 0;
    }

    return 1;
}

#define CAN_ID_STD_STD	CAN_ID_ST
#define CAN_ID_EXT_EXT	CAN_ID_EX
#define CAN_ID_STD_EXT	2
#define CAN_ID_EXT_STD	3


static int __genc_ids(int format,uint32_t *ids,uint32_t *pout)
{
    switch (format) {
    case CAN_ID_STD_STD:
        pout[0] = (ids[0] << 21) | CAN_Id_Standard;
        pout[1] = (ids[1] << 21) | CAN_Id_Standard;
        break;
    case CAN_ID_STD_EXT:
        pout[0] = (ids[0]  << 21) | CAN_Id_Standard;
        pout[1] = (ids[1] << 3) | CAN_Id_Extended;
        break;
    case CAN_ID_EXT_STD:
        pout[0] = (ids[0]  << 3) | CAN_Id_Extended;
        pout[1] = (ids[1] << 21) | CAN_Id_Standard;
        break;
    case CAN_ID_EXT_EXT:
        pout[0] = (ids[0]  << 3) | CAN_Id_Extended;
        pout[1] = (ids[1] << 3) | CAN_Id_Extended;
        break;
    default: {
        return -1;
        } 
    }
    return 0;
}
static int __p_can_set_filter_list(int filter_id, int fifo_no, int format, uint32_t id1, uint32_t id2)
{
    CAN_FilterInitTypeDef CAN_FilterInitStructure = { 0 };
    uint32_t in_ids[2] = {id1,id2};
    uint32_t out_ids[2] = {0};

    if(__genc_ids(format,in_ids,out_ids)){
        _debug(SYS_INFO, "CAN geting id is failed \n");
        return -1;
    }
    _debug(SYS_INFO, "filter_Id = 0x%x 0x%x, filter_number = %d, CAN_Filter_FIFO = %d\n",\
                         out_ids[0], out_ids[1], filter_id, fifo_no);
    CAN_FilterInitStructure.CAN_FilterNumber = filter_id;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = (out_ids[0] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterIdLow = out_ids[0] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (out_ids[1] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = out_ids[1] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = fifo_no;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
    return 0;
}

static int __p_can_set_filter_mask(int filter_id, int fifo_no, int format, uint32_t id, uint32_t mask)
{
    CAN_FilterInitTypeDef CAN_FilterInitStructure = { 0 };
    uint32_t in_ids[2] = {id,mask};
    uint32_t out_ids[2] = {0};

    if(__genc_ids(format,in_ids,out_ids)){
        _debug(SYS_INFO, "CAN geting id is successed ...\n");
        return -1;
    }
    _debug(SYS_INFO, "------ filter_Id = 0x%x 0x%x, filter_number = %d, CAN_Filter_FIFO = %d ----------\n",\
                         out_ids[0], out_ids[1], filter_id, fifo_no);
    CAN_FilterInitStructure.CAN_FilterNumber = filter_id;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = (out_ids[0] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterIdLow = out_ids[0] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (out_ids[1] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = out_ids[1] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = fifo_no; // CAN_Filter_FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
    return 0;
}

/*
@filter_mode FILTER_LIST  FILTER_MASK
@format  CAN_ID_ST CAN_ID_EX
*/
int p_can_set_filter(int can_dev, int filter_mode, int format, uint32_t* ids, int id_cnt)
{
    int i;
    can_cfg_t* pparam = &can_cfg[can_dev];
    uint32_t r_ids[28] = {0};
    CAN_SlaveStartBank(CAN2_FILTER_S);
    
    if (id_cnt & 1) { //奇数
        for(i = 0; i < id_cnt; i++){
            r_ids[i] = ids[i];
        }
        if(filter_mode == FILTER_LIST){
            r_ids[i] = r_ids[i-1];
        }else{
            r_ids[i] = 0xffffffff;
        }
        id_cnt++;
    }else{
        for(i = 0; i < id_cnt; i++){
            r_ids[i] = ids[i];
        }
    }

    if (filter_mode == FILTER_LIST) {
        for (i = 0; i < id_cnt / 2; i++) {
            __p_can_set_filter_list(pparam->filter_start + i, pparam->fifo_no, format, r_ids[2*i], r_ids[2*i + 1]);
        }
    } else {
        for (i = 0; i < id_cnt / 2; i++) {
            __p_can_set_filter_mask(pparam->filter_start + i, pparam->fifo_no, format, r_ids[2*i], r_ids[2*i + 1]);
        }
    }

    return 0;
}

(2)can.h

#ifndef __p_can_h__
#define __p_can_h__
#if 0
  .word CAN2_TX_IRQHandler
  .word CAN2_RX0_IRQHandler
  .word CAN2_RX1_IRQHandler
  .word CAN2_SCE_IRQHandler
#define CAN_Id_Standard ((uint32_t)0x00000000) /*!< Standard Id */
#define CAN_Id_Extended ((uint32_t)0x00000004) /*!< Extended Id */
#endif

typedef enum {
    CAN_DEV1,
    CAN_DEV2,
    CAN_DEV_CNT
} CAN_DEV_E;


#define CAN_ID_ST 0 //标准帧
#define CAN_ID_EX 1 //扩展帧

#define CAN_FR_DATA 0
#define CAN_FR_REMOTE 1

#define FILTER_LIST 0
#define FILTER_MASK 1

typedef struct _can_msg_t {
    uint8_t id_type; //0:标准帧 1:扩展帧
    uint8_t id_frame; //0:数据帧 1:远程帧
    uint8_t len;
    uint8_t res;
    uint32_t id;
    uint8_t data[8];
} can_msg_t;

int can_dev_init(int can_dev, int can_mode, int brp);
int p_can_open(int can_dev,int bps);
void p_can_close(int can_dev);
int p_can_read(int can_dev,can_msg_t *msg);
int p_can_send(int can_dev,can_msg_t *msg);
/*
@filter_mode FILTER_LIST  FILTER_MASK
@format  CAN_ID_ST CAN_ID_EX
*/
int p_can_set_filter(int can_dev, int filter_mode, int format, uint32_t* ids, int id_cnt);

void p_can_task_start(int can_dev);
void p_can_task_stop(int can_dev);
void p_can_task(void);
#endif


你可能感兴趣的:((二)CAN通信协议代码-升级版)