历史上的今天
今天是:2024年09月13日(星期五)
2021年09月13日 | STM8S自学笔记-003 GPIO输出:点亮LED灯 and 跑马灯特效
2021-09-13 来源:eefocus
点亮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.c和Drv_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,而且它们在物理上要排成一行,这样看的才明显。
实现的原理也很简单:
只开第一个LED;
只开第二个LED;
只开第三个LED;
返回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 %drn", 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****/
史海拾趣
|
问题1:是不是越小的粉尘,越难被口罩过滤呢? 解答:一般而言,我们会以为越小的粉尘越难被过滤,但这是个似是而非的观念,以过滤理论而言,主要有五种过滤粉尘的方法:(1)布郎运动[Brownian Diffusion]-对越小的粒子,效应越强。(2)拦 ...… 查看全部问答> |
|
DSP烧写方法 1、TMS320LF24xx, TMS320LF28xx: 利用CCS里面自带的flash burn插件,很容易烧写。 不必专门编程,只要输入.out文件即可。 2、TMS320C5x 需要自己手工编写BootLoader程序,和烧写flash ...… 查看全部问答> |
|
我用SAA7113对视频信号进行A/D转换,芯片输入时钟采用晶振产生,波形正常,可是LLC管脚怎么也出不来信号,一直为低电平。电路图是按照datasheet上给的。求教原因。… 查看全部问答> |
|
我建了一个工程然后把sfilter.c加进来,编译的时候老是有如下的错误: C:\\WINDDK\\2600.1106\\INC\\DDK\\WXP\\ntddk.h(23) : fatal error C1189: #error : Compiler version not supported by Windows DDK queue.c C:\\WINDDK\\2600 ...… 查看全部问答> |
|
相信不少人都调试过吧! 那个忙检测到底怎么实现,读时序是怎么样的,主要是 E 脚的时序, 所以我现在都是用一段delay来了事, 看过厂商的文档了觉得有错误,他的时序图和后面的文字描述以及后面的示例代码好像有矛盾。 文档上说,E下降沿开始 ...… 查看全部问答> |
|
AN2656 - STM32F10xxx LCD glass driver firmwareIntroductionThis application note describes a technique for driving liquid crystal displays (L ...… 查看全部问答> |
|
大家好: 最近在看时钟发生器,我是新手,看的是ADI公司的AD9517,文档介绍说时钟发生器,可以采用外部VCO输入,我想问下,这个外部VCO输入是不是通过CLK管脚输入的。 还有就是PLL的1路差分或2路单端基准输入基准监控功能,有什么作用。 还有就 ...… 查看全部问答> |




