使用stm32f103c8芯片,创建基于HAL库的工程,编写程序,实现测量两个同频方波的相位差,并将测得的结果通过三个共阳数码管显示出来,并且每秒钟更新一次,并且要求当相位差小于3或大于97时,通过蜂鸣器发出警报,并且要求蜂鸣器发出的声音有明显区别,给出具体的程序以及必要的注释
时间: 2024-05-08 16:21:57 浏览: 101
以下是基于HAL库的STM32F103C8工程代码,用于实现测量两个同频方波的相位差,并将测得的结果通过三个共阳数码管显示出来,并且每秒钟更新一次,并且当相位差小于3或大于97时,通过蜂鸣器发出警报,并且蜂鸣器发出的声音有明显区别。
注:本示例代码使用PA0和PA1作为输入引脚,使用PB0-PB7作为三个共阳数码管的控制引脚,使用PC13作为蜂鸣器控制引脚。
```
#include "stm32f1xx_hal.h"
/* 定义数码管显示数字的段码 */
#define NUM_0 0x3f
#define NUM_1 0x06
#define NUM_2 0x5b
#define NUM_3 0x4f
#define NUM_4 0x66
#define NUM_5 0x6d
#define NUM_6 0x7d
#define NUM_7 0x07
#define NUM_8 0x7f
#define NUM_9 0x6f
/* 声明函数原型 */
void SystemClock_Config(void);
void GPIO_Init(void);
void TIM2_Init(void);
void TIM3_Init(void);
void TIM4_Init(void);
void Buzzer_Init(void);
void Display_Result(uint8_t num1, uint8_t num2, uint8_t num3);
void Delay_ms(uint16_t ms);
/* 定义全局变量 */
volatile uint32_t counter1 = 0; // 计数器1
volatile uint32_t counter2 = 0; // 计数器2
volatile uint8_t flag = 0; // 标志位,用于判断是否需要更新显示
volatile uint8_t buzzer_flag = 0; // 蜂鸣器标志位,用于控制蜂鸣器发声
int main(void)
{
/* 初始化HAL库 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
/* 初始化GPIO */
GPIO_Init();
/* 初始化定时器 */
TIM2_Init();
TIM3_Init();
TIM4_Init();
/* 初始化蜂鸣器 */
Buzzer_Init();
/* 无限循环 */
while (1)
{
/* 如果标志位为1,更新显示 */
if (flag)
{
flag = 0;
uint32_t phase_diff = (counter2 - counter1) * 100 / counter2;
uint8_t num1 = phase_diff / 100;
uint8_t num2 = (phase_diff % 100) / 10;
uint8_t num3 = phase_diff % 10;
Display_Result(num1, num2, num3);
/* 如果相位差小于3或大于97,控制蜂鸣器发声 */
if (phase_diff < 3 || phase_diff > 97)
{
if (buzzer_flag)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
buzzer_flag = 0;
}
else
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
buzzer_flag = 1;
}
}
else
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
buzzer_flag = 0;
}
}
}
}
/* 系统时钟配置 */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/**配置内部时钟源
*/
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_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**配置系统时钟,APB1/APB2时钟源,AHB 时钟源
*/
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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* GPIO初始化 */
void GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 使能GPIOA、GPIOB、GPIOC时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/* 配置PA0和PA1为输入引脚 */
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* 配置PB0-PB7为输出引脚 */
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.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* 配置PC13为输出引脚 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/* 定时器2初始化 */
void TIM2_Init(void)
{
TIM_HandleTypeDef htim2 = {0};
/* 使能TIM2时钟 */
__HAL_RCC_TIM2_CLK_ENABLE();
/* 配置TIM2参数 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xFFFFFFFF;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
/* 初始化TIM2 */
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
/* 启动TIM2 */
if (HAL_TIM_Base_Start(&htim2) != HAL_OK)
{
Error_Handler();
}
}
/* 定时器3初始化 */
void TIM3_Init(void)
{
TIM_HandleTypeDef htim3 = {0};
/* 使能TIM3时钟 */
__HAL_RCC_TIM3_CLK_ENABLE();
/* 配置TIM3参数 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 0xFFFFFFFF;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
/* 初始化TIM3 */
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
/* 启动TIM3 */
if (HAL_TIM_Base_Start(&htim3) != HAL_OK)
{
Error_Handler();
}
}
/* 定时器4初始化 */
void TIM4_Init(void)
{
TIM_HandleTypeDef htim4 = {0};
/* 使能TIM4时钟 */
__HAL_RCC_TIM4_CLK_ENABLE();
/* 配置TIM4参数 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 7199;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 999;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
/* 初始化TIM4 */
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
/* 启动TIM4 */
if (HAL_TIM_Base_Start_IT(&htim4) != HAL_OK)
{
Error_Handler();
}
}
/* 蜂鸣器初始化 */
void Buzzer_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 配置PC13为输出引脚 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* 设置初始状态为关闭 */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
}
/* 显示结果 */
void Display_Result(uint8_t num1, uint8_t num2, uint8_t num3)
{
static uint8_t digit = 0; // 当前显示的数码管位数
static uint8_t num_count = 0; // 当前显示的数字计数器
static uint8_t num1_code = 0; // 数字1的段码
static uint8_t num2_code = 0; // 数字2的段码
static uint8_t num3_code = 0; // 数字3的段码
/* 根据数字获取段码 */
switch (num1)
{
case 0:
num1_code = NUM_0;
break;
case 1:
num1_code = NUM_1;
break;
case 2:
num1_code = NUM_2;
break;
case 3:
num1_code = NUM_3;
break;
case 4:
num1_code = NUM_4;
break;
case 5:
num1_code = NUM_5;
break;
case 6:
num1_code = NUM_6;
break;
case 7:
num1_code = NUM_7;
break;
case 8:
num1_code = NUM_8;
break;
case 9:
num1_code = NUM_9;
break;
}
switch (num2)
{
case 0:
num2_code = NUM_0;
break;
case 1:
num2_code = NUM_1;
break;
case 2:
num2_code = NUM_2;
break;
case 3:
num2_code = NUM_3;
break;
case 4:
num2_code = NUM_4;
break;
case 5:
num2_code = NUM_5;
break;
case 6:
num2_code = NUM_6;
break;
case 7:
num2_code = NUM_7;
break;
case 8:
num2_code = NUM_8;
break;
case 9:
num2_code = NUM_9;
break;
}
switch (num3)
{
case 0:
num3_code = NUM_0;
break;
case 1:
num3_code = NUM_1;
break;
case 2:
num3_code = NUM_2;
break;
case 3:
num3_code = NUM_3;
break;
case 4:
num3_code = NUM_4;
break;
case 5:
num3_code = NUM_5;
break;
case 6:
num3_code = NUM_6;
break;
case 7:
num3_code = NUM_7;
break;
case 8:
num3_code = NUM_8;
break;
case 9:
num3_code = NUM_9;
break;
}
/* 根据位数选择要显示的数码管 */
switch (digit)
{
case 0:
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, num1_code & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, (num1_code >> 1) & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, (num1_code >> 2) & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, (num1_code >> 3) & 0x01);
break;
case 1:
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, num2_code & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, (num2_code >> 1) & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, (num2_code >> 2) & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, (num2_code >> 3) & 0x01);
break;
case 2:
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, num3_code & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, (num3_code >> 1) & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, (num3_code >> 2) & 0x01);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, (num3_code >> 3) & 0x01);
break;
}
/* 数码管位数加1 */
digit++;
if (digit > 2)
{
digit = 0;
}
/* 数字计数器加1 */
num_count++;
if (num_count > 99)
{
num_count = 0;
}
}
/* 延时函数 */
void Delay_ms(uint16_t ms)
{
HAL_Delay(ms);
}
/* 定时器4中断处理函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* 如果是TIM4溢出中断,更新标志位 */
if (htim->Instance == TIM4)
{
flag = 1;
counter1 = TIM2->CNT;
counter2 = TIM3->CNT;
TIM2->CNT = 0;
TIM3->CNT = 0;
}
}
/* 错误处理函数 */
void Error_Handler(void)
{
while (1)
{
}
}
```
阅读全文