基于Stm32F3+CA-IS3050隔离CAN设计参考原理图/PCB图/教程/源码等开源分享
公众号:游名开源
一、概述
控制器区域网络(CAN)物理层收发器芯片采用了高速、高隔离耐压、低环路延时的高性价比的隔离式收发器CA-IS3050,此器件采用片上二氧化硅(SiO2) 电容作为隔离层,在 CAN协议控制器和物理层总线之间创建一个完全隔离的接口,与隔离电源一起使用,可隔绝噪声和干扰并防止损坏敏感电路。
CA-IS3050可为 CAN协议控制器和物理层总线分别提供差分接收和差分发射能力,信号传输速率最高可达1Mbps。该器件具有限流、过压和接地损耗保护(–40 V至 40 V)以及热关断功能, 可防止输出短路,
共模电压范围为–12 V 至 12 V。CA-IS3050额定温度范围为–40°C至 125°C, 提供宽体SOIC-16封装。
引脚配置和引脚功能描述如下图:
图1 引脚配置
图2 引脚功能描述
该芯片具有凉薄的保护功能:
信号隔离:CA-IS3050 信号隔离是通过基于电容隔离方案的数字隔离器实现的,在逻辑侧通过数字隔离器采用开关键控(On-OffKey, OOK)调制方式将输入信号调制到高频然后通过起隔离耐压作用的片上二氧化硅电容,在总线侧数字隔离器部分电路将接收到的信号恢复然后转换成符合标准的电平输出至 CAN 总线。同理,总线侧的电平被总线侧电路处理后同样通过数字隔离器调制到高频然后传输回逻辑侧,然后在逻辑侧解调恢复输出至 RXD。逻辑侧和总线侧的地完全可以分开,并通过片上二氧化硅电容实现高达 5 kVRMS的隔离耐压等级,确保了实际使用时微控制器和高压总线之间信号传输的完整性和安全性。
主动态超时功能:CA-IS3050 具有主动态超时功能,防止 TXD 因为软件或者硬件故障一直被下拉到低电平,造成总线持续进入主动态从而被锁死(阻断整个网络通信)。主动态超时功能通过使用一个计数器,在 TXD 输入信号的负边沿发生期间被触发,当 TXD 的低电平持续时间长于主动态超时时间 tTXD_DTO 时,收发器会被关断,此时总线被释放并进入被动态。在 TXD输入信号的正边沿期间,计数器会被置位。
热关断保护功能:CA-IS3050 集成有热关断保护功能,可在过温情况下对器件内部电路进行保护。如果器件的结温超过热关断温度TJ(shutdown), 驱动器会被关断,从而阻断 TXD 到总线的信号传输路径,典型的热关断温度为 165°C。当器件结温低于热关断温度后,驱动器会被重新使能。
限流保护:CA-IS3050 集成有限流保护功能,可防止总线侧输出短路至电源或地瞬间过流对器件造成损坏,注意限流保护一旦发生会产生较大的电流,从而带来较大损耗。
二、硬件设计
模块原理图如下图:
原理图主要分为隔离电源部分和CAN通信隔离部分;隔离电源主要是通过3510微功率隔离式反激式转换器和变压器将VDD1=3V转换为VDD2=5V,然后CAN模块就可以正常通信。接线图如下表:
设备1 | CAN通信模块1 | CAN通信模块2 | 设备2 | ||
CAN_TX | CAN_TX | CANH | CANH | CAN_TX | CAN_RX |
CAN_RX | CAN_RX | CANL | CANL | CAN_RX | CAN_TX |
参考PCB图及3D显示:
模块如下图
补充说明:
有条件的最好对CAN接口加保护,电路参考如下图:
要是对成本比较敏感,可以参考如下方案:数字隔离器(或光耦)+CAN芯片(可选择国产的QBD1044:1元多些);
三、软件设计
在Cube MX中将基本的串口配置和CAN通信的基础配置好后生成Keil 5工程并使用Keil 5打开对应工程;
在can.c文件下,最开始添加三个宏定义,由于新版HAL库取消了TXheader的初始化,这里需要自行添加想关初始化;如下:
CAN_TxHeaderTypeDef hCAN1_TxHeader;
CAN_RxHeaderTypeDef hCAN1_RxHeader;
CAN_FilterTypeDef hCAN1_Filter;
void CAN_TxHeader_Init(CAN_TxHeaderTypeDef * pHeader,
uint32_t StdId,
uint32_t ExtId,
uint32_t IDE,
uint32_t RTR,
uint32_t DLC)
{
pHeader->StdId = StdId;
pHeader->ExtId = ExtId;
pHeader->IDE = IDE;
pHeader->RTR = RTR;
pHeader->DLC = DLC;
pHeader->TransmitGlobalTime = ENABLE;
}
voidMX_CAN_Init(void)
{
hcan.Instance = CAN;
hcan.Init.Prescaler = 6;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_9TQ;
hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority= DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
}
在初始化函数中,这四个参数hcan.Init.Prescaler, hcan.Init.SyncJumpWidth, hcan.Init.TimeSeg1,hcan.Init.TimeSeg2用来配置CAN通信波特率,CA-IS3050支持传输速率最高可达 1Mbps,即我们既可以用通用的500Kbps通信也可以用1Mbps进行通信,计算公式为:
按照公式计算,我们用的是1Mbps的波特率在通信,hcan.Init.Mode用来设置单片机工作模式(普通模式(CAN_MODE_NORMAL)和回环模式(CAN_MODE_LOOPBACK)等)。我们这里设置普通模式
然后添加如下几个功能函数:
void CAN_Filter_Init(CAN_FilterTypeDef * pFilter,
uint32_tIdHigh,
uint32_tIdLow,
uint32_tMaskIdHigh,
uint32_tMaskIdLow,
uint32_tFIFOAssignment,
uint32_tBank,
uint32_tMode,
uint32_tScale,
uint32_tActivation,
uint32_tSlaveStartFilterBank)
{
pFilter->FilterIdHigh = 0; //32 位 ID
pFilter->FilterIdLow =0;
pFilter->FilterMaskIdHigh = 0; //32 位 MASK
pFilter->FilterMaskIdLow =0;
pFilter->FilterFIFOAssignment= CAN_FILTER_FIFO0; // FIFO0
pFilter->FilterBank =0;
pFilter->FilterMode =CAN_FILTERMODE_IDMASK;
pFilter->FilterScale = CAN_FILTERSCALE_32BIT; //32 位
pFilter->FilterActivation = ENABLE; ////激活过滤器 0
pFilter->SlaveStartFilterBank = 0;
}
首先是CAN过滤器的配置函数,
/***********************CAN通信发送函数***************************/
void CAN_TxMessage(CAN_HandleTypeDef *hcan,CAN_TxHeaderTypeDef * pTxHeader, uint8_t aData[], uint8_t DLC)
{
uint32_tTx_MailBox;
pTxHeader->DLC = DLC;
while(HAL_CAN_AddTxMessage(hcan, pTxHeader, aData, &Tx_MailBox) !=HAL_OK)
{
printf("TxMsg Failed!!");
HAL_Delay(100);
}
printf("\nSend Tx Message Success!!Tx_Mail:%d", Tx_MailBox);
}
void User_CAN1_TxMessage(uint8_t aTxData[], uint8_tDLC)
{
CAN_TxMessage(&hcan,&hCAN1_TxHeader, aTxData, DLC);
}
/*********************** CAN启动测试函数****************************/
void CAN_Configuration(CAN_TxHeaderTypeDef * pTxHeader,
CAN_FilterTypeDef * pFilter,
uint32_t StdId,
uint32_t ExtId,
uint32_t IDE,
uint32_t RTR,
uint32_t DLC,
uint32_t IdHigh,
uint32_t IdLow,
uint32_t MaskIdHigh,
uint32_t MaskIdLow,
uint32_t FIFOAssignment,
uint32_t Bank,
uint32_t Mode,
uint32_t Scale,
uint32_t Activation,
uint32_t SlaveStartFilterBank)
{
CAN_TxHeader_Init(pTxHeader, StdId, ExtId, IDE, RTR, DLC);
CAN_Filter_Init(pFilter, IdHigh, IdLow, MaskIdHigh, MaskIdLow,FIFOAssignment, Bank, Mode, Scale, Activation, SlaveStartFilterBank);
HAL_CAN_ConfigFilter(&hcan,pFilter);
while(HAL_CAN_Start(&hcan) != HAL_OK )
{
printf("\nCAN_Start Failed!!");
HAL_Delay(100);
}
printf("\nCAN_Start Success!!");
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
}
//启动测试函数主要为测试单片机CAN功能是否能正常启动,启动成功与否通过串口发送出来,方便我们观测,所以需要包含usart.h文件;
配置完成后,在stm32f3xx_it.c文件中添加CAN接收中断函数,
void CAN_RX1_IRQHandler()
{
HAL_CAN_RxFifo0MsgPendingCallback(&hcan);
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef*hcan)
{
uint8_taRxData[8], i;
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &hCAN1_RxHeader,aRxData) == HAL_OK)
{
printf("\nGet Rx Message Success!!\nData:");
for(i=0; i<8; i++)
printf("%x ", aRxData[i]);
}
}
中断服务函数中首先用if确定是否接收到数据,若没有接收到数据直接退出,接收到则使用串口将对应数据打印;由于我们在main函数中的发送数据为16进制数据,打印也用16进制数据打印,更便于观察;
最后为main.c文件内容
int main(void)
{
uint8_t TxData[8] = {0x12, 0x23, 0x34, 0x45, 0x56,0x67, 0x78, 0x89};
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_CAN_Init();
MX_USART1_UART_Init();
__HAL_CAN_ENABLE_IT(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);//CAN中断使能函数
User_CAN_Configuration();
while (1)
{
User_CAN1_TxMessage(TxData,8);
HAL_Delay(1000);
}
}
在main函数中,只要是对CAN通信的中断使能,只能之后前面写的中断服务函数才能正常起作用
实验结果:
程序编译成功后,下载到板卡,两块板卡其中一块可以将main.c的while中的User_CAN1_TxMessage(TxData, 8);函数屏蔽掉,专门用来接收数据,另一个则每隔1秒发送一次数据,打开两个串口通信助手,就可以看到如下信息;