对于微控制器,LED 闪烁程序相当于“hello world”程序。在我们之前的教程中,我们学习了如何开始使用 STM8S103F3 开发板以及如何设置 IDE 和编译器来对我们的 STM8S 控制器进行编程。我们还学习了如何使用标准外设库,以及如何编译代码并将其上传到我们的微控制器中。涵盖了所有基础知识,让我们真正开始编写代码。在本教程中,我们将学习如何在 STM8S 控制器上执行通用 GPIO 功能。该板已经有一个连接到端口 B 的引脚 5 的板载 LED,我们将学习如何使该 LED 闪烁,并添加一个外部 LED 并使用按钮对其进行控制。
准备好硬件
在我们深入研究程序之前,让硬件连接准备好。如前所述,我们将在这里使用两个 LED,一个是板载 LED,它会持续闪烁,另一个是外部 LED,可以通过按钮进行切换。这个想法是在一个简单的设置中学习所有的 GPIO 功能。板载 LED 已经连接到 PB5(PORTB 的引脚 5),所以我刚刚将 LED 连接到 PA3,将按钮连接到 PA2,如下图所示。
但是,在我们控制的所有可用输出引脚中,为什么我选择 PA3 作为输出,PA2 作为输入?这些问题是有效的,我将在本文后面解释。我为本教程的硬件设置如下所示。如您所见,我还将我的 ST-link 编程器连接到编程引脚,这不仅可以对我们的电路板进行编程,还可以用作电源。
了解 STM8S103F 上的 GPIO 引脚排列
现在回到问题,为什么 PA2 用于输入,为什么 PA3 用于输出?为了理解这一点,让我们仔细看看微控制器的引脚排列,如下所示。
根据引脚图,我们的微控制器上有四个端口,即端口 A、B、C 和 D,分别用 PA、PB、PC 和 PD 表示。每个 GPIO 引脚还具有一些其他特殊功能。例如,PB5(PORT B 的引脚 5)不仅可以用作 GPIO 引脚,还可以用作 I2C 通信的 SDA 引脚和定时器 1 的输出引脚。因此,如果我们将此引脚用于连接 LED 等简单的 GPIO 用途,那么我们将无法同时使用 I2C 和 LED。遗憾的是,板载 LED 连接到此引脚,所以我们在这里没有太多选择,而且在这个程序中,我们不会使用 I2C,所以问题不大。
STM8S103F GPIO 选择的引脚说明和提示
说真的,使用 PA1 作为输入引脚并没有什么坏处,它只是工作引脚。但我特意提出这一点,是为了让我有机会向您展示一些在新微控制器上选择 GPIO 引脚时可能会陷入的常见陷阱。避免陷阱的最佳方法是阅读STM8S103F3P6 数据表中提供的引脚详细信息和引脚说明。数据表中提到的 STM8S103F3P6 微控制器引脚描述详细信息如下图所示。
我们微控制器上的输入引脚可以是浮动或弱上拉,输出引脚可以是开漏或推挽。已经讨论了开漏和推挽输出引脚之间的区别,因此我们不会详细介绍。简单来说,开漏输出引脚可以使输出只有低不高,而推挽输出引脚可以使输出既高又高。
除了上表之外,您还可以注意到输出引脚可以是快速输出 (10 Mhz) 或慢速输出 (2 MHz)。这决定了 GPIO 的速度,如果你想非常快速地在高低之间切换你的 GPIO 引脚,那么我们可以选择快速输出。
如上图所示,我们控制器上的一些 GPIO 引脚支持真正的漏极开路 (T)和高灌电流 (HS) 。Open Drain 和 True Open Drain 之间的一个相当大的区别是连接到开漏的输出不能被拉高超过微控制器的工作电压 (Vdd),而真正的开漏输出引脚可以被拉高到高于 Vdd。具有高吸收能力的引脚意味着它可以吸收更多电流。任何 GPIO HS 引脚的源电流和灌电流均为 20mA,而电源线可消耗高达 100mA。
仔细查看上图,您会注意到几乎所有 GPIO 引脚都是高灌电流 (HS) 类型,但 PB4 和 PB5 是真正的开漏型 (T)。这意味着这些引脚不能被拉高,即使引脚被拉高,它们也无法提供 3.3V。这就是为什么板载 LED 连接到 3.3V 并通过 PB5 接地,而不是直接从 GPIO 引脚为其供电。
有关详细的引脚说明,请参阅数据表的第 28 页。如上图所示,PA1 自动配置为弱上拉,不推荐用作输出引脚。无论如何,它可以与按钮一起用作输入引脚,但我决定使用 PA2 只是为了尝试从程序中启用上拉。这些只是一些基本的东西,当我们编写更复杂的程序时它们会很有用。现在,如果很多事情都从你的脑海中浮现出来也没关系,我们将在其他教程中深入探讨。
使用 SPL 对 STM8S 进行 GPIO 输入和输出编程
正如我们在第一个教程中讨论的那样,创建一个工作区和新项目。您可以添加所有头文件和源文件,也可以仅添加 gpio、config 和 stm8s 文件。打开main.c文件并开始编写程序。
确保您已包含如上图所示的头文件。打开main.c文件并启动代码。完整的 main.c 代码可以在此页面底部找到,您还可以从那里下载项目文件。代码解释如下,如果您对编码部分感到困惑,也可以参考SPL 用户手册或本页底部链接的视频。
取消初始化所需端口
我们通过取消初始化所需端口来开始我们的程序。正如我们之前所讨论的,每个 GPIO 引脚除了像普通的输入和输出一样工作外,还有许多其他功能与其相关联。如果这些引脚先前已用于其他应用程序,那么在我们使用它们之前应该将其取消初始化。这不是强制性的,但是,这是一个很好的做法。下面两行代码用于De-Initialize Port A和Port B。使用语法GPIO_DeInit (GPIOx)即可;并提及端口名称代替 x。
GPIO_DeInit(GPIOA); //准备端口A工作
GPIO_DeInit(GPIOB); // 准备端口 B 工作
输入输出GPIO声明
接下来,我们必须声明哪些引脚将用作输入,哪些引脚将用作输出。在我们的例子中,引脚 PA2 将用作输入,我们还将将该引脚声明为内部上拉,这样我们就不必在外部使用一个。语法为GPIO_Init (GPIOx, GPIO_PIN_y, GPIO_PIN_MODE_z);。 其中 x 是端口名称,y 是引脚编号,z 是 GPIO 引脚模式。
//声明PA2为输入上拉引脚
GPIO_Init (GPIOA, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);
接下来,我们必须将引脚 PA3 和 PB5 声明为输出。同样可以使用多种类型的输出声明,但我们将使用“GPIO_MODE_OUT_PP_LOW_SLOW”,这意味着我们将其声明为低速推挽式输出引脚。默认情况下,该值会很低。语法将是相同的。
GPIO_Init(GPIOA,GPIO_PIN_3,GPIO_MODE_OUT_PP_LOW_SLOW);
//声明PB5为推挽输出引脚
GPIO_Init(GPIOB、GPIO_PIN_5、GPIO_MODE_OUT_PP_LOW_SLOW);
SPL 用户手册中的以下快照提到了所有可能的 GPIO 模式 (z)。
无限while循环
在引脚声明之后,我们需要创建一个无限循环,在其中我们将永远闪烁 LED 并监控按钮的状态以切换 LED。无限循环可以使用while(1)或 for (;;)创建。这里我使用了while (1)。
而 (1)
{
}
检查输入引脚的状态
我们必须检查输入引脚的状态,这样做的语法是GPIO_ReadInputPin(GPIOx, GPIO_PIN_y); 其中 x 是端口名称,y 是引脚号。如果引脚为高电平,我们将得到“1”,如果引脚为低电平,我们将得到“0”。我们已经习惯在 if 循环中检查引脚是高电平还是低电平。
if (GPIO_ReadInputPin(GPIOA, GPIO_PIN_2)) //如果按钮被按下
使 GPIO 引脚为高电平或低电平
要使 GPIO 引脚高或低,我们可以使用GPIO_WriteHigh(GPIOx,GPIO_PIN_y); 和GPIO_WriteLow(GPIOx,GPIO_PIN_y); 分别。在这里,我们使 LED 在按钮被按下时打开,如果按钮未被按下则关闭。
if (GPIO_ReadInputPin(GPIOA, GPIO_PIN_2)) //如果按钮被按下
GPIO_WriteLow(GPIOA,GPIO_PIN_3); //带领
别的
GPIO_WriteHigh(GPIOA,GPIO_PIN_3); //LED关闭
切换 GPIO 引脚
要切换 GPIO 引脚,我们有GPIO_WriteReverse(GPIOx,GPIO_PIN_y); 调用此函数将改变输出引脚的状态。该引脚为高电平时,变为低电平,为低电平时,变为高电平。我们正在使用此功能来闪烁 PB5 上的板载 LED。
GPIO_WriteReverse(GPIOB,GPIO_PIN_5);
延迟功能
与 Arduino 不同的是,cosmic 编译器没有预定义的延迟函数。所以我们必须自己创造一个。我的延迟函数如下所示。延迟的值将在变量 ms 中接收,我们将使用两个 for 循环来保持或程序执行。就像_asm(“nop”) 是一个汇编指令,它代表无操作。这意味着控制器将在不执行任何操作的情况下循环进入 for 循环,从而产生延迟。
void delay (int ms) //函数定义
{
整数 i =0 ;
诠释 j = 0;
对于 (i=0; i《=ms; i++)
{
for (j=0; j《120; j++) // Nop = Dark/4
_asm(“nop”); //执行无操作 //汇编代码
}
}
上传和测试程序
现在我们的程序已经准备好了,我们可以上传它并测试它。上传后,我的硬件按预期工作。板载红色 LED 每 500 毫秒闪烁一次,每次按下开关时外部绿色 LED 都会亮起。
/* MAIN.C 文件
*
* 版权所有 (c) 2002-2005 STMicroelectronics
*/
#define Green_LED GPIOA,GPIO_PIN_3
#包括“STM8S.h”
void delay (int ms) //函数定义
{
整数 i =0 ;
诠释 j = 0;
对于 (i=0; i<=ms; i++)
{
for (j=0; j<120; j++) // Nop = Dark/4
_asm("nop"); //执行无操作 //汇编代码
}
}
主要的()
{
GPIO_DeInit(GPIOA); //准备端口A工作
GPIO_DeInit(GPIOB); // 准备端口 B 工作
//声明PA2为输入上拉引脚
GPIO_Init (GPIOA, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);
//声明PA3为推挽输出引脚
GPIO_Init (Green_LED, GPIO_MODE_OUT_PP_LOW_SLOW);
//声明PB5为推挽输出引脚
GPIO_Init(GPIOB、GPIO_PIN_5、GPIO_MODE_OUT_PP_LOW_SLOW);
而 (1)
{
if (GPIO_ReadInputPin(GPIOA, GPIO_PIN_2)) //如果按钮被按下
GPIO_WriteLow(Green_LED);//带领
别的
GPIO_WriteHigh(绿色_LED);//LED关闭
GPIO_WriteReverse(GPIOB,GPIO_PIN_5);
延迟(100);
}
}
全部0条评论
快来发表一下你的评论吧 !