STM32F10X CAN+TJA1050中断 接受例程详解,测试无误

硬件平台:STM32F10X内部CAN模块 + TJA1050 + JLink

软件平台:Keil 4 

一、结果演示



二、接受程序例程

程序涉及的模块有:

USART:通用同步异步收发器,即串口,用于发送数据至上位机显示已接收到的数据;

RCC:复位及时钟控制模块,用于初始化STM32 外设时钟及设置CAN总线通信的波特率;

GPIO:通用输入输出口;

NVIC:中断服务程序;

CAN:STM32F10X自带的CAN通信模块,F1系列只有1个CAN,F4系列含有2个CAN,大容量的由2个,小容量的只有一个;

Delay:延时等待模块

Led:用led灯来指示是否正常发送,系统是否工作正常。


RCC

  #include "Rcc.h"
  
  void RCC_Init(void)
  {	 
  	 ErrorStatus HSEStartUpStatus;	//定义枚举类型错误状态变量		 
  	 RCC_DeInit();//复位系统时钟设置		
  	 RCC_HSEConfig(RCC_HSE_ON); //打开外部高速时钟晶振,使能HSE
  	/*RCC_HSE_ON  开
  	 _off 关  _bypass hse晶振被外部时钟旁路*/		 
  	HSEStartUpStatus = RCC_WaitForHSEStartUp();
  	/*RCC_WaitForHSEStartUp()返回一个ErrorStatus枚举值,
  	success好,error未好*/	
  	 if(HSEStartUpStatus == SUCCESS)//HES就绪
  	 {		 
  		 RCC_HCLKConfig(RCC_SYSCLK_Div1);
  		 //AHB时钟(HCLK)=系统时钟	
  		 RCC_PCLK1Config(RCC_HCLK_Div2);
  		 //设置低速AHB时钟(APB1)为HCLK的2分频	
  		 RCC_PCLK2Config(RCC_HCLK_Div1);
  		 //设置高速AHB时钟(APB2)=HCLK时钟
  		 FLASH_SetLatency(FLASH_Latency_2);
  		 //设置FLASH延时周期数为2
  		 //使能领取指缓存
  		 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
  		 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
  		 //设置PLL时钟源及倍频系数,为HSE的9倍频 8MHz * 9 = 72MHz
  		 /*void RCC_PLLConfig(u32 RCC_PLLSource, u32 RCC_PLLMul)
  		 RCC_PLLSource_HSI_Div2   pll输入时钟=hsi/2;
  		 RCC_PLLSource_HSE_Div1   pll输入时钟 =hse
  		 RCC_PLLSource_HSE_Div2   pll输入时钟=hse/2
  		 RCC_PLLMul_2  ------_16       pll输入时钟*2---16
  		 pll输出时钟不得超过72MHZ*/	
  		 RCC_PLLCmd(ENABLE);
  		 //ENABLE  / DISABLE
  		 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//等待PLL输出稳定
  		 /*FlagStatus RCC_GetFlagStatus(u8 RCC_FLAG)  检查指定RCC标志位
  		 返回SET OR RESET
  		 RCC_FLAG_HSIRDY  HSI晶振就绪
  		 RCC_FLAG_HSERDY
  		 RCC_FLAG_PLLRDY
  		 RCC_FLAG_LSERDY 
  		 RCC_FLAG_LSIRDY.......*/	
  		 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  		 //设置PLL为系统时钟源
  		 /*void RCC_SYSCLKConfig(u32 RCC_SYSCLKSource)  设置系统时钟
  		 RCC_SYSCLKSource_HSI 
  		 RCC_SYSCLKSource_HSE 
  		 RCC_SYSCLKSource_PLLCLK  选HSI  HSE PLL 作为系统时钟*/ 		 		 while(RCC_GetSYSCLKSource() != 0x08);
  		 //判断PLL是否是系统时钟
  		 /*u8 RCC_GetSYSCLKSource(void)  返回用作系统时钟的时钟源
  		 0x00:HSI   0x04:HSE 0x08:PLL */
  	 }	 
  	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | 
  													RCC_APB2Periph_AFIO , ENABLE);
  	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
  	 //U2  U3 时钟在APB1
  	 //打开GPIO时钟,复用功能,串口1的时钟	 								     RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟		 
  	 /*void RCC_APB2PeriphClockCmd(u32 RCC_APB2Periph, FunctionalState NewState) 
  		enable 或 disable apb2 外设时钟
  	 RCC_APB2Periph_AFIO  功能复用IO 时钟
  	 RCC_APB2Periph_GPIOA/B/C/D/E   GPIOA/B/C/D/E 时钟
  	 RCC_APB2Periph_ADC1/ADC2			ADC1/2 时钟
  	 RCC_APB2Periph_TIM1 
  	 RCC_APB2Periph_SPI1
  	 RCC_APB2Periph_USART1 
  	 RCC_APB2Periph_ALL			全部APB2外设时钟*/
  }

GPIO

  #include "GPIO.h"
  
  void MYGPIO_Init(void)
  {
  	 GPIO_InitTypeDef GPIO_InitStructure;
  	//GPIO_InitStructure初始化结构体为GPIO_InitTypeDef结构
  	 GPIO_DeInit(GPIOA);
  	 GPIO_StructInit(&GPIO_InitStructure);
  	//函数:指向结构GPIO_InitTypeDef的指针,待初始化
  	
  	//CAN TX  : A12
  	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
  	//CAN TX  : A11
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
  	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化IO
  	
  	// USART TX :A9
  	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;	
  	//GPIO_SPEED:GPIO_SPEED_10MHz/_2MHz/_50MHz   最高输出速率
  	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  	/*Mode,工作状态:GPIO_MODE_AIN  ----- 模拟输入
  														_IN_FLOATING  ----- 浮空输入
  														_IPD  ----- 上拉输出
  														_IPU  ----- 上拉输入
  														_OUT_OD  ----- 开漏输出
  														_OUT_PP  ----- 推挽输出
  														_AF_OD  ----- 复用开漏输出
  														_AF_PP  ----- 复用推挽输出*/	
  	 GPIO_Init(GPIOA , &GPIO_InitStructure);
  	
  	 // USART RX :A10
  	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	 
  	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  	 //IO浮空输入
  	 GPIO_Init(GPIOA, &GPIO_InitStructure);
  	 //初始化
  }

CAN

  #include "can.h"
  #include "delay.h"
  #include "usart.h"
  
  //波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
  //mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
  u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
  { 
  	CAN_InitTypeDef        	CAN_InitStructure;
  	CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
  NVIC_InitTypeDef  		NVIC_InitStructure;
  
  CAN_DeInit(CAN1);//重置can1为复位状态
  	//f10x的库函数文件里面居然定义了两个CAN!
  	CAN_StructInit(&CAN_InitStructure);//复位重置所有的成员变量
  	CAN_InitStructure.CAN_TTCM=DISABLE;	
  	//enable or disable 时间触发通讯模式
  	//非时间触发通信模式  
  	CAN_InitStructure.CAN_ABOM=DISABLE;		
  	//enable or disable 自动离线管理
  	//软件自动离线管理	 
  	CAN_InitStructure.CAN_AWUM=DISABLE;		
  	//enable or disable 自动唤醒模式
  	//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
  	
  	CAN_InitStructure.CAN_NART=ENABLE;			
  	//enable or disable 非自动重传
  	//禁止报文自动传送 
  	
  	CAN_InitStructure.CAN_RFLM=DISABLE;		 	
  	//enable or disable 接收FIFO 锁定模式
  	//报文不锁定,新的覆盖旧的  
  	CAN_InitStructure.CAN_TXFP=DISABLE;			
  	//enable or disable 发送FIFO 优先级
  	//优先级由报文标识符决定 
  	CAN_InitStructure.CAN_Mode= mode;	      
  	/*CAN_Mode_Normal  CAN硬件工作在正常模式
  		CAN_Mode_silent  CAN硬件工作在静默模式
  		CAN_Mode_LoopBack 环回模式
  		CAN_Mode_Silent_LoopBack  静默环回模式*/
  	//模式设置: mode:0,普通模式;1,回环模式; 
  	//设置波特率
  	CAN_InitStructure.CAN_SJW=tsjw;				
  	/*重新同步跳跃宽度(Tsjw),每位中可以延长或缩短多少个时间单位的上限
  	为tsjw+1个时间单位  
  	CAN_SJW_1tq	 重新同步跳跃宽度为 1 个时间单位
  	CAN_SJW_2tq 
  	CAN_SJW_3tq 
  	CAN_SJW_4tq*/
  	CAN_InitStructure.CAN_BS1=tbs1; 			
  	/*时间段 1 的时间单位数目  为1--16个时间单位*/
  	//Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
  	CAN_InitStructure.CAN_BS2=tbs2;				
  	/*时间段 2 的时间单位数目  为1--8个时间单位*/
  	//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
  	CAN_InitStructure.CAN_Prescaler=brp;       
  	/*设定一个时间单位的长度,范围是1---1024,实际会减一,这是什么鬼???*/ 
  	//分频系数(Fdiv)为 brp+1	因为实际会减一,所以这里有加一???
  	CAN_Init(CAN1, &CAN_InitStructure);        	//初始化CAN1 
  
  	//can 过滤器设置
  	CAN_FilterInitStructure.CAN_FilterNumber=0;	
  	//指定待初始化的过滤器,范围是1---13
  	//过滤器0
  	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	
  	/*CAN_FilterMode_IdMask   标识符屏蔽位模式
  		CAN_FilterMode_IdList   标识符列表模式*/
  	//屏蔽位模式
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; 	
  	/*过滤器位宽 
  	CAN_FilterScale_Two16bit  2 个 16 位过滤器
  	CAN_FilterScale_One32bit  1 个 32 位过滤器
  	因为版本吧 CAN_FilterScale_One32bit 已变为 CAN_FilterScale_32bit*/
  	//32位宽 	
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;	
  	/*设定过滤器标识符,范围是0x0000---0xFFFF
  	32 位位宽时为其高段位,16 位位宽时为第一个*/
  	//32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	/*设定过滤器标识符,范围是0x0000---0xFFFF
  	32 位位宽时为其低段位,16 位位宽时为第二个*/
  	
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  	/*设定过滤器屏蔽标识符或者过滤器标识符,范围是0x0000---0xFFFF
  	32 位位宽时为其高段位,16 位位宽时为第一个*/
  	//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  	/*设定过滤器屏蔽标识符或者过滤器标识符,范围是0x0000---0xFFFF
  	32 位位宽时为其低段位,16 位位宽时为第二个*/
  	
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
  	//设定了过滤器指向的FIFO : 0或1
  	/*CAN_FilterFIFO0  过滤器 FIFO 指向 过滤器x
  	  CAN_FilterFIFO1		过滤器 FIF1 指向 过滤器x  */
  	//过滤器0关联到FIFO0
  	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  	//激活过滤器0   enable or disable
  
  	CAN_FilterInit(&CAN_FilterInitStructure);			//滤波器初始化
  
  CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);				
  	/*enable or disable can中断
  	CAN_IT_FMP0   FIFO0消息挂号中断允许.		*/  
  
  	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  	//USB 低优先级 or CAN 接收 0 中断
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     
  	// 主优先级为1
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            
  	// 次优先级为0
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);	
  
  return 0; //配置成功返回 0 
  }
  
  //如果是开启了,就有中断服务函数			    
  void USB_LP_CAN1_RX0_IRQHandler(void)
  {
    CanRxMsg RxMessage;
  	int i=0;
  	can_ack = 1;
    CAN_Receive(CAN1, 0, &RxMessage);
  	for(i=0;i<8;i++)
      can_rx[i]=RxMessage.Data[i];
  }
  

Led

  #include "led.h"
  
  //初始化PB12和13为输出口.并使能这两个口的时钟		    
  
  void LED_Init(void)
  { 
   GPIO_InitTypeDef  GPIO_InitStructure; 	
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口时钟	
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;				 
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
   GPIO_Init(GPIOB, &GPIO_InitStructure);				//根据设定参数初始化GPIOB
   GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
  }

欢迎讨论,共同学习



  • 0
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
### 回答1: STM32是意法半导体(STMicroelectronics)推出的一款32位微控制器系列产品。该系列产品有丰富的外设资源和强大的性能,广泛应用于各种电子设备中。 TJA1050是一款CAN(控制器局域网络)收发器芯片,常用于汽车电子系统中。它能够实现CAN总线的物理层接口功能,实现CAN数据的传送和接收。 10k是指在CAN总线中,该芯片能够支持最高传输速率为10kbps(千比特每秒)。传输速率是指CAN总线上数据传输的速度,不同的应用场景需要不同的传输速率来满足数据传输的要求。 在STM32中使用TJA1050 10k,可以实现嵌入式设备与汽车电子系统之间的CAN通信。通过将TJA1050与STM32微控制器连接,可以实现对CAN总线的控制和数据的传输。这样,嵌入式设备可以与汽车电子系统进行双向通信,实现各种功能,如车辆故障码读取、参数设置、状态监测等。 总之,STM32 TJA1050 10k的组合,可以为嵌入式设备提供高效可靠的CAN通信功能,是汽车电子系统与嵌入式设备之间通信的重要部分。 ### 回答2: STM32是STMicroelectronics推出的一系列32位微控制器的产品线,是市场上应用广泛的嵌入式系统开发平台之一。TJA1050是一款CAN总线收发器芯片,常用于汽车电子领域。 STM32 TJA1050 10K是指在STM32微控制器与TJA1050之间使用10K欧姆电阻进行抑制。在CAN总线的设计中,为了避免总线上出现过大的电平差异,需要在总线的两端分别连接抑制电阻。这些抑制电阻的作用是限制总线上电平的过度变化,以减少干扰和反射。 而TJA1050作为CAN总线收发器,负责将微控制器的CAN信号转换为CAN总线上的差分信号,以便在总线上进行数据的传输。 通过将STM32与TJA1050之间连接一个10K欧姆的抑制电阻,可以使得CAN总线上的信号更加稳定。这是因为抑制电阻的存在使得CAN总线上信号的上升时间和下降时间变得更长,阻尼了信号的过度变化,减少了信号的反射和干扰,提高了总线的可靠性和稳定性。 因此,STM32 TJA1050 10K表示在将STM32微控制器与TJA1050连接时,使用了10K欧姆的抑制电阻以提高CAN总线的稳定性和可靠性。 ### 回答3: STM32是意法半导体(STMicroelectronics)所推出的一系列高性能、低功耗的32位微控制器。它拥有丰富的外设和强大的处理能力,适用于各种应用领域。 TJA1050是一款CAN(Controller Area Network,控制器局域网)收发器芯片,专门用于CAN总线的数据传输。它具有高速和高可靠性的特点,广泛应用于汽车电子、工业自动化、仪器仪表等领域。 "10k"可能是指TJA1050芯片的工作速率。CAN总线的速率可以根据具体需求进行配置,10k可能代表了CAN总线的传输速率为10 kbit/s(千比特/秒)。 STM32与TJA1050可以配合使用,实现CAN总线的数据收发功能。通过STM32的GPIO引脚与TJA1050芯片进行连接,可以将STM32的数据通过CAN总线发送给其他设备,也可以接收其他设备通过CAN总线发送的数据。 通过STM32的软件编程,可以配置TJA1050的工作模式、波特率等参数,进而实现对CAN总线的控制和数据传输。可以利用STM32的CAN外设中断功能,实现CAN总线的数据接收和发送的实时处理。 综上所述,STM32和TJA1050是一对合作良好的芯片组合,能够实现CAN总线的可靠数据传输,广泛应用于各种领域的汽车、工业和仪器设备中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值