STM32CubeMX | STM32使用DAC+DMA+TIM生成10KHz正弦波

STM32CubeMX | STM32使用DAC+DMA+TIM生成10KHz正弦波


工程环境:

  • STM32F103RC
  • KEIL MDK 5.20
  • STM32CubeMX 6.0

前言

  • 正弦波曲线的函数公式是:y=sin(x)

  • y的范围区间是[-1:1]

  • x的取值范围是任意实数

  • 周期为2π

如下图所示的蓝色函数曲线:

使用DAC生成正弦波比较方便的方法是预先生成一个正弦波的数据点表,为了能够快速设置到DAC上所有会使用到DMA,然后通过定时器控制DAC的出样频率就达到了生成正弦波的效果。

那么这个正弦波数据点表是怎么生成的呢?下面就来讲解一下。

将这个y=sin(x)函数映射成我们现在的这个正弦波,那么y就是代表的电压,x代表的周期。

由于y=sin(x)的值范围在[-1:1]之间,DAC设置的时候不存在负数,所以就需要加1让公式生成的值都在正数范围内,公式就变成了y=six(x) + 1,现在值范围就成了[0:2],但是这样最高能表示到2V,而DAC是能输出到3.3V的,也就是说y=six(x) + 1输出2V的时候代表3.3V,所以就需要对y=six(x) + 1进行扩大,比值关系就是3.3V:2V,所以公式又变成了y=(sin(x) + 1)*(3.3/2),这样值范围就变为了[0:3.3],然后再将电压转为DAC数值就可以了。

因为正弦波每周期的波形都是一样的,所以我们生成一个周期的数据表即可。

经试验所得,一个周期内满足32个点就能近似逼近正弦波的效果,这里为了波形更好看,我选择了100个点。

周期为2π,一共100个点,那么每两个点的间距就是2π/100。

/**
 * 生成正弦波数据点函数
 * @param NPoints       一个周期内的点数
 * @param VMaxRange     输出的电压最大值,取值范围0~3.3V
 * @param SineWaveTable 存放生成的数据点
 */
void SineWaveGen(uint32_t NPoints, float VMaxRange, uint16_t* SineWaveTable)
{
#ifndef PI
#define PI 3.14159265358979323846
#endif

	int    i       = 0;
	double radian  = 0;  // 弧度
	double setup   = 0;  // 弧度和弧度之间的大小
	double voltage = 0;  // 输出电压

	setup = (2 * PI) / NPoints;  // 两点之间的间距

	while (i < NPoints)
	{
		voltage = VMaxRange / 2.0 * (sin(radian) + 1.0);              // 计算电压
		SineWaveTable[i] = (uint16_t)(voltage * 4096 / 3.3);          // 电压转为DAC数值
		radian += setup;                                              // 下一个点的弧度
		i++;
	}
}

工程配置

时钟配置到72M主频:

配置DAC

说明:

Output Buffer:输出缓存

DAC 集成了 2 个输出缓存,可以用来减少输出阻抗,无需外部运放即可直接驱动外部负载。每个 DAC 通道输出缓存可以通过设置 DAC_CR 寄存器的 BOFFx 位来使能或者关闭。如果带载能力还不行,后面就接一个电压跟随器,选择运放一定要选择电流大的型号。
使能输出缓冲后,DAC 输出的最小电压为 0.2V,最大电压为 VREF±0.2,而未使能输出缓冲则输出可达到0V。

Tigger:触发方式

选择DAC的触发方式,可以选择为定时器触发、外部中断触发和软件触发。这里我选择了定时器6来触发DAC,因为通过设置定时器的频率就可以很方便的控制DAC输出的正弦波频率。

Wave generation mode:波形发生器

我这里没有使用。

配置DMA

配置定时器

定时器6的时钟主频为72MHz,我这里没有分频,那么把重载值设置为72,这样就得到了72M/72=1MHz的触发频率。

上面说到过我的设置是一个周期内100个点,定时器触发频率为1MHz,触发一百次才能完成一个周期的波形,所以生成的波形频率就是1MHz/100个点=10KHz。

最后启动定时器和DMA传输即可:

	HAL_TIM_Base_Start(&htim6);
	HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)SineWaveTable, POINTS, DAC_ALIGN_12B_R);

生成的波形用示波器查看如下:

版权声明:本文为CSDN博主「雍正不秃头」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq153471503/article/details/122341769

STM32CubeMX | STM32使用DAC+DMA+TIM生成10KHz正弦波


工程环境:

  • STM32F103RC
  • KEIL MDK 5.20
  • STM32CubeMX 6.0

前言

  • 正弦波曲线的函数公式是:y=sin(x)

  • y的范围区间是[-1:1]

  • x的取值范围是任意实数

  • 周期为2π

如下图所示的蓝色函数曲线:

使用DAC生成正弦波比较方便的方法是预先生成一个正弦波的数据点表,为了能够快速设置到DAC上所有会使用到DMA,然后通过定时器控制DAC的出样频率就达到了生成正弦波的效果。

那么这个正弦波数据点表是怎么生成的呢?下面就来讲解一下。

将这个y=sin(x)函数映射成我们现在的这个正弦波,那么y就是代表的电压,x代表的周期。

由于y=sin(x)的值范围在[-1:1]之间,DAC设置的时候不存在负数,所以就需要加1让公式生成的值都在正数范围内,公式就变成了y=six(x) + 1,现在值范围就成了[0:2],但是这样最高能表示到2V,而DAC是能输出到3.3V的,也就是说y=six(x) + 1输出2V的时候代表3.3V,所以就需要对y=six(x) + 1进行扩大,比值关系就是3.3V:2V,所以公式又变成了y=(sin(x) + 1)*(3.3/2),这样值范围就变为了[0:3.3],然后再将电压转为DAC数值就可以了。

因为正弦波每周期的波形都是一样的,所以我们生成一个周期的数据表即可。

经试验所得,一个周期内满足32个点就能近似逼近正弦波的效果,这里为了波形更好看,我选择了100个点。

周期为2π,一共100个点,那么每两个点的间距就是2π/100。

/**
 * 生成正弦波数据点函数
 * @param NPoints       一个周期内的点数
 * @param VMaxRange     输出的电压最大值,取值范围0~3.3V
 * @param SineWaveTable 存放生成的数据点
 */
void SineWaveGen(uint32_t NPoints, float VMaxRange, uint16_t* SineWaveTable)
{
#ifndef PI
#define PI 3.14159265358979323846
#endif

	int    i       = 0;
	double radian  = 0;  // 弧度
	double setup   = 0;  // 弧度和弧度之间的大小
	double voltage = 0;  // 输出电压

	setup = (2 * PI) / NPoints;  // 两点之间的间距

	while (i < NPoints)
	{
		voltage = VMaxRange / 2.0 * (sin(radian) + 1.0);              // 计算电压
		SineWaveTable[i] = (uint16_t)(voltage * 4096 / 3.3);          // 电压转为DAC数值
		radian += setup;                                              // 下一个点的弧度
		i++;
	}
}

工程配置

时钟配置到72M主频:

配置DAC

说明:

Output Buffer:输出缓存

DAC 集成了 2 个输出缓存,可以用来减少输出阻抗,无需外部运放即可直接驱动外部负载。每个 DAC 通道输出缓存可以通过设置 DAC_CR 寄存器的 BOFFx 位来使能或者关闭。如果带载能力还不行,后面就接一个电压跟随器,选择运放一定要选择电流大的型号。
使能输出缓冲后,DAC 输出的最小电压为 0.2V,最大电压为 VREF±0.2,而未使能输出缓冲则输出可达到0V。

Tigger:触发方式

选择DAC的触发方式,可以选择为定时器触发、外部中断触发和软件触发。这里我选择了定时器6来触发DAC,因为通过设置定时器的频率就可以很方便的控制DAC输出的正弦波频率。

Wave generation mode:波形发生器

我这里没有使用。

配置DMA

配置定时器

定时器6的时钟主频为72MHz,我这里没有分频,那么把重载值设置为72,这样就得到了72M/72=1MHz的触发频率。

上面说到过我的设置是一个周期内100个点,定时器触发频率为1MHz,触发一百次才能完成一个周期的波形,所以生成的波形频率就是1MHz/100个点=10KHz。

最后启动定时器和DMA传输即可:

	HAL_TIM_Base_Start(&htim6);
	HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)SineWaveTable, POINTS, DAC_ALIGN_12B_R);

生成的波形用示波器查看如下:

版权声明:本文为CSDN博主「雍正不秃头」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq153471503/article/details/122341769

生成海报
点赞 0

雍正不秃头

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

74HC138译码器的原理和使用

前言 译码器就是将每个输入的二进制代码译成对应的输出高低电平信号,和编码器互为逆过程。 百度百科 74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL&#xf

ESP32-GY_30光照强度传感器

GY_30光照强度传感器介绍 GY-30光强传感器特点及使用介绍 一、连接引脚 GY_30光照强度传感器使用I2C传输数据 。 5根引脚,名称与功能如下; vcc 为外接供电电源输入端 GND 地线 SCL I2C通信模式时钟