当前位置:文档之家› STM32自学笔记

STM32自学笔记

STM32自学笔记
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相电机驱动,其中的互补输出则防止电机的死区出现。

八、Systick系统时钟(以cortex-M3为基准):

其两大作用:

1、产生精确的延时

2、提供给操作系统一个单独的心跳(时钟)节拍

Cortex-M3内核中包含一个Systick时钟,其为一个24位递减计数器,计数器设定初始值并使能后,每经一个系统时钟计数值减一,计数到零时COUNTFLAG置位,计数器装载,触发中断。

3、四大寄存器:

(1)、STK_CTRL:STK控制寄存器

Bit0:ENABLE

SysTick timer的使能位,1使能Systick timer,0关闭Systick timer

Bit1:TICKINT

异常触发使能位,TICKINT=1,STK_VAL计数到0触发异常;TICKINT=0,不触发异常

Bit2:CLKSOURCE

Systick时钟选择位,SysTick = 1,时钟为AHB时钟;0时钟位AHB/8(属于它所挂的AHB中。)

Bit16:COUNTFLAG

计数为0标志位,当STK_VAL计数到0,此标志位会被置1

(2)、S TK_LOAD:STK装载寄存器位0~23

(3)、STK_VAL :STK当前值寄存器位0~23。

(4)、STK_CALIB:

九、死区时间控制:

死区,简单解释:通常,大功率电机、变频器等,末端都是由大功率管、IGBT等元件组成的H桥或3相桥。每个桥的上半桥和下半桥是是绝对不能同时导通的,但高速的PWM驱动信号在达到功率元件的控制极时,往往会由于各种各样的原因产生延迟的效果,造成某个半桥元件在应该关断时没有关断,造成功率元件烧毁。死区控制就是在上半桥关断后,延迟一段时间再打开下半桥或在下半桥关断后,延迟一段时间再打开上半桥,从而避免功率元件烧毁。这段延迟时间就是死区

PWM的上下桥臂的三极管是不能同时导通的。如果同时导通就会是电源两端短路。所以,两路触发信号要在一段时间内都是使三极管断开的。这个区域就叫做“死区”优点就不用说了。缺点是使谐波的含量有所增加。

死区时间大,模块工作更加可靠,但会带来输出波形的失真及降低输出效率。死区时间小,输出波形要好一些,只是会降低可靠性,一般为us级。最佳的设置是:在保证安全的前提下,越小越好。以不炸功率管、输出不短路为目的。

十、换相事件(COM事件):

十一、存储器的编码格式:

1、大端格式:在这种格式中,字数据的高字节存储在低地址中,而字数据的低

字节则存放在高地址中,例如存16位宽的数据0x1234,其存储方式如图:

2、小端格式:低地址中存放的是字数据的低字节,高地址存放的是字数据

的高字节,例如存16位宽的数据0x1234,其存储方式如图:

十二、位段与别区名:

现在STM32的位段、位带别名区就是为了实现对位操作的功能,它的对象可以是SRAM、I/O(STM32F407有复位/置位寄存器实现对位操作)和外设空间。要实现对这些地方的某一位的操作。它是这样做的:在寻址空间(32位对应的地址空间为4GB )的另一地方,取个别名区空间,从这个地址开始处,每一个字(32BIT)对应SRAM或I/O的一位。

使用位段的好处:可以把代码缩小,速度更快,效率更高,更安全。一般操作要6条指令,而使用位带别名区只要4条指令。一般操作是读-改-写的方式,而位带别名区是写操作。防止中断对读-改-写的方式的影响。

映射公式为:bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4) 其中:

— bit_word_addr 代表别名区域中将映射到目标位的字的地址

— bit_band_base 代表别名区域的起始地址

— byte_offset 代表目标位所在位段区域中的字节编号

— bit_number 代表目标位的位位置(0-7)

存的时候是以字节的形式存的,但是写入与写出是以32位存的,固结果是位数乘以4,

其中SRAM和外设的位带区域和位带别名如下图:

alias:别名;

十三、SYSCFG寄存器:

想要操作SYSCFG模块寄存器必须先使能SYSCFG模块时钟,

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

十三、存储器的固定存储映射:

代码区域起始地址为0x0000 0000(通过ICode和DCode访问),代码区域起始地址为0x2000 0000(通过ICode访问)。

十三、STM32的自举:

自举就是自己让自己启动吧!有一个BOOT引脚可以控制通过三种方式中的任何一种启动。

十四、上电、掉电、欠压复位:

欠压复位:单片机内部电压监控电路形成的异步复位,当电源电压VDD 电压小于一定触发阈值时,发出复位信号并保持到电源电压大于欠压复位功能恢复电压。欠压复位是用

来确保单片机的电源并不在有效工作电压范围之内时内部产生复位过程,使得单片机保持在正确的状态中,欠压复位有三个重要的参数:

1) VTR 是欠压复位功能恢复电压,大于该电压值的时单片机的欠压复位状态就结束了;

2)VTF 是欠压复位功能触发电压,小于该电压值的时单片机将保持欠压复位状态;

3) VHYS 是欠压复位的回差电压,VHYS=VTR - VTF;这个电压的主要目的是防止电源有

噪声干扰的时候频繁的反弹,一般在0.1~0.2V 之间。

如图所示,欠压复位是在电源电压达到VTR 以后,内部的计数器才工作,因此在上电复位完成以后,欠压复位继续工作直至欠压复位完成既定的延迟后,整个单片机才会退出复位状态;因此内部引入欠压复位电路对于解决电源电压上升率过快和过慢的情况都有很大的帮助。需要注意的是低电压的复位电平阈值是和供电电压相关的,并且按照比例设定的无法更改,因此如果系统上不合则需要考虑外部的复位方法。

十四、BOOT设置(BOOT1,BOOT0):

1)(BOOT1=x,BOOT0=0):主FLASH区,即扇区,正常工作模式。

2)(BOOT1=0,BOOT0=1):系统存储器,芯片内部一块特定的区域,该区域出厂时预置了一段Bootloader,即ISP程序,这部分已经被固化了,无人能改。这也

是利用串口下载时的第一步:BOOT1=0,BOOT0=1。ISP下载模式。

3)(BOOT1=1,BOOT0=1):SRAM,芯片内置RAM,即内存。调试模式。

十五、关于串口:方向以PC机为主

●RTS:请求发送,PC→→设备

●CTS:清楚发送,设备→→PC

●DTR:数据终端准备好,设备→→PC

●DSR:数据设备准备好,PC→→设备

●DCD:载波检测

十六、关于一键下载原理:

CH340G上电后DTR#和RTS#都为高电平,在用MCUISP烧写软件时,我们在软件下方选择“DTR的低电平复位,RTS高电平进BootLoader”,CH340G IC在实际操作时引脚的变化为“DTR#拉高,RTS#拉低”,即软件设置和实际情况是取非的,相反的。

十七、关于抢占优先级和响应优先级:

STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和响应优先级,也把响应优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。

(1)、抢占先式优先级(pre-emption priority)

高抢占先式优先级的中断事件会打断当前的主程序/中断程序运行—抢断式优先响应,俗称中断嵌套。

(2)、副优先级(subpriority)

在抢占先式优先级相同的情况下,高副优先级的中断优先被响应;

在抢占先式优先级相同的情况下,如果有低副优先级中断正在执行,高副优先级的中断要等待已被响应的低副优先级中断执行结束后才能得到响应—非抢断式响应(不能嵌套)。

(3)、判断中断是否是被响应的依据

首先是占先式优先级,其次是副优先级;

占先式优先级决定是否会有中断嵌套;

(4)、优先级冲突的处理

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断的嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这个两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

十八、结构体成员变量地址对齐方式:(举例解释说明)

举个例子:

struct{

char a; //1byte

int b; //4byte

char c[2] //2byte

double d; //8byte

}Struct_A;

1、8位机里就按字节对齐,那么上述结构体共占用1+4+2+8=15byte。

2、在16位机里,变量就按照2字节对齐,比如a这个成员,虽然是个char

类型,地址在0x80000000本身只占1字节,但是下一个成员b却不能使用0x80000001这个地址,而必须使用0x80000002,这就是按字长对齐。以上结构体占用的空间也就是2+4+2+8=16字节。

3、在32位机中,如果a在0x80000000的话,b只能放在0x80000004,因为

这里的字长是4个字节。以上结构体占用空间4+4+4+8=20字节。

十九、关于STM32F4的RCC:

1、F pclk是给串口的时钟(PCLK1用于USART

2、

3、

4、5,PCLK2用于USART1,

以前说过,PCLK1是由系统时钟分频得来,最大36MHZ,PCLK2是直接由系统时钟得来,最大72MHZ。)

二十、关于STM32F4的串口:

1、关于波特率的计算:

USART_BRR:波特率寄存器,其分为尾数部分DIV_Mantissa和小数部分

DIV_fraction,在计算时,尾数部分直接化成二进制存入DIV_Mantissa,而小数部

分则要乘以16再存入DIV_fraction。原理如同以下:

已知一个时间段是<1.1小时>,求相当于小时分钟。(再者到二进制小数部分第四位得乘以16)

二十一、关于串口:

1、当勾选发送新行后,串口调试助手在每次发送一段字符后会自动添加0x0d和

0x0a的换行符。

2、串口发送数据丢失:

2-1、串口发送第一个字节数据丢失

TC:发送完成,当包含有数据的一帧发送完成后,由硬件将该位置位。如USART_CR1中的TCIE为1,则产生中断。由软件序列清除该位(先读USART_SR然后写入USART_DR)。TC位也可以通过写入0来清除,只有在多缓存通讯中才荐这种清除程序。

0:发送还未完成;

1:发送完成。

注意到这一句:由软件序列清除该位(先读USART_SR,然后写入USART_DR)。也就是说,要先read USART_SR,然后write USART_DR,才能完成TC状态位的清除。

而硬件复位后,串口发送的首个数据之前没有read SR的操作,是直接write DR,也就是说,TC没有被清除掉。因此,

2-1、加了printf()函数后,串口发送字节数据有些丢失

3、printf()中,%d 是格式化为整型、%s 是格式化为字符串、%lld 是格式化为长整

型。

4、%04x 表示按16进制输出数据,最小输出宽度为4个字符,右对齐,如果输出的数据小于4个字符,前补0,如:

printf("%04x", 100 ); //输出0064 100的16进制数是64

5、s printf()

int sprintf( char *buffer, const char *format, [ argument] … );

参数列表

buffer:char型指针,指向将要写入的字符串的缓冲区。

format:格式化字符串。

[argument]...:可选参数,可以是任何类型的数据。

二十二、硬件SPI驱动OLED:

1、首先得讲解BUSY标志与TXE标志,BUSY标志指的是发送缓冲器已空且发送移位寄

存器没有数据在发送,也就是没有数据发送任务;TXE标志仅仅指的是发送缓冲器已空,并不指示发送移位寄存器有没有数据。

2、so,问题就来了,为什么STM8用TXE标志就可以发送数据而STM32必须用BUSY

标志呢?因为STM8最快速度执行速度最大是16MHZ,虽然用的TXE标志,但等到下一次发送数据时,由于速度慢,这是发送移位寄存器早就没有数据了,只是BUSY=0;

但STM32就不一样了,若用TXE标志,等到下一次发送数据时,由于STM32以168MHZ 的速度执行代码,虽然发送缓冲器没有数据了,但发送移位寄存器还有数据没有发送完,所以,这是会出现乱码或者通信失败。

二十三、FSMC(灵活的静态存储控制器):

其支持SRAM、PSRAM、NAND FLASH、NOR FLASH。

(1)、SRAM:静态随机存取存储器。它是一种具有静止存取功能的内存,不需要刷新电路即能保存它内部存储的数据。

◎优点,速度快,不必配合内存刷新电路,可提高整体的工作效率。

◎缺点,集成度低,掉电不能保存数据,功耗较大,相同的容量体积较大,而且价格

较高,少量用于关键性系统以提高效率。

(2)、PSRAM:PSRAM就是伪SRAM,内部的内存颗粒跟SDRAM的颗粒相似,但外部的接口跟SRAM相似,不需要SDRAM那样复杂的控制器和刷新机制,PSRAM

的接口跟SRAM的接口是一样的。容量没有SDRAM那样密度高,但肯定是比SRAM

的容量要高很多的,速度支持突发模式,并不是很慢。

(3)、NOR FLASH与NAND FLASH:

1、来源

(1)、NOR flash是intel公司1988年开发出了NOR flash技术。NOR的特点是芯片内执行(XIP, eXecute In Place),这样应用程序可以直接在flash 闪存内运行,不

必再把代码读到系统RAM中。NOR的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响了它的性能。

(2)、Nand-flash内存是flash内存的一种,1989年,东芝公司发表了NAND flash 结构。其内部采用非线性宏单元模式,为固态大容量内存的实现提供了廉价有效的解决方案。Nand-flash存储器具有容量较大,改写速度快等优点,适用于大量数据的存储,因而在业界得到了越来越广泛的应用,如嵌入式产品中包括数码相机、MP3随身听记忆卡、体积小巧的U盘等。

2、NAND flash和NOR flash的性能比较

flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。NAND器件执行擦除操作是十分简单的,而NOR 则要求在进行擦除前先要将目标块内所有的位都写为0。由于擦除NOR器件时是以64~128KB的块进行的,执行一个写入/擦除操作的时间为5s,与此相反,擦除NAND 器件是以8~32KB的块进行的,执行相同的操作最多只需要4ms。执行擦除时块尺寸的不同进一步拉大了NOR和NADN之间的性能差距,统计表明,对于给定的一套写入操作(尤其是更新小文件时),更多的擦除操作必须在基于NOR的单元中进行。这样,当选择存储解决方案时,设计师必须权衡以下的各项因素。

1、NOR的读速度比NAND稍快一些。

2、NAND的写入速度比NOR快很多。

3、NAND的4ms擦除速度远比NOR的5s快。

4、大多数写入操作需要先进行擦除操作。

5、NAND的擦除单元更小,相应的擦除电路更少。

3、NAND flash和NOR flash的接口差别

NOR flash带有SRAM接口,有足够的地址引脚来寻址,可以很容易地存取其内部的每一个字节。NAND器件使用复杂的I/O口来串行地存取数据,各个产品或厂商的方法可能各不相同。8个引脚用来传送控制、地址和数据信息。NAND读和写操作采用512字节的块,这一点有点像硬盘管理此类操作,很自然地,基于NAND的存储器就可以取代硬盘或其他块设备。

4、NAND flash和NOR flash的容量和成本

NAND flash的单元尺寸几乎是NOR器件的一半,由于生产过程更为简单,NAND结构可以在给定的模具尺寸内提供更高的容量,也就相应地降低了价格。

NOR flash占据了容量为1~16MB闪存市场的大部分,而NAND flash只是用在8~128MB 的产品当中,这也说明NOR主要应用在代码存储介质中,NAND适合于数据存储,NAND 在CompactFlash、Secure Digital、PC Cards和MMC存储卡市场上所占份额最大。(4)存储器的分类:

(5)、异步模式、同步模式、突发模式、复用和非复用模式。

1)、异步SRAM正如其名称,不是与特定的时钟信号同步运行,而是根据输入信号的状

态运行的。因为没有信号表示读取时已确定了有效数据,也没有信号表示写入时已接收到数据,所以,需要获取制造商的数据手册,根据时序图,按“应该已读出有效数据”及“应该能接收数据”这样的条件,进行存储器的设计。

2)、突发(Burst)模式:包括突发长度(BL)、突发类型(Burst Type)、CAS延迟(CAS

Latency)、运行方式(Operating Mode)和写入突发模式。

CAS:列地址选通信号;RAS:行地址选通信号

CL:CAS的潜伏期,在选定列地址后,就已经确定了具体的存储单元,剩下的事情就是数据通过数据I/O通道(DQ)输出到内存总线上了。但是在CAS发出之后,仍要经过一定的时间才能有数据输出,从CAS与读取命令发出到第一笔数据输出的这段时间,被定义为CL。

1、概念:所谓的“突发”是指当我们对一个地址进行寻址并操作完成后,不必再重新对下

一个地址进行寻址,而是直接进行操作。这样就节省了很多的时间。具体的情况也

很简单就是节省了延时的那段时间。

读:初始化→发行地址→RCD→发列地址→CL→数据

写:初始化→发行地址→RCD→发列地址→数据(CL、RCD)

2、突发长度突发(Burst)是指在同一行中相邻的存储单元连续进行数据传输的方式,连续传输所涉及到存储单元(列)的数量就是突发长度(Burst Lengths,简称BL)。

3、对于存储bank。

进行寻址时需要先确定是哪个L-Bank,然后再在这个选定的L-Bank中选择相应的行与列进行寻址。对内存的访问,一次只能是一个L-Bank,而每次与CPU交换的数据就

是 L-Bank 存储阵列中一个“存储单元”的容量。SDRAM内存芯片一次传输的数据量就是芯片的位宽,那么这个存储单元的容量就是芯片的位宽(也是 L-Bank 的位宽)。上图为4BANK内存颗粒内部结构示意图。

内存芯片容量的计算方法为:存储单元数量行数×列数(得到一个 L-Bank 的存储单元数量)×L-Bank 的数量。在很多内存产品介绍文档中,都会用M×W 的方式来表示芯片的容量。M 是该芯片中存储单元的总数,单位是兆,W 代表每个存储单元的容量,也就

是 SDRAM 芯片的位宽(Width),单位是 bit。计算出来的芯片容量也是以 bit 为单位,但用户可以采用除以 8 的方法换算为字节(Byte)

二十四、关于FSMC中定义结构体中变量的地址

typedef struct

{

vu16 LCD_REG;

vu16 LCD_RAM;

} LCD_TypeDef;

//使用NOR/SRAM的Bank1.sector4,地址位HADDR[27,26]=11 A6作为数据命令区分线

//注意设置时STM32内部会右移一位对其! 111 1110=0X7E

#define LCD_BASE ((u32)(0x6C000000 | 0x0000007E))

#define LCD ((LCD_TypeDef *) LCD_BASE)

将这个地址强制转换为LCD_TypeDef 结构体地址,那么可以得到LCD->LCD_REG 的地址就是0X6C00,007E,对应A6 的状态为0(即RS=0),而LCD-> LCD_RAM 的地址就是0X6C00,0080(结构体地址自增),对应A6 的状态为1(即RS=1)。

二十四、break ,continue ,return 的区别及作用

1、return 语句的作用

(1) return 从当前的方法中退出,返回到该调用的方法的语句处,继续执行。

(2) return 返回一个值给调用该方法的语句,返回值的数据类型必须与方法的声明中的返回值的类型一致。

(3) return后面也可以不带参数,不带参数就是返回空,其实主要目的就是用于想中断函数执行,返回调用函数处。

2. break 语句的作用

(1)break在循环体内,强行结束循环的执行,也就是结束整个循环过程,不在判断执行循环的条件是否成立,直接转向循环语句下面的语句。

(2)当break出现在循环体中的switch语句体内时,其作用只是跳出该switch语句体。

3.continue 语句的作用

终止本次循环的执行,即跳过当前这次循环中continue语句后尚未执行的语句,接着进行下一次循环条件的判断。

二十五、探索者开发板上显示屏的一些显示函数技巧

1、关于叠加模式还是非叠加模式:如果字体的背景颜色与屏幕的主体颜色一致,则是叠加

模式;字体的背景颜色与屏幕的主体颜色不一致,其颜色分界线呈方框状,则为非叠加模式。

2、 12*12 ASCII字符集点阵:长宽都是12个像素点,若转成引文模式,则变成长为12个

像素点,宽变为6个像素点,简称1206,其他的格式以此类推。

3、对于长度不符合字节整数倍的边长,比如12,其取模结果会以两个字节的模式生成,

最低四位或者最高四位无效(至于是哪个则取决于取模方向)。但在实际的显示时,(y -y0)==size语句的判断会去除无效的位。

4、对于取模方式:阴码+逐列式+顺向+C51格式,其扫描方向如下:

5、对于取一个整数的位用于显示,则有以下方法:temp=(num/LCD_Pow(10,len-t-1))%10; 二十六、关于C编程的技巧

1、对于extern,当一个变量如果在本C文件中被另一个C文件的函数利用,则需要在本C 文件中声明时加上一个extern说明,而且不能初始化,比如extern _lcd_dev lcddev。在另外一个C文件中像普通的变量一样定义。

二十七、ADC的理解及注意的地方

(1)、用ADC1 规则通道的顺序为CH0,CH1,CH2,CH3,

不启动SCAN模式

在单次转换模式下:

启动ADC1,则

1.开始转换CH1(ADC_SQR的第一通道)

转换完成后停止,等待ADC的下一次启动,继续从第一步开始转换在连续转换模式下:

启动ADC1,则

1.开始转换CH0(ADC_SQR的第一通道)

转换完成后回到第一步。

启动SCAN模式下

在单次转换模式下:

启动ADC1,则

1.开始转换CH0、

2.转换完成后自动开始转换CH1

3.转换完成后自动开始转换CH2

4.转换完成后自动开始转换CH3

5.转换完成后停止,等待ADC的下一次启动下一次ADC启动后从第一步开始转换在连续转换模式下:

1启动ADC1,则1.开始转换CH0、

2.转换完成后自动开始转换CH1

3.转换完成后自动开始转换CH2

4.转换完成后自动开始转换CH3

5.转换完成后返回第一步

(2)、若使能自动注入模式,则在规则组的序列转换完成后接着转换注入组。

(3)、在选择IO口引脚多用功能时,IO到内部外设有两条引入线,一是复用功能,二是模拟功能。如图:

(4)、各个ADC通道的对应表:

通道号 ADC1 ADC2 ADC3

通道 0 PA0 PA0 PA0

通道 1 PA1 PA1 PA1

通道 2 PA2 PA2 PA2

通道 3 PA3 PA3 PA3

通道 4 PA4 PA4 PF6

通道 5 PA5 PA5 PF7 通道 6 PA6 PA6 PF8 通道 7 PA7 PA7 PF9 通道 8 PB0 PB0 PF10 通道 9 PB1 PB1 PF3 通道 10 PC0 PC0 PC0 通道 11 PC1 PC1 PC1 通道 12 PC2 PC2 PC2 通道 13 PC13 PC13 PC13 通道 14 PC4 PC4 PF4 通道 15 PC5 PC5 PF5

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输出! 修改和自己写代码时候

STM32F407学习资料

使用心得: STM32F4与STM32F1在ADC方面的区别: 通常,在STM32F1中需要加自动校准的程序,如下: // 使能ADC1自动校准功能 ADC_ResetCalibration(ADC1); //检查ADC1自校准的状态位 while(ADC_GetResetCalibrationStatus(ADC1)); //启动ADC1自校准 ADC_StartCalibration(ADC1); //检查ADC1自校准是否结束 while(ADC_GetCalibrationStatus(ADC1)); // ADC自动校准结束--------------- 然而,STM32F4中无需此程序,给出STM32F407的ADC3和DMA方式的官方程序如下:/** ****************************************************************************** * @file ADC3_DMA/main.c * @author MCD Application Team * @version V1.0.0 * @date 19-September-2011 * @brief Main program body ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS A T PROVIDING CUSTOMERS * WITH CODING INFORMA TION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SA VE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY

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的学习速成

STM32入门系列教程如何提高STM32的学习效率 Revision0.01 (2010-04-08)

目录 第一章笔者的入门总结 (2) 1.1为什么要把时间花在“犹豫”上? (2) 1.2看资料需要计划、耐心和速度 (2) 1.3学STM32必备开发板 (3) 1.4熟悉开发板并试图写程序 (3) 第二章STM32入门方法谈 (4) 2.1拿到开发板我该做什么? (4) 2.2我的时间如何安排 (5) 2.3碰到问题怎么办? (5) 第三章STM32学习步骤 (6) 3.1关于STM32文档学习 (6) 3.230天上手STM32计划 (7) 3.2.1第1步:熟悉调试软件 (8) 3.2.2第2步:GPIO编程 (8) 3.2.3开始全新的STM32深入研究 (9) 福州芯达工作室简介 (9)

第一章笔者的入门总结 1.1为什么要把时间花在 犹豫””上? 为什么要把时间花在““犹豫 每当我们在入门之前(ARM是这样,DSP也一样),总会会有很多疑问,会有很多顾虑。我们渴望知道学习STM32前景如何?需要啥基础?难不难?适不适合我?但是什么时候能心潮澎湃地、相当着急地开始学STM32?日子在一天一天过去!你开始行动了吗?没有行动的思索,永远都不可能入门!把这些时间用来看书吧,效果能好一万倍。 大家一般都是从51单片机过来的,回想一下,我们之前学单片机时如何入门呢?实际上都是先看书(理论),再玩板子(实践)。严格地说,应该是模仿实验。熟悉之后才会自己写程序代码实现某个功能。因此,如果你正在咨询STM32;如果你正对STM32心潮澎湃;如果你想入门STM32;那么,从现在开始,不要犹豫了,不要想再详细地了解STM32的前景了。做一个可能影响你一生的决定吧!不用咨询,不用兴奋,开始看书籍(文档)吧!!每个人都是这么走过来的。 1.2看资料需要计划、耐心和速度 这里所谓的“资料”包括STM32书籍、文档。因为STM32有个特点,datasheet 很多都是中文的,有些同学就没有去买书籍,直接看STM32的用户手册,也是可以的。但是不管看书籍还是文档,我们是需要计划的。不是今天看3页,明天看5页。一本书看了两个月,还在磨蹭。请记住,你学的不是寂寞,是STM32!看书或文档不是用来消遣时间的。背水一战吧,给自己规定一个底线:两周内把一定粗略地过一遍!不要求都看懂,事实上,不可能都看懂。但我们必须理解基本知识,对难度高的知识有一个印象,至少以后碰到问题的时候,我们会似曾相识,感觉在哪里见到过,于是翻资料上网找答案——带着问题的时候,效率才是超高的。 两周过去了,STM32的知识你过一遍了吗?没看完?那么,你应该考虑这些天中,你是否尽力了?是否真的想学STM32?或者还是看到STM32人气很高,也想跟下时髦?是不是碰到问题没法解决就想放弃了?现在是你做第二个决定的时候了,请决定你是否继续攻读STM32。如果是一时冲动想跟时髦,请马上放弃——你已经浪费两周时间了,你还想再浪费14天吗?如果想吃得苦中苦,方为人上人,OK,请继续往下看:) 1.3学STM32必备开发板 稍微了解一些理论知识后,现在摆在你面前,有两条路: 第一,自己画PCB制板、焊接、调试。 第二,购买一套性价比高的开发板。 笔者之前做过几次PCB设计,而且当时在实验室可以报销所有费用,就自

STM32入门基本知识

STM32学前班教程之一:选择他的理由 经过几天的学习,基本掌握了STM32的调试环境和一些基本知识。想拿出来与大家共享,笨教程本着最大限度简化删减STM32入门的过程的思想,会把我的整个入门前的工作推荐给大家。就算是给网上的众多教程、笔记的一种补充吧,所以叫学前班教程。其中涉及产品一律隐去来源和品牌,以防广告之嫌。全部汉字内容为个人笔记。所有相关参考资料也全部列出。:lol 教程会分几篇,因为太长啦。今天先来说说为什么是它——我选择STM32的原因。 我对未来的规划是以功能性为主的,在功能和面积之间做以平衡是我的首要选择,而把运算放在第二位,这根我的专业有关系。里面的运算其实并不复杂,在入门阶段想尽量减少所接触的东西。 不过说实话,对DSP的外设并和开发环境不满意,这是为什么STM32一出就转向的原因。下面是我自己做过的两块DSP28的全功能最小系统板,在做这两块板子的过程中发现要想尽力缩小DSP的面积实在不容易(目前只能达到50mm×45mm,这还是没有其他器件的情况下),尤其是双电源的供电方式和的电源让人很头疼。 后来因为一个项目,接触了LPC2148并做了一块板子,发现小型的ARM7在外设够用的情况下其实很不错,于是开始搜集相关芯片资料,也同时对小面积的AVR和51都进行了大致的比较,这个时候发现了CortexM3的STM32,比2148拥有更丰富和灵活的外设,性能几乎是2148两倍(按照MIPS值计算)。正好2148我还没上手,就直接转了这款STM32F103。 与2811相比较(核心供电情况下),135MHz×1MIPS。现在用STM32F103,72MHz×,性能是DSP的66%,STM32F103R型(64管脚)芯片面积只有2811的51%,STM32F103C型(48管脚)面积是2811的25%,最大功耗是DSP的20%,单片价格是DSP的30%。且有更多的串口,CAP和PWM,这是有用的。高端型号有SDIO,理论上比SPI速度快。 由以上比较,准备将未来的拥有操作系统的高端应用交给DSP的新型浮点型单片机28335,而将所有紧凑型小型、微型应用交给STM32。 STM32学前班教程:怎么开发 sw笨笨的STM32学前班教程之二:怎么开发目前手头的入门阶段使用的开发器概述 该产品为简易STM32调试器和DEMO板一体化的调试学习设备,价格在一百多块。 2、硬件配置

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入门C语言详解精编版

阅读flash:芯片内部存储器flash操作函数我的理解——对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。 基础应用1,FLASH时序延迟几个周期,等待总线同步操作。推荐按照单片机系统运行频率,0—24MHz时,取Latency=0;24—48MHz时,取Latency=1;48~72MHz时,取Latency=2。 所有程序中必须的 用法:FLASH_SetLatency(FLASH_Latency_2); 位置:RCC初始化子函数里面,时钟起振之后。 基础应用2,开启FLASH预读缓冲功能,加速FLASH的读取。 所有程序中必须的 用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 位置:RCC初始化子函数里面,时钟起振之后。 3、阅读lib:调试所有外设初始化的函数。 我的理解——不理解,也不需要理解。只要知道所有外设在调试的时候,EWRAM需要从这个函数里面获得调试所需信息的地址或者指针之类的信息。 基础应用1,只有一个函数debug。所有程序中必须的。 用法:#ifdef DEBUG debug(); #endif 位置:main函数开头,声明变量之后。 4、阅读nvic:系统中断管理。 我的理解——管理系统内部的中断,负责打开和关闭中断。 基础应用1,中断的初始化函数,包括设置中断向量表位置,和开启所需的中断两部分。 所有程序中必须的。 用法:void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; //中断管理恢复默认参数 #ifdef VECT_TAB_RAM //如果C/C++ Compiler\Preprocessor\Defined symbols中的定义了 VECT_TAB_RAM(见程序库更改内容的表格) 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; //响应优先级

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自学笔记

一、原子位操作: 原子位操作定义在文件中。令人感到奇怪的是位操作函数是对普通的内存地址进行操作的。原子位操作在多数情况下是对一个字长的内存访问,因而位号该位于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全本

J^dt ? ? ? ?? ???? ? ????? ? q?670 ? ?8 ?Yū ?Yū ? ū a ?q? 1 /? ? ? % - ? $ L ? ) 670 &RUWH[ 0 #&RUWH[ 0 ? $50Y 0 8 ? )??? ?) b?0 ) #0 0 ? $50? 0 # 0 ?? $50 2 (? #) 8? ?? 3 δ . (?)?- ? δ 8?b q? ? - /? ??? ? ? ? ?-? -? ? -?670 ?? " $ ? -? / ) ? -?670 q ? ǎ ? ? 670 0) Ρ? ? ???p ? - ? ?? ?- # ? ) ?μ-670 )-1 ? -? - ? ? ?+ ??? ? ?? ?) ??(? C ? - ?

J^dt %- (0? ) ? (??/ ?W ? μ - d /??q670 e $% $% " - ? ?p ?" ? ?? 8 '0$ ? c? q? G>1" 3 ? $+% ?- ??? ? ? ? ? $+%"? ? $3% $3% ?P ?? ? ?? ? ! 8? $ $3% ?ǎ2-? #$3% ?ǎ?-? .1" (-? v 670 " ? 8 ?)? ?v b? 50 670 ) [[[?#μ?? 9

J^dt ? ) 670 ? ?? " ?? . 5HJ K # - 0$7 ; K - ? ? 670 ? ? %3 ? ? ? d K e d670 ) [B6WG3HULSKB/LEB9 e? LQF ?-/ / ?? 0) 670 ? ?< ? - ?) - % ? +- ?) ?> ? / -? ?? ??? ??670 t " ?J ? )- >- .? )8 t)?? ? ? - ? ? */ - -? -% + ) ? ?? % - ? ? 2 ??9 ?a- ǎ ǎ? a

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经典学习资料——SPI

SPI总线 与IIC类似,SPI也是一种通信协议。今天我们就以WX25X16芯片为例来介绍SPI.首先我们来看下硬件连接。 、从原理图可以看到该芯片需要单片机控制的管脚有4个,非别是CS,DO,DIO,CLK.其中CS 是片选信号,只有将该位拉低才能选中该芯片。DO,DIO分别是输出和输入。CLK是时钟信号。SPI通信的步骤如下所示: 1)获取地址1 2)获取地址2 3)擦除扇区 4)写入数据 好的,下面我们对每个步骤进行分析 (1)在对芯片操作前先要对端口及SPI外设进行相应的设置: /* 函数名:SPI_FLASH_Init(void) 功能:对端口和SPI初始化 输入:无 输出:无 调用:被主函数调用 */ void SPI_FLASH_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable SPI1 and GPIO clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE); /*!< SPI_FLASH_SPI Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); /*将PA5(CLK)配置成复用推挽输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /*将PA6(DO)设置成浮空输入*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOA, &GPIO_InitStructure); /将PA7(DIO)设为浮空输入/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure); /将PA4(CS)设为推挽输出/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /拉高CS,失能芯片,该语句是宏定义,就是置高PA4/ SPI_FLASH_CS_HIGH(); /* SPI配置/ // W25X16: data input on the DIO pin is sampled on the rising edge of the CLK. // Data on the DO and DIO pins are clocked out on the falling edge of CLK. /*将SPI设为全双工模式*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; /*将SPI设为主模式*/ SPI_InitStructure.SPI_Mode = SPI_Mode_Master; /*将SPI通信的数据大小设为8位*/ SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; /*将CLK的高电平设为空闲*/ SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /*设置在第二个时钟沿捕获数据*/ SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; /*指定NSS信号由软件管理*/ SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; /SPI_BaudRatePrescaler用来定义波特率预分频的值,这个值用以设置发送和接收的SCK时钟/ SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; /SPI_FirstBit指定了数据传输从高位还是低位开始/ SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; /SPI_CRCPolynomial定义了用于CRC值计算的多项式/ SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(SPI1, ENABLE); } (2)获取器件地址1

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学习心得(新手必看)

STM32学习心得(新手必看) (作者:logokfu 邮箱:g535343589@https://www.doczj.com/doc/624383283.html, ) 在这里说下我的学习心得体会(照顾下新手,老鸟都表笑哦,呵呵)。 说下关于开发环境的建立,都说万事开头难,每种芯片都有它的开发环 境,首先得熟悉STM32的开发环境。用的最多就是MDK 和IAR 了,关于MDK ,这个用过51单片机的筒子肯定都知道keil uvision 。这个MDK 其实就是专门开发ARM 芯片的工具。开发51单片机的那个叫C51 。这个C51和MDK 共同使用keil uvsion 这个UI 界面。也是说C51和MDK 共同使用keil uvsion 这个外壳。好了,关于开发软件的介绍就介绍这么多,有什么还不清楚的,筒子们可以邮箱联系我。当然支持STM32的集成开发环境(IDE )还不止MDK 和IAR ,只不过这两个使用的人相对其他工具来说用的人比较多吧。另外 RIDE, HiTOP , TrueSTUDIO 这个三个开发工具也支持STM32的开发(可能还有其他的工具,不过我不知道)。有兴趣的盆友可以使用下尝尝鲜。 说下关于ST 官方为我们提供的固件库的使用问题。不要觉得固件库是 这个什么可怕的东西,固件库是ST 为用户提供的函数库,这些函数帮 我们一次性解决多个寄存器的设置问题。如果没有固件库的话,那么我们就需要像使用51单片机那样直接设置要使用的寄存器,在51单片机上为寄存器直接赋值可能没什么的,但是由于STM32的寄存器太多,如果一个个设置的话会很麻烦,有时候还会忘掉某些寄存器的设置,ST 提供的固件库正是为我们提供了这些方便。我们只需要为相关函数指定参数就可以完成寄存器的设置了。为产品的快速开发提供了保障。当然新固件库是好,但是却会对新手理解硬件结构造成一定的影响。有的人喜欢直接为STM32的寄存器直接赋值,说这样子比较直观,有的人喜欢使用固件库。当然这个是个人喜好,大家可以根据自己的喜好进行选择。我的建议是可以直接用固件库,虽然我对硬件结构还没了解很多,用固件库的话可能会觉得有点学习的不是很踏实,因此我们可以借助开发工具的go to definition 功能,顺藤摸瓜。在最终的函数中,我们就能发现这些函数到底为哪些寄存器设置了什么值。这样看多了,时间久了各个寄存器也就了解的差不多了。当然进行下随着产品的不断推出,固件库版本可能会不断的更新。之前的固件库版 首先 其次

相关主题
文本预览
相关文档 最新文档