GD32/STM32 CAN通讯配置及应用
GD32/STM32 CAN通讯配置及应用
由于CAN通讯具有速度快,距离远的优势,现在越来越多设备采用can通讯,尤其是车企。本文形容can通讯的初始化配置以及应用。
程序初始化配置(GD32)例程
采用GD32F105互联型产品。有两路CAN。APB1时钟为16M,CAN波特率为250K。
/***********************************************************************
*@brief :CAN初始化
*@param :None
*@return:None
***********************************************************************/
void CANLoad_Init(DataRate_t DataRate)
{
uint8_t i;
// uint32_t Clock;
rcu_periph_clock_enable(RCU_CAN0);
rcu_periph_clock_enable(RCU_CAN1);
can_parameter_struct can_parameter;
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
/*GPIO Init*/
gpio_init(CAN0_RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN0_RX_PIN);
gpio_init(CAN0_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN0_TX_PIN);
gpio_init(CAN1_RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN1_RX_PIN);
gpio_init(CAN1_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN1_TX_PIN);
/* initialize CAN register */
can_deinit(CAN0);
can_deinit(CAN1);
//CAN由APB1时钟而来
// Clock = rcu_clock_freq_get(CK_APB1);
/* initialize CAN parameters */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = ENABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.no_auto_retrans = DISABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_6TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_1TQ;
can_parameter.prescaler = 8;
/* initialize CAN */
can_init(CAN0, &can_parameter);
can_parameter.prescaler = 8;
can_init(CAN1, &can_parameter);
can_filter_parameter_struct can_filter;
can_struct_para_init(CAN_INIT_STRUCT, &can_filter);
can_filter.filter_number = 0;
can_filter.filter_list_high = 0x3000; //过滤器高字节
can_filter.filter_list_low = 0x0000; //过滤器低字节
can_filter.filter_mask_high = 0x3000//过滤器掩码数高位
can_filter.filter_mask_low = 0x0000 //过滤器掩码数低位
can_filter.filter_fifo_number = CAN_FIFO0; //滤过器关联FIFO0
can_filter.filter_mode = CAN_FILTERMODE_MASK; //掩码模式
can_filter.filter_bits = CAN_FILTERBITS_32BIT;//32位
can_filter.filter_enable = ENABLE;
can_filter_init(&can_filter);
/* CAN1 filter number */
can_filter.filter_number = 15;
can_filter_init(&can_filter);
/* enable can receive FIFO0 not empty interrupt */
can_interrupt_enable(CAN0, CAN_INT_RFNE0);
can_interrupt_enable(CAN1, CAN_INT_RFNE0);
}
CAN滤波
CAN滤波分为掩码模式和列表按模式,掩码模式是接收什么ID。这里我们只讨论掩码模式。
在掩码模式下,标识符寄存器与掩码寄存器相关联,掩码寄存器指定将标识符的哪些位处理为“必须匹配”或“不关心”。
例如
标识符:
ID | 二进制 |
---|---|
0x18FFA1A1 | 1 1000 1111 1111 1010 0001 1010 |
掩码:
ID | 二进制 |
---|---|
0x1FFFFFFE | 1 1111 1111 1111 1111 1111 1110 |
可以过滤的CAN ID为 0x18FFA1A1和0x18FFA1A0即最后一位不关心为什么。
CAN接收发送及应用
对CANID的长度、ID和扩展帧进行判断
/*-----------------------------------------------------------------------
@brief :CAN1接收中断
-----------------------------------------------------------------------*/
void CAN1_RX0_IRQHandler(void)
{
can_receive_message_struct RxMessage;
can_message_receive(CAN1, CAN_FIFO0, &RxMessage);
CAN1_RxMessage(&RxMessage);
}
/*-----------------------------------------------------------------------
@brief :CAN1接收函数
-----------------------------------------------------------------------*/
void CAN1_RxMessage(can_receive_message_struct* RxMessage)
{
if((0x18FFFFFF == RxMessage->rx_efid)&&(CAN_FF_EXTENDED == RxMessage->rx_ff)&&(8 == RxMessage->rx_dlen))
{
Name = RxMessage->rx_data[0];
}
/*-----------------------------------------------------------------------
@brief :CAN发送函数
-----------------------------------------------------------------------*/
void CAN1_HAILI_1(void)
{
can_trasnmit_message_struct SendMessage;
TxMessage_Init(&Tx1_Data);
SendMessage.tx_data[0] = 0x11;
SendMessage.tx_data[1] = 0x22;
SendMessage.tx_dlen = 8;
SendMessage.tx_ff = CAN_FF_EXTENDED;
SendMessage.tx_ft = CAN_FT_DATA;
SendMessage.tx_sfid = 0x18FF1234;
can_message_transmit(CAN0, &SendMessage);
}
总结
实际还需要结合自己的逻辑进行改动。
作者:释博文