stm32如何实现定时器跑马灯越来越快
时间: 2024-12-29 22:18:32 浏览: 11
### STM32定时器实现逐渐加速的跑马灯效果
为了实现在STM32上通过定时器创建一个逐渐加速的跑马灯效果,可以基于状态机的概念来设计程序逻辑。此过程涉及配置定时器以生成周期性的中断,在这些中断事件中更新当前的状态并调整下一个LED亮起的时间间隔。
#### 配置定时器用于产生固定频率的中断
首先初始化一个定时器,设置其自动重装载寄存器(ARR)为某个初始值,该值决定了定时器溢出前计数的最大次数,进而影响到产生的中断频率。随着程序运行过程中逐步减小这个值,则可达到提高触发频率的目的,即实现了“加速”的视觉感受。
```c
// 初始化TIM2作为系统节拍源
void TIM2_Init(void){
__HAL_RCC_TIM2_CLK_ENABLE(); // 使能定时器2时钟
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = SystemCoreClock / 1000000 - 1; // 设置预分频系数使得定时单位为微秒级
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = INITIAL_PERIOD_US - 1; // 初始周期设定较长
HAL_TIM_Base_Init(&htim2);
}
```
#### 使用状态机管理不同阶段的行为模式
定义一组枚举类型表示各个可能的状态,并编写相应的处理函数完成特定的任务转换:
```c
typedef enum {
STATE_INIT,
STATE_RUNNING_FORWARD,
STATE_ACCELERATING,
} StateTypeDef;
StateTypeDef currentState = STATE_INIT;
uint8_t ledIndex = 0;
const uint8_t LED_PINS[] = {GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7, GPIO_PIN_8}; // 假设有四个LED连接至PA5~PA8引脚
volatile bool timerEventFlag = false;
void UpdateLedStatus(uint8_t index) {
for (int i=0;i<4;i++) {
if(i==index)
HAL_GPIO_WritePin(GPIOA, LED_PINS[i], GPIO_PIN_SET); // 打开指定编号的LED
else
HAL_GPIO_WritePin(GPIOA, LED_PINS[i], GPIO_PIN_RESET); // 关闭其他所有LED
}
}
void HandleStateMachine() {
switch(currentState) {
case STATE_INIT:
UpdateLedStatus(ledIndex++);
if(timerEventFlag && ++currentState == STATE_RUNNING_FORWARD) ResetTimerPeriod(INITIAL_PERIOD_US * ACCEL_RATE);
break;
case STATE_RUNNING_FORWARD:
if(timerEventFlag) {
UpdateLedStatus((++ledIndex)%4);
if(++accelCounter >= MAX_ACCEL_STEPS){ // 达到最大步数则停止加速
accelCounter = 0;
currentState++;
}else{
AdjustAcceleration();
}
timerEventFlag = false;
}
break;
default:
; // 可扩展更多状态...
}
}
```
其中`AdjustAcceleration()`负责按照预定规律减少定时器周期长度,以此模拟速度增加的过程;而当满足一定条件后会切换进入新的行为模式。
#### 动态调节定时器参数达成渐变效果
每当需要改变运动节奏的时候调用下面的方法重新加载定时器的自动重载值:
```c
#define ACCEL_RATE 0.9f // 每一步减速比例因子
static float currentRate = 1.f;
static int initialPeriodUs = INITIAL_PERIOD_US;
void AdjustAcceleration(){
currentRate *= ACCEL_RATE;
SetNewPeriod(initialPeriodUs * currentRate);
}
void SetNewPeriod(int new_period_us){
__HAL_TIM_SET_AUTORELOAD(&htim2, new_period_us-1);
__HAL_TIM_GENERATE_EVENT(&htim2,TIM_EGR_UG); // 更新请求
}
```
以上代码片段展示了如何利用STM32硬件资源配合简单的算法技巧创造出具有动态变化特性的灯光序列[^1]。
阅读全文