文档库 最新最全的文档下载
当前位置:文档库 › Stm32中断优先级相关概念与使用笔记(NVIC)

Stm32中断优先级相关概念与使用笔记(NVIC)

Stm32中断优先级相关概念与使用笔记(NVIC)
Stm32中断优先级相关概念与使用笔记(NVIC)

Stm32中断优先级相关概念与使用笔记

一、基本概念

1.ARM cortex_m3内核支持256个中断(16个内核+240外部)和可编程256级中断优先级的设置,与中断控制核中断优先级控制的寄存器(NVIC、SYSTICK等)属于cortex_m3内核的部分。STM32采用了cortex_m3内核,所以这些部分仍旧保留使用,但并不是完全使用的,只是使用了一部分。

2.STM32目前支持的中断共为84个(16个内核+68个外部),和16级可编程中断优先级的设置(仅使用中断优先级设置8bit中的高4位,见后面解释)。《参考最新101xx-107xx STM32 Reference manual, RM0008》。

以下主要对外部中断进行说明。

3.68个外部中断(通道)在STM32中已经固定的分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但在STM32中只有高4位有效),每4个通道的8位中断优先级控制字(PRI_n)构成一个32位的优先级寄存器(Priority Register)。68个通道的优先级寄存器至少有是17个32位的寄存器,它们是NVIC寄存器的一部分。

4.这4bit的中断优先级控制位还要分成2组看,从高位开始,前面的定义抢先式优先级,后面为子优先级。4bit的组合可以有以下几种形式:

5.在一个系统中,通常只使用上面5种分配情况的一种,具体采用哪一种,需要在初始化时写入到一个32位寄存器AIRC(Application Interrupt and Reset Control Register)的第[10:8]这2个位中。这3个bit位有专门的称呼:PRIGROUP(具体写操作后面介绍)。比如你将0x05(上表的编号)写到AIRC的[10:8]中,那么也就规定了你的系统中只有4个抢先式优先级,相同的抢先式优先级下还可以有4个不同级别的子优先级。

6.AIRC中PRIGROUP的值规定了设置和确定每个外部中断通道优先级的格式。例如,在上面将0x05写入了AIRC中PRIGROUP,也就规定了当前系统中只能有4个抢先式优先级,相同的抢先式优先级下还可以有4个不同级别的子优先级,他们分别为:

7.如果在你的系统中使用了TIME2(中断通道28)和EXTI0(中断通道6)两个中断,而TIME2中断必须优先响应,而且当系统在执行EXIT0中断服务时也必须打断(抢先、嵌套),就必须设置TIME2的抢先优先级比EXTI0的抢先优先级要高(数目小)。假定EXTI0位2号抢先优先级,那么TIME2就必须设置成0或1号抢先优先级。这些工作需要在AIRC中PRIGROUP后进行设置。

8.具体优先级的确定和嵌套规则。ARM cortex_m3(STM32)规定

a/ 只能高抢先优先级的中断可以打断低抢先优先级的中断服务,构成中断嵌套。

b/ 当2(n)个相同抢先优先级的中断出现,它们之间不能构成中断嵌套,但STM32首先响应子优先级高的中断。

c/ 当2(n)个相同抢先优先级和相同子优先级的中断出现,STM32首先响应在该中断通道向量地址低的中断(ROM0008,表52)。

具体一点:

0号抢先优先级的中断,可以打断任何中断抢先优先级为非0号的中断;1号抢先优先级的中断,可以打断任何中断抢先优先级为2、3、4号的中断;…..构成中断嵌套。

如果两个中断的抢先优先级相同,谁先出现,就先响应谁,不构成嵌套。如果一起出现(或挂在那里等待),就看它们2个谁的子优先级高了,如果子优先级也相同,就看它们的中断向量位置了。

9.上电RESET后,AIRC中PRIGROUP[10:8],因此此时系统使用16个抢先优先级,无子优先级。另外由于所有外部中断通道的优先级控制字PRI_n也都是0,所以根据上面的定义可以得出,此时68个外部中断通道的抢先优先级都是0号,没有子优先级的区分。故此时不会发生任何的中断嵌套行为,谁也不能打断当前正在执行的中断服务。当多个中断出现后,则看它们的中断向量地址:地址越低,中断级别越高,STM32优先响应。注意:此时内部中断的抢先优先级也都是0号,由于它们的中断向量地址比外部中断向量地址都低,所以它们的优先级比外部中断高,但如果此时正在执行一个外部中断服务,它们也必须排队等待,只是可以插队,当正在执行的中断完成后,它们可以优先得到执行。

了解以上基本概念还是不够的,还要了解具体中断的控制有那些途径,中断服务程序如何正确的编写。下面的描述主要以TIME2通道为例。

二、中断控制

1.对于STM32讲,外部中断通道位置28(35号优先级)是给外部设备TIME2的,但TIME2本身能够引起中断的中断源或事件有好多个,比如更新事件(上溢/下溢)、输入捕获、输出匹配、DMA申请等。

(题外话:就一个通用定时计数器,比8位控制器中TIME要复杂多了。学过A VR的,可能对输入捕获、输出匹配等还有概念,如果你学的标准架构的MCS-51,那么上手32位控制困难就更多了。所以我一直推荐学习8位应该认真从A VR开始,尽管51有很大的市场,价格也相对便宜些,但从发展的眼光,从后续掌握32位的使用,A VR是比较好的选择。)

所有TIME2的中断事件都是通过一个TIME2的中断通道向STM32内核提出申请的,那么STM32中如何处理和控制TIME2和它众多的、不同的、中断申请呢?

2.cortex_m3内核对于每一个外部中断通道都有相应的控制字和控制位,用于单独的和总的控制该中断通道。它们包括有:

中断优先级控制字:PRI_n(上面提到的)

中断允许设置位:在ISER寄存器中

中断允许清除位:在ICER寄存器中

中断悬挂Pending(排队等待)位置位:在ISPR寄存器中(类似于置中断通道标志位)

中断悬挂Pending(排队等待)位清除:在ICPR寄存器中(用于清除中断通道标志位)

正在被服务的中断(Active)标志位:在IABR寄存器中,(只读,可以知道当前内核正在处理哪个中断通道)

因此,与TIME2中断通道相关的,在NVIC中有13个bits,它们是PRI_28,8个bits(只用高4位);中断通道允许,中断通道清除(相当禁止),中断通道Pending置位(我的理解是中断请求发生了,但当前有其它中断服务在执行,你的中断级别又不能打断别人,所以Pending等待,这个应该由硬件置位的),中断Pending位清除(可以通过软件将本次中断请求且尚处在Pending状态,取消掉),正在被服务的中断(Active)标志位,各1个bit。

上面的控制字和控制位都是在NVIC中的寄存器组中,可惜的是在STM32中竟然不给出任何的解释和说明。

3.作为外围设备TIME2本身也包括更具体的,管理自己不同中断的中断控制器(位),它们主要是各个不同类型中断的允许控制位,和各自相应中断标志位。(这个STM32的手册中有详细的说明了)

4.在弄清楚2、3两点的基础上,我们可以看看TIME2的中断过程,以及如何控制的了。

a/ 初始化过程

设置AIRC中PRIGROUP的值,规定系统中的抢先优先级和子优先级的个数(在4个bits中占用的位数)

设置TIME2本身的寄存器,允许相应的中断,如允许UIE(TIME2_DIER的第[0]位)设置TIME2中断通道的抢先优先级和子优先级(PRI_28,在NVIC寄存器组中)

设置允许TIME2中断通道。在NVIC寄存器组的ISER寄存器中的一位。

b/ 中断响应过程

当TIME2的UIE条件成立(更新,上溢或下溢),硬件将TIME2本身寄存器中UIE中断标志置位,然后通过TIME2中断通道向内核申请中断。

此时硬件将TIME2的Pending标志置位,相当与中断通道标志置位,表示TIME2有中断申请。

如果当前有中断在处理,TIME2的中断级别不高,那么就保持Pending,当然软件可以通过写ICPR寄存器中相应的位把本次中断清除掉。

当内核有空,开始响应TIME2的中断,进入TIME2的中断服务。此时硬件将IABR寄存器中相应的标志位置位,表示TIME2中断正在被处理。同时硬件清除TIME2的Pending 标志位。

c/ 执行TIME2的中断服务程序

所有TIME2的中断事件,都是在一个TIME2中断服务程序中完成的,所以进入中断程序后,中断程序需要首先判断是哪个TIME2的具体事件的中断,然后转移到相应的服务代码段去。

注意不要忘了把该具体中断事件的中断标志位清除掉,硬件是不会自动清除TIME2寄存器中具体的中断标志位的。

d/ 中断返回

执行完中断服务后,中断返回过程,在这个过程中需要:

硬件将IABR寄存器中相应的标志位清另,表示该中断处理完成

如果TIME2本身还有中断标志位置位,表示TIME2 还有中断在申请,则重新将TIME2的Pending标志置为1,等待再次进入TIME2的中断服务。

注意:以上中断过程在《ARM Cortex-M3权威指南》中有详细描述,并配合时序图说明,可以参考。

如果以上明白了,那么可以在ST提供的函数库的帮助下,正确的设置和使用STM32的中断系统了。

如果你要了解更深入的东西,或者直接对寄存器操作,还要继续望下看。

三、深入NVIC

1. 看看Cortex-M3中定义与NVIC相关的寄存器有那些

SysTick Control and Status Register Read/write 0xE000E010 SysTick Reload Value Register Read/write 0xE000E014 SysTick Current Value Register Read/write clear 0xE000E018 SysTick Calibration Value Register Read-only 0xE000E01C

Irq 0 to 31 Set Enable Register Read/write 0xE000E100 . . . . .

Irq 224 to 239 Set Enable Register Read/write 0xE000E11C

Irq 0 to 31 Clear Enable Register Read/write 0xE000E180 . . . . .

Irq 224 to 239 Clear Enable Register Read/write 0xE000E19C

Irq 0 to 31 Set Pending Register Read/write 0xE000E200 . . . . .

Irq 224 to 239 Set Pending Register Read/write 0xE000E21C

Irq 0 to 31 Clear Pending Register Read/write 0xE000E280 . . . . .

Irq 224 to 239 Clear Pending Register Read/write 0xE000E29C

Irq 0 to 31 Active Bit Register Read-only 0xE000E300 . . . . . .

Irq 224 to 239 Active Bit Register Read-only 0xE000E31C

Irq 0 to 3 Priority Register Read/write 0xE000E400 . . . . .

Irq 224 to 239 Priority Register Read/write 0xE000E4EC

CPUID Base Register Read-only 0xE000ED00 Interrupt Control State Register Read/write or read-only 0xE000ED04 Vector Table Offset Register Read/write 0xE000ED08 Application Interrupt/Reset Control Register Read/write 0xE000ED0C System Control Register Read/write 0xE000ED10 Configuration Control Register Read/write 0xE000ED14 System Handlers 4-7 Priority Register Read/write 0xE000ED18 System Handlers 8-11 Priority Register Read/write 0xE000ED1C System Handlers 12-15 Priority Register Read/write 0xE000ED20 . . . . .

2.Stm32中用了那些

下面是从ST公司提供的函数库的头文件得到的,库是v3.1.0

/* memory mapping struct for Nested V ectored Interrupt Controller (NVIC) */

typedef struct

{

__IO uint32_t ISER[8]; /*!< Interrupt Set Enable Register */ uint32_t RESERVED0[24];

__IO uint32_t ICER[8]; /*!< Interrupt Clear Enable Register */ uint32_t RSERVED1[24];

__IO uint32_t ISPR[8]; /*!< Interrupt Set Pending Register */ uint32_t RESERVED2[24];

__IO uint32_t ICPR[8]; /*!< Interrupt Clear Pending Register */ uint32_t RESERVED3[24];

__IO uint32_t IABR[8]; /*!< Interrupt Active bit Register */ uint32_t RESERVED4[56];

__IO uint8_t IP[240]; /*!< Interrupt Priority Register, 8Bit wide */ uint32_t RESERVED5[644];

__O uint32_t STIR; /*!< Software Trigger Interrupt Register */ } NVIC_Type;

a/ 寄存器ISER、ICER、ISPR、ICPR、IABR在STM32中都使用的8个(实际3个就够了,后面的将来还要扩充?)。这些32位的寄存器中每一位对应了一个中断通道相应的标志。

比如地址在0xE000E100的ISER[0]这个32位的寄存器,第0位是中断通道0的允许位,第2位是中断通道1的允许标志……第32位是中断通道31的允许位;接下来地址在0xE000E104的ISER[1]则是中断通道32-63的允许位。ICER、ISPR、ICPR、IABR的结构相同,只是含义不同。

注意是对这些寄存器的操作:写1表示置位或清除,写0无任何影响。

例如:

对0xE000E100的ISER[0]的第0位写1,表示允许中断通道0中断;

但对0xE000E100的ISER[0]的第0位写0,则没有任何作用,该位保持不变。

如果要禁止中断通道0的中断响应,那么就必须:

对0xE000E180的ICER[0]的第0位写1,表示禁止中断通道0的中断;

对0xE000E180的ICER[0]的第0位写0,也是不起任何作用的。

b/ IP[240]用于定义240个外部中断通道的优先级,每1个字节对应一个通道。4个通道的IP[]构成一个32位的寄存器。在STM32中最多有68个外部中断通道,每个IP[]的1个字节中只使用高4位(见前面介绍)。IP[]的结构如下:

c/ 在ST公司提供的函数库的头文件中另一个数据结构中,还有一个寄存器需要关注:

/* memory mapping struct for System Control Block */

typedef struct

{

__I uint32_t CPUID; /*!

__IO uint32_t ICSR; /*!< Interrupt Control State Register */

__IO uint32_t VTOR; /*!< Vector Table Offset Register */

__IO uint32_t AIRCR; /*!< Application Interrupt / Reset Control Register */ __IO uint32_t SCR; /*!< System Control Register */

__IO uint32_t CCR; /*!< Configuration Control Register */

__IO uint8_t SHP[12]; /*!< System Handlers Priority Registers (4-7, 8-11, 12-15)*/

__IO uint32_t SHCSR; /*!< System Handler Control and State Register */

__IO uint32_t CFSR; /*!< Configurable Fault Status Register */

__IO uint32_t HFSR; /*!< Hard Fault Status Register */

__IO uint32_t DFSR; /*!< Debug Fault Status Register */

__IO uint32_t MMFAR; /*!< Mem Manage Address Register */

__IO uint32_t BFAR; /*!< Bus Fault Address Register */

__IO uint32_t AFSR; /*!< Auxiliary Fault Status Register */

__I uint32_t PFR[2]; /*!< Processor Feature Register */

__I uint32_t DFR; /*!< Debug Feature Register */

__I uint32_t ADR; /*!< Auxiliary Feature Register */

__I uint32_t MMFR[4]; /*!< Memory Model Feature Register */

__I uint32_t ISAR[5]; /*!< ISA Feature Register */

} SCB_Type;

它就是地址在0xE000ED0C的32位寄存器AIRCR(Application Interrupt/Reset Control Register),该寄存器的[10:8]3位就是PRIGROUP的定义位值,它规定了系统中有多少个抢先级中断和子优先级中断。而STM32只使用高4位bits,起可能的值如下(来自ST的函数库头文件中的定义)

#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority

4 bits for subpriority */ #define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority

3 bits for subpriority */ #define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority

2 bits for subpriority */ #define NVIC_PriorityGroup_

3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority

1 bits for subpriority */ #define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority

0 bits for subpriority */

由于这个寄存器相当重要,所以为了防止误操作(写),因此要改写这个寄存器的内容时,必须同时向这个寄存器的高16位[31:16]写验证字(Register key) 0x05FA。

例如:SBC->AIRCR |= (0x05FA0000 || 0x300); // 设置系统中断有16个抢先优先

// 级,无子优先级

d/ 下面的定义与SYSTICK相关,有时也会用到的。

/* memory mapping struct for SysTick */

typedef struct

{

__IO uint32_t CTRL; /*!< SysTick Control and Status Register */

__IO uint32_t LOAD; /*!< SysTick Reload Value Register */

__IO uint32_t VAL; /*!< SysTick Current Value Register */

__I uint32_t CALIB; /*!< SysTick Calibration Register */

} SysTick_Type;

STM32学习笔记

输入模式初始化GPIOE2,3,4 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PORTA,PORTE时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE); ③PE.2.3.4端口配置:GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; ④设置成(上拉)输入:GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; ⑤GPIO_Init(GPIOE, &GPIO_InitStructure); 输出模式初始化 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PB,PE端口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); ③3LED0-->PB.5 端口配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; ④设置(推挽)输出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ⑤设置IO口速度为50MHz GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ⑥说明初始化哪个端口GPIO_Init(GPIOB, &GPIO_InitStructure); 在LED灯试验中初始为高电平灭GPIO_SetBits(GPIOB,GPIO_Pin_5); 再初始化相同发输出模式时③④⑤可省略例如(经实验初始化恰好为不同IO口相同IO序号③可省略,应该不规范吧) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 1,头文件可以定义所用的函数列表,方便查阅你可以调用的函数; 2,头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的情况下,只要修改头文件的内容,程序就可以做相应的修改,不用亲自跑到繁琐的代码内去搜索。 3,头文件只是声明,不占内存空间,要知道其执行过程,要看你头文件所申明的函数是在哪个.c文件里定义的,才知道。 4,他并不是C自带的,可以不用。 5,调用了头文件,就等于赋予了调用某些函数的权限,如果你要算一个数的N次方,就要调用Pow()函数,而这个函数是定义在math.c里面的,要用这个函数,就必需调用math.h 这个头文件。

STM32学习笔记_STM32F103ZET6

STM32F103 系列芯片的系统架构: 系统结构: 在每一次复位以后,所有除SRAM 和FLITF 以外的外设都被关闭,在使用一个外设之前,必须设置寄存器RCC_AHBENR 来打开该外设的时钟。

GPIO 输入输出,外部中断,定时器,串口。理解了这四个外设,基本就入门了一款MCU。 时钟控制RCC: -4~16M 的外部高速晶振 -内部8MHz 的高速RC 振荡器 -内部40KHz低速RC 振荡器,看门狗时钟 -内部锁相环(PLL,倍频),一般系统时钟都是外部或者内部高速时钟经过PLL 倍频后得到 - 外部低速32.768K 的晶振,主要做RTC 时钟源

ARM存储器映像: 数据字节以小端格式存放在存储器中。一个字里的最低地址字节被认为是该字的最低有效字节,而最高地址字节是最高有效字节。

存储器映像与寄存器映射: ARM 存储器映像 4GB 0X0000 00000X1FFF FFFF 0X2000 00000X3FFF FFFF 0X4000 00000X5FFF FFFF

寄存器说明: 寄存器名称 相对外设基地址的偏移值 编号 位表 读写权限 寄存器位 功能说明 使用C语言封装寄存器: 1、总线和外设基地址封装利用地址偏移 (1)定义外设基地址(Block2 首地址) (2)定义APB2总线基地址(相对外设基地址偏移固定) (3)定义GPIOX外设基地址(相对APB2总线基地址偏移固定)(4)定义GPIOX寄存器地址(相对GPIOX外设基地址偏移固定)(5)使用 C 语言指针操作寄存器进行读/写 //定义外设基地址 #define PERIPH_BASE ((unsigned int)0x40000000) 1) //定义APB2 总线基地址 #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) 2) //定义GPIOC 外设基地址 #define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800) 3) //定义寄存器基地址这里以GPIOC 为例 #define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) 4) #define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04) #define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08) #define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C) #define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10) #define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14) #define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18) //控制GPIOC 第0 管脚输出一个低电平5) GPIOC_BSRR = (0x01<<(16+0)); //控制GPIOC 第0 管脚输出一个高电平 GPIOC_BSRR = (0x01<<0);

stm32学习 c语言笔记

这是前段时间做彩屏显示时候遇到的难题, *(__IO uint16_t *) (Bank1_LCD_C)这个就是将后面的数据转换为地址,然后对地址单元存放数据。可如下等效: __IO uint16_t *addr; addr = (__IO uint16_t *) Bank1_LCD_C; #ifdef和#elif连用,语法和if。。。else if语句一样 推挽输出增加驱动,可以驱动LED起来 static int count=0 count++ 这个语句中,count仅仅被初始化一次 以后加加一次期中的值就不会变化了 SysTick_CTRL(控制和状态寄存器) SysTick_LOAD(重装载寄存器) SysTick_VAL(当前值寄存器) SysTick_CALIB(校准值寄存器)

TFT经验:弄多大的相片,必须先把那个相片的尺寸改掉,再去取模,才可以,要不会有重影的嘿嘿嘿嘿 VBAT 是电池供电的引脚 VBAT和ADD同时都掉电时才能让备份区复位。 volatile一个变量的存储单元可以在定义该变量的程序之外的某处被引用。 volatile主要是程序员要告诉编译器不要对其定义的这个变量进行优化,防止其不能被引用,不能被改变。 VDDA>2.4V ADC才能工作 VDDA>2.7V USB才能工作 VDD(1.8-3.6v) VBAT=1.8-3.6v VSS VSSA VREF必须接到地线 没有外部电源供电时必须VBAT接上VDD 使用PLL时,VDDA必须供电

printf("abs(x)=%d\n",x<0?(-1)*x:x) 条件编译是问号前边为真则取冒号前边的值,为假的,则取后边的值。 所以说上边这条打印的语句是打印x的绝对值。 //stm32f10x_nvic.c stm32f10x_lib.c stm32f10x_gpio.c stm32f10x_flash.c stm32f10x_rcc.c TIM6 TIM7基本定时器 (只有这两个定时器不能产生PWM) TIM1 TIM8高级控制定时器 TIM2 TIM3 TIM4 TIM5为通用定时器 其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出,这样,STM32最多可以同时产生30路PWM输出! 修改和自己写代码时候

STM32学习笔记

STM32学习笔记——时钟频率 ******************************** 本学习笔记基于STM32固件库V3.0 使用芯片型号:STM32F103 开发环境:MDK ******************************** 第一课时钟频率 STM32F103内部8M的内部震荡,经过倍频后最高可以达到72M。目前TI的M3系列芯片最高频率可以达到80M。 在stm32固件库3.0中对时钟频率的选择进行了大大的简化,原先的一大堆操作都在后台进行。系统给出的函数为SystemInit()。但在调用前还需要进行一些宏定义的设置,具体的设置在system_stm32f10x.c文件中。 文件开头就有一个这样的定义: //#define SYSCLK_FREQ_HSE HSE_Value //#define SYSCLK_FREQ_20MHz 20000000 //#define SYSCLK_FREQ_36MHz 36000000 //#define SYSCLK_FREQ_48MHz 48000000 //#define SYSCLK_FREQ_56MHz 56000000 #define SYSCLK_FREQ_72MHz 72000000 ST 官方推荐的外接晶振是8M,所以库函数的设置都是假定你的硬件已经接了8M 晶振来运算的.以上东西就是默认晶振8M 的时候,推荐的CPU 频率选择.在这里选择了: #define SYSCLK_FREQ_72MHz 72000000 也就是103系列能跑到的最大值72M 然后这个C文件继续往下看 #elif defined SYSCLK_FREQ_72MHz const uint32_t SystemFrequency = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_SysClk = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_AHBClk = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_APB1Clk = (SYSCLK_FREQ_72MHz/2); const uint32_t SystemFrequency_APB2Clk = SYSCLK_FREQ_72MHz; 这就是在定义了CPU跑72M的时候,各个系统的速度了.他们分别是:硬件频率,系统时 钟,AHB总线频率,APB1总线频率,APB2总线频率.再往下看,看到这个了: #elif defined SYSCLK_FREQ_72MHz static void SetSysClockTo72(void); 这就是定义72M 的时候,设置时钟的函数.这个函数被SetSysClock ()函数调用,而SetSysClock ()函数则是被SystemInit()函数调用.最后SystemInit()函数,就是被你调用的了

STM32学习笔记(5)通用定时器PWM输出

STM32学习笔记(5):通用定时器PWM输出 2011年3月30日TIMER输出PWM 1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。 STM32的定时器除了TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出。 1.1PWM输出模式 STM32的PWM输出有两种模式,模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。模式1和模式2的区别如下: 110:PWM模式1-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。 111:PWM模式2-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为有效电平,否则为无效电平。 由此看来,模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。 而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《STM32参考手册》的“14.3.9 PWM模式”一节,在此就不详细赘述了。 1.2PWM输出管脚 PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7 定时器复用功能重映射”一节。在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。但是这些重映像的管脚也是由参考手册给出的。比如

STM32学习笔记

1、GPIO函数: 输出: HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);//此例以PA12口为例 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET); //此例以PA12口为例 HAL_GPIO_ TogglePin(GPIOA,GPIO_PIN_12); //此例以PA12口为例 2、串口函数: 1、串口发送/接收函数 HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制 HAL_UART_Receive();串口轮询模式接收,使用超时管理机制 HAL_UART_Transmit_IT();串口中断模式发送 HAL_UART_Receive_IT();串口中断模式接收 HAL_UART_Transmit_DMA();串口DMA模式发送 HAL_UART_Transmit_DMA();串口DMA模式接收 2、串口中断函数 HAL_UART_TxHalfCpltCallback();一半数据发送完成时调用 HAL_UART_TxCpltCallback();数据完全发送完成后调用 HAL_UART_RxHalfCpltCallback();一半数据接收完成时调用 HAL_UART_RxCpltCallback();数据完全接受完成后调用 HAL_UART_ErrorCallback();传输出现错误时调用 例程:串口接收中断 uint8_t aTxStartMessages[] = "\r\n******UART commucition using IT******\r\nPlease enter 10 characters:\r\n"; uint8_t aRxBuffer[20]; 2、在main函数中添加两个语句通过串口中断发送aTxStartMessage数组的数据和接收数据10个字符,保存在数组aRxBuffer中 HAL_UART_Transmit_IT(&huart1 ,(uint8_t*)aTxStartMessages,sizeof(aTxStartMessages)); //sizeof()可读取目标长度 HAL_UART_Receive_IT(&huart1,(uint8_t*)aRxBuffer,10); 3、在main.c文件后面添加中断接收完成函数,将接收到的数据又通过串口发送回去。 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { UNUSED(huart); HAL_UART_Transmit(&huart1,(uint8_t*)aRxBuffer,10,0xFFFF);//(uint8_t*)aRxBuffer为字符串地址,10为字符串长度,0xFFFF为超时时可以在中间加任何可执行代码。 }

STM32学习心得笔记

STM32学习心得笔记 时钟篇 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍, 但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外, 实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB 模块,其串行接口引擎需要一个频率为48MHz的时

钟源。该时钟源只能 从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL 必须使能, 并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL 输出、HSI或者HSE。系统时钟最 大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分 频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB 总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz), 另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。

STM32学习笔记(18)-数据的保存和毁灭

数据的保存和毁灭(2) 和以前学到的有关数据保存不同,这里的数据保存还有“保密”之意,即一旦受到意外的侵入,STM32将毁灭数据。这是通过Tamper机制来实现的。 以下是数据手册中的有关说明: 5.3.1 侵入检测 当TAMPER引脚上的信号从0变成1或者从1变成0(取决于备份控制寄存器BKP_CR的TPAL 位),会产生一个侵入检测事件。侵入检测事件将所有数据备份寄存器内容清除。然而为了避免丢失侵入事件,侵入检测信号是边沿检测的信号与侵入检测允许位的逻辑与,从而在侵入检测引脚被允许前发生的侵入事件也可以被检测到。 ●当 TPAL=0 时:如果在启动侵入检测TAMPER引脚前(通过设置TPE位)该引脚已经为高电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现上升沿)。 ●当 TPAL=1 时:如果在启动侵入检测引脚TAMPER前(通过设置TPE位)该引脚已经为低电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现下降沿)。 设置BKP_CSR寄存器的TPIE位为’1’,当检测到侵入事件时就会产生一个中断。 在一个侵入事件被检测到并被清除后,侵入检测引脚TAMPER应该被禁止。然后,在再次写入备份数据寄存器前重新用TPE位启动侵入检测功能。这样,可以阻止软件在侵入检测引脚上仍然有侵入事件时对备份数据寄存器进行写操作。这相当于对侵入引脚TAMPER进行电平检测。 注:当V DD电源断开时,侵入检测功能仍然有效。为了避免不必要的复位数据备份寄存器,TAMPER引脚应该在片外连接到正确的电平。 显然,Tamper需要硬件与之配合。以上数据手册描述了硬件配置时的一些注意事项。 (1)可以是把引脚由低电平到高电平认为是一次侵入,也可以把引脚从高电平变到低电平认为是一次侵入,这通过TPAL来设置。

STM32自学笔记

一、原子位操作: 原子位操作定义在文件中。令人感到奇怪的是位操作函数是对普通的内存地址进行操作的。原子位操作在多数情况下是对一个字长的内存访问,因而位号该位于0-31之间(在64位机器上是0-63之间),但是对位号的范围没有限制。 原子操作中的位操作部分函数如下: void set_bit(int nr, void *addr)原子设置addr所指的第nr位 void clear_bit(int nr, void *addr)原子的清空所指对象的第nr位 void change_bit(nr, void *addr)原子的翻转addr所指的第nr位int test_bit(nr, void *addr)原子的返回addr位所指对象nr位int test_and_set_bit(nr, void *addr)原子设置addr所指对象的第nr位,并返回原先的值 int test_and_clear_bit(nr, void *addr)原子清空addr所指对象的第nr位,并返回原先的值 int test_and_change_bit(nr, void *addr)原子翻转addr所指对象的第nr位,并返回原先的值 unsigned long word = 0; set_bit(0, &word); /*第0位被设置*/ set_bit(1, &word); /*第1位被设置*/ clear_bit(1, &word); /*第1位被清空*/ change_bit(0, &word); /*翻转第0位*/ 二、STM32的GPIO锁定: 三、中断挂起: 因为某种原因,中断不能马上执行,所以“挂起”等待。比如有高、低级别的中断同时发生,就挂起低级别中断,等高级别中断程序执行完,在执行低级别中断。四、固文件: 固件(Firmware)就是写入EROM(可擦写只读存储器)或EEPROM(电可擦可编程只读存储器)中的程序。 五、固件库:包含各个外设或者内核的驱动头文件和C文件。 六、TIx的输入捕获滤波器(消抖): 采样频率fSAMPLING,采样次数N,如果以采样频率对一脉冲进行采样时,如果在N个采样方波里该脉宽不变,则视为一次有效的脉冲,否则视为无效的脉冲。 七、高级定时器的PWM互补输出: 常用于X相电机驱动,其中的互补输出则防止电机的死区出现。

STM32学习LCD的显示

STM32学习LCD的显示 1.LCD/LCM的基本概念 液晶显示器(Liquid Crystal Display: LCD)的构造是在两片平行的玻璃当中放置液态的晶体,两片玻璃中间有许多垂直和水平的细小电线,透过通电与否来控制杆状水晶分子改变方向,将光线折射出来产生画面。 LCM(LCD Module)即LCD显示模组、液晶模块,是指将液晶显示器件,连接件,控制与驱动等外围电路,PCB电路板,背光源,结构件等装配在一起的组件。 在平时的学习开发中,我们一般使用的是LCM,带有驱动IC和LCD屏幕等多个模块。 2.FSMC的基本概念 在STM32上开发LCD显示,可以有两种方式来对LCD进行操作,一种是通过普通的IO 口,连接LCM的相应引脚来进行操作,第2种是通过FSMC来进行操作。 可变静态存储控制器(Flexible Static Memory Controller: FSMC) 是STM32系列中内部集成256 KB以上FlaSh,后缀为xC、xD和xE的高存储密度微控制器特有的存储控制机制。之所以称为“可变”,是由于通过对特殊功能寄存器的设置,FSMC能够根据不同的外部存储器类型,发出相应的数据/地址/控制信号类型以匹配信号的速度,从而使得STM32系列微控制器不仅能够应用各种不同类型、不同速度的外部静态存储器,而且能够在不增加外部器件的情况下同时扩展多种不同类型的静态存储器,满足系统设计对存储容量、产品体积以及成本的综合要求。 FSMC有很多优点: 1.支持多种静态存储器类型。STM32通过FSMC可以与SRAM、ROM、PSRAM、NOR Flash和NANDFlash存储器的引脚直接相连。 2.支持丰富的存储操作方法。FSMC不仅支持多种数据宽度的异步读/写操作,而且支持对NOR、PSRAM、NAND存储器的同步突发访问方式。 3.支持同时扩展多种存储器。FSMC的映射地址空间中,不同的BANK是独立的,可用于扩展不同类型的存储器。当系统中扩展和使用多个外部存储器时,FSMC会通过总线悬空延迟时间参数的设置,防止各存储器对总线的访问冲突。 4.支持更为广泛的存储器型号。通过对FSMC的时间参数设置,扩大了系统中可用存储器的速度范围,为用户提供了灵活的存储芯片选择空间。 5.支持代码从FSMC扩展的外部存储器中直接运行,而不需要首先调入内部SRAM。FSMC包含两类控制器: 1.1个NOR闪存/SRAM控制器,可以与NOR闪存、SRAM和PSRAM存储器接口。 2.1个NAND闪存/PC卡控制器,可以与NAND闪存、PC卡,CF卡和CF+存储器接口。控制器产生所有驱动这些存储器的信号时序: 1.16位数据线,用于连接8位或16位的存储器; 2.26位地址线,最多可连续64MB的存储器(这里不包括片选线); 3.5位独立的片选信号线; 4.1组适合不同类型存储器的控制信号线: -控制读/写操作 -与存储器通信,提供就绪/繁忙信号和中断信号 -与所用配置的PC卡接口:PC存储卡、PC I/O卡和真正的IDE接口 从FSMC的角度看,可以把外部存储器划分为固定大小为256MB的4个存储块 · 存储块1用于访问最多4个NOR闪存或者PSRAM存储设备。这个存储区被划分为4个

STM32学习笔记:LCD的显示

年月日显示 . 地基本概念 液晶显示器( : )地构造是在两片平行地玻璃当中放置液态地晶体,两片玻璃中间有许多垂直和水平地细小电线,透过通电与否来控制杆状水晶分子改变方向,将光线折射出来产生画面.文档来自于网络搜索 ( )即显示模组、液晶模块,是指将液晶显示器件,连接件,控制与驱动等外围电路,电路板,背光源,结构件等装配在一起地组件.文档来自于网络搜索 在平时地学习开发中,我们一般使用地是,带有驱动和屏幕等多个模块. . 地基本概念 在上开发显示,可以有两种方式来对进行操作,一种是通过普通地口,连接地相应引脚来进行操作,第种是通过来进行操作.文档来自于网络搜索 可变静态存储控制器( : ) 是系列中内部集成以上,后缀为、和地高存储密度微控制器特有地存储控制机制.之所以称为“可变”,是由于通过对特殊功能寄存器地设置,能够根据不同地外部存储器类型,发出相应地数据地址控制信号类型以匹配信号地速度,从而使得系列微控制器不仅能够应用各种不同类型、不同速度地外部静态存储器,而且能够在不增加外部器件地情况下同时扩展多种不同类型地静态存储器,满足系统设计对存储容量、产品体积以及成本地综合要求.文档来自于网络搜索 有很多优点: . 支持多种静态存储器类型.通过可以与、、、和存储器地引脚直接相连.文档来自于网络搜索 . 支持丰富地存储操作方法.不仅支持多种数据宽度地异步读写操作,而且支持对、、存储器地同步突发访问方式.文档来自于网络搜索 . 支持同时扩展多种存储器.地映射地址空间中,不同地是独立地,可用于扩展不同类型地存储器.当系统中扩展和使用多个外部存储器时,会通过总线悬空延迟时间参数地设置,防止各存储器对总线地访问冲突.文档来自于网络搜索 . 支持更为广泛地存储器型号.通过对地时间参数设置,扩大了系统中可用存储器地速度范围,为用户提供了灵活地存储芯片选择空间.文档来自于网络搜索 . 支持代码从扩展地外部存储器中直接运行,而不需要首先调入内部. 包含两类控制器: . 个闪存控制器,可以与闪存、和存储器接口. . 个闪存卡控制器,可以与闪存、卡,卡和存储器接口. 控制器产生所有驱动这些存储器地信号时序: . 位数据线,用于连接位或位地存储器; . 位地址线,最多可连续地存储器(这里不包括片选线); . 位独立地片选信号线; . 组适合不同类型存储器地控制信号线: 控制读写操作 与存储器通信,提供就绪繁忙信号和中断信号 与所用配置地卡接口:存储卡、卡和真正地接口 从地角度看,可以把外部存储器划分为固定大小为地个存储块 ·存储块用于访问最多个闪存或者存储设备.这个存储区被划分为个区,并有个专用地片选.文档来自于网络搜索·存储块和用于访问闪存设备,每个存储块连接一个闪存. ·存储块用于访问卡设备 每一个存储块上地存储器类型是由用户在配置寄存器中定义地. 注意:只是提供了一个控制器,并不提供相应地存储设备,至于外设接地是什么设备,完全是由用户自己选择,只要能用于控制,就可以,像本次实验中,我们接地就是.文档来自于网络搜索 . 本例中地使用 由于本例只是利用对进行操作,因此不用完全懂得地所有功能,而是懂得一部分相应地操作即可.文档来自于网络搜索 . 包括哪几个部分

STM32学习笔记-USART程序解释(原子)

USART程序分析 一 .H文件 #ifndef __USART_H #define __USART_H #include #include "stdio.h" extern u8 USART_RX_BUF[64]; //接收缓冲,最大63个字节.末字节为换行符extern u8 USART_RX_STA; //接收状态标记 //如果想串口中断接收,请不要注释以下宏定义 //#define EN_USART1_RX 使能串口1接收 void uart_init(u32 pclk2,u32 bound); #endif 解释:extern 作用域:如果整个工程由多个文件组成,在一个文件中想引用另外一个文件中已经定义的外部变量时,则只需在引用变量的文件中用extern关键字加以声明即可。可见,其作用域从一个文件扩展到多个文件了。 例子: 文件a.c的内容: #include int BASE=2; //变量定义 int exe(int x); //外部函数提前声明 int main(int argc, char *agrv[]) { int a=10; printf("%d^%d = %d\n",BASE,a,exe(a)); return 0; } 文件b.c的内容: #include extern BASE; //外部变量声明 int exe(int x) { int i; int ret=1; for(i=0;i

STM32学习笔记(初学者快速入门

STM32学习笔记(初学者快速入门 STM32 学习笔记 从51 开始单片机玩了很长时间了有51PICAVR 等等早就想跟潮 流玩玩ARM 但一直没有开始原因-----不知道玩了ARM 可以做什么对我自 己而言如果为学习而学习肯定学不好然后cortex-m3 出来了据说这 东西可以替代单片机于是马上开始关注也在第一时间开始学习可惜一开始 就有点站错了队选错了型仍是对我自己而言我希望这种芯片应该是满大 街都是随便哪里都可以买得到但我选的第一种显然做不到为此大概浪费

了一年多时间吧现在回到对我来说是正确的道路上来啦边学边写点东西 这里写的是我的学习的过程显然很多时候会是不全面的不系统的感 悟式的甚至有时会是错误的有些做法会是不专业的那么为什么我还要写 呢这是一个有趣的问题它甚至涉及到博客为什么要存在的问题显然博客 里面的写的东西其正确性权威性大多没法和书比可为什么博客会存在呢 理由很多我非专家只说我的感慨 我们读武侠小说总会有一些创出独门功夫的宗师功夫极高然后他的弟 子则基本上无法超越他我在想这位宗师在创造他自己的独门功

夫时必然会 有很多的次的曲折弯路甚至失败会浪费他的很多时间而他教给弟子时 则已去掉了这些曲折和弯路当然更不会把失败教给弟子按理说效率应该更 高可是没用弟子大都不如师为什么呢也许知识本身并不是最重要的获 取知识的过程才是最重要的也许所谓的知识并不仅仅是一条条的结论而是 附带着很多说不清道不明的东西如植物的根一条主根上必带有大量的小小的 触须 闲话多了些就权当前言了下面准备开始 一条件的准备

我的习惯第一步是先搭建一个学习的平台原来学51PICAVR 时都 是想方设法自己做些工具实验板之类现在人懒了直接购买成品了 硬件电路板火牛板 软件有keil 和iar 可供选择网上的口水仗不少我选keil理由很简单 这个我熟目前要学的知识中软硬件我都不熟所以找一个我有点熟的东西 就很重要在我相当熟练之前肯定不会用到IAR如果真的有一天不得不用I AR 相信学起来也很容易因为这个时候硬件部分我肯定很熟了再加上有ke il 的基础所以应该很容易学会了

STM32学习笔记(关于时钟)

STM32学习----时钟(转载) 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 HSE/LSE时钟源 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz 的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL输出、HSI或者HSE。系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。

STM32学习笔记

FLASH篇: 一、闪存:主存储器,信息块和闪存存储器接口寄存器等3部分组成。 1、主存储器:存放代码与数据常量(编译器编译完成后CODE=,RO=,RW=,ZI=,依次为代码,常量,初始化变量,未初始化变量),即前面两个。B0,B1都为GND时,从0x08000000开始运行代码。 2、信息块:分为启动代码和用户选择字节。启动代码是生产线上少些进去的,用于USART1串口下载时使用,B0=1,B1=0时运行这段代码。用户选择字用于配制写保护杜保护等功能。 3、闪存存储器接口寄存器:控制闪存的读写,用于控制整个模块。 二、闪存编程/擦除控制器(FPEC) 对主存储器和信息块的写入管理。在执行写操作时,任何对闪存读操作都会锁住总线,在写操作完成后读操作才正确而执行。 包含有7个32位寄存器: 键寄存器FLASH_KEYR; 选择字节键寄存器FLASH_OPTKEYR; 闪存控制寄存器FLASH_CR; 闪存地址寄存器FLASH_AR; 闪存状态寄存器FLASH_SR; 选择字节寄存器FLASH_ORR; 写保护寄存器FLASH_WRPR; 复位后,FPEC模块是被保护的,不能写入FLASH_CR寄存器,通过写入特定的序列到FLASH_KEYR寄存器可以打开FPEC模块(写入KEY1和KEY2),当其中有一个写入错误,写入RDPRT进行解锁。 RDPRT=0X0000000A5; KEY1=0X45670123; KEY2=0XCDEF99AB; 注:每次必须写入16位,也只有写16位。 三、闪存读取 直接寻址方式,任何32为数据读操作都能访问闪存模块的内容并得到相应的数据。读操作时FLASH_ACR寄存器配置FLASH等待周期为2。 DATA=*(U16)*ADDR; 四、闪存的编程和擦除

牛人的STM32学习笔记(寄存器版本)

一、GPIO口的配置 STM32的DGPIO口最多可以有7组(GPIOa~GPIOg),而每一组GPIO口均有16个 双向IO组成。并且没个IO口均可配置成8种模式(4种输入模式,4种输出模式)。不管 配置哪个IO口也不论将其配置成哪种模式(但是配置成哪种模式要看具体应用,参考《中 文参考手册》第105页)都可以按以下步骤来进行配置: (1)使能PORTx(x=A~G)时钟 这里就得操作寄存器RCC_APB2ENR(32为寄存器)了 15 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN 7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留AFIOEN RCC_APB2ENR的0~15位(06~32位保留) 第2~8分别是使能GPIOA~GPIOG时钟的,只要将其置“1”即可,如 RCC_APB2ENR|=1<<2;就是使能GPIOA的时钟;其余IO口的始终使能一次类推。 (2)对相应的IO模式进行配置,低8位配置GPIOx_CRL;高8位配置GPIOx_CRH 31 30 29 28 27 26 25 24 CNF7[1:0] MODE7[1:0] CNF6[1:0] MODE6[1:0] 23 22 21 20 19 18 17 16 CNF5[1:0] MODE5[1:0] CNF4[1:0] MODE4[1:0] 15 14 13 12 11 10 9 8 CNF3[1:0] MODE3[1:0] CNF2[1:0] MODE2[1:0] 7 6 5 4 3 2 1 0 CNF1[1:0] MODE1[1:0] CNF0[1:0] MODE0[1:0] GPIOx_CRL(x=A~G(端口配置低寄存器x=A…E) 该寄存器用于配置GPIOx的低8位,具体8种模式的配置见《中文参考手册》例如: GPIOD->CRL&=0XFFFFF0FF;GPIOD->CRL|=0X00000300;/PD.2推挽输出;其余IO口的 低8位以此类推。 31 30 29 28 27 26 25 24 CNF15[1:0] MODE15[1:0] CNF14[1:0] MODE14[1:0] 23 22 21 20 19 18 17 16 CNF13[1:0] MODE13[1:0] CNF12[1:0] MODE12[1:0] 15 14 13 12 11 10 9 8 CNF11[1:0] MODE11[1:0] CNF10[1:0] MODE10[1:0] 7 6 5 4 3 2 1 0 CNF9[1:0] MODE9[1:0] CNF8[1:0] MODE8[1:0] GPIOx_CRH(端口配置高寄存器x=A…E) 该寄存器用于配置GPIOx的高8位,具体8种模式的配置见《中文参考手册》例如: GPIOA->CRH&=0XFFFFFFF0;;GPIOA->CRH|=0X00000003;//PA8 推挽输出;其余IO口 的高8位以此类推。

STM32学习笔记系统时钟和SysTick定时器

STM32学习笔记(3):系统时钟和SysTick定时器 1.STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI、HSE、LSI、LSE、PLL (1)HSI是高速内部时钟,RC振荡器,频率为8MHz; (2)HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz; (3)LSI是低速内部时钟,RC振荡器,频率为40KHz; (4)LSE是低速外部时钟,接频率为32.768KHz的石英晶体; (5)PLL为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL 的输入可以接HSI/2、HSE或者HSE/2。倍频可选择为2 – 16倍,但 是其输出频率最大不得超过72MHz。 其中,40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为 48MHz的时钟源。该时钟源只能从PLL端获取,可以选择为1.5分频或者1分频,也就是,当需使用到USB模块时,PLL必须使能,并且时钟配置为48MHz 或72MHz。 另外STM32还可以选择一个时钟信号输出到MCO脚(PA.8)上,可以选择为PLL输出的2分频、HSI、HSE或者系统时钟。 系统时钟SYSCLK,它是提供STM32中绝大部分部件工作的时钟源。系统时钟可以选择为PLL输出、HSI、HSE。系系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各个模块使用,AHB分频器可以选择1、2、4、8、16、64、128、256、512分频,其分频器输出的时钟送给5大模块使用: (1)送给AHB总线、内核、内存和DMA使用的HCLK时钟; (2)通过8分频后送给Cortex的系统定时器时钟; (3)直接送给Cortex的空闲运行时钟FCLK; (4)送给APB1分频器。APB1分频器可以选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一

相关文档