STM32:CAN功能板设计和调试

0前言

本文主要目的是,总结去年设计stm32-CAN板子过程中遇到的问题,分为keil嵌入式软件和嘉立创EDA设计两个部分。

1 STM32F1 CAN功能

芯片型号

物料芯片型号明确,明确例程芯片型号。不同芯片密度不同,LD、MD和HD等。不同芯片的时钟树不同,比如F4与F1系列,这影响软件初始化。

移植CAN例程,can收发器没有反应

从如下方面定位问题:

  1. 注意波特率的配置、板子晶振、时钟树结构、can初始化配置
  2. CAN收发器没有电压供应。设计的板子包含三个输入电源,只有一个5v输入。忘记接入5V电源输入

理想测试流程是:

  1. 测试CAN收发器、stm32的电气特性,确保正确的电压供应
  2. 测试LED闪烁功能,确保main程序正常运行。
  3. 测试CAN回环功能,确保软件层面CAN控制器没有问题。此外涉及到CAN外设的正常初始化
  4. 测试CAN发送功能,此时需要使用CAN-BUS逻辑分析仪。注意CAN协议存在ACK信号,因为没有其它CAN设备回应CAN帧时,会产生两种可能现象:1,无法接收CAN信号;2,自动重发功能会导致CAN总线一直出现CAN帧。

整个过程中,遇到两个奇怪现象:

  1. 测试中间,板子的led全部无法使用,猜想板子被烧掉。后来观察到,梦源的排线接口地线接到板子的3V3接口上,导致板子没有压差。
  2. 有接收的逻辑信号,发送的信号却没有。不明原因
    懵逼ing

stm32f103cbt8的can发送pending异常

自设的STM32板子,LED正常点亮,但是,在测试CAN的回环模式时,发送状态为CAN_TxStatus_Pending ,而非正常的CAN_TxStatus_Ok

从以下几个方面定位问题:

  1. 测试CAN收发器的5V电压,正常
  2. 检查CAN初始化配置,can接收引脚的设置IPU。猜想此外问题
  3. 对比CAN stm32f1和stm32f4的初始化程序,观察到时钟和引脚映射等方面的差别
  4. 采用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 、重映射和复用的关系。
选择PA11和PA12为CAN口,打开GPIOB时钟
在这里插入图片描述

芯片选择

物料芯片购买错误,导致出现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短路

芯片焊接不好,电源与地短路,直接测量去耦电容两边电压是直连的状态、蜂鸣器响起。测试定位问题点,本身只是一种行为,花费大量时间记录行为,确定行为正确性,反而降低效率。

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值