国产 MCU AT32F403A 替换 STM32F105 移植双can通讯

第十章AT32F403A替换stm32f105 can通讯测试

前言

        此文章是修改stm32f105的工程,可在AT32F403A上跑双can通讯功能。

硬件

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

        本测试是使用的板子上的CAN1CAN2互发信息,所以右上角的用跳线帽把H1H2对接,L1L2对接。

         

  

软件

    

        测试使用的软件是stm32f105的3.5标准库的工程代码。由于AT32F403A的CAN2和stm32f105的CAN2是存在差异的,AT32的CAN1和CAN2是相互独立的,滤波器也是相互独立的,而f105的CAN2和CAN1有关联,所以必须修改库才能使用CAN2。

        系统时钟差异:AT32时钟配置是可以直接替换f103的,但是f103和f105的系统时钟是不一样的,所以需要配置系统时钟的和f103的一样的。

void RCC_Config(void)
{
  u8 HSEStartUpStatus = 0;
  
  RCC_DeInit();                     //初始化

  RCC_HSEConfig(RCC_HSE_ON);        //时能外部晶振

  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    RCC_PCLK2Config(RCC_HCLK_Div1);                         //APB2预分频    /* PCLK2 = HCLK 最大72Mhz*/

    RCC_PCLK1Config(RCC_HCLK_Div2);                         //APB1预分频 = 72Mhz / 2 = 36MHz    /* PCLK1 = HCLK/4 最大36MHz*/

    RCC_HCLKConfig(RCC_SYSCLK_Div1);                        //AHB预分频     /* HCLK = SYSCLK */

    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);     /* PLLCLK = 8MHz * 9 = 72 MHz */

    RCC_PLLCmd(ENABLE);                                     /* Enable PLL */ 

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)      /* Wait till PLL is ready */
    {
    }

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);              /* Select PLL as system clock source */

    while(RCC_GetSYSCLKSource() != 0x08)                    /* Wait till PLL is used as system clock source */
    {
    }    
  }
}

    中断号差异:

 CAN滤波器初始化函数:

void CAN_FilterInit(CAN_TypeDef* CANx,CAN_FilterInitTypeDef* CAN_FilterInitStruct)    //AT32 CAN2
{
  uint32_t filter_number_bit_pos = 0;
  /* Check the parameters */
  assert_param(IS_CAN_ALL_PERIPH(CANx));
  assert_param(IS_CAN_FILTER_NUMBER(CAN_FilterInitStruct->CAN_FilterNumber));
  assert_param(IS_CAN_FILTER_MODE(CAN_FilterInitStruct->CAN_FilterMode));
  assert_param(IS_CAN_FILTER_SCALE(CAN_FilterInitStruct->CAN_FilterScale));
  assert_param(IS_CAN_FILTER_FIFO(CAN_FilterInitStruct->CAN_FilterFIFOAssignment));
  assert_param(IS_FUNCTIONAL_STATE(CAN_FilterInitStruct->CAN_FilterActivation));

  filter_number_bit_pos = ((uint32_t)1) << CAN_FilterInitStruct->CAN_FilterNumber;

  /* Initialisation mode for the filter */
  CANx->FMR |= FMR_FINIT;

  /* Filter Deactivation */
  CANx->FA1R &= ~(uint32_t)filter_number_bit_pos;

  /* Filter Scale */
  if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_16bit)
  {
    /* 16-bit scale for the filter */
    CANx->FS1R &= ~(uint32_t)filter_number_bit_pos;

    /* First 16-bit identifier and First 16-bit mask */
    /* Or First 16-bit identifier and Second 16-bit identifier */
    CANx->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = 
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow) << 16) |
        (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);

    /* Second 16-bit identifier and Second 16-bit mask */
    /* Or Third 16-bit identifier and Fourth 16-bit identifier */
    CANx->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = 
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |
        (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh);
  }

  if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)
  {
    /* 32-bit scale for the filter */
    CANx->FS1R |= filter_number_bit_pos;
    /* 32-bit identifier or First 32-bit identifier */
    CANx->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = 
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) << 16) |
        (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);
    /* 32-bit mask or Second 32-bit identifier */
    CANx->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = 
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |
        (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow);
  }

  /* Filter Mode */
  if (CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdMask)
  {
    /*Id/Mask mode for the filter*/
    CANx->FM1R &= ~(uint32_t)filter_number_bit_pos;
  }
  else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
  {
    /*Identifier list mode for the filter*/
    CANx->FM1R |= (uint32_t)filter_number_bit_pos;
  }

  /* Filter FIFO assignment */
  if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO0)
  {
    /* FIFO 0 assignation for the filter */
    CANx->FFA1R &= ~(uint32_t)filter_number_bit_pos;
  }

  if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO1)
  {
    /* FIFO 1 assignation for the filter */
    CANx->FFA1R |= (uint32_t)filter_number_bit_pos;
  }
  
  /* Filter activation */
  if (CAN_FilterInitStruct->CAN_FilterActivation == ENABLE)
  {
    CANx->FA1R |= filter_number_bit_pos;
  }

  /* Leave the initialisation mode for the filter */
  CANx->FMR &= ~FMR_FINIT;
}

软件相关部分:

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

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

相关代码如下:

u8 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);		//使能GPIOB时钟	 
	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

	//CAN单元设置
	CAN_InitStructure.CAN_TTCM=DISABLE;			//非时间触发通信模式  
	CAN_InitStructure.CAN_ABOM=ENABLE;			//软件自动离线管理	 
	CAN_InitStructure.CAN_AWUM=ENABLE;			//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
	CAN_InitStructure.CAN_NART=DISABLE;			//禁止报文自动传送 
	CAN_InitStructure.CAN_RFLM=DISABLE;		 	//报文不锁定,新的覆盖旧的  
	CAN_InitStructure.CAN_TXFP=DISABLE;			//优先级由报文标识符决定 
	CAN_InitStructure.CAN_Mode= CAN_Mode_Normal;	        //模式设置: mode:0,普通模式;1,回环模式; 
	
	//设置波特率  36M/((8+9+1)*4)=500Kbps
	CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;				//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq	 CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
	CAN_InitStructure.CAN_BS1=CAN_BS1_9tq; 			//Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
	CAN_InitStructure.CAN_BS2=CAN_BS2_8tq;				//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
	CAN_InitStructure.CAN_Prescaler=4;        //分频系数(Fdiv)为brp+1	
	CAN_Init(CAN1, &CAN_InitStructure);        	//初始化CAN1 

	CAN_FilterInitStructure.CAN_FilterNumber=0;	//过滤器0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	//屏蔽位模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; 	//32位宽 
	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;	//32位ID
	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0

	CAN_FilterInit(CAN1,&CAN_FilterInitStructure);			//滤波器初始化
	

	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);				//FIFO0消息挂号中断允许.		    

	NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     // 主优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;            // 次优先级为0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	return 0;
} 


u8 CAN2_Init()
{ 
	GPIO_InitTypeDef 		GPIO_InitStructure; 
	CAN_InitTypeDef        	CAN_InitStructure;
	CAN_FilterInitTypeDef  	CAN_FilterInitStructure; 
	NVIC_InitTypeDef  		NVIC_InitStructure;


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

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);//使能CAN2时钟	

    //CAN2 GPIO配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;           //带上拉输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);	
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         //推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);

	//CAN单元设置
	CAN_InitStructure.CAN_TTCM=DISABLE;			//非时间触发通信模式  
	CAN_InitStructure.CAN_ABOM=ENABLE;			//软件自动离线管理	 
	CAN_InitStructure.CAN_AWUM=ENABLE;			//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
	CAN_InitStructure.CAN_NART=DISABLE;			//禁止报文自动传送 
	CAN_InitStructure.CAN_RFLM=DISABLE;		 	//报文不锁定,新的覆盖旧的  
	CAN_InitStructure.CAN_TXFP=DISABLE;			//优先级由报文标识符决定 
	CAN_InitStructure.CAN_Mode= CAN_Mode_Normal;	        //模式设置: mode:0,普通模式;1,回环模式; 

	//设置波特率  36M/((8+9+1)*4)=500Kbps
	CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;				//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq	 CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
	CAN_InitStructure.CAN_BS1=CAN_BS1_9tq; 			//Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
	CAN_InitStructure.CAN_BS2=CAN_BS2_8tq;				//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
	CAN_InitStructure.CAN_Prescaler=4;        //分频系数(Fdiv)为brp+1	
	CAN_Init(CAN2, &CAN_InitStructure);        	//初始化CAN1 

	CAN_FilterInitStructure.CAN_FilterNumber=0;	//过滤器0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	//屏蔽位模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; 	//32位宽 
	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;	//32位ID
	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0

	CAN_FilterInit(CAN2,&CAN_FilterInitStructure);			//滤波器初始化
	

	CAN_ITConfig(CAN2,CAN_IT_FMP0,ENABLE);				//FIFO0消息挂号中断允许.		    

	NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     // 主优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;            // 次优先级为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);
	printf ("CAN1_RX0_IRQHandler:\r\n");
	if(RxMessage.StdId==0x12)
	{
		printf ("rxbuf:\r\n");
		for(i=0;i<8;i++)
		printf("%02x ",RxMessage.Data[i]);
	}
	printf("\r\n");
}

void CAN2_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN2, 0, &RxMessage);
	printf ("CAN2_RX0_IRQHandler:\r\n");
	if(RxMessage.StdId==0x11)
	{
		printf ("rxbuf:\r\n");
		for(i=0;i<8;i++)
		printf("%02x ",RxMessage.Data[i]);
	}
	printf("\r\n");
}




//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 Can1_Send_Msg()
{	
	u8 mbox;
	u16 i=0;
	CanTxMsg TxMessage;
	TxMessage.StdId=0x11;			// 标准标识符 
	TxMessage.ExtId=0x12;			// 设置扩展标示符 
	TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
	TxMessage.RTR=CAN_RTR_Data;		// 数据帧
	TxMessage.DLC=8;				// 要发送的数据长度

	TxMessage.Data[0]=0x01;
	TxMessage.Data[1]=0x01;
	TxMessage.Data[2]=0x01;
	TxMessage.Data[3]=0x01;
	TxMessage.Data[4]=0x01;
	TxMessage.Data[5]=0x01;
	TxMessage.Data[6]=0x01;
	TxMessage.Data[7]=0x01;	
	
	mbox= CAN_Transmit(CAN1, &TxMessage);   
	i=0; 
	while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
	if(i>=0XFFF)return 1;
	return 0;	 
}

u8 Can2_Send_Msg()
{	
	u8 mbox;
	u16 i=0;
	CanTxMsg TxMessage;
	TxMessage.StdId=0x12;			// 标准标识符 
	TxMessage.ExtId=0x12;			// 设置扩展标示符 
	TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
	TxMessage.RTR=CAN_RTR_Data;		// 数据帧
	TxMessage.DLC=8;				// 要发送的数据长度

	TxMessage.Data[0]=0x02;
	TxMessage.Data[1]=0x02;
	TxMessage.Data[2]=0x02;
	TxMessage.Data[3]=0x02;
	TxMessage.Data[4]=0x02;
	TxMessage.Data[5]=0x02;
	TxMessage.Data[6]=0x02;
	TxMessage.Data[7]=0x02;	
	
	mbox= CAN_Transmit(CAN2, &TxMessage);   
	i=0; 
	while((CAN_TransmitStatus(CAN2, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
	if(i>=0XFFF)return 1;
	return 0;	 
}


int main(void)
 {	 

    u8 t=0;
	RCC_Config();
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
	printf ("AT32F403A 替换SXX32f105 双can通讯测试!!\r\n");
	AT32LED_Init();		  		 	

	CAN1_Init(); 
	CAN2_Init();

	GetClk();
	
 	while(1)
	{		 

		t++; 
		delay_ms(10);
		if(t%50==0)
		{
			LED4=!LED4;//提示系统正在运行	

		}
		if(t%100==0)
		{	   
			Can1_Send_Msg();
			delay_ms(500);
			Can2_Send_Msg();
			LED2=!LED2;
		}	        
	}
}

测试结果

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

总结

        AT32F403A的CAN2STM32F105CAN2是不一样的,不能兼容。必须修改库才能在AT32上使用,主要就是中断号以及滤波器不一样。

本文仅供于学习、测试使用。  

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值