用stm32cube写stm32f103zet6带8个灯的流水灯,使用外部中断4个按钮分别控制开始,暂停,加速,减速主函数具体代码
时间: 2024-02-11 09:08:21 浏览: 79
stm32单片机的按键中断控制流水灯最简程序.doc
5星 · 资源好评率100%
好的,下面是一个完整的代码示例,可以实现您所需的功能:
```c
#include "stm32f1xx_hal.h"
#define LED_NUM 8
GPIO_TypeDef* LED_GPIO_PORT[LED_NUM] = {GPIOA, GPIOA, GPIOA, GPIOA, GPIOB, GPIOB, GPIOB, GPIOB};
const uint16_t LED_GPIO_PIN[LED_NUM] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_10, GPIO_PIN_11};
uint8_t led_state[LED_NUM] = {0}; // 记录每个灯的状态,0 表示灭,1 表示亮
int main(void)
{
// 初始化 HAL 库
HAL_Init();
// 初始化时钟,使用 HSI 时钟源
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
// 初始化时钟,设置系统时钟为 HSI
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
// 初始化 GPIO 端口,将所有 LED 置为输出模式
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
for (int i = 0; i < LED_NUM; i++) {
GPIO_InitStruct.Pin = LED_GPIO_PIN[i];
HAL_GPIO_Init(LED_GPIO_PORT[i], &GPIO_InitStruct);
}
// 初始化外部中断,使用 PA0、PA1、PA2、PA3 四个引脚
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 将外部中断的优先级设置为最高
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
// 使能外部中断
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
// 初始化定时器 TIM2,用于定时更新 LED 的亮灭状态
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999; // 1ms 定时器中断
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
// 将定时器 TIM2 的中断优先级设置为最低
HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
// 等待开始信号
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET);
// 开始流水灯
HAL_TIM_Base_Start_IT(&htim2);
while (1)
{
// TODO: 可以在这里添加一些其他的处理逻辑
}
}
// 暂停流水灯
void pause_led() {
HAL_TIM_Base_Stop_IT(&htim2); // 停止定时器更新 LED 的亮灭状态
}
// 恢复流水灯
void resume_led() {
HAL_TIM_Base_Start_IT(&htim2); // 开始定时器更新 LED 的亮灭状态
}
// 加速流水灯
void speed_up_led() {
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
uint32_t new_period = htim2.Init.Period * 0.8; // 将定时器周期缩短 20%
if (new_period < 10) {
new_period = 10; // 限制最小周期为 10
}
htim2.Init.Period = new_period;
HAL_TIM_Base_Init(&htim2);
}
// 减速流水灯
void speed_down_led() {
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
uint32_t new_period = htim2.Init.Period * 1.2; // 将定时器周期增加 20%
if (new_period > 2000) {
new_period = 2000; // 限制最大周期为 2000
}
htim2.Init.Period = new_period;
HAL_TIM_Base_Init(&htim2);
}
// 处理外部中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch (GPIO_Pin) {
case GPIO_PIN_0:
// 开始流水灯
HAL_TIM_Base_Start_IT(&htim2);
break;
case GPIO_PIN_1:
// 暂停流水灯
pause_led();
break;
case GPIO_PIN_2:
// 加速流水灯
speed_up_led();
break;
case GPIO_PIN_3:
// 减速流水灯
speed_down_led();
break;
default:
break;
}
}
// 定时器中断处理
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2) {
// 更新 LED 的亮灭状态
for (int i = 0; i < LED_NUM; i++) {
if (led_state[i] == 0) {
// 灭 -> 亮
led_state[i] = 1;
HAL_GPIO_WritePin(LED_GPIO_PORT[i], LED_GPIO_PIN[i], GPIO_PIN_SET);
} else {
// 亮 -> 灭
led_state[i] = 0;
HAL_GPIO_WritePin(LED_GPIO_PORT[i], LED_GPIO_PIN[i], GPIO_PIN_RESET);
}
}
}
}
```
在上面的代码中,我们使用了定时器 TIM2 来定时更新 LED 的亮灭状态。具体来说,定时器的周期为 1ms,每次定时器中断被触发时,我们遍历所有的 LED,将其状态取反。这样可以模拟出流水灯的效果。
在外部中断处理函数中,我们根据不同的引脚号来执行不同的操作,比如开始流水灯、暂停流水灯、加速流水灯、减速流水灯等。这些操作都可以通过调整定时器的周期来实现。
祝顺利!
阅读全文