一、基础知识
关于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¸ö×Ö½Ú. } }
明天放假,后天更新,拜拜。。。