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
;
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
},
.r_pin
= { GPIO_Pin_11
, RCC_APB2Periph_GPIOA
, GPIOA
},
.pin_map
= 0,
.can_rcc
= RCC_APB1Periph_CAN1
,
.can_ch
= CAN1
,
.filter_start
= 0,
.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
},
.r_pin
= { GPIO_Pin_12
, RCC_APB2Periph_GPIOB
, GPIOB
},
.pin_map
= 0,
.can_rcc
= RCC_APB1Periph_CAN2
,
.can_ch
= CAN2
,
.filter_start
= CAN2_FILTER_S
,
.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);
}else{
pp_ctrl_set(PIN_CAN1_STB
,1);
}
}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);
}else{
pp_ctrl_set(PIN_CAN2_STB
,1);
}
}
}
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
);
RCC_APB1PeriphClockCmd(pparam
->can_rcc
, ENABLE
);
RCC_APB2PeriphClockCmd(pparam
->r_pin
.gpio_rcc
| pparam
->t_pin
.gpio_rcc
, ENABLE
);
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_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
);
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_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_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
);
NVIC_InitStructure
.NVIC_IRQChannel
= pparam
->irq
;
NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= 1;
NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= 1;
NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
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_FilterInitStructure
.CAN_FilterActivation
= ENABLE
;
CAN_FilterInit(&CAN_FilterInitStructure
);
return 0;
}
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)
#define CAN_Id_Extended ((uint32_t)0x00000004)
#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
;
uint8_t id_frame
;
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
);
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