stm32f103c8t6最小系统板pwm采用TIM1输出俩路呼吸灯使用标准库
时间: 2025-05-25 14:06:51 浏览: 33
### 实现 STM32F103C8T6 的 TIM1 两路 PWM 输出以制作呼吸灯效果
为了实现基于 STM32F103C8T6 使用 TIM1 定时器的标准库来生成两路 PWM 输出并完成呼吸灯效果,以下是详细的解决方案。
#### 硬件说明
STM32F103C8T6 是一款基于 ARM Cortex-M3 内核的微控制器。其 TIM1 定时器是一个高级控制定时器,支持多通道 PWM 输出模式。在此场景下,可以利用 TIM1 的两个通道(如 CH1 和 CH2)分别驱动两颗 LED 来实现呼吸灯效果[^1]。
---
#### 编程实现
##### 1. **硬件相关宏定义**
在程序中需要先定义 GPIO 及 TIM1 的相关参数:
```c
#define LED_PIN_1 GPIO_Pin_8 // PA8 对应 TIM1_CH1
#define LED_PIN_2 GPIO_Pin_9 // PA9 对应 TIM1_CH2
#define LED_GPIO_PORT GPIOA // TIM1 的 CH1/CH2 都位于 GPIOA 上
```
上述代码片段指定了用于输出 PWM 波形的具体引脚以及对应的端口。
---
##### 2. **GPIO 初始化**
初始化 GPIO 引脚以便它们能够作为 TIM1 的 PWM 输出通道工作:
```c
void GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE);
// 配置 PA8 (TIM1_CH1) 和 PA9 (TIM1_CH2) 为复用推挽输出
GPIO_InitStructure.GPIO_Pin = LED_PIN_1 | LED_PIN_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置速度为 50 MHz
GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
}
```
此部分完成了对 GPIO 的设置,使其适配于 TIM1 的 PWM 功能需求。
---
##### 3. **定义 PWM 表**
创建一个数组存储不同占空比下的亮度变化数据,模拟呼吸灯的效果曲线:
```c
uint16_t pwm_table[] = {0, 10, 20, ..., 100}; // 假设这是一个线性递增再递减的数据序列
const uint16_t table_size = sizeof(pwm_table)/sizeof(uint16_t); // 记录表格大小
volatile uint16_t current_index = 0; // 当前索引位置
```
该 `pwm_table` 数组中的数值代表了不同的占空比百分比,从而形成平滑过渡的呼吸灯效果[^2]。
---
##### 4. **定时器 PWM 配置**
配置 TIM1 工作在 PWM 模式,并设定频率和初始占空比:
```c
void TIM1_PWM_Configuration(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// 配置基本时间基底结构体
TIM_TimeBaseStructure.TIM_Period = 999; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 预分频系数,假设系统时钟为 72 MHz,则最终频率约为 1 kHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// 配置通道 1 和通道 2 的 PWM 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure); // 初始化 TIM1 Channel 1
TIM_OC2Init(TIM1, &TIM_OCInitStructure); // 初始化 TIM1 Channel 2
TIM_Cmd(TIM1, ENABLE); // 启用 TIM1
}
```
以上代码设置了 TIM1 的计数方向、预分频器以及自动重载寄存器等关键参数,同时启用了两个通道的工作状态。
---
##### 5. **更新 PWM 占空比**
通过中断或其他方式动态调整当前显示的占空比,使灯光呈现渐变效果:
```c
void Update_DutyCycle(void) {
static int direction = 1; // 控制递增还是递减的方向标志位
if ((current_index >= table_size - 1 && direction == 1) ||
(current_index <= 0 && direction == -1)) {
direction *= -1; // 到达边界则反转方向
}
current_index += direction; // 更新到下一个索引
// 将新的占空比应用至 TIM1 的两个通道上
TIM_SetCompare1(TIM1, pwm_table[current_index]); // 应用于 CH1
TIM_SetCompare2(TIM1, pwm_table[current_index]); // 应用于 CH2
}
```
这段逻辑实现了根据预先设计好的 `pwm_table` 数据逐步改变实际点亮程度的功能。
---
##### 6. **主循环调用**
最后,在主函数或者特定事件触发的地方不断刷新占空比即可达到理想中的呼吸灯视觉体验:
```c
int main(void) {
GPIO_Configuration();
TIM1_PWM_Configuration();
while(1){
Update_DutyCycle(); // 不断更新占空比
Delay_ms(20); // 添加适当延时让眼睛能感知变化过程
}
}
// 示例延迟函数
void Delay_ms(uint32_t ms) {
volatile uint32_t i,j;
for(i=ms;i>0;i--){
j=1000;
while(j--);
}
}
```
整个流程至此结束,成功构建了一个双路独立可调节亮度的呼吸灯控制系统。
---
###
阅读全文
相关推荐


















