当前位置:   article > 正文

STM32F407使用内置DAC+DMA+TIM制作DDS信号源_stm32 dds

stm32 dds

STM32F407使用内置DAC+DMA+TIM制作DDS信号源

电赛的时候需要制作能够实现分辨率到0.001Hz的信号源,平常使用的信号源模块达不到这个精度,故使用DDS算法实现

一、简单原理讲解(个人理解)

频率:

现在假设我们有2的32次方这么大个正弦波波表(当然后面教程中不会这么大,这里方便理解),然后DDS输出波表直接查表的时候频率控制字取1,本振(定时器6)为2MHz,此时输出频率为2M除以2的32次方乘以1约等于0.0004656Hz;若频率控制字取2,输出频率为2M除以2的32次方乘以2约等于0.0009312Hz。这里就能得到频率控制字的计算公式了为:2的32次方除以本振(2M)乘以输出频率。然而在实际工程中,一般情况下,我们不可能有这么大的存储空间去储存2的32次方这么大个正弦波表,这个时候相位累加器的作用就出现了,可以将正弦波波表取样量化到一个2的次方大小的数组,比如2的8次方,相位累加器为32位(也可以取其他的),取高八位作为DDS输出查表的索引,便解决了。

相位:

实际上相位累加器32位,就对应了2的32次方这么大个正弦波波表(虚拟出来的,一个周期),改变相位,只需要在当前相位累加器的基础上加减一次即可,相位控制字计算公式为:改变相位除以360°乘以2的32次方

幅度:

取决于正弦波波表

二、DDS缺陷

尽管DDS能够实现精准的频率相位控制,但在输出高频信号时,会出现不明显的上下波动的现象,笔者在使用这个算法出三角波的时候吃的亏,原因是因为,在频率越高,频率控制字越大,输出对应的DDS数组中一个周期数量少,导致,在DDS查表的时候,取峰峰值取不到。(可通过提高本振频率,相位累加器位数和数组大小改善)

三、DDS算法实现

在使用DDS算法中,有相位累加器uint32_t place=0,频率控制字 uint32_t ctrl_word,相位控制字uint32_t phase_word,DDS输出波表uin32_t pData[256],正弦波波表uint16_t Sine_WAVE[256];,输出频率uint32_t Fre=10000,输出相对相位float phase=0(0到360°)系统时钟(本振)2MHz。故分辨率为2M/2的32次方约等于0.0004656Hz,在配置好cubemx后生成代码。


在这里插入图片描述
这里我的f4主频设置成160MHz
在这里插入图片描述

一些变量

#define  WAVE_POINT  256

#define OF 2147.483648 //2的32次方除以2M

uint16_t pData[WAVE_POINT];

uint16_t Sine_WAVE[WAVE_POINT];

uint32_t place=0;

uint32_t ctrl_word=0;

uint32_t phase_word=0;

uint32_t Fre=10000;

uint8_t phaseFlag=1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

一些代码

void SineWave_Data(uint16_t num, uint16_t* D, float U)//正弦波生成波表代码

{

​	num++;uint16_t i;

​    U=U/2;for (i = 0; i < num-1; i++){

​        D[i] = (uint16_t)((U*sin((1.0 * i / (num - 1)) * 2 * 3.1415926) + U) * 4095 / 3.3)+300;}

}

void phaseChange(float phase)``//相位改变代码

{

​	phase_word=phase/360*4294967295;if(phaseFlag==1){

​		phaseFlag=0;

​		place+=phase_word;}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

主函数代码

int main(void)

{

  /* USER CODE BEGIN 1 */



  /* USER CODE END 1 */



  /* MCU Configuration--------------------------------------------------------*/



  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();



  /* USER CODE BEGIN Init */



  /* USER CODE END Init */



  /* Configure the system clock */

  SystemClock_Config();



  /* USER CODE BEGIN SysInit */



  /* USER CODE END SysInit */



  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_DMA_Init();

  MX_DAC_Init();

  MX_TIM6_Init();

  /* USER CODE BEGIN 2 */

 	SineWave_Data(WAVE_POINT ,Sine_WAVE,2);//生成正弦波数组**

	HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)pData,  WAVE_POINT, DAC_ALIGN_12B_R);//使能DAC**

  	HAL_TIM_Base_Start(&htim6);//使能定时器**

  /* USER CODE END 2 */



  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */

	 phaseChange(phase);//更改相位

	 ctrl_word=Fre*OF;//频率控制字

  }

  /* USER CODE END 3 */

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

核心代码

在DMA传输中断中更改波表,传输完成前半段更改前半段波表,完成后半段更改后半段波表

void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef *hdac)

{for(uint16_t i=0;i<WAVE_POINT/2;i++){

​		pData[i]=Sine_WAVE[place>>24];

​		place+=ctrl_word;}

}

void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)

{for(uint16_t i=WAVE_POINT/2;i<WAVE_POINT;i++){

​		pData[i]=Sine_WAVE[place>>24];

​		place+=ctrl_word;}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/945153
推荐阅读
相关标签
  

闽ICP备14008679号