你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32使用DAC+DMA+TIM生成10KHz正弦波

[复制链接]
STMCU小助手 发布时间:2022-4-8 23:30
前言
正弦波曲线的函数公式是:y=sin(x)

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

x的取值范围是任意实数

周期为2π

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

R)J9`VX8$`U][LTT)@@Y%R1.png

使用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。

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

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

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

  17.         while (i < NPoints)
  18.         {
  19.                 voltage = VMaxRange / 2.0 * (sin(radian) + 1.0);              // 计算电压
  20.                 SineWaveTable<i> = (uint16_t)(voltage * 4096 / 3.3);          // 电压转为DAC数值
  21.                 radian += setup;                                              // 下一个点的弧度
  22.                 i++;
  23.         }
  24. }</i>
复制代码

工程配置
时钟配置到72M主频:


R07[V]RE()9QNS)VMMRMT5N.png

配置DAC

4N$$YM_S{LT`{NM3X06BV~F.png

说明:


Output Buffer:输出缓存

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

Tigger:触发方式

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

Wave generation mode:波形发生器

我这里没有使用。

配置DMA

7(B[K5{_`T[NN4$~D%]CI@H.png

配置定时器


NY~O}[$M10@`_~6ONL_()}J.png

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

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

最后启动定时器和DMA传输即可:
  1.         HAL_TIM_Base_Start(&htim6);
  2.         HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)SineWaveTable, POINTS, DAC_ALIGN_12B_R);
复制代码

7$R4%{_PB9Y5J[N94TB8}JO.png

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

_QX6MBWHTEUHCZQB0%[RXM5.png

收藏 评论0 发布时间:2022-4-8 23:30

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版