一、在STM32F407VGT6芯片中配置GPIO环境
- 对于一个跑马灯实验,首先,要了解的就是,芯片是如何构造出来的,设计GPIO引脚:根据原理图, PC4,PC5,PC6,PC7 为 LED 输出控制管脚,PE0 为蜂鸣器输出控制管脚, 配置为 GPIO_Output 输出模式, PA0,PE2,PE3,PE4 为按键输入管脚,配置为 GPIO_Input 输 入模式。
-
外射配置:
以 LED1 配置为例,点击 PC4,选择模式为 GPIO_Output 模式,LED1 的负极接 PC4 引 脚,所以,PC4 为高电平时 LED 熄灭,这里 PC4 的 output level 选择高电平,即上电复位 后 PC4 位高电平,默认为熄灭,把 User Label 标记为 LED1,同理 PC5、PA6、PA7 做同样 的选择和配置。 蜂鸣器引脚为 PE0,根据原理图高电平时蜂鸣器有电,低电平时蜂鸣器截止,因此 output level 配置为 low 低电平,上电保持截止,user label 标记为 BUZ。
-
工程配置:
设置一个文件夹,生成代码。
二、在keil中配置代码的生成环境
-
然后,就来到了Keil配置环境中:
设置跑马灯的代码,设置四个文件:<led.h>,<led.c>,<key.h>,<key.c>。
代码实现为:
-
接下来在 led.c 文件中添加 LED1-LED4 的管脚的数组变量和三个函数代码:
//接下来在 led.c 文件中添加 LED1-LED4 的管脚的数组变量和三个函数代码GPIO_TypeDef* GPIO_PORT[] = {LED1_GPIO_Port, LED2_GPIO_Port, LED3_GPIO_Port, LED4_GPIO_Port}; const uint16_t GPIO_PIN[] = {LED1_Pin, LED2_Pin, LED3_Pin, LED4_Pin};
uint16_t buzDs = 0;
void LED_On(Led_TypeDef Led) { HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led],
GPIO_PIN_RESET); } void LED_Off(Led_TypeDef Led) { HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led],
GPIO_PIN_SET); } void LED_Toggle(Led_TypeDef Led) { HAL_GPIO_TogglePin(GPIO_PORT[Led], GPIO_PIN[Led]); }
void BUZ_On(void) { HAL_GPIO_WritePin(BUZ_GPIO_Port, BUZ_Pin, GPIO_PIN_SET); } void BUZ_Off(void) { HAL_GPIO_WritePin(BUZ_GPIO_Port, BUZ_Pin, GPIO_PIN_RESET); }
void BUZ_Prc(void) { if(buzDs) { BUZ_On(); buzDs--; } else BUZ_Off(); }
-
在 led.h 前面添加 Led_TypeDef 枚举类型。声明刚才添加的 2 个函数、会在 mian.c 中调用:在 key.c 中编写按键扫描和按键处理的代码
//在 led.h 前面添加 Led_TypeDef 枚举类型。声明刚才添加的 2 个函数、会在 mian.c 中调用
#ifndef __LED_H__
#define __LED_H__
#include "main.h"
/************************************************************* 用户自定义数据类型
**************************************************************/
typedef enum { LED1 = 0, LED2 = 1, LED3 = 2, LED4 = 3, LED_NO = 4 }Led_TypeDef; extern uint16_t Select_DelayT ; extern uint16_t Select_Dir ;
/*******************************
本模块提供给外部调用的函数
*********************************/
void LED_Prc(void);
void BUZ_Prc(void);
#endif
-
在 key.h 中,定义几个宏定义:
//在 key.h 中,定义几个宏定义
#ifndef __KEY_H__ 定义指示灯序号的数据类型,使用枚举类型
实现,包括 LED1——LED4 四个枚举常量,用来
表示四个 LED 灯 避免头文件的重复包含 提供给外部使用的函数声明
蜂鸣器控制函数
存放的都是 LED 灯
控制引脚
#define __KEY_H__
#include "main.h" typedef enum { KEY1 = 0, KEY2 = 1, KEY3 = 2, KEY4 = 3 }Key_TypeDef;
extern uint16_t buzDs ;#define READ_KEY1 (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin))
#define READ_KEY2 (!HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin))
#define READ_KEY3 (!HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin))
#define READ_KEY4 (!HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin))
void KEY_Prc(void);
#endif
-
在 key.c 中编写按键扫描和按键处理的代码
//在 key.c 中编写按键扫描和按键处理的代码
uint8_t keyScan(void) { static uint8_t pressed =0; static uint8_t keyCnt = 0; uint8_t key_num = 0; if(( READ_KEY1 || READ_KEY2 || READ_KEY3 || READ_KEY4) && (pressed ==1)) { if(keyCnt < 5) keyCnt++; else { if(READ_KEY1) { pressed =0; key_num = 1; } else if(READ_KEY2)
{ pressed =0; key_num = 2; } else if(READ_KEY3) { pressed =0; key_num = 3; } else if(READ_KEY4) { pressed =0; key_num = 4; } } } if( !READ_KEY1 && !READ_KEY2 && !READ_KEY3 && !READ_KEY4 &&(pressed == 0)) { pressed =1; keyCnt = 0; } return key_num; }
void KEY_Prc(void) { uint8_t key_val = 0; key_val = keyScan(); if(key_val != 0) buzDs = 10; switch(key_val) { case 1: Select_Dir ^= 1; break; case 2:
Select_DelayT = 10; break; case 3: Select_DelayT = 50; break;
case 4: Select_DelayT = 100; default: break; } }
-
值得注意的是:必须在.c文件中加入对应的.h文件。
-
最后,在<main.c>中加入
uint32_t startTimeTick = 0; uint32_t endTimeTick = 0;
- 至此,在keil中的代码文件都相继完成了。
三、在Proteus中配置模拟环境
- 接下来,就需要配置模拟环境了。这里就需要用到:
-
其对应的图片是:
- 最后就能跑起来了。纵观整个过程,其最难的部分就是keil写代码的部分了。