STM32G431RBT6产生正弦波
时间: 2025-06-25 12:27:06 浏览: 11
### STM32G431RBT6生成正弦波的方法
#### 正弦波生成概述
STM32G431RBT6是一款基于ARM Cortex-M4内核的微控制器,具有丰富的外设资源,其中包括定时器和DAC模块。这些功能可以用来生成正弦波信号。具体来说,可以通过PWM或者DAC两种方式来实现。
---
#### 使用PWM生成正弦波
##### 配置步骤说明
利用STM32的高级控制定时器(TIMx),配合DMA传输数据到比较寄存器,从而生成SPWM(Sinusoidal Pulse Width Modulation)。这种方法的核心在于构建一个正弦表并将其映射为占空比变化序列[^2]。
以下是主要配置要点:
- **定时器设置**:选择一个高级定时器(如TIM1或TIM8),配置其工作模式为PWM输出。
- **正弦表创建**:预先计算一组代表正弦曲线的数据点,并存储在一个数组中。
- **DMA传输**:将正弦表中的数值通过DMA发送至定时器的捕获/比较寄存器,动态调整PWM脉宽。
##### 示例代码
以下是一个简单的示例程序,展示如何使用TIM1生成SPWM:
```c
#include "stm32g4xx_hal.h"
// 定义正弦表参数
#define SIN_TABLE_SIZE 100 // 表长度
uint16_t sine_table[SIN_TABLE_SIZE];
void TIM1_Init(void) {
__HAL_RCC_TIM1_CLK_ENABLE(); // 启用TIM1时钟
TIM_HandleTypeDef htim;
htim.Instance = TIM1;
// 初始化结构体
htim.Init.Prescaler = 83; // 设置预分频系数 (f_clk / Prescaler - 1)
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = 999; // 自由运行计数周期
HAL_TIM_PWM_Init(&htim); // 初始化为PWM模式
// 配置通道1作为PWM输出
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; // 初始占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1);
}
void Generate_Sine_Table(void) {
float amplitude = 500.0; // 波幅范围 [0, Period]
for(int i=0;i<SIN_TABLE_SIZE;i++) {
sine_table[i] = (int)(amplitude * sin(2*M_PI*i/SIN_TABLE_SIZE)) + 500;
}
}
int main(void) {
HAL_Init();
TIM1_Init();
Generate_Sine_Table();
DMA_HandleTypeDef hdma_tim1_ch1;
hdma_tim1_ch1.Init.Request = DMA_REQUEST_MEMTOMEM;
hdma_tim1_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim1_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim1_ch1.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim1_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_tim1_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_tim1_ch1.Channel = DMA_CHANNEL_7;
HAL_DMA_Init(&hdma_tim1_ch1);
__HAL_LINKDMA(TIM1, hdmar, hdma_tim1_ch1);
HAL_TIMEx_StartPWM(&htim, TIM_CHANNEL_1, sine_table, SIN_TABLE_SIZE);
while (1) {}
}
```
上述代码实现了通过DMA循环加载正弦表的方式生成SPWM信号。
---
#### 使用DAC生成正弦波
##### 配置步骤说明
另一种方法是借助STM32内置的DAC模块直接输出模拟电压信号。这种方式更加直观,适合需要高质量正弦波的应用场景。同样需要先准备一张正弦查找表,然后依次更新DAC输出值。
##### 示例代码
下面展示了如何使用DAC生成正弦波:
```c
#include "stm32g4xx_hal.h"
// 定义正弦表参数
#define SIN_TABLE_SIZE 100 // 表长度
uint16_t sine_table[SIN_TABLE_SIZE];
void DAC_Init(void) {
__HAL_RCC_DAC1_CLK_ENABLE(); // 启用DAC时钟
DAC_ChannelConfTypeDef sConfig;
sConfig.DAC_Trigger = DAC_TRIGGER_Timers; // 触发源来自定时器
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
HAL_DAC_Init(&hdac1);
HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1);
}
void Generate_Sine_Table(void) {
float amplitude = 3276.0; // 基于12-bit分辨率的最大值
for(int i=0;i<SIN_TABLE_SIZE;i++) {
sine_table[i] = (int)(amplitude * sin(2*M_PI*i/SIN_TABLE_SIZE));
}
}
int main(void) {
HAL_Init();
DAC_Init();
Generate_Sine_Table();
TIM_HandleTypeDef htim;
htim.Instance = TIM2;
htim.Init.Prescaler = 83;
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = SIN_TABLE_SIZE - 1;
HAL_TIM_Base_Init(&htim);
uint32_t index = 0;
HAL_TIM_Base_Start_IT(&htim);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if(htim->Instance == TIM2){
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sine_table[index]);
index++;
if(index >= SIN_TABLE_SIZE)index = 0;
}
}
while (1) {}
}
```
此代码片段演示了通过定时器触发DAC转换的过程,最终形成连续的正弦波输出[^3]。
---
#### 总结
无论是采用PWM还是DAC方案,都需要提前准备好正弦表以便实时更新输出值。对于低失真度的要求较高的场合推荐选用后者;而对于成本敏感型项目则优先考虑前者。
阅读全文
相关推荐


















