123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- #include "st_sys.h"
- //////////////////////////////////////////////////////////////////////////////////
- //本程序只供学习使用,未经作者许可,不得用于其它任何用途
- //ALIENTEK STM32开发板
- //系统时钟初始化(适合STM32F10x系列)
- //正点原子@ALIENTEK
- //技术论坛:www.openedv.com
- //创建日期:2010/1/1
- //版本:V1.9
- //版权所有,盗版必究。
- //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
- //All rights reserved
- //********************************************************************************
- //V1.4修改说明
- //把NVIC KO了,没有使用任何库文件!
- //加入了JTAG_Set函数
- //V1.5 20120322
- //增加void INTX_DISABLE(void)和void INTX_ENABLE(void)两个函数
- //V1.6 20120412
- //1,增加MSR_MSP函数
- //2,修改VECT_TAB_RAM的默认偏移,设置为0.
- //V1.7 20120818
- //1,添加ucos支持配置宏SYSTEM_SUPPORT_UCOS
- //2,修改了注释
- //3,去掉了不常用函数BKP_Write
- //V1.8 20131120
- //1,修改头文件为stm32f10x.h,不再使用stm32f10x_lib.h及其相关头文件
- //V1.9 20150109
- //1,修改头文件为MY_NVIC_Init函数部分代码以支持向量号大于63的中断的设置
- //2,修改WFI_SET/INTX_DISABLE/INTX_ENABLE等函数的实现方式
- //V2.0 20150322
- //修改SYSTEM_SUPPORT_UCOS为SYSTEM_SUPPORT_OS
- //////////////////////////////////////////////////////////////////////////////////
- //设置向量表偏移地址
- //NVIC_VectTab:基址
- //Offset:偏移量
- void Sys_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset) {
- SCB->VTOR = NVIC_VectTab | (Offset & (u32)0x1FFFFF80); //设置NVIC的向量表偏移寄存器
- //用于标识向量表是在CODE区还是在RAM区
- }
- //设置NVIC分组
- //NVIC_Group:NVIC分组 0~4 总共5组
- void Sys_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; //设置分组
- }
- //设置NVIC
- //NVIC_PreemptionPriority:抢占优先级
- //NVIC_SubPriority :响应优先级
- //NVIC_Channel :中断编号
- //NVIC_Group :中断分组 0~4
- //注意优先级不能超过设定的组的范围!否则会有意想不到的错误
- //组划分:
- //组0:0位抢占优先级,4位响应优先级
- //组1:1位抢占优先级,3位响应优先级
- //组2:2位抢占优先级,2位响应优先级
- //组3:3位抢占优先级,1位响应优先级
- //组4:4位抢占优先级,0位响应优先级
- //NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
- void Sys_NVIC_Init(u8 NVIC_PreemptionPriority, u8 NVIC_SubPriority, u8 NVIC_Channel, u8 NVIC_Group) {
- u32 temp;
- Sys_NVIC_PriorityGroupConfig(NVIC_Group); //设置分组
- temp = NVIC_PreemptionPriority << (4 - NVIC_Group);
- temp |= NVIC_SubPriority & (0x0f >> NVIC_Group);
- temp &= 0xf; //取低四位
- NVIC->ISER[NVIC_Channel / 32] |= (1 << NVIC_Channel % 32); //使能中断位(要清除的话,相反操作就OK)
- NVIC->IP[NVIC_Channel] |= temp << 4; //设置响应优先级和抢断优先级
- }
- //外部中断配置函数
- //只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
- //参数:
- //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 << EXTOFFSET); //清除原来设置!!!
- AFIO->EXTICR[EXTADDR] |= GPIOx << EXTOFFSET; //EXTI.BITx映射到GPIOx.BITx
- //自动设置
- EXTI->IMR |= 1 << BITx; // 开启line BITx上的中断
- //EXTI->EMR|=1<<BITx;//不屏蔽line BITx上的事件 (如果不屏蔽这句,在硬件上是可以的,但是在软件仿真的时候无法进入中断!)
- if (TRIM & 0x01) EXTI->FTSR |= 1 << BITx; //line BITx上事件下降沿触发
- if (TRIM & 0x02) EXTI->RTSR |= 1 << BITx; //line BITx上事件上升降沿触发
- }
- #define EVCR_PORTPINCONFIG_MASK ((uint16_t)0xFF80)
- #define LSB_MASK ((uint16_t)0xFFFF)
- #define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000)
- #define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF)
- #define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000)
- #define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000)
- /**
- * 管脚复用设置
- *
- * @author lxz (121319 14:46:01)
- *
- * @param GPIOx
- * @param BITx
- * @param AFx
- */
- void GPIO_Remap_Set(uint32_t GPIO_Remap, u8 newstate) {
- uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00;
- if ((GPIO_Remap & 0x80000000) == 0x80000000) {
- tmpreg = AFIO->MAPR2;
- } else {
- tmpreg = AFIO->MAPR;
- }
- tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10;
- tmp = GPIO_Remap & LSB_MASK;
- if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) {
- tmpreg &= DBGAFR_SWJCFG_MASK;
- AFIO->MAPR &= DBGAFR_SWJCFG_MASK;
- } else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) {
- tmp1 = ((uint32_t)0x03) << tmpmask;
- tmpreg &= ~tmp1;
- tmpreg |= ~DBGAFR_SWJCFG_MASK;
- } else {
- tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15) * 0x10));
- tmpreg |= ~DBGAFR_SWJCFG_MASK;
- }
- if (newstate != 0) {
- tmpreg |= (tmp << ((GPIO_Remap >> 0x15) * 0x10));
- }
- if ((GPIO_Remap & 0x80000000) == 0x80000000) {
- AFIO->MAPR2 = tmpreg;
- } else {
- AFIO->MAPR = tmpreg;
- }
- }
- /**
- * 管脚模式设置
- *
- * @author lxz (121319 14:46:04)
- *
- * @param GPIOx
- * @param BITx
- * @param MODE
- * @param OTYPE
- * @param OSPEED
- * @param PUPD
- */
- void GPIO_Set(GPIO_TypeDef *GPIOx, u32 BITx, u32 MODE, u32 OSPEED, u32 PUPD) {
- u32 pinpos = 0, pos = 0, curpin = 0;
- int currentmode = 0;
- for (pinpos = 0; pinpos < 16; pinpos++) {
- pos = 1 << pinpos; //一个个位检查
- curpin = BITx & pos; //检查引脚是否要设置
- if (curpin == pos) { //需要设置
- //获取设置
- currentmode = 0;
- if (MODE != GPIO_MODE_IN_FLOATING && MODE != GPIO_MODE_AIN &&
- MODE != GPIO_MODE_IPD && MODE != GPIO_MODE_IPU) { //如果是输出模式
- currentmode |= OSPEED; //设置输出速度
- }
- if (PUPD == GPIO_PUPD_PU) { //设置上拉
- GPIOx->BSRR = 1 << pinpos;
- } else if (PUPD == GPIO_PUPD_PD) { //设置下拉
- GPIOx->BRR = 1 << pinpos;
- }
- currentmode |= MODE & 0x0f;
- //将设置保存到寄存器
- if (pinpos < 8) {
- GPIOx->CRL &= ~(0x0f << (pinpos * 4));
- GPIOx->CRL |= currentmode << (pinpos * 4);
- } else {
- GPIOx->CRH &= ~(0x0f << ((pinpos - 8) * 4));
- GPIOx->CRH |= currentmode << ((pinpos - 8) * 4);
- }
- }
- }
- }
- //不能在这里执行所有外设复位!否则至少引起串口不工作.
- //把所有时钟寄存器复位
- void MYRCC_DeInit(void) {
- RCC->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
- //Sys_NVIC_SetVectorTable(0x20000000, 0x0);
- #else
- //Sys_NVIC_SetVectorTable(0x08000000,0x0);
- #endif
- }
- //THUMB指令不支持汇编内联
- //采用如下方法实现执行汇编指令WFI
- void WFI_SET(void) {
- __ASM volatile("wfi");
- }
- //关闭所有中断
- void INTX_DISABLE(void) {
- __ASM volatile("cpsid i");
- }
- //开启所有中断
- void INTX_ENABLE(void) {
- __ASM volatile("cpsie i");
- }
- //设置栈顶地址
- //addr:栈顶地址
- void MSR_MSP(u32 addr)
- {
- __ASM volatile("MSR MSP, r0"); //set Main Stack value
- __ASM volatile("BX r14");
- }
- //进入待机模式
- 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指令
- }
- //系统软复位
- void Sys_Soft_Reset(void) {
- SCB->AIRCR = 0X05FA0000 | (u32)0x04;
- }
- //JTAG模式设置,用于设置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模式
- }
- //系统时钟初始化函数
- //pll:选择的倍频数,从2开始,最大值为16
- void Stm32_Clock_Init(u8 PLL) {
- unsigned char temp = 0;
- MYRCC_DeInit(); //复位并配置向量表
- //RCC->APB1ENR |=1<<28;
- //PMU->CTL |= 3<<14;
- RCC->CR |= 0x00010000; //外部高速时钟使能HSEON
- while (!(RCC->CR >> 17)); //等待外部时钟就绪
- RCC->CFGR = 0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
- PLL -= 2; //抵消2个单位(因为是从2开始的,设置0就是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锁定
- /* enable the high-drive to extend the clock frequency to 120 MHz */
- //PMU->CTL |= 1<<16;
- //while(0U == (PMU->CS & (1<<16))){
- //}
- /* select the high-drive mode */
- // PMU->CTL |= 1<<17;
- //while(0U == (PMU->CS & (1<<17))){
- //}
- RCC->CFGR |= 0x00000002; //PLL作为系统时钟
- while (temp != 0x02) { //等待PLL作为系统时钟设置成功
- temp = RCC->CFGR >> 2;
- temp &= 0x03;
- }
- }
|