西安饮食 2024-03-08 17:31 采纳率: 0%
浏览 42

STM32H743DAC_DMA双通道输出100k方波

参照安富莱的H743的DAC.c和.h程序,结合野火103的DAC的,main程序,写了一个STM32H753II的DAC,TIM6触发DMA双通道采集100KHZ的程序,示波器采不到波形是什么情况呢,能改成安富莱的我都改了。包括堆栈和一些设置。怎么办才能采集到波形
DAC.C文件

#if defined ( __ICCARM__ )
#pragma location = ".RAM_D3"  
ALIGN_32BYTES(uint16_t g_usWaveBuff[64]);
#elif defined ( __CC_ARM )
ALIGN_32BYTES(__attribute__((section (".RAM_D3"))) uint16_t g_usWaveBuff[64]);
#endif

static    TIM_HandleTypeDef          htim;
static    DAC_HandleTypeDef        DacHandle;
static    DAC_ChannelConfTypeDef  sConfig;
static    DMA_HandleTypeDef          hdma_dac1;
static    DMA_HandleTypeDef          hdma_dac2;

/**
  * @brief  使能DAC的时钟,初始化GPIO
  * @param  无
  * @retval 无
  */
static void DAC_Config(void)
{
    GPIO_InitTypeDef    GPIO_InitStruct;
    
    //使能时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_DAC12_CLK_ENABLE();
    __HAL_RCC_DMA1_CLK_ENABLE();

    //DAC的GPIO配置,模拟输入
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    //初始化DAC外设
    DacHandle.Instance = DAC1;
    
    HAL_DAC_DeInit(&DacHandle);
    
    HAL_DAC_Init(&DacHandle);
    
    //配置DAC 通道
    sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;            //关闭采样保持模式,这个模式主要用于低功耗
    sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;                        //采用定时器6触发
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;                //使能输出缓冲
    sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;    //不将DAC连接到片上外设
    sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;                //使用出厂校准

    HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_1);
    
    HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_2);
    
        //配置DMA1
    hdma_dac1.Instance = DMA1_Stream0;                                //使用的DAM1 Stream0
    hdma_dac1.Init.Request  = DMA_REQUEST_DAC1;                        //DAC触发DMA传输
    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;    //外设数据以半字为单位
    hdma_dac1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;        //内存数据以半字为单位    
    hdma_dac1.Init.Mode = DMA_CIRCULAR;                                //循环模式
    hdma_dac1.Init.Priority = DMA_PRIORITY_HIGH;                    //高DMA通道优先级

    HAL_DMA_Init(&hdma_dac1);
    
    __HAL_LINKDMA(&DacHandle, DMA_Handle1, hdma_dac1);
    
    HAL_DAC_Start_DMA(&DacHandle, DAC_CHANNEL_1, (uint32_t *)g_usWaveBuff, 64, DAC_ALIGN_12B_R);
    
    //配置DMA2
    hdma_dac2.Instance = DMA1_Stream1;                                //使用的DAM1 Stream0
    hdma_dac2.Init.Request  = DMA_REQUEST_DAC2;                        //DAC触发DMA传输
    hdma_dac2.Init.Direction = DMA_MEMORY_TO_PERIPH;                //数据传输方向内存至外设
    hdma_dac2.Init.PeriphInc = DMA_PINC_DISABLE;                    //外设数据地址固定
    hdma_dac2.Init.MemInc = DMA_MINC_ENABLE;                        //内存数据地址自增
    hdma_dac2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;    //外设数据以半字为单位
    hdma_dac2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;        //内存数据以半字为单位    
    hdma_dac2.Init.Mode = DMA_CIRCULAR;                                //循环模式
    hdma_dac2.Init.Priority = DMA_PRIORITY_HIGH;                    //高DMA通道优先级

    HAL_DMA_Init(&hdma_dac2);
    
    __HAL_LINKDMA(&DacHandle, DMA_Handle1, hdma_dac2);
    
    HAL_DAC_Start_DMA(&DacHandle, DAC_CHANNEL_2, (uint32_t *)g_usWaveBuff, 64, DAC_ALIGN_12B_R);
}

/**
  * @brief  TIM6 Configuration
  * @note   TIM6 configuration is based on APB1 frequency
  * @note   TIM6 Update event occurs each TIM6CLK/256
  * @param  None
  * @retval None
  */
void DAC_TIM_Config(void)
{
        /*-----------------------------------------------------------------------
        void SystemClock_Config(void) 函数对时钟的配置如下: 

        System Clock source       = PLL (HSE)
        SYSCLK(Hz)                = 400000000 (CPU Clock)
        HCLK(Hz)                  = 200000000 (AXI and AHBs Clock)
        AHB Prescaler             = 2
        D1 APB3 Prescaler         = 2 (APB3 Clock  100MHz)
        D2 APB1 Prescaler         = 2 (APB1 Clock  100MHz)
        D2 APB2 Prescaler         = 2 (APB2 Clock  100MHz)
        D3 APB4 Prescaler         = 2 (APB4 Clock  100MHz)

        因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = APB1 x 2 = 200MHz;
        因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = APB2 x 2 = 200MHz;
        APB4上面的TIMxCLK没有分频,所以就是100MHz;

        APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14,LPTIM1
        APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17

        APB4 定时器有 LPTIM2,LPTIM3,LPTIM4,LPTIM5
    
    TIM6 更新周期是 = TIM6CLK / (Period + 1)/(Prescaler + 1)
    根据如下的配置,更新周期是:
    TIM6CLK /(Period + 1)/(Prescaler + 1)
    = 200MHz /(30+1)/(0+1)
    ≈ 6.45MHz
    ----------------------------------------------------------------------- */
    
    TIM_MasterConfigTypeDef sMasterConfig;

    __HAL_RCC_TIM6_CLK_ENABLE();

    //TIM6基本定时器配置
    htim.Instance = TIM6;

    htim.Init.Period            = 30;                                //定时周期 
    htim.Init.Prescaler         = 0;                                //预分频,不分频 400M / (0+1) = 400M
    htim.Init.ClockDivision     = 0;                                //时钟分频系数
    htim.Init.CounterMode       = TIM_COUNTERMODE_UP;                //向上计数模式
    htim.Init.RepetitionCounter = 0;
    HAL_TIM_Base_Init(&htim);

    //TIM6 TRGO selection
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

    HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig);

    //使能TIM
    HAL_TIM_Base_Start(&htim);
}

/**
  * @brief  DAC初始化函数
  * @param  无
  * @retval 无
  */
void DAC_Mode_Init(void)
{
    uint8_t i;

    //一个周期的方波
    for(i =0; i < 32; i++)
    {
        g_usWaveBuff[i] = 0;
    }
    
    for(i =0; i < 32; i++)
    {
        g_usWaveBuff[i+32] = 4095;
    }
    
    DAC_Config();    
    
    DAC_TIM_Config();
}

main.c文件

int main(void)
{
    MPU_Config();            //配置MPU
    
    CPU_CACHE_Enable();        //使能L1 Cache
    
    HAL_Init();

    SystemClock_Config();    //系统时钟初始化成400MHz

    LED_GPIO_Config();
    
    UARTx_Config();            //配置串口1为:115200 8-N-1

        DAC_Mode_Init();

    while(1)
    {
        
    }    
}

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-08 17:32
    关注

    引自免费微信小程序:皆我百晓生

    针对您提供的问题,STM32H753II无法通过示波器采集到DAC通过DMA双通道输出的100kHz方波,这里有几个可能的原因和相应的解决方案:

    1. 定时器配置不正确

      • 您在DAC_TIM_Config()函数中设置了TIM6的预分频为0且周期为30,这会导致TIM6的更新频率远超过100kHz。根据您的时钟配置(APB1 100MHz),TIM6的更新频率应接近6.45MHz而不是100kHz。
      • 要生成100kHz的触发信号,请重新计算并设置TIM6的预分频和周期值,例如,若要得到100kHz的更新频率,可以尝试以下配置:
        htim.Init.Period            = (100000 / SystemCoreClock) - 1; // 计算得出周期值,假设SystemCoreClock为200MHz
        htim.Init.Prescaler         = (SystemCoreClock / 100000) - 1; // 计算得出预分频值
        
    2. DAC采样率与定时器触发频率不匹配

      • 确保DMA传输速率能跟上定时器触发的频率,即一个TIM6更新事件发生时,DAC能够接收到新的数据。由于您配置了DMA循环模式,所以缓冲区大小也需要考虑进去。
      • 根据您当前的代码,每个通道使用同一个64元素的缓冲区,这意味着每秒内需要完成至少100k * 64次的数据更新才能维持100kHz的方波输出。检查一下这个速率是否超过了DMA和DAC的最大工作速率。
    3. DAC配置或DMA传输错误

      • 检查两个DMA流(DMA1_Stream0 和 DMA1_Stream1)是否都被正确地关联到了DAC通道,并确保它们同时启动而不会互相干扰。
      • DAC_Mode_Init()函数中,似乎对两个DMA流都使用了相同的句柄__HAL_LINKDMA(&DacHandle, DMA_Handle1, hdma_dac1);__HAL_LINKDMA(&DacHandle, DMA_Handle1, hdma_dac2);,这可能是错误的,应该分别链接到对应的DMA通道。对于DAC通道2,应当是__HAL_LINKDMA(&DacHandle, DMA_Handle2, hdma_dac2);(假设存在DMA_Handle2这样的成员)。
    4. 硬件连接问题

      • 确认示波器探头已经正确连接到DAC输出引脚(GPIOA Pin 4 和 Pin 5),并且示波器的设置(如带宽、衰减、触发源等)也适合观测100kHz的方波。
    5. 波形数据填充问题

      • 检查波形数据数组g_usWaveBuff中的内容是否正确表示了期望的方波形状。根据您给出的代码片段,它填充的是一个占空比为50%的方波,但没有详细说明这个方波的频率是否是100kHz。

    综上所述,请首先调整TIM6的配置以产生准确的100kHz触发信号,并核实DMA以及DAC的相关配置。此外,请仔细检查硬件连接及示波器设置,并确保波形数据符合预期。如有必要,请修改上述提到的错误点。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 3月8日

悬赏问题

  • ¥15 esp32驱动GC9A01循环播放视频
  • ¥15 惠普360g9的最新bios
  • ¥15 配置hadoop时start-all.sh老是启动失败
  • ¥30 这个功能用什么软件发合适?
  • ¥60 微信小程序,取消订单,偶尔订单没有改变状态
  • ¥15 用pytorch实现PPO算法
  • ¥15 关于调制信号的星座图?
  • ¥30 前端传参时,后端接收不到参数
  • ¥15 这是有什么问题吗,我检查许可证了但是显示有呢
  • ¥15 机器学习预测遇到的目标函数问题