一. 了解并掌握HAL库函数开发方法。安装 stm32CubeMX,配合Keil,使用HAL库方式完成下列任务:
1、一个LED流水灯作业,用GPIO端口完成2只LED灯的周期闪烁。
-- 使用HAL库函数开发LED流水灯
-- 导入HAL库
local gpio = require("hal.gpio")
-- 定义LED引脚
local LED_PIN_1 = gpio.Pin.GPIO_PIN_1
local LED_PIN_2 = gpio.Pin.GPIO_PIN_2
-- 初始化LED引脚
gpio.initPin(LED_PIN_1, gpio.Mode.OUTPUT)
gpio.initPin(LED_PIN_2, gpio.Mode.OUTPUT)
-- 定义LED流水灯函数
local function runLEDs()
while true do
-- 依次点亮LED
gpio.writePin(LED_PIN_1, gpio.State.HIGH)
gpio.writePin(LED_PIN_2, gpio.State.LOW)
-- 等待一段时间
tmr.delay(1000000) -- 延时1秒
-- 切换LED状态
gpio.writePin(LED_PIN_1, gpio.State.LOW)
gpio.writePin(LED_PIN_2, gpio.State.HIGH)
-- 等待一段时间
tmr.delay(1000000) -- 延时1秒
end
end
-- 启动LED流水灯
runLEDs()
2、接上,再用GPIO端某一管脚接2个开关(用杜邦线模拟代替)。采用中断模式编程,当2分开关接高电平时,
对应的两个LED灯停止工作(即停止周期性闪烁),接低电平时,恢复工作。(参考教材图6-12)
#include "stm32f4xx_hal.h"
// 定义LED灯的GPIO引脚
#define LED1_PIN GPIO_PIN_0
#define LED2_PIN GPIO_PIN_1
#define LED_PORT GPIOA
// 定义开关的GPIO引脚
#define SWITCH1_PIN GPIO_PIN_2
#define SWITCH2_PIN GPIO_PIN_3
#define SWITCH_PORT GPIOB
// LED状态标志
volatile uint8_t led1_state = 1; // LED1默认为开启状态
volatile uint8_t led2_state = 1; // LED2默认为开启状态
// 中断处理函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == SWITCH1_PIN) {
// 检查开关1的状态
if (HAL_GPIO_ReadPin(SWITCH_PORT, SWITCH1_PIN) == GPIO_PIN_SET) {
led1_state = 0; // 关闭LED1
} else {
led1_state = 1; // 打开LED1
}
} else if (GPIO_Pin == SWITCH2_PIN) {
// 检查开关2的状态
if (HAL_GPIO_ReadPin(SWITCH_PORT, SWITCH2_PIN) == GPIO_PIN_SET) {
led2_state = 0; // 关闭LED2
} else {
led2_state = 1; // 打开LED2
}
}
}
// 主函数
int main(void)
{
// 初始化HAL库
HAL_Init();
// 配置LED引脚为输出模式
HAL_GPIO_WritePin(LED_PORT, LED1_PIN | LED2_PIN, GPIO_PIN_RESET);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LED1_PIN | LED2_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
// 配置开关引脚为输入模式,并启用中断
GPIO_InitStruct.Pin = SWITCH1_PIN | SWITCH2_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(SWITCH_PORT, &GPIO_InitStruct);
// 启用外部中断线0和1
HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
// 循环执行任务
while (1)
{
// 控制LED的闪烁
if (led1_state) {
HAL_GPIO_TogglePin(LED_PORT, LED1_PIN);
} else {
HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET);
}
if (led2_state) {
HAL_GPIO_TogglePin(LED_PORT, LED2_PIN);
} else {
HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET);
}
HAL_Delay(500); // 延时500ms
}
}
// 开关1的外部中断处理函数
void EXTI2_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(SWITCH1_PIN);
}
// 开关2的外部中断处理函数
void EXTI3_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(SWITCH2_PIN);
}
二. 在没有示波器条件下,使用Keil的软件仿真逻辑分析仪功能观察LED管脚的时序波形
设置仿真配置。配置正确的目标设备,并启用了仿真选项。
通过添加监视窗口来监视LED管脚的状态变化。