stm32通过hal库实现dac输出正弦波

在 STM32 微控制器中,通过 HAL 库可以使用 DAC 输出正弦波信号。实现的步骤包括以下几个部分:

  1. DAC 初始化:配置 DAC 外设。
  2. DMA 初始化:将正弦波数据通过 DMA 传输给 DAC,实现连续的输出。
  3. 定时器初始化:配置定时器触发 DAC,以设定输出信号的频率。
  4. 正弦波表生成:生成一个正弦波查找表,用于输出模拟信号。

以下是通过 HAL 库实现 DAC 输出正弦波的详细步骤:

1. 正弦波数据生成

首先,我们需要生成一个正弦波查找表。假设使用 12 位分辨率 DAC,DAC 的输出范围是 0 到 4095。

#define SINE_RES 128  // 正弦波数据点数
uint32_t sine_wave[SINE_RES];

void generate_sine_wave(void)
{
    for (int i = 0; i < SINE_RES; i++) {
        // 生成从 0 到 4095 的正弦波
        sine_wave[i] = (uint32_t)((sin(i * 2 * M_PI / SINE_RES) + 1) * 2047.5);
    }
}

2. DAC 配置与初始化

使用 DAC1 的通道 1 (PA4),配置 DAC 和 DMA 以便通过 DMA 传输正弦波数据给 DAC。

DAC_HandleTypeDef hdac;
DMA_HandleTypeDef hdma_dac1;

void dac_init(void)
{
    // 启用 DAC 和 GPIOA 时钟
    __HAL_RCC_DAC1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    // 配置 DAC GPIO:PA4 = DAC_OUT1
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 配置 DAC
    hdac.Instance = DAC1;
    HAL_DAC_Init(&hdac);
    
    // 配置 DAC 通道1
    DAC_ChannelConfTypeDef sConfig = {0};
    sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;  // 使用定时器触发
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; // 输出缓冲使能
    HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1);
    
    // 启用 DAC1 通道1
    HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
}

3. DMA 配置与初始化

配置 DMA,用于将正弦波表的数据传输到 DAC 外设。

void dma_init(void)
{
    __HAL_RCC_DMA1_CLK_ENABLE();  // 启用 DMA1 时钟
    
    // 配置 DMA
    hdma_dac1.Instance = DMA1_Channel1;
    hdma_dac1.Init.Direction = DMA_MEMORY_TO_PERIPH;  // 内存到外设传输
    hdma_dac1.Init.PeriphInc = DMA_PINC_DISABLE;      // 外设地址不增量
    hdma_dac1.Init.MemInc = DMA_MINC_ENABLE;          // 内存地址增量
    hdma_dac1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  // 外设数据对齐为16位
    hdma_dac1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     // 内存数据对齐为16位
    hdma_dac1.Init.Mode = DMA_CIRCULAR;               // 循环模式
    hdma_dac1.Init.Priority = DMA_PRIORITY_LOW;

    // 初始化 DMA 并链接到 DAC
    HAL_DMA_Init(&hdma_dac1);
    __HAL_LINKDMA(&hdac, DMA_Handle1, hdma_dac1);

    // 启动 DAC 通道1 的 DMA
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sine_wave, SINE_RES, DAC_ALIGN_12B_R);
}

4. 定时器配置

定时器用于设定 DAC 的更新速率,控制 DAC 的输出频率。

TIM_HandleTypeDef htim6;

void tim6_init(void)
{
    __HAL_RCC_TIM6_CLK_ENABLE();  // 启用 TIM6 时钟
    
    // 配置 TIM6 以产生触发输出
    htim6.Instance = TIM6;
    htim6.Init.Prescaler = 80 - 1;  // 根据系统时钟,假设系统时钟为 80MHz
    htim6.Init.Period = 1000 - 1;   // 定时器周期设定,控制 DAC 更新频率
    htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
    HAL_TIM_Base_Init(&htim6);

    // 配置 TIM6 的触发输出 TRGO
    HAL_TIM_Base_Start(&htim6);
    
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;  // 定时器更新事件触发
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig);
}

5. 主函数

初始化 DAC、DMA、定时器,并输出正弦波信号。

int main(void)
{
    HAL_Init();  // 初始化 HAL 库
    SystemClock_Config();  // 配置系统时钟
    
    generate_sine_wave();  // 生成正弦波查找表
    dac_init();            // 初始化 DAC
    dma_init();            // 初始化 DMA
    tim6_init();           // 初始化 TIM6,定时触发 DAC
    
    while (1) {
        // 主循环
    }
}

6. 结果

通过定时器触发 DAC 更新,DAC 会输出通过 DMA 传输的正弦波数据,从而在 DAC 通道上输出连续的正弦波信号。

调整正弦波频率

正弦波的输出频率由定时器的频率控制,通过调整 TIM6PrescalerPeriod,你可以改变 DAC 的更新频率,从而控制正弦波的输出频率。

例如,频率计算公式为:

作者:wys99999

物联沃分享整理
物联沃-IOTWORD物联网 » stm32通过hal库实现dac输出正弦波

发表回复