目录

电气原理图
8个LED灯采用共阳极方式接在PC口的PC0-PC7引脚上,输出低电平为点亮、高电平熄灭。
测试实物开发板

复制第一节所创建的库函数模板空工程,重新编译没有错误没有警告。然后开始接下来的工程配置和代码编写等工作。
在工程文件中新建文件夹取名APP,用来存放外部设备驱动程序。在APP文件夹中新建文件夹led,用以存放led灯相关的驱动程序。
(1)led文件夹路径添加
若不添加后面程序编译将报错。

(2)创建led驱动程序文件
分别创建led.c和led.h文件,保存在APP-led文件夹中

(3)工程Project中新建APP分组

(4)工程APP中添加led.c文件

- #ifndef _LED_H_
- #define _LED_H_
-
- #include "stm32f10x.h"
-
- void Led_Init(void); //led Init Function
-
- #endif
#ifndef _LED_H_
#define _LED_H
_ #endif
的作用是:
如果led.h第一次被引用,那么__LED_H没有被定义,所以#define __LED_H和#endif 中间的头文件内容就被执行,也就是头文件内容被定义。那么如果led.h第二次被引用,由于__LED_H已经被第一次引用时定义了,所以不会执行#define __LED_H和#endif 中间的头文件内容,也就是不会重复定义头文件内容。
这样,可以避免头文件的内容被重复定义。头文件中定义的变量不存在重复声明或定义
①GPIO_InitTypeDef结构体变量定义和赋值
在STM32的GPIO的驱动文件上
找到GPIO_StructInit()。

在Led_Init()中定义GPIO_InitTypeDef结构体变量,同时给结构体变量成员GPIO_Pin、GPIO_Speed、GPIO_Mode赋值
GPIO_Pin:需要使用的IO引脚
GPIO_Speed:IO输出最高带宽频率
GPIO_Mode:IO输出模式,四种模式。一般常用为普通推挽输
普通推挽输出(GPIO_Mode_Out_PP:电平匹配场合。低电平0V、高电平3.3V
普通开漏输出(GPIO_Mode_Out_OD):电平不匹配场合,一般5V以上
复用推挽输出(GPIO_Mode_AF_PP):用作串口的输出
复用开漏输出(GPIO_Mode_AF_OD):用在IIC

具体要赋什么值,鼠标分别放在GPIO_Pin_All、GPIO_Speed_2MHz、GPIO_Mode_IN_FLOATING上面右击,然后选择Go To Definition of 'XXX'跳转到其头文件中相应的宏、枚举定义,如下图所示

GPIO_Pin

GPIO_Speed

GPIO_Mode
结构体变量重新赋值后的程序如下

②时钟使能
在STM32的rcc.c文件夹中找到RCC_APB2PeriphClockCmd(),使能或者失能 APB2 外设时钟

第二个参数就是ENABLE或者DISENABLE,
参数1选择如下:

另外说明:
(1)APB2负责AD,I/O,串口1,高级定时器TIM。如上图参数1表格所示。
(2)APB1负责DA,串口2,3,4,5,普通定时器TIM, USB , IIC , CAN。如下图所示

最终的LED代码如下

- void Led_Init()
- {
- GPIO_InitTypeDef GPIO_InitTypeStruct; //结构体定义
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //时钟使能
-
- GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
- GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz; //输出口的最高带宽频率:50MHz
- GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_AF_PP; //普通推挽输出
- GPIO_Init(GPIOC,&GPIO_InitTypeStruct); //初始化GPIO的C口
-
- //设置IO高电平输出,LED在初始状态下都保持熄灭状态
- GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
-
- }
(3)在Main.c主函数中点亮led灯
首先引用led.h头文件,调用Led_Init()。
Main程序
- #include "stm32f10x.h"
- #include "led.h"
-
-
-
- int main()
- {
- Led_Init();
- while(1)
- {
- //8个引脚都设置为低电平,将8个LED灯都点亮
- GPIO_ResetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
- }
- }
编译没有错误,生成HEX文件。

使用烧录软件,将HEX文件写到单片机中

实验结果实物展示

为了方便代码移植,将引脚、IO口和时钟等在头文件中使用宏定义,代码在移植到别的工程项目中,只需要修改宏定义文件即可。宏定义如下。
- #define LED_PORT_RCC RCC_APB2Periph_GPIOC
- #define LED_PIN GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7
- #define LED_PORT GPIOC
然后将程序中的原变量名,修改为定义的宏名称即可
- #ifndef _LED_H_
- #define _LED_H_
-
- #include "stm32f10x.h"
-
- #define LED_PORT_RCC RCC_APB2Periph_GPIOC
- #define LED_PIN (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)
- #define LED_PORT GPIOC
-
-
- void Led_Init(void); //led Init Function
-
- #endif
- void Led_Init()
- {
- GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
- RCC_APB2PeriphClockCmd(LED_PORT_RCC,ENABLE);
-
- GPIO_InitStructure.GPIO_Pin=LED_PIN; //选择要设置的IO口
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
- GPIO_Init(LED_PORT,&GPIO_InitStructure); /* 初始化GPIO */
-
- GPIO_SetBits(LED_PORT,LED_PIN); //设置IO口高电平输出,熄灭所有LED灯
- }
- #include "stm32f10x.h"
- #include "led.h"
-
-
-
- int main()
- {
- Led_Init();
- while(1)
- {
- //
- GPIO_ResetBits(LED_PORT,GPIO_Pin_0); //点亮LED1
- GPIO_ResetBits(LED_PORT,GPIO_Pin_1); //点亮LED2
- GPIO_ResetBits(LED_PORT,GPIO_Pin_2); //点亮LED3
- //GPIO_ResetBits(GPIOC,GPIO_Pin_0); //点亮LED1
- }
- }
创建system.c源文件和system.h头文件,创建Public文件夹和Public文件组。使用前面讲解的方法添加文件


将stm32f10x.h文件在system.h头文件中引用,其它文件中不在引用,只需要引用system.h即可。
system.c中只调用system.h,没有其它代码操作。
system.h中代码如下
- #ifndef _system_H
- #define _system_H
-
-
- #include "stm32f10x.h"
-
-
- //位带操作,实现类似于51单片机中IO口操作方式
- //IO口宏定义
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
- //IO¿ÚµØÖ·Ó³Éä
- #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
- #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
- #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
- #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
- #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
- #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
- #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
-
- #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
- #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
- #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
- #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
- #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
- #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
- #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
-
- //IO口操作,只对单一的IO口
- //确保n的值小于16
- #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
- #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
-
- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
- #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
-
- #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
- #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
-
- #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
- #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
-
- #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
- #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
-
- #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
- #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
-
- #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
- #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
-
-
- #endif
修改后的led.h代码如下
- #ifndef _LED_H_
- #define _LED_H_
-
- #include "system.h"
-
- #define LED_PORT_RCC RCC_APB2Periph_GPIOC
- #define LED_PIN (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)
- #define LED_PORT GPIOC
-
- #define led1 PCout(0) //D1灯连接引脚PC0
- #define led2 PCout(1) //D2灯连接引脚PC1
- #define led3 PCout(2) //D3灯连接引脚PC2
-
-
- void Led_Init(void); //led Init Function
-
- #endif
修改后的main代码如下
- #include "system.h"
- #include "led.h"
-
-
-
- int main()
- {
- Led_Init();
- while(1)
- {
- //
- // GPIO_ResetBits(LED_PORT,GPIO_Pin_0); //点亮LED1
- // GPIO_ResetBits(LED_PORT,GPIO_Pin_1); //点亮LED2
- // GPIO_ResetBits(LED_PORT,GPIO_Pin_2); //点亮LED3
- // //GPIO_ResetBits(GPIOC,GPIO_Pin_0); //点亮LED4
-
- led1=0;
- led2=0;
- }
- }
-
通过这种定义方式,这样就可以像在C51单片机中那样操作IO口了。
若要取反,led1=~led1;
https://download.csdn.net/download/panjinliang066333/86507279