STM32-F407 CAN的双机通讯

CSDN的第一篇博客,记录个自己犯的大傻,也希望对之后看到的人能够有所帮助,不要像我一样调几天才发现。

直奔主题,我是在原子哥F407例程的基础上想实现双机CAN通讯

STM32-F407 CAN的双机通讯_第1张图片

我用的核心板为STM32-F407ZGT6,原理图上看到PA11、PA12引脚可以复用为CAN1_RX和CAN1_TX,在与CAN收发器接线时不要接错,PA11与收发器TXD相连,PA12与收发器RXD相连。收发器建议用HVP230,可以用板子3.3V供电;TJA1050也可以,不过需要5V供电,这点需要注意。

CAN的初始化:

u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

  	GPIO_InitTypeDef       GPIO_InitStructure; 
	CAN_InitTypeDef        CAN_InitStructure;
  	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
    //时钟使能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//PORTA时钟使能                  											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//CAN1时钟使能
	
    //GPIO初始化
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
	
	//CAN引脚复用	
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); 	  
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);
	  
  	//CAN单元设置
   	CAN_InitStructure.CAN_TTCM=DISABLE;	
  	CAN_InitStructure.CAN_ABOM=DISABLE;	  
  	CAN_InitStructure.CAN_AWUM=DISABLE;
  	CAN_InitStructure.CAN_NART=ENABLE;	
  	CAN_InitStructure.CAN_RFLM=DISABLE;
  	CAN_InitStructure.CAN_TXFP=DISABLE;	
  	CAN_InitStructure.CAN_Mode= mode;	//CAN模式设置
  	CAN_InitStructure.CAN_SJW=tsjw;	
  	CAN_InitStructure.CAN_BS1=tbs1;
  	CAN_InitStructure.CAN_BS2=tbs2;
  	CAN_InitStructure.CAN_Prescaler=brp; 
  	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1
    
	//配置过滤器
 	CAN_FilterInitStructure.CAN_FilterNumber=0;	 
  	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
   	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
  	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器
  	CAN_FilterInit(&CAN_FilterInitStructure);//过滤器初始化,此处设置接收所有报文
		

	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);
	return 0;
}   

中断处理函数为: 

void CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
        CAN_Receive(CAN1, 0, &RxMessage);
	for(i=0;i<8;i++)
	printf("DATA[%d]:%d\r\n",i,RxMessage.Data[i]);
	LED1=!LED1;
}

发送函数就根据自己的需求设置ID,数据等,此处不表,例程里都有。

重点:主函数中两个板子的模式初始化不同!!!

CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,Mode);

CAN1模式初始化中,前4位设置总线波特率为500Kbps,重点在于最后的Mode。原子哥例程和我看到的其他例程相同,都是可以选择自发自收或者普通模式。实际操作程序下到两块板子里,检查各自报文的自发自收也确实没有问题,但就是不能互相通讯。

查看STM32F4中文参考手册,CAN_Mode可以设置为静默、环回、环回与静默组合、正常模式。于是试着将其中一块板子的CAN模式改为静默模式(即只接收而不发送),另一块仍然是正常模式,结果接收消息没有问题!

泪流满面,仰天长啸啊,折腾了几天的问题原来这么简单。细细思考,自己一开始就没有仔细想过CAN报文ID冲突的问题,一套例程下到两块板子里,同时发送相同ID的CAN报文,总线上的仲裁机制失效,当然就不能够正常通讯了。如果想要实现两块板子的互发互收,就要设置不同ID的CAN报文。

以此为鉴,以后对待别人的东西,不仅要会用,还要能懂,最重要的是实践。否则就会像上文这样,因为小细节耽误很长时间。

 

你可能感兴趣的:(STM32-F407 CAN的双机通讯)