1.首先把文件中需要的头文件路径加好
2.整理文件夹
3.电路知识
首先应该对led灯亮灭的原理理解,懂得其是通过gpio口的高低电平来控制的。
其次就是在原理图上找到该引脚。知道引脚名字后,就可以针对该引脚进行配置。为什么需要配置?也许你会问在51中不是直接对该引脚赋值0,和1从而使得引脚输出高低电平?
这里就要讲一下了。
通用gpio端口结构图:
51单片机的P0引脚结构图
可以比较发现51p0口不能通过软件进行上拉,只能同引脚外面自己手动焊接一个电阻连接到电源上。而stm32通用gpio口则不然,把上拉,下拉功能通过一个开关就可以使用,如果不同直接关掉,断路即可。
如果你想要通过p0来实现P0.0引脚的电压可以被控制为高与低。那么你只能在po.0进行上拉操作。这样就相当于,开漏加上上拉就可以了。如果不接上拉,当Q-为0时,引脚电压不确定,不一定为1或0;
如果你想在stm32上实现该功能,也可以同样设置。当然,还可以设置为推挽输出,当输出控制为0时,P-mos导通,N-mos关断此时引脚为高电平。反之,N-mos导通,P-mos关断,此时引脚为低电平。这种引脚状态是稳定的,因为其引脚直接与电源和地相连接。
这时,我脑子里面突然有一个基础问题!
为什么控制外设就是控制寄存器?
在51单片机中,控制p0.0引脚的电压,就可以通过对p0寄存器进行赋值而获得。
如何实现这个功能?
首先要知道锁存器发挥的作用!没有这个家伙来存储值,单片机啥都做不了。
内核51只能通过总线来控制外设。比如某一脉冲周期,51给其总线一系列操作,使得P0.0锁存器的输入端获得低电平,紧接着,下一个周期,内核又去执行其他指令了,P0.0锁存器的输入端又变成默认值了。但是由于锁存器的存在,其内部形成一个自循环,所以始终能保持Q-为1;
4.接下来就是led.c和led.h以及main.c编程
led.c如下图所示
这个文件就是对那个与led相连接的引脚的配置,以及使得小灯闪烁的函数编写。
对于这样一个简单的程序,我们应该了解什么?
我们从前面知道,控制引脚电压就是控制相对应的寄存器。对与51而言,只需要对一个寄存器进行控制。对于32而言,则需要控制几个寄存器。在51中,P0是0x80.那么在32中,对应寄存器也有相应地址,比较方便的是,这几个寄存器的地址还是连着的,所以就建立一个结构体,把对应的寄存器对应结构体中的(32位)变量(x1,x2,x3,x4…)。比如,控制4个寄存器,就相当于控制这个结构体的4个变量。4个32位的值与寄存器首地址可以用来初始化寄存器。
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); //初始化GPIO
可以看出,此初始化,是针对整个GPIOI的,是16个引脚。
HAL_GPIO_WritePin(GPIOI,GPIO_PIN_1,GPIO_PIN_RESET);//GPIOI1拉低,灯灭。
可以看出,此操作是针对某个引脚。
具体如下所示:
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_PIN_ACTION(PinState));
if (PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = (uint32_t)GPIO_Pin;//如果是GPIO_PIN_SET,则将GPIO的BSRR寄存器低16位置为GPIO_Pin
}
else
{
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16 ;//如果是GPIO_PIN_RESET,则将GPIO的BSRR寄存器的高16位置为GPIO_Pin
}
}
再看看该寄存器定义:
看完上面几个图,应该知道原理了。把对应的位写1,实现输出高和低电平。
然而对GPIO_TypeDef* GPIOx 这个指针的操作没看懂。。。