CELIS/HARDWARE/CAN/bsp_can.c
2024-08-09 14:24:48 +08:00

495 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************** (C) COPYRIGHT 2011 嵌入式开发工作室 ********************
* 文件名 bsp_can.c
* 描述
*
* 实验平台:
* 硬件连接:
*
* 作者
* 时间 2022-10-12
* 版本 V1.0
**********************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include "can.h"
#include "stm32f10x_can.h"
#include "misc.h"
#include "Sys.h"
#include "bsp_can.h"
#include "canbusdrv.h"
#include "REV_CarMessage.h"
#include "Sleep.h"
#include "SecTimer.h"
#define DEBUG_BSP_CAN 1
#if DEBUG_BSP_CAN > 0
#define CAN_PRINT DEPRINT
#define CAN_PRINT_ARRAY DEPRINT_ARRAY
#else
#define CAN_PRINT(...) ;
#define CAN_PRINT_ARRAY(...) ;
#endif
u8 CAN_Mode_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);//使能PORTD时钟,使能功能复用时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
CAN_OperatingModeRequest(CAN1, CAN_OperatingMode_Initialization);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO
// GPIO_PinRemapConfig(GPIO_Remap2_CAN1,ENABLE);
//GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //
CAN_InitStructure.CAN_ABOM=ENABLE;
// 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= CAN_Mode_Normal; //模式设置: mode:0,普通模式;1,回环模式; //
//设置波特率
#if 0
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=9; //分频系数(Fdiv)为brp+1 //
#else
/* 250k采样点在87.5%为好下面设置正好是87.5%*/
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=CAN_BS1_13tq; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=9; //分频系数(Fdiv)为brp+1 //
#endif
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1 CAN = 36000000 / 9 / (1 + 7 + 8); 250k
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN_RX0_INT_ENABLE
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
CAN_ITConfig(CAN1,CAN_IT_TME,ENABLE);//FIFO0消息挂号中断允许.
// CAN_ClearITPendingBit(CAN1, CAN_IT_EPV);
// CAN_ClearITPendingBit(CAN1, CAN_IT_BOF);
CAN_ITConfig(CAN1,CAN_IT_EPV,ENABLE); /* Error passive Interrupt */
CAN_ITConfig(CAN1,CAN_IT_BOF,ENABLE); /* Error bus off Interrupt */
CAN_ITConfig(CAN1,CAN_IT_ERR,ENABLE); /* Error bus off Interrupt */
CAN_OperatingModeRequest(CAN1, CAN_OperatingMode_Normal);
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);
NVIC_InitStructure.NVIC_IRQChannel = CAN1_SCE_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
printf("can 1 open!\n");
return 0;
}
void CAN1_TX_IRQHandler(void)
{
unsigned char ret;
ret = CAN_TransmitStatus(CAN1, 0);
if (ret != CAN_TxStatus_Pending)
{
bsp_can_msg_sent_hook(0, 0, ret == CAN_TxStatus_Ok);
}
ret = CAN_TransmitStatus(CAN1, 1);
if (ret != CAN_TxStatus_Pending)
{
bsp_can_msg_sent_hook(0, 1, ret == CAN_TxStatus_Ok);
}
ret = CAN_TransmitStatus(CAN1, 2);
if (ret != CAN_TxStatus_Pending)
{
bsp_can_msg_sent_hook(0, 2, ret == CAN_TxStatus_Ok);
}
CAN_ClearITPendingBit(CAN1, CAN_IT_TME);
}
void CAN1_SCE_IRQHandler(void)
{
if (CAN_GetITStatus(CAN1, CAN_IT_EPV) == SET)
{
if (CAN_GetFlagStatus(CAN1, CAN_FLAG_EPV) == SET)
{
can_bus_err_passive_hook(0);
// printf("!!!CAN1 ERR passive\n");
//CAN_ClearFlag(CAN1, CAN_FLAG_EPV);
}
else
{
// printf("!!!CAN1 ERR active\n");
}
CAN_ClearITPendingBit(CAN1, CAN_IT_EPV);
}
if (CAN_GetITStatus(CAN1, CAN_IT_BOF) == SET)
{
if (CAN_GetFlagStatus(CAN1, CAN_FLAG_BOF) == SET)
{
can_bus_off_hook(0);
// printf("!!!CAN1 BUS OFF\n");
//CAN_ClearFlag(CAN1, CAN_FLAG_BOF);
}
else
{
// printf("!!!CAN1 BUS ON\n");
}
CAN_ClearITPendingBit(CAN1, CAN_IT_BOF);
}
}
void CAN2_SCE_IRQHandler(void)
{
if (CAN_GetITStatus(CAN2, CAN_IT_EPV) == SET)
{
if (CAN_GetFlagStatus(CAN2, CAN_FLAG_EPV) == SET)
{
can_bus_err_passive_hook(1);
// printf("!!!CAN2 ERR passive\n");
CAN_ClearFlag(CAN2, CAN_FLAG_EPV);
}
else
{
// printf("!!!CAN2 ERR active\n");
}
CAN_ClearITPendingBit(CAN2, CAN_IT_EPV);
}
if (CAN_GetITStatus(CAN2, CAN_IT_BOF) == SET)
{
if (CAN_GetFlagStatus(CAN2, CAN_FLAG_BOF) == SET)
{
Sleep_Parame.BufFlag = 1;
Sleep_Parame.BusoffCnt++;
SecStop(&SecTimer[BusoffCnt_Free_SecTimerNUM]);
can_bus_off_hook(1);
// printf("!!!CAN2 BUS OFF\n");
CAN_ClearFlag(CAN2, CAN_FLAG_BOF);
}
else
{
Sleep_Parame.BusoffCnt=0;
// printf("!!!CAN2 BUS ON\n");
}
CAN_ClearITPendingBit(CAN2, CAN_IT_BOF);
}
}
#if CAN_RX0_INT_ENABLE //使能RX0中断
//中断服务函数
void CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
// int i=0;
// CAN_Receive(CAN1, 0, &RxMessage);
// Can_Send_Msg(RxMessage.Data,8);
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);
bsp_can_msg_receive_hook(0, (CanTxMsg *)&RxMessage); /* 注意这里CanRxMsg 和 CanTxMsg 格式不同,但是能兼容*/
}
#endif
///////////////////////////////////////////////////CAN2////////////////////////////////////////////////////
void CAN2_TX_IRQHandler(void)
{
unsigned char ret;
ret = CAN_TransmitStatus(CAN2, 0);
if (ret != CAN_TxStatus_Pending)
{
bsp_can_msg_sent_hook(1, 0, ret == CAN_TxStatus_Ok);
}
ret = CAN_TransmitStatus(CAN2, 1);
if (ret != CAN_TxStatus_Pending)
{
bsp_can_msg_sent_hook(1, 1, ret == CAN_TxStatus_Ok);
}
ret = CAN_TransmitStatus(CAN2, 2);
if (ret != CAN_TxStatus_Pending)
{
bsp_can_msg_sent_hook(1, 2, ret == CAN_TxStatus_Ok);
}
CAN_ClearITPendingBit(CAN2, CAN_IT_TME);
}
u8 CAN2_Mode_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN_RX2_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
SYS_ENTER_CRITICAL();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);//使能PORTB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);//使能CAN2时钟
CAN_OperatingModeRequest(CAN2, CAN_OperatingMode_Initialization);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化IO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化IO
// GPIO_PinRemapConfig(GPIO_Remap_CAN2,ENABLE);
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //
CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //
CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
CAN_InitStructure.CAN_NART=DISABLE; //禁止报文自动传送 //
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 //
CAN_InitStructure.CAN_TXFP=ENABLE; //优先级由报文标识符决定 //
CAN_InitStructure.CAN_Mode= CAN_Mode_Normal; //模式设置: mode:0,普通模式;1,回环模式; //
//设置波特率
#if 0
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=CAN_BS1_4tq; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_3tq; //Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=9; //分频系数(Fdiv)为brp+1 //
#else
/* 500kpbs 采样点应该在80%多一点为好 */
CAN_InitStructure.CAN_SJW=CAN_SJW_2tq;
CAN_InitStructure.CAN_BS1=CAN_BS1_9tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;
CAN_InitStructure.CAN_Prescaler=6; // 83.3%采样点 //
#endif
CAN_Init(CAN2, &CAN_InitStructure); // 初始化CAN2
//#ifdef _Filter
if(Sleep_Parame.False_sleep_State)
{
CAN_FilterInitStructure.CAN_FilterNumber=14; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位宽
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO1;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化
}
//#else
else
{
CAN_Filter_register(Standard_frame,Evcan_HandleTable);
}
//#endif
#if CAN_RX2_INT_ENABLE
CAN_ITConfig(CAN2,CAN_IT_FMP1,ENABLE);//FIFO0消息挂号中断允许.
NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
CAN_ITConfig(CAN2,CAN_IT_TME,ENABLE);//FIFO0消息挂号中断允许.
// CAN_ClearITPendingBit(CAN1, CAN_IT_EPV);
// CAN_ClearITPendingBit(CAN1, CAN_IT_BOF);
CAN_ITConfig(CAN2,CAN_IT_EPV,ENABLE); /* Error passive Interrupt */
CAN_ITConfig(CAN2,CAN_IT_BOF,ENABLE); /* Error bus off Interrupt */
CAN_ITConfig(CAN2,CAN_IT_ERR,ENABLE); /* Error bus off Interrupt */
CAN_OperatingModeRequest(CAN2, CAN_OperatingMode_Normal);
NVIC_InitStructure.NVIC_IRQChannel = CAN2_TX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = CAN2_SCE_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
SYS_EXIT_CRITICAL();
printf("can 2 open!\n");
return 0;
}
///////////////////////////////////////////////////CAN2////////////////////////////////////////////////////
#if CAN_RX2_INT_ENABLE //使能RX2中断
//中断服务函数
void CAN2_RX1_IRQHandler(void)
{
CanRxMsg RxMessage2;
// CAN_Receive(CAN2, CAN_FIFO0, &RxMessage);
Sleep_Parame.Bus_Packet_Free = 1;
SecStop(&SecTimer[Bus_Packet_Free_SecTimerNUM]);
for (uint8_t fifoMsgNum = 0; fifoMsgNum < 3; fifoMsgNum ++)
{
if (CAN_MessagePending(CAN2, CAN_FIFO1))
{
CAN_Receive(CAN2, CAN_FIFO1, &RxMessage2);
if (RxMessage2.RTR == CAN_RTR_DATA)
{
bsp_can_msg_receive_hook(1, (CanTxMsg *)&RxMessage2); /* 注意这里CanRxMsg 和 CanTxMsg 格式不同,但是能兼容*/
UdsApi_MsgQueueIn(RxMessage2);
}
}
else
{
break;
}
}
// Can2_Send_Msg(RxMessage2.Data,8);
}
#endif
/**
* @brief: 接口的配置信息
*
* @param channel: can 通道号, 不大于MCU_CAN_CHANNEL_NUM
* @param pt_bsp_cfg[IN]: 总线自动配置
*
* @return:
* 返回结果: true - open 成功 false - open 失败
*/
bool bsp_can_open(unsigned char channel, const bsp_can_cfg_t * pt_bsp_cfg)
{
if (channel == 0)
{
CAN_Mode_Init();
}
else
{
CAN2_Mode_Init();
}
return true;
}
/**
* @brief: 关闭接口
*
* @return:
* 返回结果: true - open 成功 false - open 失败
*/
bool bsp_can_close(unsigned char channel)
{
if (channel == 0)
{
CAN_OperatingModeRequest(CAN1, CAN_OperatingMode_Initialization);
CAN_DeInit(CAN1);
}
else
{
CAN_OperatingModeRequest(CAN2, CAN_OperatingMode_Initialization);
CAN_DeInit(CAN2);
}
return true;
}
unsigned char bsp_can_msg_send(unsigned char channel, const can_frame_t * pt_fram)
{
u8 mbox;
mbox= CAN_Transmit((channel == 0)?CAN1:CAN2, (can_frame_t *)pt_fram);
if (mbox == CAN_TxStatus_NoMailBox)
{
mbox = BSP_CAN_SEND_FAIL;
}
return mbox;
}