硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1135|回复: 6
收起左侧

定时器触发DAC输出正弦波少输出一个点

[复制链接]

5

主题

20

回帖

35

积分

新手上路

积分
35
发表于 2021-12-10 09:14:43 | 显示全部楼层 |阅读模式
求助大神,使用定时器+DMA+DAC输出一个正弦波,因为每次只需要输出一个波形,DMA为Normal模式,在DMA完成中断后就停止定时器,下一次使用时再启动DAC DMA和定时器,如此循环。
问题是经常最后一个点没有输出,怀疑是定时器触发时,先将DHR现有的数据传递至DOR转换输出,然后DMA将正弦波数组从内存再搬运至DHR?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107477
QQ
发表于 2021-12-10 09:51:23 | 显示全部楼层
经常没输出的话。简单省事些,就DMA缓冲多输出1个点。
回复

使用道具 举报

5

主题

20

回帖

35

积分

新手上路

积分
35
 楼主| 发表于 2021-12-10 10:18:23 | 显示全部楼层
eric2013 发表于 2021-12-10 09:51
经常没输出的话。简单省事些,就DMA缓冲多输出1个点。

现在就是这样妥协处理的,这算是STM32 DAC的一个缺陷么
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107477
QQ
发表于 2021-12-10 10:48:48 | 显示全部楼层
分享你的配置代码看下,如果方便的话。
回复

使用道具 举报

5

主题

20

回帖

35

积分

新手上路

积分
35
 楼主| 发表于 2021-12-10 11:15:03 | 显示全部楼层
eric2013 发表于 2021-12-10 10:48
分享你的配置代码看下,如果方便的话。

//配置DAC
void bsp_InitDAC1(void)
{       
        /* 配置DAC, 定时器6触发,使用用DMA */       
        DAC_ChannelConfTypeDef sConfig = {0};
       
        hdac.Instance = DACx;

        HAL_DAC_DeInit(&hdac);
       
          /*##-1- Initialize the DAC peripheral ######################################*/
        if (HAL_DAC_Init(&hdac) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }

        /*##-1- DAC channel OUT1 config #########################################*/
        sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
        sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
        sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
        sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;
        sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
       
        if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DACx_CHANNEL) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
}

void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        if(dacHandle->Instance == DACx)
        {
                /*##-1- 使能时钟 #################################*/               
                /* 使能DAC外设时钟 */
            DACx_CLK_ENABLE();         
                /* 使能GPIO时钟 */
            DACx_CHANNEL_GPIO_CLK_ENABLE();
                /* 使能DMA时钟 */
                DMAx_CLK_ENABLE();
               
                /*##-2- 配置GPIO ##########################################*/
                /* DAC Channel1 GPIO 配置 */
                GPIO_InitStruct.Pin = DACx_CHANNEL_PIN;
                GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
                GPIO_InitStruct.Pull = GPIO_NOPULL;
                HAL_GPIO_Init(DACx_CHANNEL_GPIO_PORT, &GPIO_InitStruct);
               
                /*##-3- 配置DMA ##########################################*/
                /* DAC1 DMA Init */
                hdma_dac1.Instance = DACx_DMA_INSTANCE;
                hdma_dac1.Init.Request = DMA_REQUEST_5;
                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_NORMAL;//DMA_CIRCULAR
                hdma_dac1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
                if (HAL_DMA_Init(&hdma_dac1) != HAL_OK)
                {
                        Error_Handler(__FILE__, __LINE__);
                }
               
                __HAL_LINKDMA(dacHandle,DMA_Handle2,hdma_dac1);
        
                /* DAC interrupt Init */
                HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0, 0);  
                HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);

                /* DMA1_Stream5_IRQn interrupt configuration */
                HAL_NVIC_SetPriority(DACx_DMA_IRQn, 0, 0);
                HAL_NVIC_EnableIRQ(DACx_DMA_IRQn);
        }
}

//配置定时器
void TIM6_Config(uint32_t uiFreq)
{       
        TIM_MasterConfigTypeDef sMasterConfig;

        /*##-1- Configure the TIM peripheral #######################################*/
        /* Time base configuration */
        htim6.Instance = TIM6;

        htim6.Init.Period            = SystemCoreClock / uiFreq - 1;
        htim6.Init.Prescaler         = 0;        //时钟源APB1 80MHz 1分频(0 + 1)
        htim6.Init.CounterMode       = TIM_COUNTERMODE_UP;
        htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
        HAL_TIM_Base_Init(&htim6);

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

        if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
}


//启动一个波形的DAC输出
void DAC1_StartTimerAndDMA(uint8_t ch)
{
      HAL_DAC_Start_DMA(&hdac, DACx_CHANNEL, (uint32_t *)g_SineWave12bit,
      SIN_WAVE_TOTAL_DOT, DAC_ALIGN_12B_R);//启动DAC DMA
      HAL_TIM_Base_Start(&htim6); //启动定时器
}

//DAC DMA传输完成中断回调处理
void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef *hdac)
{
        HAL_TIM_Base_Stop(&htim6);  //停止定时器计数
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107477
QQ
发表于 2021-12-10 11:35:41 | 显示全部楼层
rnjack 发表于 2021-12-10 11:15
//配置DAC
void bsp_InitDAC1(void)
{       

1、定时器,DAC和DMA初始化里面都分别做个DeInit处理。完成回调里面直接关闭定时器时钟就行。
2、 TIM_MasterConfigTypeDef sMasterConfig = {0}


回复

使用道具 举报

5

主题

20

回帖

35

积分

新手上路

积分
35
 楼主| 发表于 2021-12-10 14:52:31 | 显示全部楼层
eric2013 发表于 2021-12-10 11:35
1、定时器,DAC和DMA初始化里面都分别做个DeInit处理。完成回调里面直接关闭定时器时钟就行。
2、 TIM_M ...

没什么效果,只有多发一个点的方式处理,看这个说明就是先将DHR传递到DOR输出,再产生DMA请求,机制就如此
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-6-3 10:05 , Processed in 0.301226 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表