编写代码实现使用TIM1和TIM3分别输出250Hz和300Hz的矩形波,用TIM2测量矩形波的周期和脉冲宽度; 矩形脉冲占空比可通过B2按钮调节,调节范围0-90%,调节步长10%,并用LCD显示调节占空比情况。
时间: 2024-04-07 20:32:24 浏览: 13
以下是基于STM32 HAL库编写的代码实现:
```c
#include "stm32f4xx_hal.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
LCD_HandleTypeDef hlcd;
uint16_t duty_cycle = 50; // 默认占空比50%
char lcd_buffer[16]; // LCD显示缓存
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_TIM1_Init(void);
void MX_TIM2_Init(void);
void MX_TIM3_Init(void);
void MX_LCD_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_LCD_Init();
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // 启动TIM1通道1 PWM输出
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // 启动TIM3通道1 PWM输出
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // 启动TIM2通道1输入捕获中断
while (1)
{
// 读取B2按钮状态,调节占空比
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
duty_cycle += 10;
if (duty_cycle > 90) duty_cycle = 90;
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (duty_cycle / 100.0) * htim1.Init.Period);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, (duty_cycle / 100.0) * htim3.Init.Period);
}
// 更新LCD显示
sprintf(lcd_buffer, "Duty Cycle:%d%%", duty_cycle);
HAL_LCD_Clear(&hlcd);
HAL_LCD_WriteString(&hlcd, lcd_buffer);
HAL_Delay(50);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// B2按键输入
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// LED输出
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void MX_TIM1_Init(void)
{
TIM_OC_InitTypeDef sConfigOC = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 95;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 63999;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 31999;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
}
void MX_TIM2_Init(void)
{
TIM_IC_InitTypeDef sConfigIC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 95;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 63999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 15;
if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
}
void MX_TIM3_Init(void)
{
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 79;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 42666;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 21333;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
}
void MX_LCD_Init(void)
{
hlcd.Instance = LCD;
hlcd.Init.Prescaler = LCD_PRESCALER_16;
hlcd.Init.Divider = LCD_DIVIDER_31;
hlcd.Init.Duty = LCD_DUTY_1_4;
hlcd.Init.Bias = LCD_BIAS_1_3;
hlcd.Init.VoltageSource = LCD_VOLTAGESOURCE_INTERNAL;
hlcd.Init.Contrast = LCD_CONTRASTLEVEL_3;
hlcd.Init.DeadTime = LCD_DEADTIME_0;
hlcd.Init.PulseOnDuration = LCD_PULSEONDURATION_2;
hlcd.Init.MuxSegment = LCD_MUXSEGMENT_ENABLE;
if (HAL_LCD_Init(&hlcd) != HAL_OK)
{
Error_Handler();
}
HAL_LCD_Clear(&hlcd);
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim == &htim2)
{
uint32_t pulse_width = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);
uint32_t period = __HAL_TIM_GET_AUTORELOAD(htim) + 1;
float duty_cycle = (float)pulse_width / period * 100.0;
sprintf(lcd_buffer, "Pulse Width:%dus", pulse_width);
HAL_LCD_WriteString(&hlcd, lcd_buffer);
sprintf(lcd_buffer, "Period:%dus", period);
HAL_LCD_WriteString(&hlcd, lcd_buffer);
sprintf(lcd_buffer, "Duty Cycle:%.2f%%", duty_cycle);
HAL_LCD_WriteString(&hlcd, lcd_buffer);
}
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
```
注释详细,主要实现了以下功能:
1. 初始化TIM1和TIM3为PWM输出,分别输出250Hz和300Hz的矩形波;
2. 初始化TIM2为输入捕获模式,并启动输入捕获中断;
3. 通过B2按钮调节占空比,更新TIM1和TIM3的PWM输出;
4. 在输入捕获中断中测量矩形波的周期、脉冲宽度和占空比,并在LCD上显示。