0前言
本文主要目的是,总结去年设计stm32-CAN板子过程中遇到的问题,分为keil嵌入式软件和嘉立创EDA设计两个部分。
1 STM32F1 CAN功能
芯片型号
物料芯片型号明确,明确例程芯片型号。不同芯片密度不同,LD、MD和HD等。不同芯片的时钟树不同,比如F4与F1系列,这影响软件初始化。
移植CAN例程,can收发器没有反应
从如下方面定位问题:
- 注意波特率的配置、板子晶振、时钟树结构、can初始化配置
- CAN收发器没有电压供应。设计的板子包含三个输入电源,只有一个5v输入。忘记接入5V电源输入
理想测试流程是:
- 测试CAN收发器、stm32的电气特性,确保正确的电压供应
- 测试LED闪烁功能,确保main程序正常运行。
- 测试CAN回环功能,确保软件层面CAN控制器没有问题。此外涉及到CAN外设的正常初始化
- 测试CAN发送功能,此时需要使用CAN-BUS逻辑分析仪。注意CAN协议存在ACK信号,因为没有其它CAN设备回应CAN帧时,会产生两种可能现象:1,无法接收CAN信号;2,自动重发功能会导致CAN总线一直出现CAN帧。
整个过程中,遇到两个奇怪现象:
- 测试中间,板子的led全部无法使用,猜想板子被烧掉。后来观察到,梦源的排线接口地线接到板子的3V3接口上,导致板子没有压差。
- 有接收的逻辑信号,发送的信号却没有。不明原因
stm32f103cbt8的can发送pending异常
自设的STM32板子,LED正常点亮,但是,在测试CAN的回环模式时,发送状态为CAN_TxStatus_Pending ,而非正常的CAN_TxStatus_Ok 。
从以下几个方面定位问题:
- 测试CAN收发器的5V电压,正常
- 检查CAN初始化配置,can接收引脚的设置IPU。猜想此外问题
- 对比CAN stm32f1和stm32f4的初始化程序,观察到时钟和引脚映射等方面的差别
- 采用cubeMX软件,查看CAN初始化程序特点
stm32f1
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
此贴指出,GPIO_Remap1_CAN1、GPIO_Remap2_CAN1、alternate function 、重映射和复用的关系。
芯片选择
物料芯片购买错误,导致出现Flash Timeout等大量问题。ST-link utility工具能够帮助定位问题,同时STM32芯片可以使用内部晶振工作,从而可以定位晶振。
void SystemInit(void)
{
RCC_DeInit();//将外设 RCC寄存器重设为缺省值
RCC_HSICmd(ENABLE);//使能HSI
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);//等待HSI使能成功
//加上这两句才能到64M
// FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //FLASH半周期访问
// FLASH_SetLatency(FLASH_Latency_2); //设置代码延时值
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PCLK2Config(RCC_HCLK_Div1);
//设置 PLL 时钟源及倍频系数
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_10);//使能或者失能 PLL,这个参数可以取:ENABLE或者DISABLE
//此处不能太高,我刚开始设置50多,系统都无法运行。
RCC_PLLCmd(ENABLE);//如果PLL被用于系统时钟,那么它不能被失能
//等待指定的 RCC 标志位设置成功 等待PLL初始化成功
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//设置系统时钟(SYSCLK) 设置PLL为系统时钟源
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//选择想要的系统时钟
//等待PLL成功用作于系统时钟的时钟源
// 0x00:HSI 作为系统时钟
// 0x04:HSE作为系统时钟
// 0x08:PLL作为系统时钟
while(RCC_GetSYSCLKSource() != 0x08);//需与被选择的系统时钟对应起来,RCC_SYSCLKSource_PLL
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
}
CAN自动重发功能
STM32F4的CAN自动重发功能,会导致CAN帧无法正常发送时,一直向CAN总线发送CAN帧,影响总线负载率。
/*CAN单元初始化*/
CAN_InitStructure.CAN_TTCM=DISABLE; //MCR-TTCM 关闭时间触发通信模式使能
CAN_InitStructure.CAN_ABOM=ENABLE; //MCR-ABOM 自动离线管理
CAN_InitStructure.CAN_AWUM=ENABLE; //MCR-AWUM 使用自动唤醒模式
这里 CAN_InitStructure.CAN_NART=ENABLE; //MCR-NART 禁止报文自动重传 DISABLE-自动重传
CAN_InitStructure.CAN_RFLM=DISABLE; //MCR-RFLM 接收FIFO 锁定模式 DISABLE-溢出时新报文会覆盖原有报文
CAN_InitStructure.CAN_TXFP=DISABLE; //MCR-TXFP 发送FIFO优先级 DISABLE-优先级取决于报文标示符
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; //回环工作模式
CAN_InitStructure.CAN_SJW=CAN_SJW_2tq; //BTR-SJW 重新同步跳跃宽度 2个时间单元
Keil no target connected
电源供应,线路松动如USB接触不良或者杜邦线接触不好。
CAN发送失败
硬件层面问题:电源供应【自设电路问题多】,线路连接,芯片工作
软件层面问题:keil配置错误,初始化问题如筛选器、映射接口【PA11和PA12】和FIFO设置。
工具:ECanTool配置错误 ,双通道接口错误
static void CAN_Filter_Config(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/*CAN筛选器初始化*/
CAN_FilterInitStructure.CAN_FilterNumber=0; //筛选器组0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //工作在掩码模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //筛选器位宽为单个32位。
/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */
CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16; //要筛选的ID高位
CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要筛选的ID低位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0xFFFF; //筛选器高16位每位必须匹配
CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF; //筛选器低16位每位必须匹配
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ; //筛选器被关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=DISABLE; //使能筛选器
CAN_FilterInit(&CAN_FilterInitStructure);
/*CAN通信中断使能*/
CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}
CAN无法进入中断
联想到,筛选器的初始化影响CAN发送回ACK信号,筛选掩码的配置可能影响CAN接收实际帧内容和中断位置置1。
static void CAN_Filter_Config(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/*CAN筛选器初始化*/
CAN_FilterInitStructure.CAN_FilterNumber=0; //筛选器组0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //工作在掩码模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //筛选器位宽为单个32位。
/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */
CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16; //要筛选的ID高位
CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要筛选的ID低位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0xFFFF; //筛选器高16位每位必须匹配
CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF; //筛选器低16位每位必须匹配
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ; //筛选器被关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //使能筛选器
CAN_FilterInit(&CAN_FilterInitStructure);
/*CAN通信中断使能*/
CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}
如上图代码,野火的例程实际添加了0x1314这样的ID。此前,所有的CAN测试都是发送代码,没有使用筛选器的功能。现在从另一个板子接收CAN帧,这段初始化代码的功能就体现出来。
在配置筛选器为32位宽的掩码模式后,掩码全部设置为0x00,示意CAN收发器全部接收。问题是,led仍然没有任何变化,尝试keil的调试模式定位问题。进入keil调试模式打断点,程序如果进入中断就会在中断程序断点处暂停,结果是CAN没有在断点处暂停。
尝试查看FIFO的状态标志位是否正常,再进一步考虑中断为什么没有产生。测试代码如下,在通过ECAN发送CAN帧后,如果CAN的FIFO0正常接收到CAN帧,相关的状态标志位是置1的。此时程序能够进入if里面的条件语句,LED1也能够翻转。通过修改中断逻辑,先接收CAN,程序正常进入中断。
if(CAN_GetFlagStatus(CANx,CAN_FLAG_FMP0)==SET||CAN_GetFlagStatus(CANx,CAN_FLAG_FF0)==SET)
{
LED1_TOGGLE;
can_delay(0x2dc6c0);
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
/*从邮箱中读出报文*/
CAN_Receive(CANx, CAN_FIFO0, &RxMessage);
if(RxMessage.Data[0]==0x11){//
CAN_FIFORelease(CANx,CAN_FIFO0);
CAN_SetMsg(&TxMessage);
Txmail=CAN_Transmit(CANx,&TxMessage);
while(CAN_TransmitStatus(CANx,Txmail)!=CAN_TxStatus_Ok)
{}
}
}
CubeMx的HAL库工具
HAL库工具搭建工程效率高,可以减少许多重复的配置操作。由于HAL资源较少,可以借助ChatGPT提供例程。
STM32延时功能
计数延时、TIM延时与systick延时功能,三种功能各有特点。CAN通信测试中,主要采用TIM延时,方便而且精确度高。
2 嘉立创EDA设计PCB
立创PCB打板
嘉立创元器件价格
嘉立创平台的元器件性价比低,同样商品在淘宝能够以一半价格购买。淘宝购买元器件可以节省物料开销。
电源接口防反接设计
电源排针接口,注意正反接;CAN器件电源输入,注意正反接。
PCB插件设计
PCB机械稳定性,可以保证USB接口电压稳定;杜邦线机械连接弱,信号比较差,CAN信号采用双绞线较好。
STM32重置电路设计
stm32重置原理知识,见stm32f407手册。
判断自锁开关方向
察看PCB的3D图,可以直接看到开关的正确方向。
PCB短路
芯片焊接不好,电源与地短路,直接测量去耦电容两边电压是直连的状态、蜂鸣器响起。测试定位问题点,本身只是一种行为,花费大量时间记录行为,确定行为正确性,反而降低效率。