/*********************************************** 公司:轮趣科技(东莞)有限公司 品牌:WHEELTEC 官网:wheeltec.net 淘宝店铺:shop114407458.taobao.com 速卖通: https://minibalance.aliexpress.com/store/4455017 版本:5.7 修改时间:2021-04-29 Brand: WHEELTEC Website: wheeltec.net Taobao shop: shop114407458.taobao.com Aliexpress: https://minibalance.aliexpress.com/store/4455017 Version:5.7 Update:2021-04-29 All rights reserved ***********************************************/ #include "sys.h" /************************************************************************** Function: Set the vector table offset address Input : Base site Offsets Output : none 函数功能:设置向量表偏移地址 入口参数:NVIC_VectTab:基址 Offset:偏移量 返回 值:无 **************************************************************************/ void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset) { SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//设置NVIC的向量表偏移寄存器 //用于标识向量表是在CODE区还是在RAM区 } /************************************************************************** Function: Set NVIC group Input : NVIC_Group Output : none 函数功能:设置中断分组 入口参数:NVIC_Group:NVIC分组 0~4 总共5组 返回 值:无 **************************************************************************/ void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group) { u32 temp,temp1; temp1=(~NVIC_Group)&0x07;//取后三位 temp1<<=8; temp=SCB->AIRCR; //读取先前的设置 temp&=0X0000F8FF; //清空先前分组 temp|=0X05FA0000; //写入钥匙 temp|=temp1; SCB->AIRCR=temp; //设置分组 } /************************************************************************** Function: Set NVIC group Input : NVIC_PreemptionPriority NVIC_SubPriority NVIC_Channel NVIC_Group Output : none 函数功能:设置中断分组 入口参数:抢占优先级 响应优先级 中断编号 中断分组号 返回 值:无 * 中断分组 | 作用 * --------+-------------------------------------- * 组0 | 0位抢占优先级,4位响应优先级 * 组1 | 1位抢占优先级,3位响应优先级 * 组2 | 2位抢占优先级,2位响应优先级 * 组3 | 3位抢占优先级,1位响应优先级 * 组4 | 4位抢占优先级,0位响应优先级 *NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先 **************************************************************************/ void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group) { //注意优先级不能超过设定的组的范围!否则会有意想不到的错误 u32 temp; MY_NVIC_PriorityGroupConfig(NVIC_Group); //设置分组 temp=NVIC_PreemptionPriority<<(4-NVIC_Group); temp|=NVIC_SubPriority&(0x0f>>NVIC_Group); temp&=0xf;//取低四位 NVIC->ISER[NVIC_Channel/32]|=(1<IP[NVIC_Channel]|=temp<<4; //设置响应优先级和抢断优先级 } /************************************************************************** Function: External interrupt function configuration Input : GPIOx:General-purpose input/output BITx:The port needed enable TRIM:Trigger mode Output : none 函数功能:外部中断函数配置 入口参数:GPIOx:0~6,代表GPIOA~G; BITx:需要使能的位; TRIM:触发模式,1,下升沿;2,上降沿;3,任意电平触发 返回 值:无 **************************************************************************/ //该函数一次只能配置1个IO口,多个IO口,需多次调用 //该函数会自动开启对应中断,以及屏蔽线 void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM) { u8 EXTADDR; u8 EXTOFFSET; EXTADDR=BITx/4;//得到中断寄存器组的编号 EXTOFFSET=(BITx%4)*4; RCC->APB2ENR|=0x01;//使能io复用时钟 AFIO->EXTICR[EXTADDR]&=~(0x000F<EXTICR[EXTADDR]|=GPIOx<IMR|=1<EMR|=1<FTSR|=1<RTSR|=1<APB1RSTR = 0x00000000;//复位结束 RCC->APB2RSTR = 0x00000000; RCC->AHBENR = 0x00000014; //睡眠模式闪存和SRAM时钟使能.其他关闭. RCC->APB2ENR = 0x00000000; //外设时钟关闭. RCC->APB1ENR = 0x00000000; RCC->CR |= 0x00000001; //使能内部高速时钟HSION RCC->CFGR &= 0xF8FF0000; //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0] RCC->CR &= 0xFEF6FFFF; //复位HSEON,CSSON,PLLON RCC->CR &= 0xFFFBFFFF; //复位HSEBYP RCC->CFGR &= 0xFF80FFFF; //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE RCC->CIR = 0x00000000; //关闭所有中断 //配置向量表 #ifdef VECT_TAB_RAM MY_NVIC_SetVectorTable(0x20000000, 0x0); #else MY_NVIC_SetVectorTable(0x08000000,0x0); #endif } //THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI __asm void WFI_SET(void) { WFI; } //关闭所有中断 __asm void INTX_DISABLE(void) { CPSID I; } //开启所有中断 __asm void INTX_ENABLE(void) { CPSIE I; } //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 } /************************************************************************** Function: Go to standby mode Input : none Output : none 函数功能:进入待机模式 入口参数:无 返回 值:无 **************************************************************************/ void Sys_Standby(void) { SCB->SCR|=1<<2; //使能SLEEPDEEP位 (SYS->CTRL) RCC->APB1ENR|=1<<28; //使能电源时钟 PWR->CSR|=1<<8; //设置WKUP用于唤醒 PWR->CR|=1<<2; //清除Wake-up 标志 PWR->CR|=1<<1; //PDDS置位 WFI_SET(); //执行WFI指令 } /************************************************************************** Function: System soft reset Input : none Output : none 函数功能:系统软复位 入口参数:无 返回 值:无 **************************************************************************/ void Sys_Soft_Reset(void) { SCB->AIRCR =0X05FA0000|(u32)0x04; } /************************************************************************** Function: Set JTAG mode Input : mode:JTAG, swd mode settings;00,all enable;01,enable SWD;10,Full shutdown Output : none 函数功能:设置JTAG模式 入口参数:mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭; 返回 值:无 **************************************************************************/ //#define JTAG_SWD_DISABLE 0X02 //#define SWD_ENABLE 0X01 //#define JTAG_SWD_ENABLE 0X00 void JTAG_Set(u8 mode) { u32 temp; temp=mode; temp<<=25; RCC->APB2ENR|=1<<0; //开启辅助时钟 AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24] AFIO->MAPR|=temp; //设置jtag模式 } /************************************************************************** Function: System clock initialization function Input : pll:Selected frequency multiplication,Starting at 2, the maximum value is 16 Output : none 函数功能:系统时钟初始化函数 入口参数:pll:选择的倍频数,从2开始,最大值为16 返回 值:无 **************************************************************************/ void Stm32_Clock_Init(u8 PLL) { unsigned char temp=0; MYRCC_DeInit(); //复位并配置向量表 RCC->CR|=0x00010000; //外部高速时钟使能HSEON while(!(RCC->CR>>17)); //等待外部时钟就绪 RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1; PLL-=2; //抵消2个单位 RCC->CFGR|=PLL<<18; //设置PLL值 2~16 RCC->CFGR|=1<<16; //PLLSRC ON FLASH->ACR|=0x32; //FLASH 2个延时周期 RCC->CR|=0x01000000; //PLLON while(!(RCC->CR>>25)); //等待PLL锁定 RCC->CFGR|=0x00000002; //PLL作为系统时钟 while(temp!=0x02) //等待PLL作为系统时钟设置成功 { temp=RCC->CFGR>>2; temp&=0x03; } }