PWM捕获值能获取到(CCR1:999 CCR2:199)
但最终显示结果没有数值
导致问题的原因:
浮点数计算可能存在精度问题
printf格式化字符串与数据类型不匹配
单位换算计算复杂化了问题
解决方案
数据获取:
简化计算:
移除复杂的浮点运算
使用整数运算代替浮点运算
直接使用计数值作为微秒值
格式化输出:
使用%lu替代%.1f
直接输出原始计数值
技术要点
时钟配置:
系统时钟:HSI/8 = 8MHz
定时器预分频:8
最终定时器时钟:1MHz(1计数 = 1微秒)
硬件设置:
TIM3:生成PWM(Period=999, Pulse=200)
TIM1:输入捕获模式
通道1上升沿触发,通道2下降沿触发
调试技巧:
添加全局调试变量
使用超时机制避免死循环
串口打印原始值进行验证
这次的解决过程很好地展示了:有时候简单直接的方法比复杂的计算更可靠。通过去除不必要的浮点运算和单位转换,我们成功实现了稳定的PWM测量功能。
修改后的代码
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
// HAL_UART_Transmit(&huart1, (const uint8_t *)"你好世界", 12, HAL_MAX_DELAY);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
__HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);
// 启动输入捕获
HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
// 等待第一次捕获,添加超时检测
uint32_t timeoutStart = HAL_GetTick();
while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0)
{
if(HAL_GetTick() - timeoutStart > 1000)
{
UART_Printf("Capture timeout!\r\n");
goto capture_end;
}
}
__HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);
// 等待第二次捕获
timeoutStart = HAL_GetTick();
while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0)
{
if(HAL_GetTick() - timeoutStart > 1000)
{
UART_Printf("Capture timeout!\r\n");
goto capture_end;
}
}
// 停止捕获
HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_1);
HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_2);
// 使用正确的函数获取捕获值
uint32_t ccr1 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);
uint32_t ccr2 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2);
debug_ccr1 = ccr1;
debug_ccr2 = ccr2;
// 直接使用整数计算以避免浮点数问题
uint32_t duty = (ccr2 * 100) / ccr1; // 先乘100再除以总数,避免浮点数
UART_Printf("CCR1:%lu CCR2:%lu 脉宽:%lu us 周期:%lu us 占空比:%lu%%\r\n",
ccr1, ccr2,
ccr2, // 直接使用整数值
ccr1, // 直接使用整数值
duty); // 直接使用整数值
capture_end:
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
修改前的代码
#include
#include
#include
static void UART_Printf(const char *format, ...)
{
char tmp[128];
va_list argptr;
va_start(argptr, format);
vsprintf((char* )tmp, format, argptr);
va_end(argptr);
HAL_UART_Transmit(&huart1, (const uint8_t *)&tmp, strlen(tmp), HAL_MAX_DELAY);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
// HAL_UART_Transmit(&huart1, (const uint8_t *)"你好世界", 12, HAL_MAX_DELAY);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//1
__HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);
//2
HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
//3
while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0);
__HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);
//4
while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0);
//5
HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_1);
HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_2);
//6
uint16_t ccr1 = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_1);
uint16_t ccr2 = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_2);
float period = ccr1*1e-6f;
float pluseWidth = ccr2*1e-6f;
float duty = pluseWidth/period;
UART_Printf("脉宽: %.1f us, 周期: %.1f us, 占空比: %.1f%%\r\n", period*1e6f, pluseWidth*1e6f, duty*100.0f);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}