STM32Fxxx CAN通信代码

  • (1)CAN初始化函数
  • (2)CAN过滤器函数
  • (3)CAN 发送/接收函数
  • 头文件

(1)CAN初始化函数


/* -------------------------- Filter global --------------------------*/
#define STDID 0
#define EXTID 1/* 过滤器编号 */
static u8 filterNumber = 0;/* 内部函数声明 */
void myCanFilterList(u8 can_dev, uint32_t* p_canId, int size, int flag);
u8 myCanFilterMask(u8 can_dev, uint32_t* p_canIdMask, int size, int flag);
u8 canIdSeparation(u8 can_dev, uint32_t* p_canId, int size, u8 filterMode);
u8 myFilter(u8 can_dev, u32* p_canId, u8 filterMode, u8 filterScale);/* --- CANx 设备属性设置 --- */
typedef struct __can_port_t {u32 can_dev;gpio_pin_t tpin;gpio_pin_t rpin;u32 pin_map;u32 can_rcc;CAN_TypeDef* can_channel;u8 irq;u8 pre_priority;u8 sub_priority;u8 can_res;u32 IT_flag;
} can_port_t;static can_port_t can_port[CAN_DEV_CNT] = {[CAN_DEV1] = {.can_dev = CAN_DEV1,.tpin = { GPIO_Pin_12, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_TX PA12.rpin = { GPIO_Pin_11, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_RX PA11.pin_map = 0,.can_rcc = RCC_APB1Periph_CAN1,.can_channel = CAN1,.irq = CAN1_RX0_IRQn,.pre_priority = 0,.sub_priority = 0,.IT_flag = CAN_IT_FMP0,},[CAN_DEV2] = {.can_dev = CAN_DEV2,.tpin = { GPIO_Pin_13, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_TX PB13.rpin = { GPIO_Pin_12, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_RX PB12.pin_map = 0,.can_rcc = RCC_APB1Periph_CAN2,.can_channel = CAN2,.irq = CAN1_RX1_IRQn,.pre_priority = 0,.sub_priority = 0,.IT_flag = CAN_IT_FMP1,}
};/*--- 常用CAN波特率 ---*/
typedef struct __can_tq_t {u16 can_baudrate;u16 can_prescaler;u8 can_syn_jump_width;u8 can_time_bit_seg1;u8 can_time_bit_seg2;u8 can_res;
}can_tq_t;typedef enum __can_baud_t{CAN_BAUD_5KHZ,CAN_BAUD_10KHZ,CAN_BAUD_20KHZ,CAN_BAUD_40KHZ,CAN_BAUD_50KHZ,CAN_BAUD_80KHZ,CAN_BAUD_100KHZ,CAN_BAUD_125KHZ,CAN_BAUD_200KHZ,CAN_BAUD_250KHZ,CAN_BAUD_400KHZ,CAN_BAUD_500KHZ,CAN_BAUD_666KHZ,CAN_BAUD_800KHZ,CAN_BAUD_1000KHZ,CAN_BAUD_NUM
}can_baud_t;/*CAN 波特率,预分频值,SJW,BS1,BS2 */
static can_tq_t can_baud_array[CAN_BAUD_NUM] = {[CAN_BAUD_5KHZ]    =  {5,    400, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_10KHZ]   =  {10,   200, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_20KHZ]   =  {20,   100, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_40KHZ]   =  {40,   50,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_50KHZ]   =  {50,   40,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_80KHZ]   =  {80,   25,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_100KHZ]  =  {100,  20,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_125KHZ]  =  {125,  16,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_200KHZ]  =  {200,  10,  CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_250KHZ]  =  {250,  36,  CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq},[CAN_BAUD_400KHZ]  =  {400,  5,   CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_500KHZ]  =  {500,  4,   CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_666KHZ]  =  {666,  3,   CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq},[CAN_BAUD_800KHZ]  =  {800,  11,  CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq},[CAN_BAUD_1000KHZ] =  {1000, 9,   CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq}
};/*--- 设置CAN波特率 ---*/
int canBaudSet(u32 BaudRate)
{   can_tq_t* pcanbaud = can_baud_array;u8 c_i;u8 canBaudNum;for (c_i = 0; c_i < CAN_BAUD_NUM; c_i++) {if(pcanbaud->can_baudrate == BaudRate) {canBaudNum = c_i;break;}pcanbaud++;}if (c_i >= CAN_BAUD_NUM) {_debug(SYS_INFO, "Setting BaudRate param is unqualified \n");return -1;}return canBaudNum;
}/** ------------------------ CAN 初始化 ------------------------- ** @brief  CAN初始化、配置GPIO为复用功能、CAN过滤器Filter初始化* @param  can_dev can设备号*         can_mode 工作模式,正常/环回/静默*         BaudRate 波特率,注意单位:KHZ* @retval 成功 0*         失败 1* ------------------------------------------------------------ */
u8 can_dev_init(u8 can_dev, u8 can_mode, u32 BaudRate)
{GPIO_InitTypeDef GPIO_InitStructure;CAN_InitTypeDef CAN_InitStructure;can_port_t* pparam = &can_port[can_dev];_debug(SYS_INFO, "CAN%d Init start ...\n", pparam->can_dev + 1);/* 使能GPIO、CANx外设复用功能时钟使能 */RCC_APB1PeriphClockCmd(pparam->can_rcc, ENABLE);RCC_APB2PeriphClockCmd(pparam->rpin.gpio_rcc | pparam->tpin.gpio_rcc, ENABLE);if (pparam->pin_map != 0) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);}/* GPIO 复用功能初始化:Rx */GPIO_InitStructure.GPIO_Pin = pparam->rpin.pin_bit;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入GPIO_Init(pparam->rpin.gpio_port, &GPIO_InitStructure);/* GPIO 复用功能初始化:Tx */GPIO_InitStructure.GPIO_Pin = pparam->tpin.pin_bit;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出GPIO_Init(pparam->tpin.gpio_port, &GPIO_InitStructure);/* CAN 初始化 */u8 ret_can;u8 canBaudNo;can_tq_t* pcanbaud = NULL;canBaudNo = canBaudSet(BaudRate);if (canBaudNo == -1) {_debug(SYS_INFO, "Setting BaudRate param is unqualified \n");return 1;}pcanbaud = &can_baud_array[canBaudNo];CAN_InitStructure.CAN_Prescaler = pcanbaud->can_prescaler;CAN_InitStructure.CAN_SJW = pcanbaud->can_syn_jump_width;CAN_InitStructure.CAN_BS1 = pcanbaud->can_time_bit_seg1;CAN_InitStructure.CAN_BS2 = pcanbaud->can_time_bit_seg2;_debug(SYS_INFO, "BaudRate = %dKHZ, can_prescaler = %d, CAN_SJW_%dtq, CAN_BS1_%dtq, CAN_BS2_%dtq \n",pcanbaud->can_baudrate, pcanbaud->can_prescaler, pcanbaud->can_syn_jump_width + 1, pcanbaud->can_time_bit_seg1 + 1, pcanbaud->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_channel, &CAN_InitStructure);if (ret_can == 0) {_debug(SYS_EMERG, "CAN%d Initialize is fail ...\n", pparam->can_dev + 1);return 1; }#if 0/* CAN接收中断参数配置 */NVIC_InitTypeDef NVIC_InitStructure;CAN_ITConfig(pparam->can_channel, pparam->IT_flag, ENABLE);                    // FIFO消息挂号中断允许NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;                              // 设置IRQ通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = pparam->pre_priority;   // 设置抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = pparam->sub_priority;          // 设置响应优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                // 使能IRQ通道NVIC_Init(&NVIC_InitStructure);                                                // 初始化CAN中断配置
#endif_debug(SYS_INFO, "CAN%d Init end ...\n", pparam->can_dev + 1);return 0;
}/*--------------------------- CANx 去初始化 ---------------------------*/
void can_uninit(u8 can_dev)
{can_port_t* pparam = &can_port[can_dev];clearFilter(can_dev);                              // 所有过滤器的id都失效CAN_DeInit(pparam->can_channel);                   // 复位默认值RCC_APB1PeriphClockCmd(pparam->can_rcc, DISABLE);  // 禁止(关闭)CAN_RCC时钟
}void CAN1_RX0_IRQHandler(void)
{CAN_Receive_Msg(CAN_DEV1);_debug(SYS_INFO, "CAN1 RX0_IRQHandler...\n");
}void CAN2_RX0_IRQHandler(void)
{CAN_Receive_Msg(CAN_DEV2);_debug(SYS_INFO, "CAN2 RX0_IRQHandler...\n");
}

(2)CAN过滤器函数


/*------------------------- 列表模式配置can_id ------------------------*/
/*** @brief CAN过滤器 标识符列表模式添加can_id* @param can_dev       *        p_canList    指向32位地址的指针;*                     最高位设置为0表示stdid,11位标准id(0x00 ~ 0x7FF) eg: id = 0x12*                     最高位设置为1表示extid,29位扩展id(0x00 ~ 0x1FFF FFFF) eg: id = 0x80000001*        size         过滤器的id总数* @retval 成功 0*         失败 1*/
u8 myCAN_Filter_List(u8 can_dev, uint32_t* p_canList, int size)
{can_port_t* pparam = &can_port[can_dev];if ((pparam->can_channel != CAN1) && (pparam->can_channel != CAN2)) {_debug(SYS_EMERG, "Can channel is error!\n");return 1;}canIdSeparation(can_dev, p_canList, size, CAN_FilterMode_IdList);return 0;
}/*** @brief CAN过滤器 列表模式(默认canId = 0为通用id地址,即id = 0,默认可以通过过滤器)* @param can_dev  *        p_canId  指向id数组*        size     id的个数*        flag     过滤器标识符id格式:0-标准id,1-扩展id* @retval None*/
void myCanFilterList(u8 can_dev, uint32_t* p_canId, int size, int flag)
{u8 i = 0;u8 position; // 保存整数(取整 /)u8 remain;   // 保存余数(取余 %)u16 filterIdLow;u16 filterIdHigh;u16 filterMaskIdLow;u16 filterMaskIdHigh;u32 canId[2] = { 0 }; // 用于保存can过滤器组的2个32位寄存器:filterid和maskidswitch (flag) { // 标准id,列表模式:按16位宽填充filterId和maskId,最多一次填充4个stdIdcase 0: { position = size / 4;remain = size % 4;for (i = 0; i < position; i++) { // 左移5位原因: 低5位id映射是 RTR IDE EXID[17:15]filterIdLow = *p_canId << 5; p_canId++;filterIdHigh = *p_canId << 5;p_canId++;filterMaskIdLow = *p_canId << 5;p_canId++;filterMaskIdHigh = *p_canId << 5;p_canId++;canId[0] = (filterIdHigh << 16) | filterIdLow; // 默认ide = 0,rtr = 0:标准id,数据帧canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow;myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_16bit);}if (remain > 0) {filterIdLow = *p_canId << 5; // 在(4 - remain)的剩余区间为无id值,此时默认设置:can_id = 0p_canId++;filterIdHigh = *p_canId << 5;p_canId++;filterMaskIdLow = *p_canId << 5;p_canId++;filterMaskIdHigh = *p_canId << 5;p_canId++; // 不可省略canId[0] = (filterIdHigh << 16) | filterIdLow;canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow;myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_16bit);}break;}// 扩展id,列表模式:按32位宽填充filterId和maskId,最多一次填充2个extIdcase 1: { position = size / 2;remain = size % 2;for (i = 0; i < position; i++) {filterIdLow = *p_canId << 3;filterIdHigh = (*p_canId << 3) >> 16;p_canId++;filterMaskIdLow = *p_canId << 3;filterMaskIdHigh = (*p_canId << 3) >> 16;p_canId++;canId[0] = (filterIdHigh << 16) | filterIdLow | (1 << 2); // 设置ide = 1,rtr = 0:扩展id,数据帧canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow | (1 << 2);myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_32bit);}if (remain > 0) {filterIdLow = *p_canId << 3;          // 在(2 - remain)的剩余区间为无id值,此时默认设置:can_id = 0filterIdHigh = (*p_canId << 3) >> 16;filterMaskIdLow = filterIdLow;        // 将剩下的一个32位寄存器,填充和上一个寄存器相同的id filterMaskIdHigh = filterIdHigh;canId[0] = (filterIdHigh << 16) | filterIdLow | (1 << 2);canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow | (1 << 2);myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_32bit);}break;}}
}/*----------------------------- 掩码模式配置can_id --------------------------------*/
/*** @brief CAN过滤器 标识符掩码模式 * @param can_dev*        p_canList 指向32位地址的指针;最高位设置为0表示stdid,11位标准id(0x00 ~ 0x7FF)*                  最高位设置为1表示extid,29位扩展id(0x00 ~ 0x1FFF FFFF)*        size      过滤器的id总数* @retval 成功 0*         失败 1*/
u8 myCAN_Filter_Mask(u8 can_dev, uint32_t* p_canIdMask, int size)
{can_port_t* pparam = &can_port[can_dev];if ((pparam->can_channel != CAN1) && (pparam->can_channel != CAN2)) {_debug(SYS_INFO, "Can channel is error!\n");return 1;}canIdSeparation(can_dev, p_canIdMask, size, CAN_FilterMode_IdMask);return 0;
}/*** @brief CAN过滤器 掩码模式* @param can_dev  *        p_canId  指定的id组*        size     id的个数*        flag     过滤器标识符id格式:0-标准id,1-扩展id* @retval 成功 0*         失败 1*/
u8 myCanFilterMask(u8 can_dev, uint32_t* p_canIdMask, int size, int flag)
{u8 i = 0;u8 position = 0;u32 canId[2] = { 0 };if (size % 2) { // 确保掩码id:filterId和maskId成对出现_debug(SYS_INFO, "the number of Mask_canId is not pow(2) \n");return 1;}switch (flag) {// 标准id掩码模式,按32位宽处理case 0: {position = size / 2;for (i = 0; i < position; i++) {canId[0] = *p_canIdMask << 21; // 默认ide = 0,rtr = 0; 标准id,数据帧p_canIdMask++;canId[1] = *p_canIdMask << 21;p_canIdMask++;printf("can_id[0] = 0x%x, can_id[1] = 0x%x\n", canId[0], canId[1]);myFilter(can_dev, canId, CAN_FilterMode_IdMask, CAN_FilterScale_32bit);}break;}// 扩展id掩码模式,按32位宽处理case 1: {position = size / 2;for (i = 0; i < position; i++) {canId[0] = (*p_canIdMask << 3) | (1 << 2); // 设置ide = 1,rtr = 0; 扩展id,数据帧p_canIdMask++;canId[1] = (*p_canIdMask << 3) | (1 << 2);p_canIdMask++;myFilter(can_dev, canId, CAN_FilterMode_IdMask, CAN_FilterScale_32bit);}break;}}return 0;
}/*----------------------- canIdSeparation 分离 ---------------------------*/
/*** @brief 将canId数组分离出标准id(11bits)和扩展id(29bits)* @param can_dev  *        p_canId  指向can_id数组*        size     id的个数*        filterMode 过滤器模式* @retval 成功 0*         失败 1*/
u8 canIdSeparation(u8 can_dev, uint32_t* p_canId, int size, u8 filterMode)
{u8 i;u32 canId;u32 stdIdBuff[56] = { 0 }; // canId为标准id:按16位宽处理节约资源(56 = 14组过滤器 * 4个stdid)u32 extIdBuff[28] = { 0 }; // canId为扩展id:按32位宽处理(28 = 14 * 2个extid)u8 std_i = 0;              // 记录id的个数u8 ext_i = 0;/* 把标准id和扩展id分离出来后放入:stdIdBuff、extIdBuff*/for (i = 0; i < size; i++) {canId = *p_canId;_debug(SYS_INFO, "canId = 0x%x\n", canId);/* 整个id的值超过取值范围:canId & 0x7FFFFFFF:不考虑最高位,只考虑后31位; & (~ 0x1FFFFFFF):不考虑低29位,如果(30:31)位有数据,则超过取值 */if ((canId & 0x7FFFFFFF) & (~ 0x1FFFFFFF)) { _debug(SYS_INFO, "CAN id is unqualified, beyond scale \n");return 1;}/* 标准id最高位为0时,stdid取值范围超过0x7FF */if (((canId >> 31) == 0) && (canId & (~ 0x7FF))) {_debug(SYS_INFO, "CAN stdid is unqualified, beyond scale \n");return 1;}/* 将标准id和扩展id各自分离出来:移除低31位,只保留最高位:标识位 */if (canId >> 31) { // 1 = 扩展帧extIdBuff[ext_i] = canId & 0x7FFFFFFF; // 除去最高位(标识位),以获得扩展帧ext_i++;} else { stdIdBuff[std_i] = canId;std_i++;}p_canId++; // canid地址自动加1}for (i = 0; i < std_i; i++) {_debug(SYS_INFO, "stdIdBuff[%d] = 0x%x, std_i = %d\n", i, stdIdBuff[i], std_i);}printf("---------------------------------\n");for (i = 0; i < ext_i; i++) {_debug(SYS_INFO, "extIdBuff[%d] = 0x%x, ext_i = %d\n", i, extIdBuff[i], ext_i);}_debug(SYS_INFO, "---------------------------------\n");/* 清除can通道的所有过滤器中的id */clearFilter(can_dev);/* 设置can_id  0:标准Id; 1:扩展Id */if (filterMode == CAN_FilterMode_IdList) { myCanFilterList(can_dev, stdIdBuff, std_i, STDID);  myCanFilterList(can_dev, extIdBuff, ext_i, EXTID);} else {myCanFilterMask(can_dev, stdIdBuff, std_i, STDID);myCanFilterMask(can_dev, extIdBuff, ext_i, EXTID);}return 0;
}/**--------------------------- myFilter CAN过滤器配置 ---------------------*/
/* @brief CAN过滤器,寄存器配置 * @param can_dev *        p_canId  指定的id组*        size     id的个数*        filterMode   过滤的模式:列表/掩码*        filterScale  过滤器位宽* @retval 成功:0*         失败:1*/
u8 myFilter(u8 can_dev, u32* p_canId, u8 filterMode, u8 filterScale)
{CAN_FilterInitTypeDef CAN_FilterInitStructure;can_port_t* pparam = &can_port[can_dev];u32 can_id[2] = {p_canId[0], p_canId[1]};// printf("canId[0] = 0x%x, canId[1] = 0x%x, filternum = %d\n", can_id[0], can_id[1], filterNumber);// printf("p_canId[0] = 0x%x, p_canId[1] = 0x%x, filternum = %d\n", p_canId[0], p_canId[1], filterNumber);/* 防止can通道分配的过滤器编号超过编号取值范围:CAN1:0 ~ 13; CAN2:14 ~ 27 */if (pparam->can_channel == CAN1) {if(filterNumber > 13) {_debug(SYS_INFO, "the distribution of Can Filter Number go beyond rank: CAN1 > 13\n");return 1;}} else { CAN_SlaveStartBank(14); // 开启CAN2通道if(filterNumber > 27) {_debug(SYS_INFO, "the distribution of Can Filter Number go beyond rank:  CAN2 > 27\n");return 1;}}/* 一组过滤器的2个32位寄存器拆分成四个16位的基础寄存器 */CAN_FilterInitStructure.CAN_FilterIdLow = *p_canId;CAN_FilterInitStructure.CAN_FilterIdHigh = *p_canId >> 16;_debug(SYS_INFO, "CAN_FilterId = 0x%x\n", *p_canId);  p_canId++;CAN_FilterInitStructure.CAN_FilterMaskIdLow = *p_canId;CAN_FilterInitStructure.CAN_FilterMaskIdHigh = *p_canId >> 16;_debug(SYS_INFO, "CAN_FilterMaskId = 0x%x\n", *p_canId); _debug(SYS_INFO, "filterNumber = %d\n", filterNumber);if (pparam->can_channel == CAN1) { CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; } else { CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1; }CAN_FilterInitStructure.CAN_FilterNumber = filterNumber; // CAN1:0 ~ 13; CAN2:14 ~ 27filterNumber++;CAN_FilterInitStructure.CAN_FilterScale = filterScale;CAN_FilterInitStructure.CAN_FilterMode = filterMode; CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;CAN_FilterInit(&CAN_FilterInitStructure);return 0;
}/*------------------------ 清除CANx通道 过滤器 --------------------------*/
/* 清除can通道的所有过滤器中的id * 思路:将所有过滤器组全部以掩码模式(扩展id)填充:filterid和maskid对应位全置1,不过滤任何id*/
void clearFilter(u8 can_dev)
{   can_port_t* pparam = &can_port[can_dev];u8 i = 0;u32 maskId = 0xFFFFFFF8 | (0x1 << 2);u32 canIdClear[2] = {0};canIdClear[0] = maskId;canIdClear[1] = maskId;if(pparam->can_channel == CAN1) {filterNumber = 0;} else {filterNumber = 14;}// 以掩码模式,扩展id填充过滤器for(i = 0; i < 14; i++) {myFilter(can_dev, canIdClear, CAN_FilterMode_IdMask, CAN_FilterScale_32bit);}// 恢复过滤器的默认起始编码号if (pparam->can_channel == CAN1) {filterNumber = 0;} else {filterNumber = 14;}
}

(3)CAN 发送/接收函数

/* ------------------------ CANx 发送msg --------------------------------
* @功能:CANx 发送一组数据(固定can_id = 0x12, 标准帧, 数据帧)
* @参数:len:数据长度(最大为 8)msg:数据指针,数据最大为 8 个字节.
* @返回值:0, 成功;其他,失败;
* -------------------------------------------------------------------- */
u8 CAN_Transmit_Msg(u8 can_dev, u8* msg, u8 len)
{u16 i;u8 tx_mbox;CanTxMsg TxMessage;can_port_t* pparam = &can_port[can_dev];TxMessage.StdId = 0x12;TxMessage.ExtId = 0x12;TxMessage.IDE = CAN_Id_Standard;TxMessage.RTR = CAN_RTR_Data; TxMessage.DLC = len;for (i = 0; i < len; i++) {TxMessage.Data[i] = msg[i];}_debug(SYS_INFO, "can%d translate = %s\n", pparam->can_dev + 1, msg);tx_mbox = CAN_Transmit(pparam->can_channel, &TxMessage);if (tx_mbox == CAN_TxStatus_NoMailBox) {_debug(SYS_INFO, "CAN%d Transmit Status is No MailBox ...\n", pparam->can_dev + 1);return 1;}/* 等待CAN发送一段时间;如果超时,则失败 */i = 0;while ((CAN_TransmitStatus(pparam->can_channel, tx_mbox) == CAN_TxStatus_Failed) && (i < 0xFFF)) {i++;}if (i >= 0xFFF) {_debug(SYS_INFO, "CAN%d Transmit fail, time out ...\n", pparam->can_dev + 1);return 1;}return 0;
}/** ------------------------ CANx 接收msg ------------------------------* @brief CANx 接收一组数据(固定格式:ID = 0X12, 标准帧, 数据帧)* @param can_dev CAN设备号*        msg:数据指针,数据最大为 8 个字节* @retval 0:无数据被收到*      其他:成功接收的数据长度* ------------------------------------------------------------------ */
u8 CAN_Receive_Msg(u8 can_dev, u8 * msg)
{u32 i;CanRxMsg RxMessage;can_port_t* pparam = &can_port[can_dev];/* 判别是哪个接收邮箱有数据挂起 */if (CAN_MessagePending(pparam->can_channel, CAN_FIFO0)) {CAN_Receive(pparam->can_channel, CAN_FIFO0, &RxMessage);for (i = 0; i < RxMessage.DLC; i++) {msg[i] = RxMessage.Data[i];printf("CAN1 msg[%d]\n", i, msg[i]);}return RxMessage.DLC;} else if (CAN_MessagePending(pparam->can_channel, CAN_FIFO1)) {CAN_Receive(pparam->can_channel, CAN_FIFO1, &RxMessage);for (i = 0; i < RxMessage.DLC; i++) {msg[i] = RxMessage.Data[i];printf("CAN2 msg[%d]\n", i, msg[i]);}_debug(SYS_INFO, "can receive msg CAN_id = 0x%x ...\n", RxMessage.StdId);return RxMessage.DLC;}/* 没有接收到数据,直接退出 */return 0;
}

头文件

#ifndef __P_CAN_H__
#define __P_CAN_H__/*------------- type define -----------------*/
// can_dev 参数取值范围
typedef enum {CAN_DEV1,CAN_DEV2,CAN_DEV_CNT
} CAN_DEV_E;/*------------- Function --------------------*/
// BaudRate 单位为HKZ
u8 can_dev_init(u8 can_dev, u8 can_mode, u32 BaudRate);
void can_uninit(u8 can_dev);// 过滤器函数
u8 myCAN_Filter_List(u8 can_dev, uint32_t* p_canList, int size);
u8 myCAN_Filter_Mask(u8 can_dev, uint32_t* p_canIdMask, int size);
void clearFilter(u8 can_dev);// can发送msg,固定can_id = 0x12, 标准帧, 数据帧
u8 CAN_Transmit_Msg(u8 can_dev, u8* msg, u8 len);
u8 CAN_Receive_Msg(u8 can_dev, u8 * msg);
#endif

(二)CAN通信协议代码-基础版相关推荐

  1. 致远OA二开整理(基础版,本地环境搭建,插件project设置,页面引入外部js文档)

    最近在看致远OA开发相关,顺便整理了分文档(基础的). 关注下方公众号 回复"致远OA"免费获取.

  2. 用python语言实现反恐精英基础版-案例

    """ 写了大概有1个多小时吧,中途多多少少都出现了一些bug,最终还是码出来,Talk is cheap, show me code!(屁话少说,放码过来) PS:Ma ...

  3. 接入百度智能云的营业执照识别接口、工商信息查询(基础版)接口到实际业务,参考代码

    我的代码放在公共模块如下: 1.根据百度云官方文档-SDK中心,下载sdk对应jar包,我下载下来的版本是bce-java-sdk.0.10.254 2.使用mvn命令手动引入jar mvn inst ...

  4. 【移动端网页布局】移动端网页布局基础概念 ⑤ ( 视网膜屏技术 | 二倍图概念 | 代码示例 )

    文章目录 一.视网膜屏技术 二.二倍图概念 三.代码示例 一.视网膜屏技术 PC 端 和 早期的 移动端 网页中 , CSS 中配置的 1 像素 对应的就是物理屏幕中的 1 像素 ; Retina 视 ...

  5. spring boot构建基础版web项目(一)springboot、thymeleaf控制层基础构

    原文作者:弥诺R 原文地址:http://www.minuor.com/147852147/article 转载声明:转载请注明原文地址,注意版权维护,谢谢! 写前说明 根据个人在各篇博文中看到的信息 ...

  6. 小米路由器青春版装linux,比较费心的折腾 篇二:小米路由器青春版折腾负载均衡...

    比较费心的折腾 篇二:小米路由器青春版折腾负载均衡 2020-06-04 11:00:23 3点赞 10收藏 8评论 创作立场声明:本文的核心目的是对于比较久远的硬件进行折腾,提及的软件可以在官网.软 ...

  7. AnalyticDB for MySQL 3.0基础版重磅发布

    随着大数据技术的迅速发展以及对数据价值的认识逐渐加深,大数据已经融合到各行各业.据可靠权威数据显示,超过39.6%的企业正在应用数据并从中获益,超过89.6%的企业已经成立或计划成立相关的大数据分析部 ...

  8. 超详细的Java面试题总结(二)之Java基础知识篇

    系列文章: 超详细的Java面试题总结(一)之Java基本知识 超详细的Java面试题总结(二)之Java基础知识篇 超详细的Java面试题总结(三)之Java集合篇常见问题 超详细的Java面试题总 ...

  9. 【基础版】大学计算机-计算思维导论

    超星尔雅[基础版]大学计算机-计算思维导论章节测验答案,下面就是按照章节顺序的题目 计算机.计算与计算思维 1[单选题]人类应具备的三大思维能力是指_____.答案:实验思维.理论思维和计算思维 A. ...

最新文章

  1. 中体骏彩C++面试题
  2. Oracle 中文排序
  3. VSTS For Testers读书笔记(5)
  4. 超越 YOLOv5 的目标检测开源项目又上新了
  5. 线上一个数组查询遇到的坑
  6. 今天参加广州.NET俱乐部活动,运气超好
  7. 想要转人工智能,程序员该如何学习?
  8. c盘满了一键检测,清理,瘦身!
  9. 统计推断——假设检验——t 检验(总体的标准差未知)
  10. oa服务器硬件配置,OA办公系统
  11. 什么是索引?索引的作用是什么?Mysql目前主要的几种索引类型
  12. 产品思维训练 | 你的项目总是不能按期上线,你会如何解决?
  13. 2019NEFU寒假集训新生考试 2020.1.6
  14. SD卡插入手机容量变小,U盘低级格式化HA-LLFTOOL
  15. php 搜索关键字,PHP获取搜索关键字有关问题_PHP教程
  16. 2022-02-13 机器学习基本概念
  17. 基于Joplin和WebDAV搭建私有云笔记
  18. Java同步技术 (一)
  19. 关于迅盘Turbo Memory的ReadyDrive功能被禁用的思考
  20. MFC 加载jpg等图片

热门文章

  1. 用一个视频尽可能标准化测试你的电视 — MDT TV TEST V0.9 (2020.6 更新)
  2. C++单例模式与线程安全
  3. win ce车载系统刷机包_Android 11 喜讯!小米 10 率先尝鲜,官方刷机包发布下载
  4. 制作马赛克拼图的工具:TurboMosaic Mac版
  5. Linus 命名 [冰封荒原] 版 Linux 内核的思考
  6. 如何查看删了的通话记录
  7. 即时通讯开发之WebRTC服务器是如何联接通话的
  8. 项目管理:硬件类项目完整开发流程
  9. 将虚拟机的Ubuntu映射为windows的网络驱动器
  10. 再见了 Docker!K8S 已成气候!