STM32各模块学习笔记
- 格式:pdf
- 大小:6.35 MB
- 文档页数:44
《STM32Cube高效开发教程》读书笔记目录一、前言 (2)1.1 书籍简介 (3)1.2 编写目的 (4)二、STM32Cube概述 (5)2.1 STM32Cube的意义 (6)2.2 STM32Cube的主要特点 (7)三、安装与配置 (9)3.1 STM32Cube的安装 (10)3.2 开发环境的配置 (11)四、创建项目 (12)4.1 新建项目 (13)4.2 项目设置 (14)五、HAL库介绍 (15)5.1 HAL库简介 (16)5.2 HAL库的主要组件 (18)六、STM32最小系统 (19)6.1 STM32最小系统的组成 (21)6.2 STM32最小系统的应用 (22)七、GPIO操作 (24)7.1 GPIO的基本概念 (25)7.2 GPIO的操作方法 (26)八、中断系统 (28)8.1 中断的基本概念 (29)8.2 中断的处理过程 (31)九、定时器 (33)9.1 定时器的功能介绍 (34)9.2 定时器的操作方法 (36)十五、文件系统 (37)一、前言随着科技的飞速发展,嵌入式系统已广泛应用于我们生活的方方面面,从智能手机到自动驾驶汽车,其重要性不言而喻。
而STM32作为一款广泛应用的微控制器系列,以其高性能、低功耗和丰富的外设资源赢得了广大开发者的青睐。
为了帮助开发者更好地掌握STM32系列微控制器的开发技巧,提升开发效率,我们特别推出了《STM32Cube 高效开发教程》。
本书以STM32Cube为核心,通过生动的实例和详细的讲解,全面介绍了STM32系列微控制器的开发过程。
无论是初学者还是有一定基础的开发者,都能从中找到适合自己的学习内容。
通过本书的学习,读者将能够更加深入地理解STM32的内部结构和工作原理,掌握其编程方法和调试技巧,从而更加高效地进行嵌入式系统的开发和应用。
在科技日新月异的今天,STM32系列微控制器将继续扮演着举足轻重的角色。
STM32学习笔记:读写内部Flash(介绍+附代码)⼀、介绍⾸先我们需要了解⼀个内存映射:stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯⽚实际的flash⼤⼩,不同的芯⽚flash⼤⼩不同。
RAM起始地址是0x2000 0000,结束地址是0x2000 0000加上芯⽚的RAM⼤⼩。
不同的芯⽚RAM也不同。
Flash中的内容⼀般⽤来存储代码和⼀些定义为const的数据,断电不丢失,RAM可以理解为内存,⽤来存储代码运⾏时的数据,变量等等。
掉电数据丢失。
STM32将外设等都映射为地址的形式,对地址的操作就是对外设的操作。
stm32的外设地址从0x4000 0000开始,可以看到在库⽂件中,是通过基于0x4000 0000地址的偏移量来操作寄存器以及外设的。
⼀般情况下,程序⽂件是从 0x0800 0000 地址写⼊,这个是STM32开始执⾏的地⽅,0x0800 0004是STM32的中断向量表的起始地址。
在使⽤keil进⾏编写程序时,其编程地址的设置⼀般是这样的:程序的写⼊地址从0x08000000(数好零的个数)开始的,其⼤⼩为0x80000也就是512K的空间,换句话说就是告诉编译器flash的空间是从0x08000000-0x08080000,RAM的地址从0x20000000开始,⼤⼩为0x10000也就是64K的RAM。
这与STM32的内存地址映射关系是对应的。
M3复位后,从0x08000004取出复位中断的地址,并且跳转到复位中断程序,中断执⾏完之后会跳到我们的main函数,main函数⾥边⼀般是⼀个死循环,进去后就不会再退出,当有中断发⽣的时候,M3将PC指针强制跳转回中断向量表,然后根据中断源进⼊对应的中断函数,执⾏完中断函数之后,再次返回main函数中。
⼤致的流程就是这样。
1.1、内部Flash的构成:STM32F429 的内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及⼤⼩如下:STM32F103的中容量内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及⼤⼩如下:注意STM32F105VC的是有64K或128页x2K=256k字节的内置闪存存储器,⽤于存放程序和数据。
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位inttest_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(电可擦可编程只读存储器)中的程序。
/******************************************************************* 文件名:书写程序中一些特别需要留意的地方文件编辑人:张恒编辑日期:15/11/23功能:快速查阅巩固知识点*******************************************************************/ 版本说明:v1.0版本:1.开始编辑书写整个文档,开始用的为TXT文档的形式,整理了部分学习到的东西和一些在书写常用程序中容易出错的地方,以及经常忽视细节而导致程序运行失败,是巩固知识点,提醒值得注意地方的工具文档。
2.添加的功能上基本涵盖了所有的模块,除了串口通信中的SPI和I2C、I2S等,应用是比较简单后续可能会添加。
3.对一些特定的功能综合应用并未加入进去,这是一个不好的地方,后续应该会随着学习总结更新,每次更新记录为一个版本。
// 2015/11/24;v1.1版本:1.将所有的TXT版本的文档全部转换为DOC模式,并且更新的加入了目录显示,显示为1级目录,方便查阅相关内容。
2.更新了SysTick书写中值得注意的地方3.更新了FSMC的一些细微操作,后续继续追捕更新书写细节。
V1.2版本:1.更新了FSMC部分功能显示,详细了FSMC的使用注意事项2.添加了RTC实时时钟的一些注意事项。
//2015/12/1;V1.3版本:1.更新RTC部分注意事项。
//2015/12/11V1.4版本:1.更新ADC校准标志部分注意事项。
2.更新了TIM1和TIM8的高级定时器特殊功能说明。
//2015/12/13V1.5版本:1.优化了部分注意事项,SysTick的写法上重新的定制写法。
2.优化了ADC在使用过程的一些细节注意地方。
3.面对最近出现的浮点数运算错误,配合AD数据进行总结。
4.RTC细节的把握-配置正确顺序的错误。
stm32相关笔记——ADC部分我们在学习⼀门技术的时候,应该对它的理论部分有所了解,然后才能在实践中进⼀步加深理解,进⽽掌握。
对于stm32来说,我认为学习的时候应该先仔细阅读相关的参考⼿册,然后再动⼿实践,这样才能理解得更加透彻,掌握得更加牢固!今天记录⼀下我学习stm32的ADC部分的了解。
1.介绍⼩结:stm32的ADC有18个通道(16个外部通道+2个内部通道),有单次、连续、扫描和间断四种模式,ADC的结果可以左对齐和右对齐的⽅式存储在16位的数据寄存器中(⼀般我们都是使⽤右对齐的⽅式)2、特征3、框图框图应该是最重要的部分了,理解了框图,对这个外设的理解就⽐较透彻了。
①模拟⾄数字转换器中有两个通道,⼀个是注⼊通道,⼀个是规则通道,对应的转换结果也是存储到注⼊通道数据寄存器和规则通道数据寄存器中(都是16位的);②注⼊通道数据寄存器有4个,规则通道数据寄存器只有1个,规则通道最多可以转化16个通道的数据,⽽结果都是存储在⼀个规则通道数据寄存器中,为了避免数据丢失,可以采⽤DMA搬运数据,提⾼效率。
③触发注⼊通道开始转化的外部触发信号有8种,如图所⽰,其中TIM8_CH4及其重映射只存在于⼤容量的产品中。
④类似于注⼊通道,触发规则通道的外部触发信号也有8种,如图所⽰,其中TIM8_TRGO及其重映射也只存在于⼤容量产品中。
⑤以上的两点只针对ADC1和ADC2,ADC3的触发信号有所不同,如图所⽰:⑥转换的过程如图,ADCx_IN0~ADCx_IN15共16个外部通道,通过GPIO端⼝将模拟量传达到模拟⾄数字转化器中的注⼊通道或者规则通道,另外还有两个内部通道温度传感器和V REFINT,同样也可以将模拟量传送到模拟⾄数字转化器中的注⼊通道或者规则通道,注⼊通道最多可以转换4个通道的模拟量,转换结果存储到注⼊通道数据寄存器中,转换完成后会产⽣JEOC标志位,规则通道最多可以转换16个通道,转换结果存储到规则通道数据寄存器中,转换完成后会产⽣EOC标志位。
stm32学习笔记--spi与iic关于上次说的要改程序的问题,//读ADXL345 寄存器//addr:寄存器地址//返回值:读到的值u8 ADXL345_RD_Reg(u8 addr){u8 temp=0; IIC_Start(); IIC_Send_Byte(ADXL_WRITE); //发送写器件指令temp=IIC_Wait_Ack(); IIC_Send_Byte(addr); //发送寄存器地址temp=IIC_Wait_Ack(); IIC_Start(); //重新启动IIC_Send_Byte(ADXL_READ); //发送读器件指令temp=IIC_Wait_Ack(); temp=IIC_Read_Byte(0); //读取一个字节,不继续再读,发送NAK IIC_Stop(); //产生一个停止条件return temp; //返回读到的值} 这段写寄存器代码,不理解temp 为什么要被频繁的赋值,去掉后,宏观看来对结果没有影响。
第二个不理解的地方是为什么在发送寄存器地址之后要从新启动一次,因为在相似的写寄存器函数中,在相同的位置不存在重启代码。
注释掉该句之后显示ADXL345 error。
这两天主要看了三轴加速度计的程序,虽然例程里的能看懂,但是在四轴里的程序却不那么容易,我甚至不明白为什么他要自己写一个iic 的函数,我打算接下来把它的程序和例程里的程序对照来看,看能不能找到什么头绪。
下面是对以前学过内容的总结:对位的寻址操作为了实现对SARM、I/O 外设空间中某一位的操作,在寻址空间(4GB)另一地方取个别名区空间,从这地址开始,每一个字(32bit)就对应SRAM 或I/O 的一位。
即原来每个字节用一个地址,现在给字节中的每个位一个地址,实现了对位的寻址。
spi 与iic 之间各自的优劣1 硬件连接的优劣SPI 是[单主设备(single-master )]通信协议,这意味着总线中的只有一支中心设备能发起通信。
STM32F103学习笔记(五)外部中断首先是外部中断基本的概念:STM32 的每个IO 都可以作为外部中断的中断输入口,这点也是STM32 的强大之处。
STM32F103 的中断控制器支持19 个外部中断/事件请求。
每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F103 的19 个外部中断为:线0~15:对应外部IO 口的输入中断。
线16:连接到PVD 输出。
线17:连接到RTC 闹钟事件。
线18:连接到USB 唤醒事件。
线16~18还没有学到只看了线0~15。
每个中断线对应着7个GPIO口,形成映射关系,以线0 为例:它对应了GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0。
而中断线每次只能连接到1 个IO 口上,这样就需要通过配置来决定对应的中断线配置到哪个GPIO 上了。
下面我们看看GPIO 跟中断线的映射关系图:根据映射关系,就开始配置按键对应GPIO口和中断的映射了:[csharp] view plain copy <pre name="code" class="csharp"><prename="code" class="html">void EXTIX_Init(void){ EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; KEY_Init(); // 按键端口初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,EN ABLE); //使能复用功能时钟//GPIOE.2 中断线以及中断初始化配置下降沿触发GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_Pi nSource2);EXTI_InitStructure.EXTI_Line=EXTI_Line2; //KEY2 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOE.3 中断线以及中断初始化配置下降沿触发//KEY1GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_Pi nSource3);EXTI_InitStructure.EXTI_Line=EXTI_Line3;EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOE.4 中断线以及中断初始化配置下降沿触发//KEY0GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_Pi nSource4);EXTI_InitStructure.EXTI_Line=EXTI_Line4;EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOA.0 中断线以及中断初始化配置上升沿触发PA0 WK_UPGPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_Pi nSource0);EXTI_InitStructure.EXTI_Line=EXTI_Line0;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能按键WK_UP所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//使能按键KEY2所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//使能按键KEY1所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//使能按键KEY0所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器} //外部中断0服务程序voidEXTI0_IRQHandler(void) { delay_ms(10);//消抖if(KEY3==1) //WK_UP按键{ BEEP=!BEEP; } EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位} //外部中断2服务程序voidEXTI2_IRQHandler(void) { delay_ms(10);//消抖if(KEY2==0) //按键KEY2{ LED0=!LED0; }EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE2上的中断标志位} //外部中断3服务程序voidEXTI3_IRQHandler(void) { delay_ms(10);//消抖if(KEY1==0) //按键KEY1{ LED1=!LED1; }EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位} void EXTI4_IRQHandler(void){ delay_ms(10);//消抖if(KEY0==0) //按键KEY0 { LED0=!LED0;LED1=!LED1; }EXTI_ClearITPendingBit(EXTI_Line4); //清除LINE4上的中断标志位} [html] view plain copy。
STM32学习笔记之—RTC写这篇学习笔记的时候距上一篇笔记间隔的时间不短了,期间有网友关心询问为什么不更新文章,主要是这一段时间工作太忙了没有闲暇时间做下来学习,工作是重要的事情,不能把饭碗丢了啊o(∩_∩)o…,好了废话少说切入正题。
既然我们要使用RTC就要先对它有个大致的了解,知己知彼才能百战不殆嘛!STM32内部RTC功能非常实用,它的供电和时钟是独立于内核的,可以说是STM32内部独立的外设模块,有加上RTC内部寄存器不受系统复位掉电的影响,我们可以才用外部电池供电和32768表振晶体来实现真正RTC(实时时钟)功能。
的这里引用手册里一段概述“RTC由两个主要部分组成。
第一部分(APB1接口)用来和APB1总线相连。
此单元还包含一组16位寄存器,可通过APB1总线对其进行读写操作。
APB1接口以APB1总线时钟为时钟,用来与APB1总线接口。
另一部分(RTC核)由一系列可编程计数器组成,分成两个主要模块。
第一个模块是RTC的预分频模块,它可编程产生最长为1秒的RTC时间基准TR_CLK。
RTC的预分频模块包含了一个20位的可编程分频器(RTC预分频器)。
在每个TR_CLK周期中,如果在RTC_CR 寄存器中设置了相应允许位,则RTC产生一个中断(秒中断)。
第2个模块是一个32位的可编程的计数器,它可被初始化为当前的系统时间。
系统时间以TR_CLK速度增长并与存储在RTC_ALR寄存器中的可编程的时间相比较,如果RTC_CR控制寄存器中设置了相应允许位,则比较匹配时将产生一个闹钟中断。
”对于第一次实用RTC的时候我们要对它进行配置一番,现在大致说一下(代码是通过调用RTC_Config函数来实现的):1. 打开电源管理和备份寄存器时钟,提到备份寄存器这里要说一下,引用手册--“备份寄存器是10个16位的寄存器,可用来存储20个字节的用户应用程序数据。
他们处在备份域里,当VDD电源被切断,他们仍然由VBAT维持供电。
STM32自学笔记作者:忙碌的小姚新浪微博:@忙碌的小姚新浪博客:/mlxiaoyao222目录STM32 自学笔记 (1)第一章 (3)我与STM32 的那些日子 (3)第二章 (4)使用固件库建立一个工程 (4)1、了解STM32F103的固件库 (4)2、创建第一个工程 (4)3、接下来就是管理工程文件了 (9)4、编写main.c 和文件路径 (10)第三章 (14)STM32点亮第一个LED 使用keil for ARM MDK 软件仿真 (14)1、Main.c 函数代码: (14)2、代码分析: (15)3、软件仿真介绍: (16)第四章 (19)串口的使用 (19)1、为什么要用串口? (19)2、STM32跟PC机(也就是电脑)如何连接 (19)3、代码分析 (20)4、仿真及调试 (23)5、串口接收数据 (25)第五章 (27)通用定时器的使用 (27)1、STM32F103内部定时器有哪些? (27)2、如何进行程序编写 (27)3仿真结果观察 (30)4对第四章串口的补充 (31)5工程代码 (35)第一章我与STM32 的那些日子STM32这块板子是在阿莫上跟一个老师买的,砍了半天100块钱。
包括一个Jlink v8仿真器(好像65块左右),和一块STM32系统板。
那已是一年前的事了。
那时我刚大三,刚学了半年51,于是想学点更高级的。
但我好像属于三分钟热度的这种人,买回来学了一个星期,就学不动了,寄存器操作,固件库的使用根本就没明白是怎么一回事,之后就没有然后了。
现在看到那块板子,总有一种说不出的滋味,要是当时能咬牙切齿努力学习,说不定现在也不会安静地坐在电脑前一字一句敲打这篇激励性文章了。
对于STM32我没用任何基础,唯一有的也只是一年前学的那一个星期,不过那已不重要了,我现在仍是一个小白。
作为一个初学者,也许是坐井观天,看的是片面的,可能有很多观点是错误的,希望读者朋友能勇于指出来。
推挽输出与开漏输出的区别推挽输出推挽输出::可以输出高可以输出高,,低电平低电平,,连接数字器件连接数字器件; ;开漏输出开漏输出::输出端相当于三极管的集电极输出端相当于三极管的集电极. . 要得到高电平状态需要上拉电阻才行要得到高电平状态需要上拉电阻才行. . 适合于做电流型的驱动电流型的驱动,,其吸收电流的能力相对强其吸收电流的能力相对强((一般20ma 以内以内). ).推挽结构一般是指两个三极管分别受两互补信号的控制推挽结构一般是指两个三极管分别受两互补信号的控制,,总是在一个三极管导通的时候另一个截止另一个截止. .要实现“线与”需要用OC(open collector)collector)门电路门电路门电路..是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中以推挽方式存在于电路中,,各负责正负半周的波形放大任务各负责正负半周的波形放大任务,,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小关管每次只有一个导通,所以导通损耗小,,效率高。
输出既可以向负载灌电流,也可以从负载抽取电流。
抽取电流。
问题:问题:很多芯片的供电电压不一样,有3.3v 和5.0v 5.0v,需要把几种,需要把几种IC 的不同口连接在一起,是不是直接连接就可以了?实际上系统是应用在I2C 上面。
上面。
简答:简答:1、部分3.3V 器件有5V 兼容性,可以利用这种容性直接连接兼容性,可以利用这种容性直接连接2、应用电压转换器件,如TPS76733就是5V 输入,转换成3.3V 3.3V、、1A 输出。
输出。
开漏电路特点及应用在电路设计时我们常常遇到开漏(在电路设计时我们常常遇到开漏(open drain open drain )和开集()和开集()和开集(open collector open collector )的概念。
所)的概念。
所谓开漏电路概念中提到的“漏”就是指MOSFET 的漏极。
SYS.C程序解释#i nclude <stm32f10x_lib.h>#include "sys.h"//设置向量表偏移地址〃NVIC_VectTab:基址//Offset: 偏移量//CHECK OK//091207void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset){//检查参数合法性assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));assert_param(IS_NVIC_OFFSET(Offset));SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80); // 设置NVIC 的向量表偏移寄存器//用于标识向量表是在COD区还是在RAM区}解释:前面两行是用来检查参数合法性,这里不作分析。
重点看第三行。
#defi ne NVIC_VectTab_RAM ((u32)0x)#defi ne NVIC_VectTab_FLASH @32)0x08000000)typedef struct{vuc32 CPUID; vu32 ICSR;vu32 VTOR; vu32 AIRCR;vu32 SCR;vu32 CCR;vu32 SHPR[3]; vu32 SHCSR;vu32 CFSR;vu32 HFSR;vu32 DFSR;vu32 MMFAR;vu32 BFAR; vu32 AFSR;} SCB_TypeDef;在VV权威指南>> 第一百零四页,有这么一段话:NVIC中有一个寄存器,称为向量表偏移量寄存器”在地址0xE000_ED08处),通过修改它的值就能定位向量表。
但必须注意的是:向量表的起始地址是有要求的:必须先求出系统中共有多少个向量,再把这个数字向上增大到是2的整次幕,而起始地址必须对齐到后者的边界上。
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分频器。
STM32学习笔记(5):通用定时器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_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
111:PWM模式2-在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
由此看来,模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。
而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《STM32参考手册》的“14.3.9 PWM模式”一节,在此就不详细赘述了。
1.2PWM输出管脚PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7定时器复用功能重映射”一节。
在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。
STM32学习笔记——电源管理STM32的3种低功耗模式:1、睡眠模式__WFI(); __WFE();外部中断设置为中断模式时,__WFI()和__WFE()都能被中断唤醒;外部中断设置为事件模式时,只能唤醒__WFE();用事件唤醒时会唤醒2次,未找到原因(因按键性能不良,抖动严重);另外事件产生时不会置位标志位,不需要清除。
从睡眠模式返回时不需要重新设置系统时钟。
唤醒任意中断或事件唤醒对应的WFE、WFI.2、停机模式使用void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);进入停机模式;(1) 初始化用于唤醒的中断按键,配置为中断或事件;(2) 设置停止状态时的FLASH供电或掉电;(3) 选择电压调节器的工作模式并进入停止状态;(4) 使用按键中断唤醒芯片;(5) 重启HSE时钟,使系统完全恢复停止前的状态。
重启HSE时钟函数:SYSCLKConfig_STOP();static void SYSCLKConfig_STOP(void) /* After wake-up from STOP reconfigure the system clock */{RCC_HSEConfig(RCC_HSE_ON); /* 使能HSE */while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); /* 等待HSE 准备就绪*/RCC_PLLCmd(ENABLE); /* 使能PLL */while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); /* 等待PLL 准备就绪*/RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* 选择PLL作为系统时钟源*/while (RCC_GetSYSCLKSource() != 0x08); /* 等待PLL被选择为系统时钟源*/}当进入待机和停止模式时,HSEON该位由硬件清零,外部振荡器HSE被关闭,所以如果使用到HSE,则唤醒后需要重新设置使用的HSE;当从待机和停止模式返回或用作系统时钟的外部4-16MHz振荡器发生故障时,HSI位由硬件置’1’启动内部8MHz的RC振荡器HSI 。
stm32寄存器版学习笔记定时计数器中断STM32共有8个定时计数器,⾼级定时器: TIME1 TIME8是通⽤定时器:TIME2~TIME5基本定时器: TIME6和TIME7以TIME3通⽤定时器为例总结定时计数器的基本⽤法⼀:TIM3时钟使能APB1外设时钟使能寄存器(RCC_APB1ENR)Eg:RCC->APB1ENR|=1<<1; //使能TIM3时钟⼆:设置TIM3_ARR和TIM3_PSC的值通过这两个寄存器来设置⾃动重装的值以及分频系数⾃动重装载寄存器(TIMx_ARR)预分频器(TIMx_PSC)三:设置TIM3_DIER允许更新中断中断使能寄存器(TIMx_DIER)Eg: TIM3->DIER|=1<<0; //允许更新中断四:允许TIM3⼯作控制寄存器1(TIMx_CR1)CEN:使能计数器位0 0:禁⽌计数器; 1:使能计数器Eg: TIM3->CR1|=0x01; //使能定时器3 或 TIM3->CR1|=1<<0;五:TIM3中断分组设置直接调⽤MY_NVIC_Init()函数Eg:MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,⼦优先级3,组2六:编写中断服务函数状态寄存器(TIMx_SR)Eg: if(TIM3->SR&0X0001)//溢出中断Eg: //定时器3中断服务程序 void TIM3_IRQHandler(void) //TIM3_Int_Init(5000,7199); //10Khz的计数频率,计数到5000为500ms//500ms中断⼀次 { if(TIM3->SR&0X0001) //溢出中断 { //add your code } TIM3->SR&=~(1<<0); //清除中断标志位 }六:关于溢出事件的计算因为Stm32_Clock_Init函数⾥⾯已经初始化APB1的时钟为2分频,所以APB1的时钟是32MHz(系统时钟72MHz)。