STM32标准外设库DAC输出SPL篇16

Posted:   2020-08-11

Status:   Completed

Tags :   STM32 SPL DAC

Categories :   STM32 DAC

Previous:   STM32标准外设库计时器做按键消抖SPL篇15

Next:   STM32标准外设库资源总结SPL篇17


添加库函数

  • 打开 Manage Run-Time Environment
  • 选择Device->StdPeriph Drivers->DAC

DAC初始化

DAC宏定义

  • my_dac.h
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
#ifndef __DAC_H
#define	__DAC_H


#include "stm32f10x.h"
//12位、右对齐、通道1
#define DAC_DHR12R1_ADDRESS      (DAC_BASE+0x08)
//12位、左对齐、通道1
#define DAC_DHR12L1_ADDRESS      (DAC_BASE+0x0C)
//8位、右对齐、通道1
#define DAC_DHR8R1_ADDRESS       (DAC_BASE+0x10)
//12位、右对齐、通道2
#define DAC_DHR12R2_ADDRESS      (DAC_BASE+0x14)
//12位、左对齐、通道2
#define DAC_DHR12L2_ADDRESS      (DAC_BASE+0x18)
//8位、右对齐、通道2
#define DAC_DHR8R2_ADDRESS       (DAC_BASE+0x1C)
//12位、右对齐、双通道
#define DAC_DHR12RD_ADDRESS      (DAC_BASE+0x20)
//12位、左对齐、双通道
#define DAC_DHR12LD_ADDRESS      (DAC_BASE+0x24)
//8位、右对齐、双通道
#define DAC_DHR8RD_ADDRESS       (DAC_BASE+0x28)

void DAC_Mode_Init(void);


#endif /* __DAC_H */

DAC管脚设置和工作模式配置

  • my_dac.c
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "my_dac.h"
//正弦波单个周期的点数
#define POINT_NUM 32

/* 波形数据 ---------------------------------------------------------*/
const uint16_t Sine12bit[POINT_NUM] = {
    2048,2460,2856,3218,3532,3786,3969,4072,
    4093,4031,3887,3668,3382,3042,2661,2255,
    1841,1435,1054,714,428,209,65,3,
    24,127,310,564,878,1240,1636,2048
};


uint32_t DualSine12bit[POINT_NUM];
/**
  * @brief  使能DAC的时钟,初始化GPIO
  * @param  无
  * @retval 无
  */
static void DAC_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef  DAC_InitStructure;

    /* 使能GPIOA时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* 使能DAC时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

    /* DAC的GPIO配置,模拟输入 */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);



    /* 配置DAC 通道1 */
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;						//使用TIM2作为触发源
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;	//不使用波形发生器
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;	//不使用DAC输出缓冲
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);

    /* 配置DAC 通道2 */
    DAC_Init(DAC_Channel_2, &DAC_InitStructure);

    /* 使能通道1 由PA4输出 */
    DAC_Cmd(DAC_Channel_1, ENABLE);
    /* 使能通道2 由PA5输出 */
    DAC_Cmd(DAC_Channel_2, ENABLE);

    /* 使能DAC的DMA请求 */
    DAC_DMACmd(DAC_Channel_2, ENABLE);
}


/**
  * @brief  配置TIM
  * @param  无
  * @retval 无
  */
static void DAC_TIM_Config(void)
{

    TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;

    /* 使能TIM2时钟,TIM2CLK 为72M */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    /* TIM2基本定时器配置 */
    TIM_TimeBaseStructure.TIM_Period = (1125-1);       					//
    TIM_TimeBaseStructure.TIM_Prescaler = 0;       							//预分频,不分频 72M / (0+1) = 72M
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    					//时钟分频系数
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    /* 配置TIM2触发源 */
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

    /* 使能TIM2 */
    TIM_Cmd(TIM2, ENABLE);

}

/**
  * @brief  配置DMA
  * @param  无
  * @retval 无
  */
static void DAC_DMA_Config(void)
{
    DMA_InitTypeDef  DMA_InitStructure;

    /* 使能DMA2时钟 */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

    /* 配置DMA2 */
    DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12RD_ADDRESS;					//外设数据地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&DualSine12bit ;				//内存数据地址 DualSine12bit
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;											//数据传输方向内存至外设
    DMA_InitStructure.DMA_BufferSize = POINT_NUM;														//缓存大小为POINT_NUM字节
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;				//外设数据地址固定
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;									//内存数据地址自增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;	//外设数据以字为单位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;					//内存数据以字为单位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;													//循环模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;											//高DMA通道优先级
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;														//非内存至内存模式

    DMA_Init(DMA2_Channel4, &DMA_InitStructure);

    /* 使能DMA2-4通道 */
    DMA_Cmd(DMA2_Channel4, ENABLE);
}


/**
  * @brief  DAC初始化函数
  * @param  无
  * @retval 无
  */
void DAC_Mode_Init(void)
{
    uint32_t Idx = 0;

    DAC_Config();
    DAC_TIM_Config();

    /* 填充正弦波形数据,双通道右对齐*/
    for (Idx = 0; Idx < POINT_NUM; Idx++)
    {
        DualSine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]);
    }

    DAC_DMA_Config();
}


DAC结构体分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** 
  * @brief  DAC Init structure definition
  */

typedef struct
{
  uint32_t DAC_Trigger;                      /*!< Specifies the external trigger for the selected DAC channel.
                                                  This parameter can be a value of @ref DAC_trigger_selection */

  uint32_t DAC_WaveGeneration;               /*!< Specifies whether DAC channel noise waves or triangle waves
                                                  are generated, or whether no wave is generated.
                                                  This parameter can be a value of @ref DAC_wave_generation */

  uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or
                                                  the maximum amplitude triangle generation for the DAC channel. 
                                                  This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */

  uint32_t DAC_OutputBuffer;                 /*!< Specifies whether the DAC channel output buffer is enabled or disabled.
                                                  This parameter can be a value of @ref DAC_output_buffer */
}DAC_InitTypeDef;
  • 触发方式DAC_Trigger
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/** @defgroup DAC_trigger_selection 
  * @{
  */

#define DAC_Trigger_None                   ((uint32_t)0x00000000) /*!< Conversion is automatic once the DAC1_DHRxxxx register has been loaded, and not by external trigger *///硬件触发,写入寄存器DAC_DHRx的数据在1个APB1时钟周期后传入寄存器DAC_DOR1
#define DAC_Trigger_T6_TRGO                ((uint32_t)0x00000004) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel *///TIM6 TRGO事件
#define DAC_Trigger_T8_TRGO                ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel only in High-density devices*///对于小容量,中容量和互联型产品是TIM3 TRGO事件,对于大容量产品是TIM8 TRGO事件;
#define DAC_Trigger_T3_TRGO                ((uint32_t)0x0000000C) /*!< TIM3 TRGO selected as external conversion trigger for DAC channel only in Connectivity line, Medium-density and Low-density Value Line devices */
#define DAC_Trigger_T7_TRGO                ((uint32_t)0x00000014) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel *///TIM7 TRGO事件
#define DAC_Trigger_T5_TRGO                ((uint32_t)0x0000001C) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel *///TIM5 TRGO事件
#define DAC_Trigger_T15_TRGO               ((uint32_t)0x0000001C) /*!< TIM15 TRGO selected as external conversion trigger for DAC channel only in Medium-density and Low-density Value Line devices*///对于小容量和中容量是TIM15 TRGO事件
#define DAC_Trigger_T2_TRGO                ((uint32_t)0x00000024) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel *///TIM2 TRGO事件;
#define DAC_Trigger_T4_TRGO                ((uint32_t)0x0000002C) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel *///TIM4 TRGO事件
#define DAC_Trigger_Ext_IT9                ((uint32_t)0x00000034) /*!< EXTI Line9 event selected as external conversion trigger for DAC channel *///外部中断线9
#define DAC_Trigger_Software               ((uint32_t)0x0000003C) /*!< Conversion started by software trigger for DAC channel *///软件触发

注:

  1. 开启触发使能,写入寄存器DAC_DHRx的数据在3个APB1时钟周期后传入寄存器DAC_DOR1
  2. 如果选择软件触发,写入寄存器DAC_DHRx的数据只需要1个APB1时钟周期就可以传入寄存器DAC_DOR1
  3. 关闭DAC通道1触发即硬件触发,写入寄存器DAC_DHRx的数据在1个APB1时钟周期后传入寄存器DAC_DOR1
  • 是否自动输出噪声或三角波DAC_WaveGeneration
1
2
3
4
5
6
7
/** @defgroup DAC_wave_generation 
  * @{
  */

#define DAC_WaveGeneration_None            ((uint32_t)0x00000000) //关闭波形发生器
#define DAC_WaveGeneration_Noise           ((uint32_t)0x00000040) //使能噪声波形发生器
#define DAC_WaveGeneration_Triangle        ((uint32_t)0x00000080) //使能三角波发生器
  • 选择噪声生成器的低通滤波或三角波的幅值DAC_LFSRUnmask_TriangleAmplitude
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
/** @defgroup DAC_lfsrunmask_triangleamplitude
  * @{
  */

#define DAC_LFSRUnmask_Bit0                ((uint32_t)0x00000000) /*!< Unmask DAC channel LFSR bit0 for noise wave generation *///不屏蔽LSFR位0 
#define DAC_LFSRUnmask_Bits1_0             ((uint32_t)0x00000100) /*!< Unmask DAC channel LFSR bit[1:0] for noise wave generation *///不屏蔽LSFR位[1:0] 
#define DAC_LFSRUnmask_Bits2_0             ((uint32_t)0x00000200) /*!< Unmask DAC channel LFSR bit[2:0] for noise wave generation *///不屏蔽LSFR位[2:0] 
#define DAC_LFSRUnmask_Bits3_0             ((uint32_t)0x00000300) /*!< Unmask DAC channel LFSR bit[3:0] for noise wave generation *///不屏蔽LSFR位[3:0]
#define DAC_LFSRUnmask_Bits4_0             ((uint32_t)0x00000400) /*!< Unmask DAC channel LFSR bit[4:0] for noise wave generation *///不屏蔽LSFR位[4:0] 
#define DAC_LFSRUnmask_Bits5_0             ((uint32_t)0x00000500) /*!< Unmask DAC channel LFSR bit[5:0] for noise wave generation *///不屏蔽LSFR位[5:0] 
#define DAC_LFSRUnmask_Bits6_0             ((uint32_t)0x00000600) /*!< Unmask DAC channel LFSR bit[6:0] for noise wave generation *///不屏蔽LSFR位[6:0] 
#define DAC_LFSRUnmask_Bits7_0             ((uint32_t)0x00000700) /*!< Unmask DAC channel LFSR bit[7:0] for noise wave generation *///不屏蔽LSFR位[7:0] 
#define DAC_LFSRUnmask_Bits8_0             ((uint32_t)0x00000800) /*!< Unmask DAC channel LFSR bit[8:0] for noise wave generation *///不屏蔽LSFR位[8:0]
#define DAC_LFSRUnmask_Bits9_0             ((uint32_t)0x00000900) /*!< Unmask DAC channel LFSR bit[9:0] for noise wave generation *///不屏蔽LSFR位[9:0] 
#define DAC_LFSRUnmask_Bits10_0            ((uint32_t)0x00000A00) /*!< Unmask DAC channel LFSR bit[10:0] for noise wave generation *///不屏蔽LSFR位[10:0] 
#define DAC_LFSRUnmask_Bits11_0            ((uint32_t)0x00000B00) /*!< Unmask DAC channel LFSR bit[11:0] for noise wave generation *///不屏蔽LSFR位[11:0] 
#define DAC_TriangleAmplitude_1            ((uint32_t)0x00000000) /*!< Select max triangle amplitude of 1 */ //三角波幅值等于1
#define DAC_TriangleAmplitude_3            ((uint32_t)0x00000100) /*!< Select max triangle amplitude of 3 */ //三角波幅值等于3
#define DAC_TriangleAmplitude_7            ((uint32_t)0x00000200) /*!< Select max triangle amplitude of 7 */ //三角波幅值等于7
#define DAC_TriangleAmplitude_15           ((uint32_t)0x00000300) /*!< Select max triangle amplitude of 15 */ //三角波幅值等于15
#define DAC_TriangleAmplitude_31           ((uint32_t)0x00000400) /*!< Select max triangle amplitude of 31 */ //三角波幅值等于31
#define DAC_TriangleAmplitude_63           ((uint32_t)0x00000500) /*!< Select max triangle amplitude of 63 */ //三角波幅值等于63
#define DAC_TriangleAmplitude_127          ((uint32_t)0x00000600) /*!< Select max triangle amplitude of 127 */ //三角波幅值等于127
#define DAC_TriangleAmplitude_255          ((uint32_t)0x00000700) /*!< Select max triangle amplitude of 255 */ //三角波幅值等于255
#define DAC_TriangleAmplitude_511          ((uint32_t)0x00000800) /*!< Select max triangle amplitude of 511 */ //三角波幅值等于511
#define DAC_TriangleAmplitude_1023         ((uint32_t)0x00000900) /*!< Select max triangle amplitude of 1023 */ //三角波幅值等于1023
#define DAC_TriangleAmplitude_2047         ((uint32_t)0x00000A00) /*!< Select max triangle amplitude of 2047 */ //三角波幅值等于2047
#define DAC_TriangleAmplitude_4095         ((uint32_t)0x00000B00) /*!< Select max triangle amplitude of 4095 */ //三角波幅值等于4095
  • 是否使能输出缓冲器DAC_OutputBuffer
1
2
3
4
5
6
/** @defgroup DAC_output_buffer 
  * @{
  */

#define DAC_OutputBuffer_Enable            ((uint32_t)0x00000000) //使能DAC输出缓存
#define DAC_OutputBuffer_Disable           ((uint32_t)0x00000002) //关闭DAC输出缓存

波形周期

$ T=\frac{(TIM\_Period+1)\times (TIM\_Prescaler+1) \times POINT\_NUM}{TDTS} $

F=1/T=72000000/1125/1/32=2KHz

调试

添加头文件和调用DAC初始化函数

  • main.c
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "stm32f10x.h"
#include "my_gpio.h"
#include "my_usart.h"
#include "my_data_queue.h"
#include "my_process_data.h"
#include "my_adc.h"
#include "my_tim.h"
#include "my_advance_pwm.h"
#include "my_general_pwm.h"
#include "my_capture.h"
#include "my_PWM_capture.h"
#include "my_dac.h"
Channel ch[2];
__IO uint32_t time = 0; // ms 计时变量
uint32_t freq;
uint8_t duty1,duty2,duty3,duty4;
extern __IO uint16_t IC1Value;
extern __IO float DutyCycle;
extern __IO float Frequency;
int main(void)
{
    uint32_t capture_time;
    uint32_t TIM_PscCLK = 72000000 / (GENERAL_CAPTURE_TIM_PSC+1);
    /* LED 端口初始化 */
    LED_GPIO_Config();
    Key_GPIO_Config();
    /* 初始化USART 配置模式为 9600 8-N-1 */
    USART_Config();
    /*初始化接收数据队列*/
    RX_Queue_Init();
    /*初始化ADC*/
    ADCx_Init();
    /*初始化TIM 1ms*/
    MY_TIM_Init();
    /*初始化PWM  1MHz 50%*/
    ADVANCE_PWM_Init();
    /*初始化PWM  10KHz 50% 40% 30% 20%*/
    GENERAL_PWM_Init();
    /*初始化输入捕获*/
    CAPTURE_TIM_Init();
    /*初始化PWM捕获*/
    ADVANCE_CAPTURE_TIM_Init();
		/*初始化DAC 2k 正弦波*/
    DAC_Mode_Init();
    freq=10000;
    duty1=50;
    duty2=40;
    duty3=30;
    duty4=20;
    printf( "\r\n Print current Temperature  \r\n");

    while (1)
    {

        if(TIM_ICUserValueStructure.Capture_FinishFlag == 1)
        {
            // 计算高电平时间的计数器的值
            capture_time = TIM_ICUserValueStructure.Capture_Period * (GENERAL_CAPTURE_TIM_PERIOD+1) +
                           (TIM_ICUserValueStructure.Capture_CcrValue+1);

            // 打印高电平脉宽时间
            printf ( "\r\n duty time:%d.%d s\r\n",capture_time/TIM_PscCLK,capture_time%TIM_PscCLK );

            TIM_ICUserValueStructure.Capture_FinishFlag = 0;
        }
        if ( time >= 1000 ) /* 1000 * 1 ms = 1s 时间到 */
        {
            if(IC1Value!=0)
            {
                printf("DUTY:%0.2f%%   FREQ:%0.2fHz\n",DutyCycle,Frequency);
            }
            time = 0;
            /* LED1 取反 */
            LED1_TOGGLE;

            freq-=1000;
            if(freq<=1000)
            {
                freq=10000;
            }
            duty1+=10;
            duty2-=10;
            duty3+=5;
            duty4-=5;
            if(duty1>=100)
            {
                duty1=10;
            }
            if(duty2<=10)
            {
                duty2=100;
            }
            if(duty3>=100)
            {
                duty3=5;
            }
            if(duty4<=5)
            {
                duty4=100;
            }
            Set_General_PWM_FREQ(freq,duty1,duty2,duty3,duty4);
        }
        Process_Usart_Data(ch);
        if(ch[0].state==1&&ch[0].start_up==0)
        {
            ch[0].stop_up=0;
            ch[0].start_up=1;
            LED1(ON);
        }
        if(ch[0].state==2&&ch[0].stop_up==0)
        {
            ch[0].stop_up=1;
            ch[0].start_up=0;
            LED1(OFF);
        }
        if(ch[1].state==1&&ch[1].start_up==0)
        {
            ch[1].stop_up=0;
            ch[1].start_up=1;
            LED2(ON);
        }
        if(ch[1].state==2&&ch[1].stop_up==0)
        {
            ch[1].stop_up=1;
            ch[1].start_up=0;
            LED2(OFF);
        }
    }
}

下载调试

  • 编译之后下载到开发板
  • 使用示波器查看PA4,PA5输出波形,为2K正弦波