用ALIENTEK STM32F1战舰V3 开发板,芯片型号是stm32F103ZET,用库函数的开发方式编写代码实现频率计设计,编程软件是Keil5。利用外部中断和TIM2定时器实现通过按键调整输出PWM占空比信号,并通过LED灯的亮度表现出来。初始状态占空比是0,按下key0占空比变为25%,按下key1占空比变为50%,按下key2占空比变为75%。
时间: 2023-12-12 20:04:04 浏览: 70
好的,以下是基本的流程和代码实现:
1. 配置TIM2定时器为计数模式,设置预分频器为72-1,这样就可以让TIM2的计数频率为1MHz,方便后续计算占空比。
```c
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能TIM2时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_Period = 0xFFFF; // 自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler = 71; // 预分频器
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分割
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_Cmd(TIM2, ENABLE); // 使能TIM2
```
2. 配置外部中断,使得按键按下时会触发中断。在中断服务函数中,根据按下的按键设置PWM输出占空比。
```c
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能AFIO时钟
// 配置按键对应的GPIO口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
// 配置中断触发方式为下降沿触发
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1 | EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 配置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn | EXTI1_IRQn | EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断服务函数
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
// key0按下,占空比25%
PWM_DutyCycle = 25000;
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line1) != RESET) {
// key1按下,占空比50%
PWM_DutyCycle = 50000;
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void EXTI2_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line2) != RESET) {
// key2按下,占空比75%
PWM_DutyCycle = 75000;
EXTI_ClearITPendingBit(EXTI_Line2);
}
}
```
3. 在主函数中循环读取TIM2的计数器值,根据设定的PWM周期和占空比计算出当前输出的PWM信号,通过LED灯亮度表现出来。
```c
// PWM周期为1000us
const uint32_t PWM_Period = 1000;
// 初始占空比为0
uint32_t PWM_DutyCycle = 0;
while (1) {
// 读取TIM2计数器值
uint32_t cnt = TIM_GetCounter(TIM2);
// 计算PWM信号值
uint32_t pwm_val = cnt < PWM_DutyCycle ? 1 : 0;
// 输出PWM信号
GPIO_WriteBit(GPIOB, GPIO_Pin_0, pwm_val);
// 延时1us,保证PWM信号周期为1ms
Delay_us(1);
}
```
完整的代码实现如下:
阅读全文