对于微控制器,LED闪烁程序等效于“ hello world”程序。在之前的教程中,我们学习了如何开始使用STM8S103F3开发板,以及如何设置IDE和编译器来对STM8S控制器进行编程。我们还学习了如何使用标准的外围设备库,以及如何编译代码并将其上传到我们的微控制器中。涵盖所有基础知识之后,让我们开始真正地编写代码。在本教程中,我们将学习如何在STM8S控制器上执行通用GPIO功能。该开发板已经有一个内置的LED连接到端口B的引脚5,我们将学习如何使该LED闪烁,并添加一个外部LED并通过按钮进行控制。如果您是全新手,强烈建议您阅读上一教程,然后再继续进行操作。
准备好硬件
在进入程序之前,请准备好硬件连接。如前所述,我们将在这里使用两个LED,一个是板载LED,它将连续闪烁,另一个是外部LED,将通过按钮进行切换。这个想法是通过简单的设置学习所有GPIO功能。板载LED已连接到PB5(PORTB的引脚5),因此,我刚刚将LED连接到PA3,将按钮连接到PA2,如下图所示。
但是,在我们控制的所有可用输出引脚中,为什么我选择PA3作为输出,选择PA2作为输入?这些问题是有效的,我将在本文后面解释。我在本教程中的硬件设置如下所示。如您所见,我还将我的ST-link编程器连接到了编程引脚上,这些引脚不仅可以对我们的电路板进行编程,而且还可以用作电源。
了解STM8S103F上的GPIO引脚分配
现在回到问题所在,为什么要用PA2作为输入,为什么要用PA3作为输出?为了理解这一点,让我们仔细看一下如下所示的微控制器的引脚排列。
根据引脚图,我们在微控制器上有四个端口,分别是分别用PA,PB,PC和PD表示的PORT A,B,C和D。每个GPIO引脚还具有其他一些特殊功能。例如,PB5(PORT B的引脚5)不仅可以用作GPIO引脚,而且还可以用作I2C通信的SDA引脚以及定时器1的输出引脚。因此,如果我们将此引脚用于简单的GPIO目的(例如连接LED),那么我们将无法同时使用I2C和LED。可悲的是,板载LED与此引脚相连,因此我们在这里没有太多选择,在此程序中,我们将不使用I2C,因此这并不是什么大问题。
STM8S103F GPIO选择的引脚说明和技巧
诚然,使用PA1作为输入引脚并不会影响工作,而只是工作引脚即可。但是,我故意提出这一点,以便为我提供机会,向您展示一些在新的微控制器上选择GPIO引脚时可能会遇到的陷阱。避免陷阱的最佳方法是阅读STM8S103F3P6数据手册中提供的引脚详细信息和引脚描述。下图显示了STM8S103F3P6微控制器引脚说明的详细信息。
微控制器上的输入引脚可以是悬空或弱上拉,输出引脚可以是漏极开路或推挽。漏极开路和推挽输出引脚之间的差异已经讨论过,因此我们不再赘述。简而言之,漏极开路输出引脚可以使输出仅变为低电平而不是高电平,而推挽输出引脚可以使输出变为高电平和低电平。
除了上表之外,您还可以注意到输出引脚可以是快速输出(10 Mhz)或慢速输出(2 MHz)。这决定了GPIO速度,如果您想非常快速地在高和低之间切换GPIO引脚,那么我们可以选择快速输出。
如上图所示,我们控制器上的某些GPIO引脚支持真漏极开路(T)和高灌电流(HS)。漏极开路和真正漏极开路之间的显着区别是,连接到漏极开路的输出不能拉到高于微控制器的工作电压(Vdd)的水平,而真正的漏极开路输出引脚可以拉到高于Vdd的电压。具有高吸收能力的引脚意味着它可以吸收更多的电流。任何GPIO HS引脚的源电流和灌电流为20mA,而电源线最多可消耗100mA。
仔细观察上图,您会注意到几乎所有的GPIO引脚都是高灌电流(HS)类型,除了PB4和PB5是真正的漏极开路类型(T)。这意味着这些引脚不能设为高电平,即使将引脚设为高电平也无法提供3.3V电压。这就是为什么板载LED连接到3.3V并通过PB5接地而不是直接从GPIO引脚供电的原因。
有关详细的引脚说明,请参见数据手册第28页。如上图所示,PA1自动配置为弱上拉,不建议将其用作输出引脚。无论如何,它都可以与按钮一起用作输入引脚,但是我决定使用PA2只是为了尝试从程序中上拉。这些只是一些基本的东西,当我们编写更复杂的程序时将很有用。现在,如果很多事情突然发生,这是可以的,我们将在其他教程中深入探讨它。
使用SPL为GPIO输入和输出编程STM8S
正如我们在第一个教程中讨论的那样,创建工作区和新项目。您可以添加所有头文件和源文件,也可以仅添加gpio,config和stm8s文件。打开 main.c 文件并开始编写程序。
确保已包含头文件,如上图所示。打开 main.c 文件并启动代码。完整的main.c代码位于页面底部,您也可以从此处下载项目文件。代码说明如下,如果您对编码部分感到困惑,也可以参考SPL用户手册或本页底部链接的视频。
取消初始化所需的端口
我们通过取消初始化所需的端口来开始我们的程序。如前所述,每个GPIO引脚将具有许多其他功能,而不仅仅是正常的输入和输出。如果这些引脚以前曾用于其他一些应用,则在使用它们之前应先将其取消初始化。它不是强制性的,但是,这是一个好习惯。以下两行代码用于取消初始化端口A和端口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点亮;如果未按下按钮,则使LED熄灭。
if(GPIO_ReadInputPin(GPIOA,GPIO_PIN_2))//如果按下按钮GPIO_WriteLow(GPIOA,GPIO_PIN_3); // LED亮,否则GPIO_WriteHigh(GPIOA,GPIO_PIN_3); // LED熄灭
切换GPIO引脚
要切换GPIO引脚,我们有 GPIO_WriteReverse(GPIOx,GPIO_PIN_y); 调用此功能将更改输出引脚的状态。如果引脚为高电平,它将变为低电平,如果引脚为低电平,则将变为高电平。我们正在使用此功能来使PB5上的板载LED闪烁。
GPIO_WriteReverse(GPIOB,GPIO_PIN_5);
延迟功能
与Arduino不同,宇宙编译器没有预定义的延迟功能。因此,我们必须自己创建一个。我的延迟功能如下。延迟值将在变量ms中接收,我们将使用两个for循环来保持或执行程序。就像 _asm(“ nop”) 一样,它代表汇编指令,它表示不进行任何操作。这意味着控制器将在不执行任何操作的情况下循环进入for循环,从而产生延迟。
void delay(int ms)//函数定义{int i = 0; int j = 0; for(i = 0; i <= ms; i ++){for(j = 0; j <120; j ++)// Nop = Fosc / 4 _asm(“ nop”); //不执行任何操作//汇编代码}}
上载和测试程序
现在我们的程序已经准备好了,我们可以上传并测试它了。上传后,我的硬件即可正常工作。板上的红色LED指示灯每500毫秒闪烁一次,并且每当我按一下开关时,外部的绿色LED指示灯就会打开。
完整的工作可以在下面的视频链接中找到。达到这一点后,您可以尝试将开关和LED连接到不同的引脚,然后重新编写代码以了解概念。您还可以使用延迟时间来检查您是否清楚地理解了这些概念。
如果您有任何疑问,请将其留在下面的评论部分,对于其他技术问题,可以使用我们的论坛。感谢您的关注,在下一个教程中见。