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

【经验分享】STM32 DAC的配置与使用

[复制链接]
STMCU小助手 发布时间:2022-1-24 19:00
STM32 的 DAC 模块(数字/模拟转换模块)是 12 位数字输入,电压输出型的DAC。DAC 可以配置为 8 位或 12 位模式,也可以与 DMA 控制器配合使用。DAC工作在 12 位模式时,数据可以设置成左对齐或右对齐。DAC 模块有 2 个输出通道,每个通道都有单独的转换器。在双DAC 模式下,2 个通道可以独立地进行转换,也可以同时进行转换并同步地更新 2 个通道的输出。DAC 可以通过引脚输入参考电压 VREF+以获得更精确的转换结果。
STM32 的 DAC 模块主要特点有:
①  2 个 DAC 转换器:每个转换器对应 1 个输出通道
②  8 位或者 12 位单调输出
③  12 位模式下数据左对齐或者右对齐
④  同步更新功能
⑤  噪声波形生成
⑥  三角波形生成
⑦  双 DAC 通道同时或者分别转换
⑧  每个通道都有 DMA 功能
使用库函数的方法来设置 DAC 模块的通道 1 来输出模拟电压,其详细设置步骤如下:
1)开启 PA 口时钟,设置 PA4 为模拟输入。
STM32F103ZET6 的 DAC 通道 1 在 PA4 上,所以,我们先要使能 PORTA 的时钟,然后设置 PA4 为模拟输入。DAC 本身是输出,但是为什么端口要设置为模拟输入模式呢?因为一但使能 DACx 通道之后,相应的 GPIO 引脚(PA4 或者 PA5)会自动与 DAC 的模拟输出相连,设置为输入,是为了避免额外的干扰。
使能 GPIOA 时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );    //使能 PORTA 时钟
设置 PA1 为模拟输入只需要设置初始化参数即可:
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;        //模拟输入
2)使能 DAC1 时钟。
同其他外设一样,要想使用,必须先开启相应的时钟。 STM32 的 DAC 模块时钟是由 APB1提供的,所以我们调用函数 RCC_APB1PeriphClockCmd()设置 DAC 模块的时钟使能。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );    //使能 DAC 通道时钟
3)初始化 DAC,设置 DAC 的工作模式。
该部分设置全部通过 DAC_CR 设置实现,包括:DAC 通道 1 使能、DAC 通道 1 输出缓存关闭、不使用触发、不使用波形发生器等设置。这里 DMA  初始化是通过函数 DAC_Init 完成的:
void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct)
参数设置结构体类型 DAC_InitTypeDef 的定义:
  1. typedef struct: B9 s: k! _% w4 V# O
  2. - u) ?8 E4 B% X
  3. {0 q+ y1 s3 ?) d) Z! ~2 k

  4. * ]0 k9 \% m0 c3 y/ x) I
  5. uint32_t DAC_Trigger; //设置是否使用触发功能
    5 `6 S5 x+ z0 l4 q/ g0 t/ C; p

  6. . s7 e: x  c& f, a+ z6 ^
  7. uint32_t DAC_WaveGeneration; //设置是否使用波形发生
      e% V& W2 c: ~! y( B+ K

  8. . f! T0 C/ s1 a( t2 {
  9. uint32_t DAC_LFSRUnmask_TriangleAmplitude; //设置屏蔽/幅值选择器,这个变量只在使用波形发生器的时候才有用$ `3 `8 `+ E; B. u+ P
  10. 5 c+ o/ w: X+ t( Z5 A7 N1 e. k4 O2 U
  11. uint32_t DAC_OutputBuffer;  //设置输出缓存控制位
      O3 P- U. d4 j4 G8 [

  12. / T9 [) q5 C" b9 N2 V5 w
  13. }DAC_InitTypeDef;
复制代码
$ _+ F* K; r5 S
实例代码:
  1. DAC_InitTypeDef DAC_InitType;- y$ u) s( r, q% K+ e, z" E
  2. % j- H% r& L# a4 _
  3. DAC_InitType.DAC_Trigger = DAC_Trigger_None;  //不使用触发功能  TEN1=0
    # e; \6 y8 j* v2 N

  4. 3 k/ i* L7 H- F' ~! m
  5. DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生
    ) f! V8 x6 l" M2 X8 x* G7 P' U

  6. ! E! C5 q* r" {2 R8 X9 ?- `  [
  7. DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;3 `; V7 ]) I; J4 s7 @
  8. . d2 j2 V, R: v5 T# r( |
  9. DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable ;  //DAC1 输出缓存关闭 - }+ `. q0 c! V! V  W5 U

  10. ( W  M; q5 B- [2 I( h; X
  11. DAC_Init(DAC_Channel_1,&DAC_InitType);    //初始化 DAC 通道 1
复制代码
8 h7 U4 M" c/ G. u: q+ V  d6 |
! R% T2 J: G5 q, A! A
4)使能 DAC 转换通道
初始化 DAC 之后,理所当然要使能 DAC 转换通道,库函数方法是:
DAC_Cmd(DAC_Channel_1, ENABLE);   //使能 DAC1
5)设置 DAC 的输出值。
通过前面 4 个步骤的设置,DAC 就可以开始工作了,我们使用 12 位右对齐数据格式,所以我们通过设置 DHR12R1,就可以在 DAC 输出引脚(PA4)得到不同的电压值了。库函数的函数是:
DAC_SetChannel1Data(DAC_Align_12b_R, 0);
第一个参数设置对齐方式,可以为 12 位右对齐 DAC_Align_12b_R,12 位左对齐DAC_Align_12b_L 以及 8 位右对齐 DAC_Align_8b_R 方式。第二个参数就是 DAC 的输入值了,这个很好理解,初始化设置为 0。
这里,还可以读出 DAC 的数值,函数是:
DAC_GetDataOutputValue(DAC_Channel_1);

* k. Y  t0 ?. M; E9 J4 g
以下为代码:

5 u9 Q( z. |% W6 [" g
  1. //DAC通道1输出初始化
    , W: p" K1 M5 o3 w% b9 _; ^
  2. void Dac1_Init(void)
    $ M8 r! F4 N' Z3 k/ \
  3. {% @: T" _( D8 V9 g. V- p! _
  4.     GPIO_InitTypeDef GPIO_InitStructure;! I/ `- r% e) e! q6 F
  5.     DAC_InitTypeDef DAC_InitType;
    5 I2 I7 l* g7 i- m& S
  6.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );     //使能PORTA通道时钟
    ! ?1 i: w1 j/ n+ x
  7.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );     //使能DAC通道时钟: w! @5 ?- u/ v8 R
  8.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;                 // 端口配置
    1 _1 y3 X: I& a- E( }
  9.      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;          //模拟输入; L1 c: w3 Q% o( g! ^. S
  10.      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    " B& h+ w1 @7 p% j
  11.      GPIO_Init(GPIOA, &GPIO_InitStructure);
    , ^" }2 L7 g& g
  12.     GPIO_SetBits(GPIOA,GPIO_Pin_4)    ;//PA.4 输出高; K8 h( O6 A: m$ J6 m
  13.     DAC_InitType.DAC_Trigger=DAC_Trigger_None;    //不使用触发功能 TEN1=00 {$ ?- h  C2 R3 A
  14.     DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
    7 [" s$ J# X/ f6 W  J0 J3 p3 W, ~
  15.     DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置8 J5 |) l) {) c, p6 V8 `
  16.     DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ;    //DAC1输出缓存关闭 BOFF1=1' }; R* y5 h) G  u- G; V. [+ u
  17.     DAC_Init(DAC_Channel_1,&DAC_InitType);     //初始化DAC通道1* B4 U* c3 \8 H" a5 M( h* D7 t+ T4 i
  18.     DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1( |1 J( w6 J; {  U) j; @" o
  19.     DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
    ! B! c, T. b. x3 F5 T
  20. }7 S6 l7 Y7 `  e; l' @9 k8 ]! p
  21. //设置通道1输出电压# u  J) n% L" @% q
  22. //vol:0~3300,代表0~3.3V
    4 g. q4 a! G" k  r* W  {8 U- g
  23. void Dac1_Set_Vol(u16 vol)/ Q; u0 W, ~6 B9 l/ ]# Q$ r2 W0 F$ M
  24. {# @: ^* N! H# m# S) Q4 g
  25.     float temp=vol;
    ; U5 Y! b& N* O
  26.     temp/=1000;
    ' v4 u8 p# }$ x# y" I6 L
  27.     temp=temp*4096/3.3;
    ' q% I) F' I( {! B6 v3 ~6 Q3 B$ W4 m
  28.     DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值  Z4 I) D) D% H: J3 F( s! G
  29. }
复制代码

4 ~9 V1 a. D3 }0 n1 x. G4 [$ r* M
' N! i! @8 }  n9 x' V' s2 C7 D
在使用的过程中,只需要调用 DAC_SetChannel1Data(DAC_Align_12b_R,temp);该函数就可以随意设定需要输出的电压值。

, v& d" q" S$ U: e) ]: T
" _# f9 W0 r* B" i6 @( A; f/ E
+ C0 S6 x% n8 Y
赞 收藏 评论0 发布时间:2022-1-24 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版