GPIO
General Purpose Input Output,
Memory-Mapped IO
把设备,控制等寄存器映射到内存里。好处就是访问设备方式和内存一样,也不用设计复杂的IO电路,便捷;缺点在于占用了内存空间。
Peripheral-Mapped IO
IO有一块专门的存储区域,和内存不一样,也有专门的不同的电路指令去访问IO。好处就是节省内存空间,也能清晰的知道什么时候发生IO了;缺点在于开发、设计上的造价增加。
GPIO
通用IO可以判断引脚高低电平,可以给引脚赋值高低电平进行控制。
stm32有几组GPIO,每个有16个Pin,可以配置为input output pullin pullup等模式,以及定时器、串口、中断等功能。
什么是上下拉模式?如果不设置为上下拉,引脚浮空的时候(没有设置输入为高或低电平的时候)浮空引脚可能收到电磁波干扰等等问题导致输入状态不确定,有0有1的,容易造成错误。
下拉:三极管控制默认接地,无输入的时候默认低电平。
上拉:三极管控制默认接Vdd 芯片工作电压。
大多数引脚是这两个功能都有的,我们初始化GPIO的时候选用一个,寄存器根据值控制接通相应电路。
输入输出信号真的可以被称为“信号”。输入规定为0-0.5视作低电平,0.5-Vdd视作高电平,范围以外的值无效。输出电流也只有5mA左右是没有能力直接驱动一些设备的,我们可以通过一些电路比如三极管,放大器等,电路接收到信号得知”需要输出驱动电流了“然后输出大电流。
Control
每个GPIO口有:
4 * 32bit configuration registers: 配置相关信息,比如in/out,上啦下拉,开漏输出或推挽输出,输出频率等。
- 推挽输出 push-pull:能输出高低电平。
- 开漏输出 open-drain:没有能力输出高电平,想输出高电平需要设置上拉电路来输出。
2 * 32bit data registers: 输入输出数据寄存器。
1 * 32bit set/reset registers: 设置或复位寄存器。
1 * 32bit locking registers: 锁定寄存器。
2 * 32bit alternate function selection register.
Mode
如图,32个Pin,每个两位来设置4种模式(in out 可选 模拟)。
Pull
只有3种模式(无pull,上拉,下拉)。
data
输入输出数据寄存器分开的。
CMSIS
先说一下考试定义:
CMSIS transforms memory mapped registers into C structs
#define PORT0 ((struct PORT*)0x2000030)
再说一下和一些嵌入式前辈讨论的理解,以下内容不许考试写:
李肯老师:arm-M推出的一系列API和软件组件,包括核心功能、DSP库、RTOS支持和调试接口等。
李肯老师:如果芯片厂不想再多一层,CMSIS就够用;但有的厂商会再在上面封一层,可能叫driver层。
李肯老师:另外CMSIS有个限定,就是ARM的ARM Cortex-M处理器;虽然它很常见,但并不是所有的处理器都是这个内核;这个需要注意。
榊:这种与内核相关的文件,比如启动文件,内核文件是CMSIS规定。
榊:对比STM32F103和GD32E23的启动文件,我们会发现是一样的:
榊:而芯片厂商要做的是根据这个arm规定的接口二次开发库函数。
李肯老师c站账号:架构师李肯的博客_CSDN博客-程序人生,粉丝福利领域博主
榊老师c站账号:风正豪的博客_CSDN博客-C语言,MSP430F5529,Linux领域博主
平时李肯老师的交流群会讨论很多嵌入式相关问题,欢迎有兴趣的同学来学习[Doge]
感兴趣的看个乐呵。
例:
typedef enum {
Reset, //!< Resets the pin-mode to the default value.
Input, //!< Sets the pin as an input with no pull-up or pull-down.
Output, //!< Sets the pin as a low impedance output.
PullUp, //!< Enables the internal pull-up resistor and sets as input.
PullDown //!< Enables the internal pull-down resistor and sets as input.
} PinMode;
gpio_set_mode(P1_10, Input);
gpio_set_mode(P2_8, Output);
int PBstatus=gpio_get(P1_10);
gpio_set(P2_8, 1);
以上代码是老师提供的driver,大意就是选定pin,传入特定参数,即可设置模式,设置输出。
感兴趣可以看看我的这篇文章,如果使用arm定义的cmsis直接去开发也是可以的:
STM32 学习笔记_4 GPIO:LED,蜂鸣器,按键,传感器的使用_灰海宽松的博客-CSDN博客
#include "stm32f10x.h"
int main(void){
/* 控制gpio需要三个步骤:开启rcc时钟,初始化,输入输出函数控制 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_0);
while(1){}
}
drivers二次开发,可以帮助简化。
当然这一段都是题外话了。考试就理解为“cmsis是变量宏定义直接映射到寄存器上;drivers是对其添加进一步行为”即可。