STM8S自学笔记-003 GPIO输出:点亮LED灯 and 跑马灯特效


【修订记录】
1、20181226,第一版
2、20210315,错别字修正,简化文字表述
3、20210321,错误修正
4、20210808,将应用层代码与底层代码分离,增加目录

点亮LED

点亮一个LED灯,应该是大多数单片机教程的第一步。这是最简单的一步。

GPIO初始化函数:GPIO_Init()

通常,要对LED所在的单片机的LED引脚 Px(y) 进行:
模式设置
①输出模式
②哪一种输出方式)
电平设置
③高/低电平

才能够点亮LED。看上去,至少也要三个语句,方能实现对LED的控制;但是,在STM8S中,只要一个句子就可以实现!

  //假设该LED是灌电流方式
  GPIO_Init( GPIOC , GPIO_PIN_3 , GPIO_MODE_OUT_PP_LOW_SLOW );

来分析上面的句子:

  • 它调用了库函数stm8s_gpio.c中的GPIO初始化函数-GPIO_Init(),该函数可将指定的引脚配置为你想要的状态。函数的入口有三个参数:GPIOx, GPIO_Pin, GPIO_Mode

  • GPIOx:GPIO分组

  • GPIO_Pin:PIN编号

  • GPIO_Mode:模式配置,包含引脚模式、速度、电平、中断

    短短一句话完成了所有的设置,言简意赅。

GPIO电平操作库函数:GPIO_WriteHigh()、GPIO_WriteLow()、GPIO_WriteReverse()

如果要在点亮LED之后熄灭它呢,你可以写成:

	GPIO_Init( GPIOC , GPIO_PIN_3 , GPIO_MODE_OUT_PP_HIGH_SLOW );

这样做,的确是熄灭了LED,但在改变IO电平的同时还把IO再次执行了初始化,后者是无用的,还浪费CPU程序资源。
我们需要新的办法,来加快只改变输出电平的操作。而库函数里也的确有这样的函数:

	GPIO_WriteHigh( GPIOC , GPIO_PIN_3 );		//PC3输出高电平
	GPIO_WriteLow( GPIOC , GPIO_PIN_3 );		//PC3输出低电平
	GPIO_WriteReverse( GPIOC ,GPIO_PIN_3 );		//PC3输出电平取反

进入倒函数内部,你会发现这三个函数只操作了GPIOC->ODR(输出寄存器)。

LED控制代码

在《STM8S自学笔记-002 STM8初上手和开发环境的建立》中,我有介绍自己用的开发板。上面有三个LED灯,从左到右依次接在PC3,PC4和PD2上。我用宏定义给他们编了号,方便后续的开发,包含Drv_GPIO.cDrv_GPIO.h

新建源文件【Drv _GPIO.c】

/**
  ******************************************************************************
  * @file    Drv_GPIO.c
  * @author  Elsa
  * @version V1.0.0
  * @date    7-August-2021
  * @brief   
  ******************************************************************************
  */ 
/* Includes ------------------------------------------------------------------*/
#include "Drv_GPIO.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Initializes the LEDx according to the specified parameters.
  * @param  LED_MAP : This parameter contains the pin number
  * @retval None
  */
void LED_Init(uint8_t LED_MAP)
{
  if (LED_MAP & LED1) GPIO_Init(LED1_GPIO, LED1_GPIO_PIN, GPIO_MODE_OUT_PP_LOW_SLOW);    //LED1 ON
  if (LED_MAP & LED2) GPIO_Init(LED2_GPIO, LED2_GPIO_PIN, GPIO_MODE_OUT_PP_LOW_SLOW);    //LED2 ON
  if (LED_MAP & LED3) GPIO_Init(LED3_GPIO, LED3_GPIO_PIN, GPIO_MODE_OUT_PP_LOW_SLOW);    //LED3 ON  
}

/**
  * @brief  Light on the specified LEDs.
  * @param  LED_MAP : This parameter contains the pin number
  * @retval None
  */
void LED_On(uint8_t LED_MAP)
{
  if (LED_MAP & LED1) GPIO_WriteLow(LED1_GPIO, LED1_GPIO_PIN);
  if (LED_MAP & LED2) GPIO_WriteLow(LED2_GPIO, LED2_GPIO_PIN);
  if (LED_MAP & LED3) GPIO_WriteLow(LED3_GPIO, LED3_GPIO_PIN);
}

/**
  * @brief  Light off the specified LEDs.
  * @param  LED_MAP : This parameter contains the pin number
  * @retval None
  */
void LED_Off(uint8_t LED_MAP)
{
  if (LED_MAP & LED1) GPIO_WriteHigh(LED1_GPIO, LED1_GPIO_PIN);
  if (LED_MAP & LED2) GPIO_WriteHigh(LED2_GPIO, LED2_GPIO_PIN);
  if (LED_MAP & LED3) GPIO_WriteHigh(LED3_GPIO, LED3_GPIO_PIN);
}

/**
  * @brief  Blink the specified LEDs.
  * @param  LED_MAP : This parameter contains the pin number
  * @retval None
  */
void LED_Reverse(uint8_t LED_MAP)
{
  if (LED_MAP & LED1) GPIO_WriteReverse(LED1_GPIO, LED1_GPIO_PIN);
  if (LED_MAP & LED2) GPIO_WriteReverse(LED2_GPIO, LED2_GPIO_PIN);
  if (LED_MAP & LED3) GPIO_WriteReverse(LED3_GPIO, LED3_GPIO_PIN);
}

/**
  * @brief  Control the specified LEDs.
  * @param  LED_MAP : This parameter contains the pin number
  * @retval None
  */
void LED_Control(uint8_t LED_MAP)
{
  if (LED_MAP & LED1) GPIO_WriteLow(LED1_GPIO, LED1_GPIO_PIN);
  else                GPIO_WriteHigh(LED1_GPIO, LED1_GPIO_PIN);
  if (LED_MAP & LED2) GPIO_WriteLow(LED2_GPIO, LED2_GPIO_PIN);
  else                GPIO_WriteHigh(LED2_GPIO, LED2_GPIO_PIN);
  if (LED_MAP & LED3) GPIO_WriteLow(LED3_GPIO, LED3_GPIO_PIN);
  else                GPIO_WriteHigh(LED3_GPIO, LED3_GPIO_PIN);
}


新建头文件【Drv _GPIO.h】

/**
  ******************************************************************************
  * @file    Drv_GPIO.h
  * @author  ANNA
  * @version V1.0.0
  * @date    03-August-2021
  * @brief   This file contains the headers of the Drv_GPIO.c
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DRV_GPIO_H
#define __DRV_GPIO_H

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Exported types ------------------------------------------------------------*/
/* Exported defines ----------------------------------------------------------*/
//Maps of LEDx
#define LED(n)  ((uint8_t)(0x01<<(uint8_t)(n-1)))
#define LED1    LED(1)
#define LED2    LED(2)
#define LED3    LED(3)
//GPIO Definition of LEDx
#define LED1_GPIO_PIN     GPIO_PIN_3
#define LED2_GPIO_PIN     GPIO_PIN_4
#define LED3_GPIO_PIN     GPIO_PIN_2
#define LED1_GPIO         GPIOC
#define LED2_GPIO         GPIOC
#define LED3_GPIO         GPIOD

/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
void LED_Init(uint8_t LED_MAP);
void LED_On(uint8_t LED_MAP);
void LED_Off(uint8_t LED_MAP);
void LED_Reverse(uint8_t LED_MAP);
void LED_Control(uint8_t LED_MAP);




#endif

跑马灯

跑马灯原理

其实跑马灯真么什么好说的。想实现这个效果,你至少要有三个LED,而且它们在物理上要排成一行,这样看的才明显。
实现的原理也很简单:

  1. 只开第一个LED;
  2. 只开第二个LED;
  3. 只开第三个LED;
  4. 返回1 。
    为了方便肉眼观察,还需要在1、2、3步的尾部各追加一个延时函数。
    简单的延时函数如下:
#define Delay(n)	while(n--)

跑马灯代码

源文件【main.c】的内容

/**
  ******************************************************************************
  * @file    main.c
  * @author  Annakin
  * @version V1.0.0
  * @date    21-March-2018
  * @brief
  ******************************************************************************
  */

  /* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define Delay(n)	while(n--)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void Easy_Delay(void);
/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
void main(void)
{
  LED_Init(LED1 | LED2 | LED3);
  while (1)
  {
    LED_Control(LED1);
    Easy_Delay();
    LED_Control(LED2);
    Easy_Delay();
    LED_Control(LED3);
    Easy_Delay();
  }
}

void Easy_Delay(void)
{
  uint16_t i = 60000;
  Delay(i);
}


#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

     /* Infinite loop */
  while (1)
  {
  }
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

源文件【main.h】的内容

#ifndef __MAIN_H
#define __MAIN_H

/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "stm8s_it.h"
#include "Drv_GPIO.h"

/* Exported types ------------------------------------------------------------*/
/* Exported defines ----------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/



#endif
/***************************************************************END OF FILE****/

更完备的延时函数,它们和时钟系统有关系,让我们一起期待《STM8S自学笔记-004 时钟》和《STM8S自学笔记-005 精准延时》。

STM8S003K3最小系统是指一种基于STM8S003K3微控制器的最简单、最基础的硬件系统。它包含了STM8S003K3芯片、外部时钟电路、复位电路、电源电路以及必要的外围元件。 首先,STM8S003K3是意法半导体(STMicroelectronics)公司生产的一款低功耗、高性能的8位微控制器。它具有8KB的Flash存储器和1KB的SRAM,可运行高达16MHz的工作频率。此外,它还具有多个外设接口,包括SPI接口、I2C接口、USART接口、定时器和通用输入/输出端口等。 最小系统中的外部时钟电路主要是为了提供稳定的时钟信号给STM8S003K3芯片,确保程序的正常运行。外部时钟电路一般由晶体振荡器和相关的电容、电阻组成,通过将时钟信号输入芯片的时钟引脚,来驱动芯片的时钟。 复位电路是为了保证系统在上电或其他异常情况下能够正常初始化。它通常包括一个电源复位芯片,能够监测电源电压并在电源异常时发送复位信号给STM8S003K3芯片。 电源电路负责为整个最小系统提供电源电压。它通常由直流电源接入,通过稳压电路将电压调整为芯片所需的工作电压,以确保系统的正常运行。 在最小系统中,还可能包含一些必要的外围元件,如LED指示、按键、电容触摸开关等,用于测试、控制或交互等需求。 总而言之,STM8S003K3最小系统是由STM8S003K3微控制器、外部时钟电路、复位电路、电源电路以及必要的外围元件构成的一个最简单、最基础的硬件系统,能够实现基本的控制、运算和通信功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值