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

雍正不秃头

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

暂无评论

发表评论

相关推荐

基于STM32的指纹密码锁

设计简介: 本设计是基于单片机的指纹密码锁,主要实现以下功能: 矩阵按键输入密码,并通过按键显示*号可通过按键或手机开门密码可通过按键进行开门可通过蓝牙模块连接手机进行开门可通过指纹进