STM32控制第七个个灯的设置为pwm,实现由亮转暗,再有暗变亮,前六个为流水灯和跑马灯,使用按键控制这两种状态存在哪一个,第八个灯为定时器控制,亮一秒停两秒,再亮一秒停两秒,如此往复,提示:定时器里面不能添加延时
时间: 2025-03-11 08:24:17 浏览: 67
### STM32 控制 8 个 LED 灯的效果实现
#### 配置说明
为了实现所描述的功能,需要利用STM32的GPIO接口来控制LED灯,并使用定时器和PWM功能。具体来说:
- 使用TIM1通道作为PWM输出用于第7个LED灯的亮度渐变。
- 前6个LED灯通过GPIO端口直接控制,以实现流水灯和跑马灯效果。
- 第8个LED灯则由另一个独立的定时器(如TIM2)控制其亮一秒停两秒的工作模式。
对于上述需求中的PWM调光部分,可以设置不同的占空比来改变灯光强度[^1];而对于不需要复杂时序控制的普通LED,则可以直接连接至MCU的I/O引脚上并编程设定高低电平即可达到开关目的[^2]。
针对按键切换不同显示模式的需求,可以通过外部中断服务程序捕捉按钮按下事件从而触发相应的动作转换逻辑处理流程。
以下是具体的代码示例及配置方法:
#### 初始化外设资源
```c
// 定义使用的 GPIO 和 TIM 外设编号
#define LED_PORT GPIOA
#define LED_PIN_1 GPIO_PIN_0
#define LED_PIN_2 GPIO_PIN_1
#define LED_PIN_3 GPIO_PIN_2
#define LED_PIN_4 GPIO_PIN_3
#define LED_PIN_5 GPIO_PIN_4
#define LED_PIN_6 GPIO_PIN_5
#define LED_PWM GPIO_PIN_6 // PWM 输出管脚
#define LED_TIM GPIO_PIN_7 // 定时器控制管脚
void MX_GPIO_Init(void){
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_PORT, LED_PIN_1|LED_PIN_2|LED_PIN_3|
LED_PIN_4|LED_PIN_5|LED_PIN_6,
GPIO_PIN_RESET);
/*Configure GPIO pins : PA0 PA1 PA2 PA3 PA4 PA5 */
GPIO_InitStruct.Pin = LED_PIN_1 | LED_PIN_2 | LED_PIN_3 |
LED_PIN_4 | LED_PIN_5 | LED_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* 配置PWM输出 */
static void MX_TIM1_Init(void)
{
__HAL_RCC_TIM1_CLK_ENABLE();
TIM_HandleTypeDef htim1;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 8399; // 设置预分频值使得计数频率为1kHz
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 999; // 自动重装载寄存器ARR=999对应周期Tout=1ms
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; // 初始脉冲宽度为零
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
}
```
#### 主循环与定时器回调函数
```c
volatile uint8_t mode_flag = 0; // 当前工作模式标志位
volatile int duty_cycle = 0; // 调节PWM占空比变量
uint8_t led_pattern[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20}; // 流水灯序列数组
void SystemClock_Config(void); // 系统时钟初始化声明
extern void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
int main(void)
{
HAL_Init(); // 初始化HAL库
SystemClock_Config(); // 配置系统时钟
MX_GPIO_Init(); // 初始化GPIO
MX_TIM1_Init(); // 初始化PWM用定时器
MX_TIM2_Init(); // 初始化通用定时器
while (1)
{
switch(mode_flag){
case 0: // 执行流水灯效果
for(int i=0;i<sizeof(led_pattern)/sizeof(uint8_t);i++){
HAL_GPIO_WritePort(LED_PORT, ~((~0)&(~led_pattern[i])));
HAL_Delay(200);
}
break;
case 1: // 运行跑马灯效果
static unsigned char shift_reg = 0x01;
HAL_GPIO_WritePort(LED_PORT, ~(shift_reg));
shift_reg <<= 1;
if(shift_reg==0){shift_reg=0x01;}
HAL_Delay(200);
break;
default:
break;
}
// 更新PWM占空比
if(duty_cycle >= 100 || duty_cycle <= 0){
direction *= -1; // 反转方向
}
duty_cycle +=direction*step_size; // 修改占空比例
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,duty_cycle*(htim1.Init.Period/100)); // 设定比较值CRR
}
}
/**
* @brief This function handles TIM2 global interrupt.
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2){
static uint8_t state = 0;
if(state++ % 3 == 0){
HAL_GPIO_TogglePin(LED_PORT, LED_TIM); // 每三次翻转一次第八盏LED的状态
}else{
HAL_GPIO_WritePin(LED_PORT, LED_TIM, RESET); // 否则保持关闭状态
}
}
}
```
此段代码实现了对八个LED灯的不同控制策略,包括但不限于PWM调光、流水灯以及跑马灯效果,并且能够响应按键输入来进行模式间的快速切换操作。值得注意的是,在实际应用过程中还需要考虑如何优化这些算法以便更好地适应特定的应用场景。
阅读全文
相关推荐
















