跑马灯
- 工程
- LED灯原理图
- 函数介绍
-
- RCC_APB2PeriphColckCmd()
- GPIO_Init()
- GPIO_SetBits() 和GPIO_ResetBits()
- 完整代码
-
- Led.h
- Led.c
- main.c
- 函数功能
- 实验步骤
- 其他资源
工程
将00MyPro工程复制粘贴一份后,改名为01 跑马灯。
打开文件夹并新建一个文件为Hrd(硬件驱动)。并新建LED文件夹。
在Keil中新建两个文件并保存在LED文件下,命名Led.c和Led.h。
并将Led.c添加到工程中,Led.h添加到环境变量中。详细添加请看stm32新建工程模板
LED灯原理图
因为 LED1和LED2的一端(正极)连接着高电平VCC3.3,所以在另一端(负极)就要接低电平使LED灯点亮。
函数介绍
RCC_APB2PeriphColckCmd()
使能IO口时钟,不同的IO组,调用的时钟使能函数不一样。这里不做过多介绍。
函数原型
详细请看此链接:stm32时钟系统
GPIO_Init()
详细请看此链接:stm32-GPIO
初始化IO口模式。
函数原型
GPIO_TypeDef* GPIOx:选择要使用的IO口。要根据stm32的型号来选择(不同的型号的IO口会有区别),还要根据LED灯原理图中使用的IO口来进行选择(不能选择非LED的IO口取驱动LED灯)。我的stm32中LED灯使用的IO口为GPIOA和GPIOD。
#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \
((PERIPH) == GPIOB) || \
((PERIPH) == GPIOC) || \
((PERIPH) == GPIOD) || \
((PERIPH) == GPIOE) || \
((PERIPH) == GPIOF) || \
((PERIPH) == GPIOG))
GPIO_InitTypeDef* GPIO_InitStruct:结构体,里面定义了IO口要使用的引脚、模式和频率。
引脚:选择引脚8和引脚2
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */
#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */
#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00))
模式:推挽输出 GPIO_Mode_Out_PP
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \
((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \
((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \
((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP))
频率:GPIO_Speed_50MHz
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \
((SPEED) == GPIO_Speed_50MHz))
GPIO_SetBits() 和GPIO_ResetBits()
操作IO口,使其输出高低电平,让其点亮。
函数原型
`void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)`
GPIO_SetBits():给IO口输入高电平
GPIO_ResetBits():给IO口输出低电平
里面的参数参照与GPIO_Init()函数中的参数。
完整代码
Led.h
#ifndef __LED_H
#define __LED_H
//位定义
#define LED0 PAout(8) // PA8
#define LED1 PDout(2) // PD2
void LED_Init(void); //初始化
void LED_Dispaly(void); //点亮一个LED灯
void LED_OneCycle(void); //LED0闪烁,LED1常量
void LED_Cycle(void);//LED0、LED1交替闪烁
void LED_TogetherCycle(void);//LED灯一起闪烁
#endif
意思:如果
Led.h
第一次被引用,那么
__LED_H
没有被定义,因此
#define __LED_H
和
#endif
中间的头文件内容就被执行。如果
Led.h
第二次被引用(不是第一次使用 ),由于
__LED_H
已经被第一次引用时定义了,所以不会执行
#define __LED_H
和
#endif
中间的头文件内容,也就是不会重复定义头文件内容。
为什么这样写:可以避免头文件的内容被重复定义。头文件中定义的变量不存在重复声明或定义。
Led.c
#include"Led.h"
#include"delay.h"
#include"stm32f10x.h"
void LED_Init()
{
GPIO_InitTypeDef GPIO_Int;
//使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD,ENABLE); //减少内存空间
//配置IO口 初始化
GPIO_Int.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Int.GPIO_Pin = GPIO_Pin_8;
GPIO_Int.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Int);
GPIO_Int.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Int.GPIO_Pin = GPIO_Pin_2;
GPIO_Int.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_Int);
}
void LED_Dispaly(void)
{
while(1)
{
//GPIO_ResetBits(GPIOA,GPIO_Pin_8);//LED0
//GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);//LED1
GPIO_SetBits(GPIOA,GPIO_Pin_8);
}
}
void LED_OneCycle(void)
{
delay_init();
LED1 = 0; //点亮
while(1)
{
LED0 =! LED0;
delay_ms(500);
}
}
void LED_Cycle(void)
{
delay_init();
//一开始让其熄灭
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
while(1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_ms(500);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
delay_ms(500);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_ms(500);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
delay_ms(500);
}
}
void LED_TogetherCycle(void)
{
delay_init();
while(1)
{
//GPIO_ResetBits(GPIOA,GPIO_Pin_8);//LED0
//GPIO_ResetBits(GPIOD,GPIO_Pin_2);//LED1
//delay_ms(500);
//GPIO_SetBits(GPIOA,GPIO_Pin_8);
//GPIO_SetBits(GPIOD,GPIO_Pin_2);
//delay_ms(500);
LED0 = 1;
LED1 = 1;
delay_ms(500);
LED0 = 0;
LED1 = 0;
delay_ms(500);
}
}
main.c
#include"Led.h"
#include"stm32f10x.h"
#include"delay.h"
//点亮LED灯
int main()
{
LED_Init();
//LED_Dispaly(); //点亮一个LED灯
LED_OneCycle(); //LED0闪烁,LED1常亮
//LED_Cycle();//LED0、LED1交替闪烁
//LED_TogetherCycle();//LED灯一起闪烁
}
函数功能
LED_Dispaly():点亮一个LED灯
LED_OneCycle():LED0闪烁,LED1常亮
LED_Cycle();//LED0、LED1交替闪烁
LED_TogetherCycle();//LED灯一起闪烁
实验步骤
注:不同的stm32所使用的IO口会有所不同,以下步骤对ALIENTEK miniSTM32F103 的 STM32F103RTC6有效,至于其他型号的stm32请参照相关的资料进行配置。但是对于大致的步骤都基本相同
1、使能IO口时钟。调用函数:RCC_APB2PeriphColckCmd();不同的IO组,调用的时钟使能函数里面的参数不一样不一样。
2、初始化IO口模式。调用函数GPIO_Init();
3、操作IO口,输出高低电平。
GPIO_SetBits(); 高电平
GPIO_ResetBits(); 低电平
其他资源
stm32 新建工程模板