1、固件库:
固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道, 向上提供用户函数调用的接口(API)。
2、CMSIS标准与固件库的关系
就是对固件库函数的要求。
ARM 公司为了能让不同的芯片公司生产的 Cortex-M3 芯片能在软件上基本兼容,和芯片生产商共同提出了一套标准 CMSIS 标准(Cortex Microcontroller Software Interface Standard) ,翻译过来是 “ARM Cortex™ 微控制器软件接口标准”。ST 官方库就是根据这套标准设计的。
其实不用这么讲这么复杂的,一个简单的例子,我们在使用 STM32 芯片的时候首先要进行系统初始化,CMSIS 规范就规定,系统初始化函数名字必须为 SystemInit,所以各个芯片公 司写自己的库函数的时候就必须用 SystemInit 对系统进行初始化。
3、STM32 和 ARM 以及 ARM7 的关系
ARM 是一个做芯片标准的公司,它负责的是芯片内核的架构设 计,而 TI,ST 这样的公司,他们并不做标准,他们是芯片公司,他们是根据 ARM 公司提供的 芯片内核标准设计自己的芯片。
所以,任何一个做 Cortex-M3 芯片,他们的内核结构都是一样的,不同的是他们的存储器容量,片上外设,IO 以及其他模块的区别。
图1 cortex-m3 芯片结构
4、Cortex-M3内核
Cortex-M3 内核是单片机的中央处理器单元 CPU 。
特点:
1、Cortex-M3 是一个 32 位处理器内核。内部的数据路径是 32 位,寄存器是 32 位,存储器接口是 32 位。
2、Cortex-M3 采用哈佛架构。拥有独立的指令总线和数据总线,取指与数据访问可以同时进行。
3、 支持小端模式、大端模式。
组成介绍:
Cortex-M3内核的架构含有
(1)寄存器组、(2)NVIC、(3)中断和异常、(4)储存器映射、(5)总线接口、(6)调试支持(debug interface)、(7)指令集。
5、时钟使能
寄存器是基于什么的?
当然是触发器!!!准确地说应该是D触发器
触发器的赋值是一定需要时钟的, 而寄存器的时钟是由总线时钟提供的,就是说没有总线时钟的话,你给寄存器值它是不会读入的。换句话说,只有送来了时钟,触发器才能被改写值,这样寄存器才会工作。(通常会根据上升沿或者下降沿)
又会有人说为什么我之前学51的时候为什么不用使能时钟呢?
当初我们学51的时候,哪会关注功耗,我们能跑起来程序就行了,而且对于大多数厂家来说,绝大多数不会关注功耗。但是STM32不同,为了减少功耗,ST公司为了省电,使用了所谓的时钟门控的技术,这又涉及到了同步电路。同步电路中总有一个时钟控制。
在默认情况下这些时钟都是disable的。你如果要使用它,首先就需要enable。
我们也可以把这个时钟简单的比作为门,STM32之所以是低功耗,就是因为他把所有门都默认设置为disable,在你需要用哪个门的时候,开哪个门就可以,也就是说用到什么外设,只要打开对应外设的时钟就可以,其他的没用到的可以还是disable,这样耗能就会减少。
时钟门控技术就是用“与门”来控制时钟信号是否输入到外设。
6、串口通信原理
一般每次只能一个字节(8位)来接收和发送。当使用串口调试助手(XCOM)等软件时,命令行一次发送和接收到多个字节的发送数据,实际上是软件内部已经编写好的也是一个一个字节来发送和接收的。
数据缓存器实际上就是寄存器。
电脑串口是USB电平,单片机是TTL电平,相互串口通信连接需要将电平逻辑一致。通常需要用到USB电平转TTL芯片模块,例如:CH340、PL2303、FT232等,有时也需要电脑上安装电平转换芯片的驱动,如CH340。
串口发送的数据会先进入数据寄存器(TDR)中,当移位寄存器没有数据在发送时,数据就会接着进入到移位寄存器中发送。
串口通信是异步通信,双方必须约定好波特率,才能知道一个数据是什么时候传输完成的。同步通信则是例如在信号的上升沿的时候发送一个数据,就无需约定波特率。
7、串口通信标志位
状态寄存器SR:
1、RXNE:(读数据寄存器非空),当该位被置 1 的时候,就是提示已经有数据被接收到了,并 且可以读出来了。这时候我们要做的就是尽快去读取 USART_DR,通过读 USART_DR 可以将该位清零,也可以向该位写 0,直接清除。
2、TC:(发送完成),当该位被置位的时候,表示 USART_DR 内的数据已经被发送完成了。如 果设置了这个位的中断,则会产生中断。该位也有两种清零方式:1)读 USART_SR,写 USART_DR。2)直接向该位写 0。
控制寄存器CR1:
(主要用于设置是否开启中断)
1、RXNEIE:(接收缓冲区非空中断使能)。接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断,则开启该位。该位由软件设置或清除。
0:禁止产生中断;
1:当USART_SR中的TC为’1’时,产生USART中断。
2、TCIE:(发送完成中断使能)
0:禁止产生中断;
1:当USART_SR中的TC为’1’时,产生USART中断
8、端口复用和重映射
端口复用:STM32有很多的内置外设,这些外设的外部引脚都是与GPIO复用的。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做复用。
例如串口1 的发送接收引脚是PA9,PA10,当我们把PA9,PA10不用作GPIO,而用做复用功能串口1的发送接收引脚的时候,叫端口复用。
配置过程:-以PA9,PA10配置为串口1为例
(1)GPIO端口时钟使能:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
(2)复用外设时钟使能:比如将端口PA9,PA10复用为串口,所以要使能串口时钟。RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
(3)端口模式配置。 GPIO_Init()函数。 查表:
(4)如果是F407的芯片还需要配置GPIO_PinAFConfig()函数,选择GPIO复用为什么功能
但单个外设(如UART)可能可以复用到多个(多组)不同的IO口上(端口重映射),但是在同一时间内只能有一组IO口(比如RX、TX)使用该串口资源。使用时要注意资源的分配,避免冲突。
如F407的串口USART2的TX、RX就可以复用到PA2、PA3和PD5、PD6两组上。
端口重映射:每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在STM32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。
9、SPI通信
SPI是串行外设接口(Serial Peripheral Interface)的缩写,通信一次最多传输32字节数据。SPI每次数据传输可以8位或16位单位,每次传输单位数不受限制。
SPI有主、从两种模式,由主模块选择一个从模块进行同步通信,从而完成数据的交换。主设备(Master)提供时钟,从设备接收。SPI接口的读写操作都是由主设备发起,当存在多个从设备(Slave)时,通过片选信号进行管理。
SPI通信通常需要四根线,比串口的多两根:
1、MISO(Master Input Slave Output):主设备数据输入,从设备输出;
2、MOSI(Master Ouput Slave Input):主设备输出,从设备输入;
3、SCLK(Serial Clock):时钟信号,由主设备产生
4、CS/SS(Chip Select/Slave Select):从设备使能,由主设备控制(高或低电位)
一主一从:
一主多从:(每个从机都有主机对应的单独片选线)
SPI主、从设备都有一个串行移位寄存器,主设备通过向它的SPI串行移位寄存器写入一个字节发起传输。
SPI通信流程:
1、主设备发起信号,将CS/SS拉低,启动通信。
2、主设备发送时钟信号,告诉从设备进行写或读数据,从设备会立即读取数据线上的信号,即可得到一位数据(1bit)。
3、主机将数据写入发送缓存器(Menory),缓存区(缓存长度看单片机配置)经过移位寄存器通过MOSI将字节一位一位的移出去给从机,同时MISO接口接收到的数据经移位寄存器一位位移动到接收缓存区。
4、从机也将字节的串行移位寄存器种的内容通过MISO信号线返回给主机。同时通过MOSI信号线接收主机发送的数据。两个移位寄存器中的内容就被交换。
SPI只有主从模式之分,没有读和写的说法,外设的写操作和读操作都是同步完成。若要写操作,主机需要忽略接收到的字节。若要读,则发送一个空字节来引发从机传输。
10、#ifndef、#define、#endif作用
防止头文件被重复引用和重复编译。
#ifndef是if not define的缩写,是宏定义的一种,准确说是预处理功能(宏定义、文件包含、条件编译)中的条件编译。
加入后可预防以下错误:若在.h文件中定义了全局变量,C文件包含了此.h文件多次,若不加#ifndef宏定义,则会出现变量重复定义的错误,也无法定义枚举变量等情况。
interactiv_system.h文件为例:
11、..OBJLED.axf: Error: L6218E: Undefined symbol XXXXX (referred from XXXXX.o).
extern对变量范围扩展,仍然报错,原先代码:
将需要extern的变量写在函数外部,修改后解决:
10、共地
当使用不同模块通信的时候,3.3V代表信号1,0V代表信号0。但电压都是相对的参考电压,参考对象不同,电压值也不同。两个模块的电路都是分开的,但他们的电压都是相较于左边的电路的负极而言,此时右边的0V相较于左边的可能会低了2V。那么当左边发送3.3V信号的时候,右边可能只会收到1.3V的信号,导致通信失败。
同理在驱动电机的时候,如果没有供地,本来设置的5V的信号到了电机处可能只有3V,就无法驱动电机转动。
为了解决不同模块参考电位的问题,我们可以使用一根杜邦线将两个的0V连接起来,即共地,此时两个模块的0V相同,高电平的3.3V也必然相同。
11、使用其他型号开发板时,要用JTAG_Set函数
正点原子的开发板一般不需要(一般不会出现问题),但其他开发板要使能SWD,否则可能会出现烧录后,程序无法运行的情况。
12、SD卡写入,LCD显示图片
在使用LCD显示图片时,直接将png后缀更改为jpg后缀时可以发现,图像的大小并没有改变,本质上其实格式并没有修改,图片会无法显示。
jpg、jpeg格式图片若是显示不了,可用windows系统自带的画图软件打开,图片大小会增加,一般就可以显示了。
13、不同pack的安装与卸载
“Option for Target”中的Device可以看到用的pack的版本,直接点击下面链接去官网找到对应的下载就好。
在“Debug,点击“setting”进入“Flash Download”,点击“Add”
可以看到每个pack在电脑中的存储位置,一般会放在“ARMflash”中,可以把别人电脑上有的pack直接复制到这个文件中,就可以使用了
14、C语言头文件和.c文件之间的关系
头文件.h和.c文件其实都是一样的,include" "头文件其实就是把这个头文件中的内容一行行的运行一次。其中的函数声明会在编译阶段自动匹配到同名的.c文件,具体过程可以看C语言的编译四个步骤。(后续会放出一些链接)
(130条消息) C语言后缀.h文件和.c文件作用和区别_花大师的博客-CSDN博客
从本质上来说,.c和.h并没有太大区别,只是命名方式的不同,主要为了解决重复声明的问题。
15、当出现ST-link USBcommunication error和The content of the ST-link is corrupt时
当已经检测到ST-link,但是仍然ST-link USBcommunication error一般是ST-link的固件版本问题固件需要升级。
当使用固件升级的时候仍然出现The content of the ST-link is corrupt,且重启多次无用后,可以下载STM32 ST-link Utility。官方链接STSW-link004 - STM32 ST-link utility (replaced by STM32CubeProgrammer) - STMicroelectronics
使用教程可参考博客
https://www.cnblogs.com/cuter/p/8879993.html
16、STlink/v2中SWD模式(4线)连线方式
连接1、7、9、20脚。
1:TVCC,供电。
7:SWIO,SWD接口的数据线,传输数据。
9:SWCLK,SWD接口的时钟线,用于同步数据传输。
20:GND,地线。
16、串口接的电压不对,或者降压芯片出现问题
降压芯片出问题,往往会影响到串口传输的电平(串口传输的数据)。电平不对,传输的信号可能会接收到全是1,或者怎么样都是一样的数据。可以检查下电压,降压芯片。
17、短接后电流瞬间无穷大,可能直接击穿降压芯片
不要试着短接任何电线,一瞬间可能就会击穿芯片,短接电流无穷大,降压芯片很可能第一个先被击穿。
18、出现error:"..OBJWHEELTEC.axf: Error: L6218E: Undefined symbol SPI_Cmd (referred from 24l01.o)."
一般很可能是忘记添加对应的固件库,像adc、spi、usart等
添加如下,添加后正常
19、芯片引脚对应外设的查询
可在官网下载对应的芯片手册,查看每个引脚对应外设。
如下,我们可以看到PA4、PA5引脚有哪些外设可用,若是F407芯片则还需要配置GPIO_PinAFConfig()函数指名复用什么功能,F103则不需要。
数据手册下载方法:
1、进入官网:
意法半导体-STMicroelectronics
2、 搜索栏中输入你想要查找的芯片型号
3、即可进入下载对应的数据手册
20、外设资料的查询
除了正点原子和CSDN等处的资料外,可以下载STM官方中文手册查看,包括SPI、USART等的原理。
可去正点原子资料处下载
包括了各种外设原理和寄存器的讲解
21、直流电机、步进电机、伺服电机、舵机的使用
单片机IO口一般输出的电流电压较小,无法直接驱动电机和舵机,需要加上相应的驱动模块。
1、直流电机:转动速度与电流大小相关,电流越大,转动速度越快,负载越高。但无法进行精确定位。
2、步进电机:以脉冲信号驱动,脉冲的数量决定了转动的角度,可以进行转动位置定位,但为开环控制。每步的转角取决于电机本身的硬件设置,200步一转的转角为(360/200)1.8度。
步进电机也可以控制转动的速度,脉冲的频率越高,转动的速度越快。
3、伺服电机:和步进一样以脉冲信号驱动,都能控制速度和转动的位置,但多了编码器等数据反馈,能够实现闭环控制,精确度更高。
4、舵机:用PWM控制,以脉冲的占空比决定舵机转动的角度。
电机的相关原理可参考
直流电机的原理及驱动_直流电机驱动-CSDN博客
步进电机原理及驱动_步进驱动器的工作原理-CSDN博客
22、LM2596降压芯片的使用
通过调节蓝色电位器旋钮(一般顺时针旋转升压,逆时针旋转降压),使用万用表测量输出电压直至需要的电压为止。
电位器即可变电阻
23、NRF24L01无线通信模块的使用
NRF24L01与MCU间用SPI通信。
可设置每次接收0-32个字节,但实际传输(SPI)依然为8位一次。只是在NRF24L01一个一个字节取出先放入一个数组内。
NRF24L01发送和接收的字节设置
虽然NRF24L01每次可读写0-32个字节数据,但实际上每次传输都只为1个字节(8bit)的数据,通过循环来实现一次多个字节数据的读取。
读出:写入无用数据以读取数据。每次读取数据位u8类型
写入:忽略读到的数据。每次写入数据为u8类型
有效数据宽度设置:若要在过程中不断改变每次接收到的数据大小,需要对接收模式RX寄存器中的通道X有效数据宽度进行更改。或者可采用每次只接受1个字节数据,通过定时器来计算接收时间间隔,当超过定时时间没有接收到新数据则溢出,视为接收完毕,否则重启定时器。
24、通信协议间的关系及应用
NRF24L01与MCU间用SPI通信,NRF24L01与NRF24L01间则采用了自定义的通信协议。
UART和SPI是有线通信协议,无法直接实现无线通信。无线通信需要专用的无线模块,如NRF24L01、蓝牙模块(如HC-05/HC-06)或Wi-Fi模块(如ESP8266/ESP32)。这些模块内置了射频(RF)电路,能够在无线电波上进行数据传输。