STM32H750通过stm32cubemx使用keil生成工程用来测量正弦波的频率和峰峰值,并输出到串口屏中,给出代码
时间: 2023-12-03 09:45:50 浏览: 211
以下是使用STM32CubeMX和Keil编写的代码,可以测量正弦波的频率和峰峰值,并输出到串口屏幕中。
首先,我们需要在STM32CubeMX中配置外设和时钟。假设我们使用的是PA0引脚来输入正弦波信号,PA9和PA10引脚来作为串口1的TX和RX引脚。
1. 在Pinout & Configuration选项卡中,将PA0设置为GPIO输入模式。
2. 在Configuration选项卡中,启用USART1,并将其配置为115200波特率,8位数据位,无校验位和1个停止位。
3. 在Clock Configuration选项卡中,将系统时钟设置为480MHz。
接下来,在Keil中创建一个新的STM32CubeMX工程,并将生成的代码导入到工程中。然后,我们可以开始编写代码了。
首先,我们需要定义一些全局变量来存储正弦波的状态和测量结果:
```c
#define SAMPLE_SIZE 2048 // 采样点数
uint32_t adc_buf[SAMPLE_SIZE]; // 用于存储ADC采样结果
float adc_voltage[SAMPLE_SIZE]; // 用于存储ADC采样电压值
// 正弦波状态
struct sin_wave {
uint8_t index;
float freq;
float peak;
} sin;
// 测量结果
struct result {
float freq;
float peak;
} res;
```
然后,我们需要编写一些函数来初始化ADC和串口,并启动ADC转换:
```c
void init_adc() {
// 启用ADC时钟和GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_ADC3_CLK_ENABLE();
// 配置PA0为模拟输入
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置ADC
ADC_HandleTypeDef hadc3 = {0};
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc3.Init.Resolution = ADC_RESOLUTION_12B;
hadc3.Init.ScanConvMode = DISABLE;
hadc3.Init.ContinuousConvMode = ENABLE;
hadc3.Init.DiscontinuousConvMode = DISABLE;
hadc3.Init.NbrOfDiscConversion = 0;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.NbrOfConversion = 1;
hadc3.Init.DMAContinuousRequests = DISABLE;
hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc3);
// 配置ADC通道
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(&hadc3, &sConfig);
// 启动ADC转换
HAL_ADC_Start(&hadc3);
}
void init_uart() {
// 启用USART和GPIO时钟
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置PA9和PA10为USART1的TX和RX引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置USART
USART_HandleTypeDef huart1 = {0};
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
}
void start_conversion() {
HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_buf, SAMPLE_SIZE);
}
```
接下来,我们需要编写一个函数来计算正弦波的频率和峰峰值:
```c
void calc_sin_wave() {
// 计算峰峰值
float max = -INFINITY;
float min = INFINITY;
for (int i = 0; i < SAMPLE_SIZE; i++) {
float voltage = adc_voltage[i];
if (voltage > max) {
max = voltage;
}
if (voltage < min) {
min = voltage;
}
}
sin.peak = max - min;
// 计算频率
float delta = 0;
int index = 0;
for (int i = 0; i < SAMPLE_SIZE; i++) {
float voltage = adc_voltage[i];
if (voltage > 0 && adc_voltage[i-1] < 0) {
delta = i - index;
index = i;
break;
}
}
sin.freq = 1.0 / (delta * (1.0 / 480000));
}
```
最后,我们需要编写一个主函数来循环读取ADC转换结果,并周期性地输出测量结果到串口屏幕:
```c
int main(void) {
HAL_Init();
init_adc();
init_uart();
start_conversion();
// 初始化正弦波状态
sin.index = 0;
sin.freq = 50;
sin.peak = 0;
// 主循环
while (1) {
// 计算ADC采样电压
for (int i = 0; i < SAMPLE_SIZE; i++) {
adc_voltage[i] = adc_buf[i] * 3.3 / 4096;
}
// 计算正弦波状态
calc_sin_wave();
// 输出测量结果到串口屏幕
if (sin.index == 0) {
res.freq = sin.freq;
res.peak = sin.peak;
char buffer[64];
sprintf(buffer, "Freq: %.2f Hz, Peak: %.2f V\n", res.freq, res.peak);
HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), 1000);
}
// 更新正弦波状态
sin.index++;
if (sin.index >= SAMPLE_SIZE) {
sin.index = 0;
}
// 延时一段时间,以降低CPU负载
HAL_Delay(10);
}
}
```
这样,我们就完成了使用STM32H750测量正弦波的频率和峰峰值,并输出到串口屏幕的代码。
阅读全文