赞
踩
STM32
ST:意法半导体
M:微电子
32:总线宽度
也叫MCU,单片机
单片机:一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU,随机存储器RAM,只读存储器ROM,多种I/O口和中断系统,定时器/计数器等功能(可能还包括显示驱动电路,脉宽调制电路,模拟多路转换器,A/D转换器等的电路)集成到一片硅片上构成一个小而完善的微型计算机系统,在工业控制领域应用广泛。
命名规则:
STM32F051R8T6xxx
STM32:家族
F:产品类别,A——汽车级,F——基础级,L——超低功耗,S——标准型,WB——蓝牙及802.15.4, WL——长距离无限产品,H——高性能, Q——主流型
051:特定功能(3位数字)
R:引脚数
8:闪存容量
T:封装
6:温度范围
x:固件板税
xx:选项
引脚分配:
电源IO:包括输入输出引脚INPUT\OUTPUT, VBAT, (VDDA VSSA), (VREF+ VREF-)等
晶振IO:包括主晶振IO,RTC晶振IO
下载IO:用于JTAG下载的IO,包括JTMS,JTCK,JTDI,JTDO,NJTRST
BOOT IO:用于设置系统的启动方式,包括BOOT0,BOOT1
复位IO:用于外部复位 NRST
以上组成的系统叫做最小系统
GPIO(通用输入输出引脚):
(1)专用器件连接到专用的总线,比如I2C,SPI,SDIO,FSMC,DCMI,这些总线的期间需要连接专用的IO
(2)普通元器件街道GPIO,比如蜂鸣器,LED,按键等元器件用普通的GPIO即可
(3)剩余的IO可以根据项目需要引出或者不引出
什么是寄存器
寄存器就是一个内存地址
不同的外设,在不同的地址上,根据地址就可以找到外设并使用它
寄存器编程方法:
-
- int main(void){
- volatile unsigned int * pointer=(unsigned int *)0x40028000;
- //volatile unsigned int * pointer表示定义指针变量
- //volatile关键字放置编译器对程序进行优化
- //比如*pointer+=1;*pointer+=2会被优化成*pointer+=3;
- //(unsigned int *)将0x40028000强转为地址
- //0x40028000这是一个内存地址,里面保存有数据
- //这条语句表明指针已经指向一个地址
- *pointer=1;
- //*pointer解指针符,指向地址内的数据
- }
使用宏定义优化
- #define pointer (volatile unsigned int *)0x40028000;
- //宏定义只是变量替换,减少内存消耗
- int main(void){
- *pointer=1;
- }
1.什么是GPIO
GPIO是通用输入输出端口的简称,简单来说就是STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯,控制以及数据采集的功能,可以通过控制GPIO引脚的电平变化,达到各种目的
IO端口基本结构
(1)IO引脚模块:保护二极管可以防止过高或过低的电压输入,外部电压高于VDD时,上方二极管导通,外部电压过低时,电流流向为Vss——IO。
(2)推挽,开漏或关闭:
推挽输出电路:当输入信号为高电平时,上面的mos导通,下面的mos截止,电流从VDD——OUT,当输入信号为低电平时,上面的mos截止,下面的mos导通,电流:OUT——GND,此时OUT相当于低电平,驱动能力强
开漏输出电路:输入高电平时,mos截止,上拉电阻可以保证默认高电平状态(本身不能直接输出高电平),输入低电平时,mos导通,OUT接地,相当于输出低电平。优点是实现线与功能
输出数据寄存器和复用功能输出:共同决定输出如何控制
输入数据寄存器,模拟输入,复用功能输入:识别输入的低电平
TTL肖特基触发器:将正弦波变成方波,将连续信号转换为离散信号
原理图:
注意,需要自己配置运行环境,可以通过2个途径:
(1)运行环境的管理工具
勾选上core和startup,否则构建程序报错
(2)库包中添加
添加STM322Cube_FW_F1_V1.6.0库包——CMSIS,将CMSIS文件夹直接复制到当前项目目录下,具体步骤:
stm32——手动移植HAL库以及错误解决方案(以STM32F103ZE为例)_青篱竹枫的博客-CSDN博客_stm32标准库移植到hal库【野火】STM32 HAL库开发实战指南 教学视频 手把手教学STM32全系列 零基础入门CubeMX+HAL库,基于野火全系列STM32开发板_哔哩哔哩_bilibili
设计思路
通过总线的形式,可以很好地将各种外设分离开,可以独立的将各种外设来控制它的使能与否,控制外设使能与否,就是控制这个外设的时钟
编写代码前,要查询stm32F1x的参考手册,知道GPIO挂载在哪个总线上(如图,挂载在APB2线上)
软件开发步骤
(1)使能GPIOB的外设时钟
第一步:先知道GPIOB的外设使能时钟在哪里(由前面可知GPIO挂载在APB2总线上,如图可知是RCC)
其中偏移地址0x18
第二步:查找RCC_APB2ENR的基地址,去存储器映像中找(下图最后一个)
所以外设基地址为0x4002 1000
所以APB2外设使能寄存器的地址就是基地址+偏移地址(0x4002 1000+0x18)
这个设置完成之后,表示GPIO已经使能,可以开始工作了
(2)查询GPIO的功能
第一步:在这里,我们需要使用开漏输出和推挽式输出的功能,由于开漏输出设置高电平比较麻烦,因从直接采用推挽式输出
并且根据8.1的GPIO功能描述,要配置开漏输出或者推挽输出要去配置GPIOx_CRL,GPIOx_CRH寄存器,我们不需要数据存储以及复位功能
第二步:查看端口位配置表,配置相应的寄存器(采用通用输出的推挽模式)
表18中的输出速度就是高低电平的翻转速度
由表17和18可知,需要配置CNF1,CNF0,MODE1,MODE0,以及PxODR寄存器
第三步 GPIO寄存器的识别
查找GPIOx_CRL,GPIOx_CRH寄存器的具体信息以及并按照上图的表17和18确定配置方法,因为是推挽输出,所以CNF1=0,CNF0=0,MODE1,MODE0设置为01,PXODE寄存器设置为0或1,接下来查找PXODR寄存器进行设置
最后查看pxODR的资料并配置
第四步:设置GPIO的外设基地址
在这个表里,可以看到GPIO各个端口的基地址
如图所示,GPIO端口B的基地址
0X4001 0C00
根据端口配置寄存器的信息可以查到偏移地址,用于编写代码
CRL偏移地址:0x00
pxODR的地址偏移:0x0C
最后按照查询的信息编写代码,对应功能写代码,完成相应位的配置:
- #define GPIOB_CLK (*(volatile unsigned int *)(0x40021000+0x18))
- //volatile 防止编译器对代码进行优化
- //unsigned int 将地址设置为无符号数,因为地址不能是负的
- //0x40021000 RCC的外设基地址,
- //0x18 RCC的偏移地址
- #define GPIOB_CRL (*(volatile unsigned int *)(0x40010C00+0x00))
- #define GPIOB_ODR (*(volatile unsigned int *)(0x40010C00+0x0C))
-
- int main(void){
- //1.使能GPIOB的外设时钟
- GPIOB_CLK |=(1<<3);
- //2.GPIOB设置推挽输出模式
- GPIOB_CRL &=~(0xf<<(4*0));//清除低4位寄存器
- GPIOB_CRL |=(2<<0);
-
- GPIOB_ODR &=~(0x1<<(1*0));//清除低1位寄存器
- GPIOB_ODR|=(1<<0);
-
- }

编写过程分析(假设点亮PB0端口的灯)
- //1.使能GPIOB的外设时钟
- GPIOB_CLK |=(1<<3);
-
-
- 这句代码相当于GPIOB_CLK=GPIOB_CLK|(1<<3)
- 也就是将1左移3位,结果再与GPIOB_CLK取或运算,根据参考手册知
- 在CKL中,1被表示为(其中的X表示未定的结果,可以是0,也可以是1)
- 00000000 00000000 XXXXXXXX XXXXXX01
- 下面将1左移3位,舍弃掉被移除的数字,空位补0,可得(1<<3)
-
- (1<<3)=00000000 00000XXX XXXXXXXX XXX01000 //这样就将位3置1了
-
- GPIOB_CLK为
- GPIOB_CLK=00000000 00000000 XXXXXXXX XXXXXX0X
-
- 所以二者取或运算的结果为
- 00000000 00000XXX XXXXXXXX XXXX1X0X
- 可见除了位3变为1,其他位不受影响
-

通过查阅手册可知,PB端口对应的是位3,位3置0时,PB端口始终关闭,端口不能工作,当位置3置1时,PB端口可以工作,因此在这里将1左移3位,保证PB端口打开
- //2.GPIOB设置推挽输出模式
- GPIOB_CRL &=~(0xf<<(4*0));//清除低4位寄存器
- GPIOB_CRL |=(2<<0);
- GPIOB_CRL &=~(0xf<<(4*0));//清除低4位寄存器
-
- 这句代码等同于GPIOB_CRL=GPIOB_CRL&(~(oxf<<(4*0)));
-
- oxf用二进制表示就是00000000 00000000 00000000 00001111
-
- oxf<<(4*0)的意思是oxf左移0个4位,也就是
-
- oxf<<(4*0)=00000000 00000000 0000000 00001111;
-
- 所以
-
- ~(oxf<<(4*0))=11111111 11111111 11111111 11110000;
-
- GPIOB_CRL=XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
-
- 则
-
- GPIOB_CRL&(~0xf<<(4*0))=XXXXXXXX XXXXXXXX XXXXXXXX XXXX0000
-
- //这样就实现了将低4位清0

- GPIOB_CRL |=(2<<0);
-
- 这句代码等同于
-
- GPIOB_CRL=GPIOB_CRL|(2<<0);
- 经过分析,若想实现需要的功能,GPIOB_CRL的后4位应设置为0010,十进制就是2
-
- (2<<0)也就是将2左移0位,相当于不移动,因此
- (2<<0)=00000000 00000000 00000000 00000010;
-
- GPIOB_CRL=XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
-
- 所以
- GPIOB|(2<<0)=XXXXXXXX XXXXXXX XXXXXXXX XXXXXX1X
-
- 也就是只将1位置1

根据前面的分析可知,我们要配置输出模式,采用较低的速度即可,因此,MODE0应设置为10,也就是十进制的2,我们采用的是推挽输出模式,因此,CNF0应设置为00
- GPIOB_ODR &=~(0x1<<(1*0));//清除低1位寄存器
- GPIOB_ODR|=(1<<0);
要点亮PB0端口的灯,因此低1位寄存器应该为1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。