(1)CAN初始化函数
#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);
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 },
.rpin = { GPIO_Pin_11, RCC_APB2Periph_GPIOA, GPIOA },
.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 },
.rpin = { GPIO_Pin_12, RCC_APB2Periph_GPIOB, GPIOB },
.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,
}
};
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;
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}
};
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;
}
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);
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_InitStructure.GPIO_Pin = pparam->rpin.pin_bit;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(pparam->rpin.gpio_port, &GPIO_InitStructure);
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);
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_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = ENABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
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
NVIC_InitTypeDef NVIC_InitStructure;
CAN_ITConfig(pparam->can_channel, pparam->IT_flag, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = pparam->pre_priority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = pparam->sub_priority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
_debug(SYS_INFO, "CAN%d Init end ...\n", pparam->can_dev + 1);
return 0;
}
void can_uninit(u8 can_dev)
{
can_port_t* pparam = &can_port[can_dev];
clearFilter(can_dev);
CAN_DeInit(pparam->can_channel);
RCC_APB1PeriphClockCmd(pparam->can_rcc, DISABLE);
}
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过滤器函数
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;
}
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 };
switch (flag) {
case 0: {
position = size / 4;
remain = size % 4;
for (i = 0; i < position; i++) {
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;
canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow;
myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_16bit);
}
if (remain > 0) {
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;
canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow;
myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_16bit);
}
break;
}
case 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);
canId[1] = (filterMaskIdHigh << 16) | filterMaskIdLow | (1 << 2);
myFilter(can_dev, canId, CAN_FilterMode_IdList, CAN_FilterScale_32bit);
}
if (remain > 0) {
filterIdLow = *p_canId << 3;
filterIdHigh = (*p_canId << 3) >> 16;
filterMaskIdLow = filterIdLow;
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;
}
}
}
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;
}
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) {
_debug(SYS_INFO, "the number of Mask_canId is not pow(2) \n");
return 1;
}
switch (flag) {
case 0:
{
position = size / 2;
for (i = 0; i < position; i++) {
canId[0] = *p_canIdMask << 21;
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;
}
case 1:
{
position = size / 2;
for (i = 0; i < position; i++) {
canId[0] = (*p_canIdMask << 3) | (1 << 2);
p_canIdMask++;
canId[1] = (*p_canIdMask << 3) | (1 << 2);
p_canIdMask++;
myFilter(can_dev, canId, CAN_FilterMode_IdMask, CAN_FilterScale_32bit);
}
break;
}
}
return 0;
}
u8 canIdSeparation(u8 can_dev, uint32_t* p_canId, int size, u8 filterMode)
{
u8 i;
u32 canId;
u32 stdIdBuff[56] = { 0 };
u32 extIdBuff[28] = { 0 };
u8 std_i = 0;
u8 ext_i = 0;
for (i = 0; i < size; i++) {
canId = *p_canId;
_debug(SYS_INFO, "canId = 0x%x\n", canId);
if ((canId & 0x7FFFFFFF) & (~ 0x1FFFFFFF)) {
_debug(SYS_INFO, "CAN id is unqualified, beyond scale \n");
return 1;
}
if (((canId >> 31) == 0) && (canId & (~ 0x7FF))) {
_debug(SYS_INFO, "CAN stdid is unqualified, beyond scale \n");
return 1;
}
if (canId >> 31) {
extIdBuff[ext_i] = canId & 0x7FFFFFFF;
ext_i++;
} else {
stdIdBuff[std_i] = canId;
std_i++;
}
p_canId++;
}
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");
clearFilter(can_dev);
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;
}
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]};
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);
if(filterNumber > 27) {
_debug(SYS_INFO, "the distribution of Can Filter Number go beyond rank: CAN2 > 27\n");
return 1;
}
}
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;
filterNumber++;
CAN_FilterInitStructure.CAN_FilterScale = filterScale;
CAN_FilterInitStructure.CAN_FilterMode = filterMode;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
return 0;
}
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;
}
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 发送/接收函数
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;
}
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;
}
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__
typedef enum {
CAN_DEV1,
CAN_DEV2,
CAN_DEV_CNT
} CAN_DEV_E;
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);
u8 CAN_Transmit_Msg(u8 can_dev, u8* msg, u8 len);
u8 CAN_Receive_Msg(u8 can_dev, u8 * msg);
#endif