第九章AT32F403A替换stm32f103 can通讯测试

前言

        此文章是使用AT32F403A的开发板去跑stm32f103can通讯功能的测试情况

硬件

     

       硬件方面使用的是自己画的板子,使用的AT32F403ARCT7,外设方面有USART2USART3CAN1CAN2SPIIICUSBSDIOUSART接的是max485的芯片;CAN的收发芯片都是SIT1050(芯力特国产品牌,可替换tja1050);SPI的是接了一颗W25Q12816M的容量;IIC接的是一颗AT24C04SDIO可插SD卡。仿真口以及串口1则使用的ATLINK的接口定义,直接使用ATLINK插上即可。USART2USART3485芯片,可以通过跳线帽对接起来;CAN1CAN2也是一样。

      本测试是使用的两个板子的CAN1的收发芯片的H,L对接起来,要对着接不能交叉,否则无法通讯。

        

软件

        测试使用的软件是stm32f103的3.5标准库的工程代码。想快速验证的可以下正点、野火等的代码回来再根据自己外设的硬件的设计稍微修改就可以进行测试,就是库是stm32F103的3.5标准库的。

软件相关部分:

    由于CAN1的IO是使用的PB8,PB9,使用的是重映射1,软件需要配置重映射。

软件方面设定CAN的波特率是500k,使用的中断方式接收数据,接收到的帧的ID如果是我们设定的ID那就把收到的数据个打印出来。板子1发送的帧的ID是0x11,板子2发送的帧的ID是0x12。

相关代码如下:

void CAN1_Init(void)
{ 
	GPIO_InitTypeDef 		GPIO_InitStructure; 
	CAN_InitTypeDef        	CAN_InitStructure;
	CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
	NVIC_InitTypeDef  		NVIC_InitStructure;


	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//使能PORTA时钟	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);		//使能CAN1时钟

	GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;				//复用推挽
	GPIO_Init(GPIOB, &GPIO_InitStructure);						//初始化IO

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;				//上拉输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);						//初始化IO
	
	
	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	//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= CAN_Mode_Normal;
	
	//设置波特率  36M/((7+1+8+1+1)*4)=500Kbps
	CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;				
	CAN_InitStructure.CAN_BS1=CAN_BS1_9tq; 			
	CAN_InitStructure.CAN_BS2=CAN_BS2_8tq;				
	CAN_InitStructure.CAN_Prescaler=4;         
	CAN_Init(CAN1, &CAN_InitStructure);        

	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;
	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消息挂号中断允许.		    

}

板子1的发送函数和中断接收函数:
//发送的帧的ID是0x11,数据为0x11-0x18

u8 Can1_Send_Msg(void)
{	
	u8 mbox1;
	u16 i=0;
	CanTxMsg Can1TxMessage;
	Can1TxMessage.StdId=0x11;			// 标准标识符 
	Can1TxMessage.ExtId=0x11;			// 设置扩展标示符 
	Can1TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
	Can1TxMessage.RTR=CAN_RTR_Data;		// 数据帧
	Can1TxMessage.DLC=8;				// 要发送的数据长度
	
	Can1TxMessage.Data[0]=0x11;	
	Can1TxMessage.Data[1]=0x12;
	Can1TxMessage.Data[2]=0x13;
	Can1TxMessage.Data[3]=0x14;
	Can1TxMessage.Data[4]=0x15;
	Can1TxMessage.Data[5]=0x16;
	Can1TxMessage.Data[6]=0x17;
	Can1TxMessage.Data[7]=0x18;	
	mbox1= CAN_Transmit(CAN1, &Can1TxMessage);   
	i=0; 
	while((CAN_TransmitStatus(CAN1, mbox1)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
	if(i>=0XFFF)return 1;
	return 0;	 
}

//中断服务函数,接收的帧的id是0x12(也就是板子2发送的帧的id)		    
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
	if(RxMessage.StdId==0x12)
	{
		printf ("rxbuf:\r\n");
		for(i=0;i<8;i++)
		printf("%02x ",RxMessage.Data[i]);
	}
	printf("\r\n");

}

板子2的发送函数和中断接收函数:
//中断服务函数,接收的帧的id是0x11(也就是板子1发送的帧的id)			    
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
	if(RxMessage.StdId==0x11)
	{
		printf ("rxbuf:\r\n");
		for(i=0;i<8;i++)
		printf("%02x ",RxMessage.Data[i]);
	}
	printf("\r\n");

}


//发送的帧的ID是0x12,数据为0x21-0x28
u8 Can1_Send_Msg(void)
{	
	u8 mbox1;
	u16 i=0;
	CanTxMsg Can1TxMessage;
	Can1TxMessage.StdId=0x12;			// 标准标识符 
	Can1TxMessage.ExtId=0x11;			// 设置扩展标示符 
	Can1TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
	Can1TxMessage.RTR=CAN_RTR_Data;		// 数据帧
	Can1TxMessage.DLC=8;				// 要发送的数据长度
	
	Can1TxMessage.Data[0]=0x21;	
	Can1TxMessage.Data[1]=0x22;
	Can1TxMessage.Data[2]=0x23;
	Can1TxMessage.Data[3]=0x24;
	Can1TxMessage.Data[4]=0x25;
	Can1TxMessage.Data[5]=0x26;
	Can1TxMessage.Data[6]=0x27;
	Can1TxMessage.Data[7]=0x28;	
	mbox1= CAN_Transmit(CAN1, &Can1TxMessage);   
	i=0; 
	while((CAN_TransmitStatus(CAN1, mbox1)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
	if(i>=0XFFF)return 1;
	return 0;	 
}


Main函数://每1s发送一次数据。
int main(void)
 {	 
	u8 cnt=0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	 
	delay_init();	    	
	uart1_init(115200);	
	printf ("AT32F403A 替换SXX32f103 can通讯测试!!\r\n");
	AT32LED_Init();		  		
	CAN1_Init();
	
 	while(1)
	{		
		cnt++; 
		delay_ms(10);
		if(cnt==100)
		{
			LED2=!LED2;//提示系统正在运行
			Can1_Send_Msg();	
			cnt=0;
		}		   
	}
}

  

测试结果

         通过看串口助手的log,程序已经运行起来,收发的数据和我们设定的是一致的:

              

总结

        从测试来看,AT32F403A是可以直接的跑stm32f103can的代码,在使用上一致。

        这里需要注意的是使用的库的版本,at32can口需要唤醒后再初始化才能初始化成功。有的st的库在初始化函数里面没有先把can口唤醒,导致初始化没有成功,通讯异常。

        本文仅用于学习,测试使用。

        有什么问题的可加qq群技术交流。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐