LDR R0,=SystemInit杀马特是什么意思思LDR R0,=SystemInit杀马特是什么意思思

3125人阅读
STM32F4时钟设置分析
本文博客链接:,作者:jdh,转载请注明.
开发环境:MDK4.72
MCU:STM32F407VGT6
STM32F4启动与STM32F10X不同,时钟已经默认配置好.
1.启动代码:
文件:startup_stm32f4xx.s
; Reset handler
Reset_Handler
Reset_Handler
SystemInit
R0, =SystemInit
R0, =__main
可以看出,在进入main函数之前,系统调用了SystemInit函数.
<span style="color:#.SystemInit函数分析
SystemInit函数位于system_stm32f4xx.c文件中.此文件提供几个宏定义可以设置各个时钟:
/************************* PLL Parameters *************************************/
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M
#define PLL_N
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P
/* USB OTG FS, SDIO and RNG Clock =
PLL_VCO / PLLQ */
#define PLL_Q
/******************************************************************************/
而晶振频率则是在文件stm32f4xx.h中进行设置:
#if !defined
(HSE_VALUE)
#define HSE_VALUE
((uint32_t)) /*!& Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined
(HSI_VALUE)
#define HSI_VALUE
((uint32_t)) /*!& Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
综上,可以得出默认配置中:
锁相环压腔振荡器时钟PLL_VCO = 25 / 25 * 336 = 336MHz
系统时钟SYSCLK = 336 / 2 = 168MHz
USB,SD卡时钟 = 336 / 7 = 48MHz
SystemInit函数代码:
Setup the microcontroller system
Initialize the Embedded Flash Interface, the PLL and update the
SystemFrequency variable.
* @retval None
void SystemInit(void)
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB-&CPACR |= ((3UL && 10*2)|(3UL && 11*2));
/* set CP10 and CP11 Full Access */
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC-&CR |= (uint32_t)0x;
/* Reset CFGR register */
RCC-&CFGR = 0x;
/* Reset HSEON, CSSON and PLLON bits */
RCC-&CR &= (uint32_t)0xFEF6FFFF;
/* Reset PLLCFGR register */
RCC-&PLLCFGR = 0x;
/* Reset HSEBYP bit */
RCC-&CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC-&CIR = 0x;
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
SetSysClock();
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB-&VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
SCB-&VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
3.SetSysClock函数分析
在SetSysClock函数中,配置了系统时钟,PLL倍频以及分频系数:
Configures the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings
This function should be called only once the RCC clock configuration
is reset to the default reset state (done in SystemInit() function).
* @retval None
static void SetSysClock(void)
/******************************************************************************/
PLL (clocked by HSE) used as System clock source
/******************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* Enable HSE */
RCC-&CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
HSEStatus = RCC-&CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC-&CR & RCC_CR_HSERDY) != RESET)
HSEStatus = (uint32_t)0x01;
HSEStatus = (uint32_t)0x00;
if (HSEStatus == (uint32_t)0x01)
/* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */
RCC-&APB1ENR |= RCC_APB1ENR_PWREN;
PWR-&CR |= PWR_CR_VOS;
/* HCLK = SYSCLK / 1*/
RCC-&CFGR |= RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 2*/
RCC-&CFGR |= RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 4*/
RCC-&CFGR |= RCC_CFGR_PPRE1_DIV4;
/* Configure the main PLL */
RCC-&PLLCFGR = PLL_M | (PLL_N && 6) | (((PLL_P && 1) -1) && 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q && 24);
/* Enable the main PLL */
RCC-&CR |= RCC_CR_PLLON;
/* Wait till the main PLL is ready */
while((RCC-&CR & RCC_CR_PLLRDY) == 0)
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH-&ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
/* Select the main PLL as system clock source */
RCC-&CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC-&CFGR |= RCC_CFGR_SW_PLL;
/* Wait till the main PLL is used as system clock source */
while ((RCC-&CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
如果外部时钟启动失败,系统会使用内部时钟
HCLK = SYSCLK / 1 = 168MHz
PCLK2 = HCLK / 2 = 84MHz
PCLK1 = HCLK / 4 = 42MHz
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:369469次
积分:6919
积分:6919
排名:第1141名
原创:144篇
转载:19篇
评论:352条
阅读:5511
阅读:12930
文章:19篇
阅读:75563
阅读:12391
(2)(4)(3)(8)(2)(4)(2)(2)(1)(3)(4)(5)(1)(2)(4)(5)(6)(2)(1)(1)(4)(2)(1)(1)(2)(3)(1)(6)(5)(1)(6)(9)(11)(5)(4)(8)(18)(2)(2)(1)(1)(3)(2)(3)2540人阅读
写作原由:今日接手用stm32f100xx芯片开发的项目,以前用的是stm8s 和stm32f103xx芯片;因为在别人的项目代码的基础上做2次开发,但是发现那个代码main函数中没有对系统时钟的设置的相关函数,一直纳闷,但也没有深究,直至昨日 调试时出现串口收发数据出错,源代码在原项目的板子上串口发送、接收数据正常,同样程序在项目板子上收发的数据不正确, 两块板子芯片一样,串口收发管脚一样,最后发现原来板子外部晶振是8MHZ ,新板子外部晶振是12MHZ;& 而在STM32固件库中,默认的外部晶振是8MHZ,由于时钟源不正确,导致波特率不正确,当然收发的数据也不正确了.....我勒个去!都怪自己平时看问题“不求甚解”。
(波特率与时钟源关系公式:IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct-&USART_BaudRate)))
为了深入思考,我提出了一些疑问,通过解答这些问题更深入的了解时钟;
问题一:对系统时钟的设置的相关函数,在main函数中找不到,那在哪里?还是说根本没有对系统时钟进行配置?
问题二:既然用了外部晶振做系统时钟,那为什么没看到启动外部晶振的操作?
问题三:串口的时钟源是什么?串口时钟源跟系统时钟的关系?
问题四:程序中串口时钟源是怎样实现对波特率的关系的?
现附上我找到上面3个问题答案做的一张框架图:希望博友参考此图理解我后面的内容:
在进入主题之前我们先了解一些必要的基础知识----stm32系列芯片的种类和型号:
startup_stm32f10x_cl.s 互联型的器件,STM32F105xx,STM32F107xx
startup_stm32f10x_hd.s 大容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_hd_vl.s 大容量的STM32F100xx
startup_stm32f10x_ld.s 小容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_ld_vl.s 小容量的STM32F100xx
startup_stm32f10x_md.s 中容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_md_vl.s 中容量的STM32F100xx& (我项目中用的是此款芯片 stm32f100CB)
startup_stm32f10x_xl.s FLASH在512K到1024K字节的STM32F101xx,STM32F102xx,STM32F103xx
cl:互联型产品,stm32f105/107系列
vl:超&#20540;型产品,stm32f100系列
xl:超高密度产品,stm32f101/103系列
ld:低密度产品,FLASH小于64K
md:中等密度产品,FLASH=64 or 128
hd:高密度产品,FLASH大于128
(下图中的startup_stm32f10_ld.s应改为:startup_stm32f10x_md_vl.s)
问题一:对系统时钟的设置的相关函数,在main函数中找不到,那在哪里?还是说根本没有对系统时钟进行配置?
解答:高人指点,我看了一下启动文件startup_stm32f10x_md_vl.s,其中有一段汇编:
; Reset handler routine
Reset_Handler
Reset_Handler
SystemInit
R0, =SystemInit
R0, =__main
IMPORT __main IMPORT SystemInit&&&& &//IMPORT 声明了需要引用C语言中的main函数、systeminit函数,
LDR R0, = systeminint&&&&&&&//把systeminit 函数地址放到r0 寄存器;
BLX&& R0&&&&//跳到到R0 寄存器中的地址执行;
所以,在跳到main函数执行前,已经在SystemInit&函数中把系统时钟给设置好了;
问题二:既然用了外部晶振做系统时钟,那为什么没看到启动外部晶振的操作?
我们在解答这个问题前,先到SystemInit函数里面做更深入的了解:
void SystemInit (void)
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC-&CR |= (uint32_t)0x;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC-&CFGR &= (uint32_t)0xF8FF0000;
RCC-&CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC-&CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC-&CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC-&CFGR &= (uint32_t)0xFF80FFFF;
#ifdef STM32F10X_CL
/* Reset PLL2ON and PLL3ON bits */
RCC-&CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits
RCC-&CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC-&CFGR2 = 0x;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL)
/* Disable all interrupts and clear pending bits
RCC-&CIR = 0x009F0000;
/* Reset CFGR2 register */
RCC-&CFGR2 = 0x;
/* Disable all interrupts and clear pending bits
RCC-&CIR = 0x009F0000;
#endif /* STM32F10X_CL */
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
/* Configure the Flash Latency cycles and enable prefetch buffer */
SetSysClock();
#ifdef STM32F10X_HD
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif /* STM32F10X_HD */
我们进入setsysclock()函数,看其中作了哪些操作:
Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
* @retval None
static void SetSysClock(void)
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
我项目中用的是此款芯片 stm32f100CB,内部晶振是24MHZ, 所以应进入执行SetSysClockTo24() 函数:
Sets System clock frequency to 24MHz and configure HCLK, PCLK2
and PCLK1 prescalers.
This function should be used only after reset.
* @retval None
static void SetSysClockTo24(void)
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC-&CR |= ((uint32_t)RCC_CR_HSEON); //开启外部晶振
/* Wait till HSE is ready and if Time out is reached exit */
HSEStatus = RCC-&CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
if ((RCC-&CR & RCC_CR_HSERDY) != RESET)//等待外部晶振起振
HSEStatus = (uint32_t)0x01;
HSEStatus = (uint32_t)0x00;
if (HSEStatus == (uint32_t)0x01)
#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL
/* Enable Prefetch Buffer */
FLASH-&ACR |= FLASH_ACR_PRFTBE;
/* Flash 0 wait state */
FLASH-&ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH-&ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
/* HCLK = SYSCLK */
RCC-&CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC-&CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC-&CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 MHz */
RCC-&CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC-&CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL6);
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */
RCC-&CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC-&CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10);
/* Enable PLL2 */
RCC-&CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC-&CR & RCC_CR_PLL2RDY) == 0)
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL)
PLL configuration:
= (HSE / 2) * 6 = 24 MHz */
RCC-&CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC-&CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6);
PLL configuration:
= (HSE / 2) * 6 = 24 MHz */
RCC-&CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC-&CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC-&CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC-&CR & RCC_CR_PLLRDY) == 0)
/* Select PLL as system clock source */
RCC-&CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC-&CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC-&CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
#elif defined SYSCLK_FREQ_36MHz
void SetSysClockTo24函数中主要做了下面几件事:(不同颜色功能分别对应上面对应颜色代码部分)
1.启动外部晶振作为系统时钟源;
2.等待外部晶振起振;
3.(起振后)对系统时钟源进行分频:(默认外部是HSE--8MHZ晶振)& PLL configuration: = (HSE / 2) * 6 = 24 MHz
<span style="color:#. 配置HCLK、PCLK1、PCLK2 与系统时钟源的关系;
问题三:串口的时钟源是什么?串口时钟源跟系统时钟的关系?
回答这个问题前,我们先来看stm32f100芯片手册数据图(第12页):
从图里面我们可看出串口1的时钟源是PCLK1;
上面问题2的代码中我们看到PCLK1是时钟源24MHZ的1分频,即还是24MHZ;
问题四:程序中串口时钟源是怎样实现对波特率的关系的?
由问题3我们知道串口时钟源是24mhz,依据公式:IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct-&USART_BaudRate)))
库中自动设置IntegerDivider 存入寄存器中;
附加: 转自
在KEIL下可以在项目的选项C/C&#43;&#43;/PREPROMCESSOR symbols的Define栏里定义,比如STM32F10X_CL
也可以在STM32F10X.H里用宏定义
#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)
&&&&&&&&&&&
&& #define STM32F10X_HD&&&&&
&&&&&&&&&&&&&
如果芯片更换,除了做如上所述的更改外,还需以下几步
第一步 &system_stm32f10x.c的系统主频率,依实际情况修改
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL)
&#define SYSCLK_FREQ_24MHz&
#define SYSCLK_FREQ_72MHz&
另外外部时钟在文件:stm32f10x.h 依实际修改
第二步 定时器的参数依系统主时钟做适当修改
第三步 flash地址misc.h中的NVIC_VectTab_Flash 0x 要与KEIL选项target的IROM1的地址一致,如果是IAP程序,依ISP程序占用大小,APP的FLASH地址向后延,比如0X8002000,那么KEIL选项target的IROM1的地址也要就0x8002000,SIZE因为ISP占用了2000,所以就为0x0,即只能填写0X3E000
&ISP程序与APP程序连接
&打开 User 选项卡& 在 Run User Programs Before Build/Rebuild 中,勾选 Run#1,并在
&&&&&&& D:\Keil\ARM\BIN40\fromelf.exe --bin -o ./obj/Project.bin ./obj/Project.axf
&&&&&&&&&&&&& 其中,Project.bin 和 Project.axf 要和 Output 选项卡中的 Name& of& Executable& 的名字
IAP我的总结
1 先FLASH_Unlock();
2 小于或等于128K的STM每页为1k bytes,大于128K的每页为2K BYTES,减去从地址0x8002000占用的0x2000后,算出页数,比如IAP占用8K,则64K的MD的STM32F系列用for(i=0;i&(64-8);i&#43;&#43;) FLASH_ErasePage(0x;0x400*i);循环按页擦除FLASH
3 按从外部串口获取到的数据,FLASH_ProgramWord(address,dat);//注意是按4字节方式写入的
&if (*(uint32_t*)address!= dat)//字编程后校验
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:216931次
积分:3326
积分:3326
排名:第4005名
原创:116篇
转载:21篇
评论:67条
(2)(7)(3)(3)(1)(4)(5)(6)(2)(1)(4)(5)(5)(15)(36)(31)(7)[跟我学OSKinetis]第4课-从启动代码开始看!UART! | 拉普兰德电子技术&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& STM32固件库的简析
[&&11:26:00&|&By:&banyai
&&&&&&Edit&By:
STM32的V3.3.0库,内有CMSIS的文件夹为arm&Cortex微控制器软件接口标准,现在将我实际工作中的作一个简要分析:1.选择启动文件:根据自己所用的芯片的型号,选择正确的启动文件。这个根据数据手册上的划分。例如STM32F103VBT6,就选择startup_stm32f10x_md.s,在这个文件里,首选要定义自已的堆和栈的大小,这个根据自已的需要确定。文件中已经定义好了中断向量的位置及堆和栈的初始化操作。
Reset_Handler&&&&PROC&
EXPORT&&Reset_Handler&&&&&[WEAK]&
IMPORT&&__main
IMPORT&&SystemInit&
LDR&&&&&R0,&=SystemInit
BLX&&&&&R0
LDR&&&&&R0,&=__main&
BX&&&&&&R0&
下面对上面的一段汇编进行解释,相同的就省略解释。
&&&&&&&&&&&&&Reset_Handler&&&&PROC&&&//0x0复位入口
&&&&&&&&&&&&&EXPORT&&Reset_Handler&&&&&[WEAK]&//&EXPORT或者GLOBAL:制定某标号代表的程序可为其它文件调用,即是声明一个全局标号,[WEAK]选项声明其他的同名标号优先于该标号被引用。声明一个可全局引用的标号Reset_Handler
&&&&&IMPORT&&__main&&//通知编译器当前文件要引用标号__main,但__main在其他源文件中定义
&&&&&IMPORT&&SystemInit&//通知编译器当前文件要引用标号SystemInit&,但SystemInit&在其他源文件中定义
&&&&&&&&&&&&&&&&&LDR&&&&&R0,&=SystemInit&//
&&&&&&&&&&&&&&&&&BLX&&&&&R0&&&&&&&&&&&&&&//BLX指令进行ARM/Thumb状态切换并且保存返回地址的转移指令,放回地址(BLX指令指向下一条指令地址)保存链接寄存器R14中
&&&&&&&&&&&&&&&&&LDR&&&&&R0,&=__main&&&//向通用寄存器传输任意不大于232的立即数,即__main,立即数用=32位立即数,等同于MOV&R0,#_main
&&&&&&&&&&&&&&&&&BX&&&&&&R0&&&&&&&&&&&&&//BX指令进行ARM/Thumb状态切换但不保存返回地址的转移指令,R0为包含目标指令绝对地址的寄存器
&&&&&&&&&&&&&&&&&END&&&&&&&&&&&&&&&&&&&//结束
从上面这段文字中,可以看到,在系统复位后,先执行SystemInit(),再进入main()函数。SystemInit()在文件system_stm32f10x.c中定义,我们稍后再说。
&&&&2.stm32f10x.h:这个头文件包含了STM32的大部份定义:
&&&&&&&a.定义芯片的类型,如#define&STM32F10x_MD
&&&&&&&b.定义是否包含标准库,#define&USE_STDPERIPH_DRIVER
&&&&&&&c.定义外部振荡器频率,#define&HSE_VALUE
&&&&&&&上面三个定义,建议在main.c文件中刚开始就定义好,或者是在编译器选项中定义好,&&这样就可以不修改这个文件了。
&&&&&&&&d.定义中断号stm32f10x_it.c&&&&stm32f10x_it.h
&&&&&&&&e.包含&core_cm3.h,system_stm32f10x.h
&&&&&&&&f.定义数据类型,u8,s8等为了兼容以前的库所定义的数据,建议程序中用标准的uint8_t这样的类型。此外还定义了bool,FlagStatus,alStatus及ErrorStatus
&&&&&&&&g.定义外设结构体,地址及用到的数据常量。
&&&&&&&&h.包含stm32f10x_conf.h来配置外设
&&&&&&&&i.定义位操作的宏
&&&3.system_stm32f10x.h和.c,这两个文件中:
&&&&&&&a.定义一个全局变量&uint32_t&SystemCoreClock:&系统时钟频率与你选择有关
&&&&&&&b.SystemInit():这个函数就是启动文件中调用的函数
&&&&&&&&(1)&在system_stm32f10x.c的开始部份,选择相关的系统时钟频率,
&&&&&&&&&&&&&如#define&&SYSCLK_FREQ_24MHz&&
&&&&&&&&(2)&通过SystemInit()函数,就将SYSCLK&=&HCLK&=&PCLK1=PCLK2=PLL输出24MHz。注意:这个频率为HSE为8MHz时为条件,如果HSE不为8MHz或用HSI时,就会有问题。
&&&&&&&c.SystemCoreClockUpdate():更新SystemCoreClock的&#20540;,与系统频率一致。
&&&&&&&可能看到,这个文件中的RCC设置很有局限性,所以在程序中,可以不用它,而用标准库存中的stm32f10x_rcc中的函数进行设置。
&&4.stm32f10x_conf.h
&&&&&a.配置需要的标准外设库,需要用到的外设,把相应头文件包含进去就可以。
&&&&&b.定义assert_Param的模式,选择#define&USE_FULL_ASSERT时,断言输出问题所在的位置,在调试时很有用,在正式版本时,把它注释掉即可。
&&&5.core_cm3:与CM3内核相关的操作,重点如下:
&&&&&&a.&在MDK中,开总中断:__enable_irq();&&&关总中断:__disable_irq();
&&&&&&b.&中断处理程序:
&&&&&&&&&&(1)&NVIC_SetPriorityGrouping(uint32_t&PriorityGroup);
&&&&&&&&&&设置中断组,这里的&#20540;只能是0~7,在STM32中,只能用8位中的前4位来设置组,可以分为两部份:抢占优先级和亚优先级。这个数&#20540;就是亚优先级开始的位。它前面的位是抢占式优先级的位。例如:NVIC_SetPriorityGrouping(5),那么D7,D6表示抢占式优先级(0~3),D5,D4表示亚优先级(0~3)。优先级数&#20540;越小,优先级越高。抢占式优先级高的中断可以打断抢占式优先级低的中断。抢占式优先级相同,亚优先级不同的两个中断,如果同时到来,先执行亚优先级高的中断,再执行亚优先级低的中断,但不能打断。
可以理解为抢占式多任务。
&&&&&&&&&(2)&NVIC_EnableIRQ(IRQn_Type&IRQn);&&&使能一个中断EnableIRQ
&&&&&&&&&(3)&NVIC_DisableIRQ(IRQn_Type&IRQn);&&&禁止一个中断DisableIRQ
&&&&&&&&&(4)&NVIC_SetPriority(IRQn_Type&IRQn,uint32&priority);&设置一个中断的优先级
&&&&&&&&&(5)NVIC_EncodePriority(uint32_t&PriorityGroup,uint32_t&PreemptPriority,uint32_t&SubPriority);
&&&&&&&&&(4)和(5)通常一起使用,这样设置更直观,例如要将外部中断0设为抢占式优先级为0,亚优先级为2,则:
&&&&&&&&&NVIC_SetPriority(EXTI0_IRQn,NVIC_EncodePriority(5,0,2));
&&&&&&&&&注意PriorityGroup的参数应与(1)中设置的一致。
&&&&&&&&&除了这种方式设置中断外,也可以使用标准库中的misc中的中断设置函数来操作。
&&&&&c.&SysTick_Config(uint32_t&ticks):设置系统嘀嗒时钟并使能中断
&&&&&&&&&在STM32中与CM3内核描述不太一样,这个时钟源有两个选择:AHB/8和AHB,在该函数中是选择了HCLK(SysTick_CTRL_CLKSOURCE_Msk),所以定时时间=ticks&/&HCLK,当要定时10ms,而HCLK为24MHz时,ticks&=&10000&*&24&=&240000。
&&&&&&&&&如果需要选择HCLK/8,可以直接修改这个函数,或在这个函数后跟随misc中的SysTick_CLKSourceConfig(uint32_t&SysTick_CLKSource)来设置。
&&&&&&d.NVIC_SystemReset():复位芯片。
&&6.&stm32f10x_it中断实现,在这里编写相应的中断服务函数。
&&7.还需要注意的一点是:进入main函数后,除了设置嘀嗒时钟和中断外,在操作各外设之前,需要调用:
RCC_AHBPeriphClockCmd(),RCC_APB1PeriphClockCmd(),RCC_APB2PeriphClockCmd(),启动相应的时钟,否则外设就不能正常工作。
在这里简单介绍一下NVIC
NVIC嵌套向量中断控制器&Nested&Vectored&Interrupt&Controller
系统中断管理。
我的理解管理系统内部的中断,负责打开和关闭中断。
基础应用1,中断的初始化函数,包括设置中断向量表位置,和开启所需的中断两部分。所有程序中必须的。
用法:void&NVIC_Configuration(void)
NVIC_InitTypeDef&NVIC_InitS//中断管理恢复默认参数
#ifdef&&VECT_TAB_RAM&&
//如果C/C&#43;&#43;&Compiler\Preprocessor\Defined&symbols中的定义了VECT_TAB_RAM(见程序库更改内容的表&#26684;)
NVIC_SetVectorTable(NVIC_VectTab_RAM,&0x0);&//则在RAM调试
#else&&&&&&&&//如果没有定义VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_FLASH,&0x0);//则在Flash里调试
#endif&&&&&&&&//结束判断语句
//以下为中断的开启过程,不是所有程序必须的。
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);&
//设置NVIC优先级分组,方式。
//注:一共16个优先级,分为抢占式和响应式。两种优先级所占的数量由此代码确定,NVIC_PriorityGroup_x可以是0、1、&2、3、4,分别代表抢占优先级有1、2、4、8、16个和响应优先级有16、8、4、2、1个。规定两种优先级的数量后,所有的中断级别必须在其中选择,抢占级别高的会打断其他中断优先执行,而响应级别高的会在其他中断执行完优先执行。
//NVIC_InitStructure.NVIC_IRQChannel&=&中断通道名;
//开中断,中断名称见函数库
//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority&=&0;
//抢占优先级
//NVIC_InitStructure.NVIC_IRQChannelSubPriority&=&0;&
//响应优先级
//NVIC_InitStructure.NVIC_IRQChannelCmd&=&ENABLE;//启动此通道的中断
//NVIC_Init(&NVIC_InitStructure);&&&&&//中断初始化
有些是参考博客园的一些解释,至于那篇文章,我现在也不记得了。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:258339次
积分:5414
积分:5414
排名:第1802名
原创:288篇
转载:87篇
评论:24条
阅读:2523
文章:39篇
阅读:17387
(2)(2)(8)(5)(4)(10)(5)(8)(4)(4)(5)(4)(4)(5)(6)(20)(8)(13)(7)(4)(15)(13)(13)(15)(8)(7)(4)(19)(41)(36)(2)(6)(46)(11)(4)(5)(2)}

我要回帖

更多关于 绿茶婊是什么意思 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信