#include "hal_can.h" #include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include CanTxMsg tx_message; CanRxMsg rx_message; pcan_rx pcan_rx_back = NULL; pcan_tx pcan_tx_back = NULL; // CAN初始化 // tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq // tbs2:时间段2的时间单元. 范围:CAN_BS2_1tq~CAN_BS2_8tq; // tbs1:时间段1的时间单元. 范围:CAN_BS1_1tq ~CAN_BS1_16tq // brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1 // 波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp); // mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式; // Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack); // 则波特率为:42M/((6+7+1)*6)=500Kbps u8 hal_can1_mode_init(uint8_t tsjw, uint8_t tbs2, uint8_t tbs1, uint16_t brp, uint8_t mode) { GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; NVIC_InitTypeDef NVIC_InitStructure; CAN_DeInit(CAN1); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能PORTA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); // 使能CAN1时钟 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化IO GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1); // CAN单元设置 CAN_InitStructure.CAN_TTCM = DISABLE; // 非时间触发通信模式 CAN_InitStructure.CAN_ABOM = DISABLE; // 软件自动离线管理 CAN_InitStructure.CAN_AWUM = DISABLE; // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN_InitStructure.CAN_NART = DISABLE; // 禁止报文自动传送 CAN_InitStructure.CAN_RFLM = DISABLE; // 报文不锁定,新的覆盖旧的 CAN_InitStructure.CAN_TXFP = DISABLE; // 优先级由报文标识符决定 CAN_InitStructure.CAN_Mode = mode; // 模式设置 CAN_InitStructure.CAN_SJW = tsjw; // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq CAN_InitStructure.CAN_BS1 = tbs1; // Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2 = tbs2; // Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler = brp; // 分频系数(Fdiv)为brp+1 CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1 // 配置过滤器0 CAN_FilterInitStructure.CAN_FilterNumber = 0; // 过滤器0 CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; // 32位 // 只接收标识符位0x0666报文 注意:RTR IDE SRR也参与构成标识符 CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; //(((u32)0x0666<<3)&0xFFFF0000)>>16; //要过滤的ID高位 CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000; //(((u32)0x0666<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位 CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; // 32位MASK // CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfff8; // 最后3位不管 CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; // 最后3位不管 CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; // 过滤器0关联到FIFO0 CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; // 激活过滤器0 CAN_FilterInit(&CAN_FilterInitStructure); // 滤波器初始化 CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // FIFO0消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); // FIFO0消息挂号中断允许. NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //////////////////////////////////////////////// return 0; } /********************************************************************************************************** * 函 数 名: CAN1_Init * 功能说明: CAN1初始化 * 形 参: 无 * 返 回 值: 无 **********************************************************************************************************/ void hal_can_init(void) { #if defined(__CAN_BAUD_500K) hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 6, CAN_Mode_Normal); // CAN1初始化环回模式,波特率500Kbps #elif defined(__CAN_BAUD_250K) hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 12, CAN_Mode_Normal); // CAN1初始化环回模式,波特率250Kbps #else #error no can baud macro!; #endif } //(固定格式:ID为0X12,标准帧,数据帧) // len:数据长度(最大为8) // msg:数据指针,最大为8个字节. // 返回值:0,成功; // 其他,失败; /**************************************************** * 函数功能:can1发送一组数据 * 入口参数:msg 数据 len 数据长度 can_id CAN id * 说 明:group_id 从1开始 *****************************************************/ // u8 CAN1_Send_Msg(u8 *msg, u8 len, u32 can_id) // { // u16 mbox, i; // CanTxMsg TxMessage; // TxMessage.StdId = 0x00; // 标准标识符为0 // TxMessage.ExtId = can_id; // 设置扩展标示符(29位) // TxMessage.IDE = CAN_Id_Extended; // 使用扩展标识符 // TxMessage.RTR = CAN_RTR_Data; // 消息类型为数据帧 // TxMessage.DLC = len; // 发送两帧信息 // for (i = 0; i < len; i++) // TxMessage.Data[i] = msg[i]; // 第一帧信息 // mbox = CAN_Transmit(CAN1, &TxMessage); // i = 0; // while ((CAN_TransmitStatus(CAN1, mbox) == CAN_TxStatus_Failed) && (i < 0XFFF)) // i++; // 等待发送结束 // if (i >= 0XFFF) // return 1; // return 0; // } uint8_t hal_can_msg_tx(uint32_t id, uint8_t id_type, uint8_t *p_data, uint8_t len) { uint8_t flg = 0; if (id_type) { tx_message.ExtId = id; // 设置扩展标示符(29位) } else { tx_message.StdId = id_type; // 标准标识符为0 } tx_message.IDE = id_type; // 使用扩展标识符 tx_message.RTR = CAN_RTR_Data; // 消息类型为数据帧 tx_message.DLC = len; // 发送两帧信息 memcpy(tx_message.Data, p_data, len); flg = CAN_Transmit(CAN1, &tx_message); return flg; } void hal_can_rx_back_init(pcan_rx p_fun) { pcan_rx_back = p_fun; } void hal_can_tx_back_init(pcan_tx p_fun) { pcan_tx_back = p_fun; } void CAN1_TX_IRQHandler(void) { if (pcan_tx_back != NULL) { pcan_tx_back(); } } void CAN1_RX0_IRQHandler(void) { CAN_Receive(CAN1, CAN_FIFO0, &rx_message); if (pcan_rx_back != NULL) { pcan_rx_back(rx_message); } }