stm32单片机屏幕一直闪_STM32F407[3] 闪烁LED
发布日期:2021-06-24 17:13:25 浏览次数:2 分类:技术文章

本文共 3147 字,大约阅读时间需要 10 分钟。

按照上一小节的内容,我们已经能点亮LED了。同样的,把它熄灭非常简单:把对应GPIO设置为低电平即可。回忆上次的内容,想一下那个单刀双掷开关,对吧?

快速开始

结合一下,我们可以得到这样的思路:PD12设置为高电平

PD12设置为低电平

执行步骤1,循环往复

这样的话,我们的灯就会闪烁起来了。至少理论上是这样的。用于设置GPIO低电平的函数和设置高电平的函数用法类似:

GPIO_ResetBits(GPIOD, GPIO_Pin_12);

上面代码即可将PD12设置为低电平,来我们对比一下将PD12设置为高电平的写法:

GPIO_SetBits(GPIOD, GPIO_Pin_12);

可以很明显的感觉到,它们基本是一样的。我们把这两个代码组合一下,按照我们的思路,很容易写出:

while (1)

{

GPIO_SetBits(GPIOD, GPIO_Pin_12);

GPIO_ResetBits(GPIOD, GPIO_Pin_12);

}

这样的话,理论上PD12就会高低电平频繁切换,我们也就能看到LED闪烁起来了。如果你不知道如何组合代码可以参照下图:

好,首先编译,然后下载,最后按下板子的复位键。看到灯闪了吗?如果没问题的话......

看到灯闪了吗?没有?至少我是没有(理论上来说还是可以看到灯亮起的)。

看不到闪烁的原因?

我们一步步的来。检查我们的思路,是否有误:循环切换PD12的高低电平,高电平时候LED亮,低电平的时候LED灭,因此可以实现闪烁

思路,很显然没问题。其次,是板子烧掉了吗?比如没法输出低电平?我找来了一个简陋的示波器(啊啊其实是因为自己穷啊,压根不是因为别的),观察PD12的波形:PD12的波形,纵向一格是1V,横向一格是0.1us

很明显,虽然波形有很明显的变形,但是依旧是先高电平(表现在矩形波上升到最高,然后持平),然后切换为低电平(即波形和x轴重合)。这说明,PD12正如我们期望中的,先输出高电平,然后切换为低电平,然后再切换为高电平...即,芯片是正常的。

注意了一点,横向的一格是0.1us,而高低电平切换一次(一个周期)的时间只有0.3us左右...

稍微玩点游戏的读者应该知道,我们游戏一般是垂直同步在60帧,此时已经几乎不可能感觉得到卡顿了。也就是1/60 ≈ 16.667ms。而我们的LED闪烁频率是每秒钟闪烁三百万次以上...换句话说,人眼压根不可能看得到这个LED在闪。

评论区 @Rivers-Jin 提醒,查证了下,LED的响应速度也确实也没有这么高,所以本身它也不见得反应不过来。

解决方案

总归,人眼看不到我们的LED在闪烁,那么我们延长高电平的时间,也延长低电平的时间不就好了?如此一来,思路就变成这样了:PD12设置为高电平

等待一段时间

PD12设置为低电平

等待一段时间

回到步骤1,循环往复

那么现在主要问题就在于怎么等待了。对于单片机,它只有一个核心的一个CPU,因此可以用一个最简单的方法:等待的时候一直做点什么事情不就完事了,比如一个空循环,循环一百万次:

for (int i = 0; i < 1000000; i += 1)

{

// nothing to do}

我们把它插入到设置高电平完成后和设置低电平设置完成后:

while (1)

{

GPIO_SetBits(GPIOD, GPIO_Pin_12);

for (int i = 0; i < 1000000; i += 1)

{

// nothing to do }

GPIO_ResetBits(GPIOD, GPIO_Pin_12);

for (int i = 0; i < 1000000; i += 1)

{

// nothing to do }

}

整合好你的代码,下载到单片机上运行,应该可以看到LED快速闪烁起来了。如果没有看到,那么就把1000000改大一点,这样就会有更多的等待时间。

我们再测一遍PD12的波形,可以看到高电平持续时间和低电平持续的时间明显长了很多,一个i周期大概有0.15秒:PD12波形,纵向1V每格,横向50ms每格

规范代码

我们的延时部分是一致的,这意味着我们可以把它独立开来,形成一个单独的过程(函数)。例如这样:

// 延时等待// Mcnt表示循环几百万次void delay(int Mcnt)

{

for (int i = 0; i < 1000000 * Mcnt; i += 1)

{

// nothing to do }

}

如此一来,我们就可以把我们的代码变得更加漂亮了。我给程序丰富了点功能,使得四个灯能轮番亮起来,您可以尝试优化这段程序,让它看起来没这么傻:

// 延时等待// Mcnt表示循环几百万次void delay(int Mcnt)

{

for (int i = 0; i < 1000000 * Mcnt; i += 1)

{

// nothing to do }

}

int main(void)

{

// GPID时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

GPIO_InitTypeDef gpioInitInfo;

gpioInitInfo.GPIO_Pin = GPIO_Pin_12 // 要初始化的有12,13,14,15这四个 + GPIO_Pin_13

+ GPIO_Pin_14

+ GPIO_Pin_15;

gpioInitInfo.GPIO_Mode = GPIO_Mode_OUT; // 输出模式 gpioInitInfo.GPIO_OType = GPIO_OType_PP, // 推挽输出 gpioInitInfo.GPIO_PuPd = GPIO_PuPd_NOPULL; // 没有上下拉电阻 gpioInitInfo.GPIO_Speed = GPIO_Speed_100MHz; // 高速模式

GPIO_Init(GPIOD, &gpioInitInfo); // 初始化GPIO, 即PD12, PD13, PD14, PD15

while (1) // 死循环做下面这些事情 {

GPIO_ResetBits(GPIOD, GPIO_Pin_12); // PD12低电平 GPIO_SetBits(GPIOD, GPIO_Pin_13); // PD13高电平

delay(1); // 等待一段时间

GPIO_ResetBits(GPIOD, GPIO_Pin_13); // PD13低电平 GPIO_SetBits(GPIOD, GPIO_Pin_14); // PD14高电平

delay(1); // 等待一段时间

GPIO_ResetBits(GPIOD, GPIO_Pin_14); // PD14低电平 GPIO_SetBits(GPIOD, GPIO_Pin_15); // PD15高电平

delay(1); // 等待一段时间

GPIO_ResetBits(GPIOD, GPIO_Pin_15); // PD15低电平 GPIO_SetBits(GPIOD, GPIO_Pin_12); // PD12高电平

delay(1); // 等待一段时间 }

}

如果运行成功,板子上的四个LED会轮番亮起熄灭。

SUMMARY闪烁LED的思路

人眼看不到那么快的闪烁,因此需要适当延迟。事实上对于电路也是,一些硬件反应不过来,我们也需要适当延迟

未解决的问题似乎没有

F.A.Q.想到/被问到再补充

转载地址:https://blog.csdn.net/weixin_34026997/article/details/111952952 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:gorm软删除_gorm踩坑:软删除与某个字段的唯一性
下一篇:pygame 移开的矩形留痕迹_Python之pygame学习矩形区域(5)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月20日 03时39分18秒