【STM32F407】关于can通讯的简单boot loader设计

一、基础知识

  关于can和boot loader是什么,这里不阐释,网上很多资料,也可参考以下链接。

can:https://zhuanlan.zhihu.com/p/358266880 

BootLoader:https://zhuanlan.zhihu.com/p/556181275

二、代码

此部分都是基于正点原子例程的修改

1、can部分

  • can.c
#include "can.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

//can的初始化 
//tsjw:重新同步跳跃时间单位,范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单位,范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单位,范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器,范围:1~1024; tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为42M,
//如果设置为CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
//波特率: 42M/((6+7+1)*6)=500Kbps

CanRxMsg RxMessage;
u8 CANRecFlag = 0;

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;
#if CAN1_RX0_INT_ENABLE 
   	NVIC_InitTypeDef  NVIC_InitStructure;
#endif
    //使能相关时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);	                   											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
	
    //初始化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);
	
	//引脚复用映射配置
	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_InitStructure.CAN_SJW=tsjw;	
  	CAN_InitStructure.CAN_BS1=tbs1; 
  	CAN_InitStructure.CAN_BS2=tbs2;
  	CAN_InitStructure.CAN_Prescaler=brp; 	
  	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);
		
#if CAN1_RX0_INT_ENABLE
	
	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);		    
  
  	NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
}   
 
#if CAN1_RX0_INT_ENABLE	
//中断服务函数		    
void CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1,0,&RxMessage);
	for(i=0;i<8;i++)
	printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif


//can:发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)			     
//msg:数据指针,最大为八个字节。

u8 CAN1_Send_Msg(u8* msg,u8 len)
{	
  u8 mbox;
  u16 i=0;
  CanTxMsg TxMessage;
  TxMessage.StdId=0x12;	 
  TxMessage.ExtId=0x12;	 
  TxMessage.IDE=0;		 
  TxMessage.RTR=0;		  
  TxMessage.DLC=len;						
  for(i=0;i<len;i++)
  TxMessage.Data[i]=msg[i];				      
  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;		

}

//can:接收数据
//buf:数据缓存区	 
u8 CAN1_Receive_Msg(u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;
    if(CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;		
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据
    for(i=0;i<RxMessage.DLC;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}
  • can.h
    #ifndef __CAN_H
    #define __CAN_H	 
    #include "sys.h"	    
    
    
    #define CAN1_RX0_INT_ENABLE	0										    
    										 							 				    
    u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);
     
    u8 CAN1_Send_Msg(u8* msg,u8 len);						
    
    u8 CAN1_Receive_Msg(u8 *buf);							
    #endif
    

    二、flash部分

  • stm32flash.c
    #include "stmflash.h"
    #include "delay.h"
    #include "usart.h" 
     
    
    u32 STMFLASH_ReadWord(u32 faddr)
    {
    	return *(vu32*)faddr; 
    }  
    
    
    uint16_t STMFLASH_GetFlashSector(u32 addr)
    {
    	if(addr<ADDR_FLASH_SECTOR_1)return FLASH_Sector_0;
    	else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_Sector_1;
    	else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_Sector_2;
    	else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_Sector_3;
    	else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_Sector_4;
    	else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_Sector_5;
    	else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_Sector_6;
    	else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_Sector_7;
    	else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_Sector_8;
    	else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_Sector_9;
    	else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_Sector_10; 
    	return FLASH_Sector_11;	
    }
    
    
    void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)	
    { 
      FLASH_Status status = FLASH_COMPLETE;
    	u32 addrx=0;
    	u32 endaddr=0;	
      if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;	
    	FLASH_Unlock();									
      FLASH_DataCacheCmd(DISABLE);
     		
    	addrx=WriteAddr;				
    	endaddr=WriteAddr+NumToWrite*4;	
    	if(addrx<0X1FFF0000)			
    	{
    		while(addrx<endaddr)		
    		{
    			if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)
    			{   
    				status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);
    				if(status!=FLASH_COMPLETE)break;	
    			}else addrx+=4;
    		} 
    	}
    	if(status==FLASH_COMPLETE)
    	{
    		while(WriteAddr<endaddr)
    		{
    			if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)
    			{ 
    				break;	
    			}
    			WriteAddr+=4;
    			pBuffer++;
    		} 
    	}
      FLASH_DataCacheCmd(ENABLE);	
    	FLASH_Lock();
    } 
    
    
    void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)   	
    {
    	u32 i;
    	for(i=0;i<NumToRead;i++)
    	{
    		pBuffer[i]=STMFLASH_ReadWord(ReadAddr);
    		ReadAddr+=4;//Æ«ÒÆ4¸ö×Ö½Ú.	
    	}
    }

    明天放假,后天更新,拜拜。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值