野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 16865|回复: 6

DAC输出正弦波,ADC独立单通道DMA读取精度问题

[复制链接]
发表于 2020-8-18 02:33:20 | 显示全部楼层 |阅读模式
开发板是挑战者F429IGT6,调试关于DAC输出正弦波精度的问题。
我把例程库里面的DAC双通道改成了单通道输出,输出有波形,可是感觉偏差有点大,我就把里面的数组的32个数据全部改成4000,输出值浮动在0.1V,我拿ADC程序测试3.3V接口的时候输出浮动在0.01V,我想问问这个精度问题何什么有关系。
这是DAC的C文件

  1. #include "./dac/bsp_dac.h"


  2. /* 波形数据 ---------------------------------------------------------*/
  3. const uint16_t Sine12bit[32] = {4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,
  4.                                                                                                                                 4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000,4000
  5. //        2048        , 2460        , 2856        , 3218        , 3532        , 3786        , 3969        , 4072        ,
  6. //        4093        , 4031        , 3887        , 3668        , 3382        , 3042        ,        2661        , 2255        ,
  7. //        1841        , 1435        , 1054        , 714                , 428                , 209                , 65                , 3                        ,
  8. //        24                , 127                , 310                , 564                , 878                , 1240        , 1636        , 2048

  9. };
  10. /*0x0800, 0x099c, 0x0b28, 0x0c92, 0x0dcc, 0x0eca, 0x0f81, 0x0fe8,
  11.         0x0ffd, 0x0fbf, 0x0f2f, 0x0e54, 0x0d36, 0x0be2, 0x0a65, 0x08cf,
  12.         0x0731, 0x059b, 0x041e, 0x02ca, 0x01ac, 0x00d1, 0x0041, 0x0003,
  13.         0x0018, 0x007f, 0x0136, 0x0234, 0x036e, 0x04d8, 0x0664, 0x0800,
  14. */
  15. uint16_t DualSine12bit[32];


  16. /**
  17.   * [url=home.php?mod=space&uid=41770]@brief[/url]  使能DAC的时钟,初始化GPIO
  18.   * @param  无
  19.   * @retval 无
  20.   */
  21. static void DAC_Config(void)
  22. {
  23.   GPIO_InitTypeDef GPIO_InitStructure;
  24.         DAC_InitTypeDef  DAC_InitStructure;

  25.   /* 使能GPIOA时钟 */
  26.   RCC_AHB1PeriphClockCmd(DAC_CH1_GPIO_CLK, ENABLE);       
  27.        
  28.         /* 使能DAC时钟 */       
  29.   RCC_APB1PeriphClockCmd(DAC_CLK, ENABLE);
  30.   
  31.   /* DAC的GPIO配置,模拟输入 */
  32.   GPIO_InitStructure.GPIO_Pin =  DAC_CH1_GPIO_PIN;
  33.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  34.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  35.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
  36.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  37.   GPIO_Init(DAC_CH1_GPIO_PORT, &GPIO_InitStructure);
  38.        
  39. //  GPIO_InitStructure.GPIO_Pin =  DAC_CH2_GPIO_PIN;
  40. //  GPIO_Init(DAC_CH2_GPIO_PORT, &GPIO_InitStructure);
  41.        
  42.                   /* 配置DAC 通道1 */
  43.   DAC_InitStructure.DAC_Trigger = DAC_TRIGGER;                                                //使用TIM2作为触发源
  44.   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;        //不使用波形发生器
  45.   DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;        //不使用DAC输出缓冲
  46.         //三角波振幅(本实验没有用到,可配置成任意值,但本结构体成员不能为空)
  47.         DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
  48.   DAC_Init(DAC_CH1_CHANNEL, &DAC_InitStructure);

  49.   /* 配置DAC 通道2 */
  50. //  DAC_Init(DAC_CH2_CHANNEL, &DAC_InitStructure);
  51.   
  52.         /* 配置DAC 通道1、2 */
  53.   DAC_Cmd(DAC_Channel_1, ENABLE);
  54. //  DAC_Cmd(DAC_Channel_2, ENABLE);
  55.        
  56.         /* 使能 DAC的DMA请求 */
  57.   DAC_DMACmd(DAC_Channel_1, ENABLE);
  58. //        DAC_DMACmd(DAC_Channel_2, ENABLE);

  59. }


  60. /**
  61.   * @brief  配置TIM
  62.   * @param  无
  63.   * @retval 无
  64.   */
  65. static void DAC_TIM_Config(void)
  66. {
  67.        
  68.         TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
  69.        
  70.         /* 使能TIM2时钟,TIM2CLK 为180M */
  71.   RCC_APB1PeriphClockCmd(DAC_TIM_CLK, ENABLE);
  72.        
  73.   /* TIM2基本定时器配置 */
  74. // TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  75.   TIM_TimeBaseStructure.TIM_Period = 19;                                                                               //定时周期 20  
  76.   TIM_TimeBaseStructure.TIM_Prescaler = 0x0;                                                               //预分频,不分频 180M / (0+1) = 180M
  77.   TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;                                                                //时钟分频系数
  78.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;          //向上计数模式
  79.   TIM_TimeBaseInit(DAC_TIM, &TIM_TimeBaseStructure);

  80.   /* 配置TIM2触发源 */
  81.   TIM_SelectOutputTrigger(DAC_TIM, TIM_TRGOSource_Update);

  82.         /* 使能TIM2 */
  83.   TIM_Cmd(DAC_TIM, ENABLE);

  84. }

  85. /**
  86.   * @brief  配置DMA
  87.   * @param  无
  88.   * @retval 无
  89.   */
  90. static void DAC_DMA_Config(void)
  91. {       
  92.         DMA_InitTypeDef  DMA_InitStructure;

  93.         /* DAC1使用DMA1 通道7 数据流5时钟 */
  94.         RCC_AHB1PeriphClockCmd(DAC_DMA_CLK, ENABLE);
  95.        
  96.         /* 配置DMA2 */
  97.   DMA_InitStructure.DMA_Channel = DAC_CHANNEL;  
  98.   DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R1_Address;                                                        //外设数据地址
  99.   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&DualSine12bit ;                                        //内存数据地址 DualSine12bit
  100.   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                                                                        //数据传输方向内存至外设
  101.   DMA_InitStructure.DMA_BufferSize = 32;                                                                                                                                                        //缓存大小为32字节       
  102.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                                //外设数据地址固定       
  103.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                                                                        //内存数据地址自增
  104.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;        //外设数据以字为单位
  105.   DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;                        //内存数据以字为单位       
  106.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                                                                                                        //循环模式
  107.   DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                                                                                        //高DMA通道优先级
  108.   DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                                                                 //FIFO模式不使用
  109.   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;                                                                //不适用FIFO,所以随便配
  110.   DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                                                                        //存储器单次突发模式
  111.   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;                                        //外设单次突发模式

  112.   DMA_Init(DAC_DMA_STREAM, &DMA_InitStructure);
  113.   
  114.   /* 使能 DMA_Stream */
  115.   DMA_Cmd(DAC_DMA_STREAM, ENABLE);
  116.   

  117. }




  118. /**
  119.   * @brief  DAC初始化函数
  120.   * @param  无
  121.   * @retval 无
  122.   */
  123. void DAC_Mode_Init(void)
  124. {
  125.         uint32_t Idx = 0;  

  126.         DAC_Config();
  127.         DAC_TIM_Config();
  128.        
  129.         /* 填充正弦波形数据,双通道右对齐*/
  130.   for (Idx = 0; Idx < 32; Idx++)
  131.   {
  132.     DualSine12bit[Idx] = (Sine12bit[Idx]);
  133.   }
  134.        
  135.         DAC_DMA_Config();
  136. }

复制代码
这是H文件
  1. #ifndef __DAC_H
  2. #define        __DAC_H


  3. #include "stm32f4xx.h"

  4. #define DAC_DHR12R1_Address     (uint32_t)(DAC_BASE+0x08)   //DAC通道数据输出寄存器地址  0x40007420//

  5. #define DAC_CLK                     RCC_APB1Periph_DAC
  6. #define DAC_TIM                     TIM2
  7. #define DAC_TIM_CLK                 RCC_APB1Periph_TIM2
  8. #define DAC_TRIGGER                 DAC_Trigger_T2_TRGO

  9. #define DAC_DMA_CLK                 RCC_AHB1Periph_DMA1
  10. #define DAC_CHANNEL                 DMA_Channel_7
  11. #define DAC_DMA_STREAM              DMA1_Stream5

  12. #define DAC_CH1_GPIO_CLK            RCC_AHB1Periph_GPIOA
  13. #define DAC_CH1_GPIO_PORT           GPIOA
  14. #define DAC_CH1_GPIO_PIN            GPIO_Pin_4
  15. #define DAC_CH1_CHANNEL             DAC_Channel_1

  16. //#define DAC_CH2_GPIO_CLK            RCC_AHB1Periph_GPIOA
  17. //#define DAC_CH2_GPIO_PORT           GPIOA
  18. //#define DAC_CH2_GPIO_PIN            GPIO_Pin_5
  19. //#define DAC_CH2_CHANNEL             DAC_Channel_2

  20. void DAC_Mode_Init(void);


  21. #endif /* __DAC_H */

复制代码
ADC那边就直接是ADC的例程,试过用ADC+中断的浮动也很大。
main函数在底下

  1. #include "stm32f4xx.h"
  2. #include "./dac/bsp_dac.h"
  3. #include "./led/bsp_led.h"
  4. #include "./usart/bsp_debug_usart.h"
  5. #include "./adc/bsp_adc.h"

  6. // ADC1转换的电压值通过MDA方式传到SRAM
  7. extern __IO uint16_t ADC_ConvertedValue;

  8. // 局部变量,用于保存转换计算后的电压值          
  9. float ADC_Vol;

  10. static void Delay(__IO uint32_t nCount)         //简单的延时函数
  11. {
  12.         for(; nCount != 0; nCount--);
  13. }

  14. int main(void)
  15. {
  16.                
  17. //        LED_GPIO_Config();
  18.        
  19.           /*初始化串口*/
  20.   Debug_USART_Config();

  21.         Rheostat_Init();       
  22.        
  23.         printf("\r\n 欢迎使用野火  STM32 F429 开发板。\r\n");       
  24.         printf("\r\n DAC输出例程,输出正弦波\r\n");       
  25.   printf("\r\n 使用示波器检测开发板的PA4、PA5引脚,可测得正弦波\r\n ");

  26.        
  27.         /*初始化DAC,开始DAC转换,使用示波器检测PA4/PA5,可观察到正弦波*/
  28.         DAC_Mode_Init();

  29.          while (1)
  30.     {
  31.             ADC_Vol =(float) ADC_ConvertedValue/4096*(float)3.3; // 读取转换的AD值

  32.   //    printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue);
  33.                         printf("\r\n The current AD value = %f V \r\n",ADC_Vol);     



  34.       Delay(0xffffee);  
  35.     }

  36. }


  37. /*********************************************END OF FILE**********************/

复制代码

回复

使用道具 举报

 楼主| 发表于 2020-8-18 02:37:05 | 显示全部楼层
这是串口输出的数据,忘记加上了;
  1. 欢迎使用野火  STM32 F429 开发板。

  2. DAC输出例程,输出正弦波

  3. 使用示波器检测开发板的PA4、PA5引脚,可测得正弦波

  4. The current AD value = 0.090234 V

  5. The current AD value = 3.168677 V

  6. The current AD value = 3.199292 V

  7. The current AD value = 3.181567 V

  8. The current AD value = 3.204126 V

  9. The current AD value = 3.232324 V

  10. The current AD value = 3.245215 V

  11. The current AD value = 3.208154 V

  12. The current AD value = 3.203320 V

  13. The current AD value = 3.216211 V

  14. The current AD value = 3.299194 V

  15. The current AD value = 3.292749 V

  16. The current AD value = 3.271802 V

  17. The current AD value = 3.170288 V

  18. The current AD value = 3.199292 V
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-8-18 17:48:14 | 显示全部楼层
等待老哥们有没有啥好的方法解决,我现在只能取均值先用着了
回复 支持 反对

使用道具 举报

发表于 2020-8-19 09:01:10 | 显示全部楼层
ADC可能就不准哦,在ADC初始化的时候校准了么?ADC的转换和ADC是否同步
回复 支持 反对

使用道具 举报

发表于 2024-3-21 14:16:59 | 显示全部楼层
你好楼主,我也遇到这个问题了,请问这个问题解决了吗
回复 支持 反对

使用道具 举报

发表于 2024-3-21 14:42:07 | 显示全部楼层
H781997429 发表于 2020-8-19 09:01
ADC可能就不准哦,在ADC初始化的时候校准了么?ADC的转换和ADC是否同步

大哥你好,我现在使用的就是指南者开发板,使用dma输出例程的时候遇到了输出不准的问题,电压的最大值只能到3.24v,无法到达3.3v,请问这个问题应该怎么解决呢
回复 支持 反对

使用道具 举报

发表于 2024-3-27 11:50:27 | 显示全部楼层
djwjc 发表于 2024-3-21 14:42
大哥你好,我现在使用的就是指南者开发板,使用dma输出例程的时候遇到了输出不准的问题,电压的最大值只 ...

有没有可能,你的电压本身就不够,测下3.3V的脚看看输出的电压是否够3.3V的
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-4-27 20:54 , Processed in 0.043402 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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