Posted
: 2020-08-20
Status
:
Completed
Previous
:
STM32硬件层HAL库TIM做按键消抖HAL篇14
Next
:
STM32底层LL库GPIO输出LL篇1
Analog
->DAC
配置OUT1 Configuration
,OUT2 Configuration
Parameter Settings
配置Disable,
Trigger——Timer2 Trigger Out Event
,Wave generation mode——Disabled
Disable,
Trigger——Timer2 Trigger Out Event
,Wave generation mode——Disabled
DMA_Settings
DAC_CH2
优先级——High
模式——Circle
存储器地址自增 外设不自增 数据字——Word
Timers
->TIM2
配置Internal Clock
Parameter Settings
配置0
,自动重载数值——1124
,计数模式——UP
,自动重载预装载——Disable
CKD——No Division
Disbale
,Trigger Event Selection——Update Event
GENERATE CODE
自动生成代码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
/**
* @brief DAC handle Structure definition
*/
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
typedef struct __DAC_HandleTypeDef
#else
typedef struct
#endif
{
DAC_TypeDef *Instance; /*!< Register base address */
__IO HAL_DAC_StateTypeDef State; /*!< DAC communication state */
HAL_LockTypeDef Lock; /*!< DAC locking object */
DMA_HandleTypeDef *DMA_Handle1; /*!< Pointer DMA handler for channel 1 */
DMA_HandleTypeDef *DMA_Handle2; /*!< Pointer DMA handler for channel 2 */
__IO uint32_t ErrorCode; /*!< DAC Error code */
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
void (* ConvCpltCallbackCh1) (struct __DAC_HandleTypeDef *hdac);
void (* ConvHalfCpltCallbackCh1) (struct __DAC_HandleTypeDef *hdac);
void (* ErrorCallbackCh1) (struct __DAC_HandleTypeDef *hdac);
void (* DMAUnderrunCallbackCh1) (struct __DAC_HandleTypeDef *hdac);
void (* ConvCpltCallbackCh2) (struct __DAC_HandleTypeDef *hdac);
void (* ConvHalfCpltCallbackCh2) (struct __DAC_HandleTypeDef *hdac);
void (* ErrorCallbackCh2) (struct __DAC_HandleTypeDef *hdac);
void (* DMAUnderrunCallbackCh2) (struct __DAC_HandleTypeDef *hdac);
void (* MspInitCallback) (struct __DAC_HandleTypeDef *hdac);
void (* MspDeInitCallback ) (struct __DAC_HandleTypeDef *hdac);
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
} DAC_HandleTypeDef;
Instance
可选参数:DAC1
State
1
2
3
4
5
6
7
8
9
10
11
12
/**
* @brief HAL State structures definition
*/
typedef enum
{
HAL_DAC_STATE_RESET = 0x00U, /*!< DAC not yet initialized or disabled *///没有初始化
HAL_DAC_STATE_READY = 0x01U, /*!< DAC initialized and ready for use *///初始化完成和准备好
HAL_DAC_STATE_BUSY = 0x02U, /*!< DAC internal processing is ongoing *///在忙
HAL_DAC_STATE_TIMEOUT = 0x03U, /*!< DAC timeout state *///超时
HAL_DAC_STATE_ERROR = 0x04U /*!< DAC error state *///错误
} HAL_DAC_StateTypeDef;
Lock
DMA_Handle1
DMA_Handle2
ErrorCode
1
2
3
4
5
6
7
8
9
10
11
/** @defgroup DAC_Error_Code DAC Error Code
* @{
*/
#define HAL_DAC_ERROR_NONE 0x00U /*!< No error *///无错误
#define HAL_DAC_ERROR_DMAUNDERRUNCH1 0x01U /*!< DAC channel1 DMA underrun error *///通道1欠载错误
#define HAL_DAC_ERROR_DMAUNDERRUNCH2 0x02U /*!< DAC channel2 DMA underrun error *///通道2欠载错误
#define HAL_DAC_ERROR_DMA 0x04U /*!< DMA error *///DNA错误
#define HAL_DAC_ERROR_TIMEOUT 0x08U /*!< Timeout error *///超时错误
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
#define HAL_DAC_ERROR_INVALID_CALLBACK 0x10U /*!< Invalid callback error *///无效的回调
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
1
2
3
4
5
6
7
8
9
10
11
12
/**
* @brief DAC Configuration regular Channel 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_OutputBuffer; /*!< Specifies whether the DAC channel output buffer is enabled or disabled.
This parameter can be a value of @ref DAC_output_buffer */
} DAC_ChannelConfTypeDef;
DAC_Trigger
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
/** @defgroup DACEx_trigger_selection DAC trigger selection
* @{
*/
#define DAC_TRIGGER_NONE 0x00000000U /*!< Conversion is automatic once the DAC1_DHRxxxx register
has been loaded, and not by external trigger */
#define DAC_TRIGGER_T6_TRGO ((uint32_t) DAC_CR_TEN1) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T7_TRGO ((uint32_t)( DAC_CR_TSEL1_1 | DAC_CR_TEN1)) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T2_TRGO ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TEN1)) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T4_TRGO ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_EXT_IT9 ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TSEL1_1 | DAC_CR_TEN1)) /*!< EXTI Line9 event selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_SOFTWARE ((uint32_t)(DAC_CR_TSEL1 | DAC_CR_TEN1)) /*!< Conversion started by software trigger for DAC channel */
#if defined (STM32F101xE) || defined (STM32F101xG) || defined (STM32F103xE) || defined (STM32F103xG)
/* For STM32F10x high-density and XL-density devices: TIM8 */
#define DAC_TRIGGER_T8_TRGO ((uint32_t) DAC_CR_TSEL1_0 | DAC_CR_TEN1) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel */
#endif /* STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
#if defined (STM32F100xB) || defined (STM32F100xE) || defined (STM32F105xC) || defined (STM32F107xC)
/* For STM32F10x connectivity line devices and STM32F100x devices: TIM3 */
#define DAC_TRIGGER_T3_TRGO ((uint32_t) DAC_CR_TSEL1_0 | DAC_CR_TEN1) /*!< TIM3 TRGO selected as external conversion trigger for DAC channel */
#endif /* STM32F100xB || STM32F100xE || STM32F105xC || STM32F107xC */
/* Availability of trigger from TIM5 and TIM15: */
/* - For STM32F10x value line devices STM32F100xB: */
/* trigger from TIM15 is available, TIM5 not available. */
/* - For STM32F10x value line devices STM32F100xE: */
/* trigger from TIM15 and TIM5 are both available, */
/* selection depends on remap (with TIM5 as default configuration). */
/* - Other STM32F1 devices: */
/* trigger from TIM5 is available, TIM15 not available. */
#if defined (STM32F100xB)
#define DAC_TRIGGER_T15_TRGO ((uint32_t)( DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) /*!< TIM15 TRGO selected as external conversion trigger for DAC channel */
#else
#define DAC_TRIGGER_T5_TRGO ((uint32_t)( DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel */
#if defined (STM32F100xE)
/*!< DAC trigger availability depending on STM32F1 devices:
For STM32F100x high-density value line devices, the TIM15 TRGO event can be selected
as replacement of TIM5 TRGO if the MISC_REMAP bit in the AFIO_MAPR2 register is set.
Refer to macro "__HAL_AFIO_REMAP_MISC_ENABLE()/__HAL_AFIO_REMAP_MISC_DISABLE()".
Otherwise, TIM5 TRGO is used and TIM15 TRGO is not used (default case).
For more details please refer to the AFIO section. */
#define DAC_TRIGGER_T15_TRGO DAC_TRIGGER_T5_TRGO
#endif /* STM32F100xE */
#endif /* STM32F100xB */
DAC_OutputBuffer
1
2
3
4
5
/** @defgroup DAC_output_buffer DAC output buffer
* @{
*/
#define DAC_OUTPUTBUFFER_ENABLE 0x00000000U //使能
#define DAC_OUTPUTBUFFER_DISABLE (DAC_CR_BOFF1)//禁止
__HAL_DAC_ENABLE(__HANDLE__, __DAC_Channel__)
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel)
HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef *hdac, uint32_t Channel)
HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length,uint32_t Alignment)
转换完成调用DAC转换完成回调函数
HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)
HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef *hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
stm32f1xx_hal_dac_ex.c
里,声明放stm32f1xx_hal_dac_ex.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
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/**
* @brief Enables DAC and starts conversion of channel.
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
* the configuration information for the specified DAC.
* @param Channel The selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_CHANNEL_1: DAC Channel1 selected
* @arg DAC_CHANNEL_2: DAC Channel2 selected
* @param pData The destination peripheral Buffer address.
* @param Length The length of data to be transferred from memory to DAC peripheral
* @param Alignment Specifies the data alignment for DAC channel.
* This parameter can be one of the following values:
* @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
* @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
* @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
* @retval HAL status
*/
//HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length,uint32_t Alignment)
HAL_StatusTypeDef HAL_DACEx_Start_DMA_Dual(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length,uint32_t Alignment)
{
HAL_StatusTypeDef status;
uint32_t tmpreg = 0U;
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(Channel));
assert_param(IS_DAC_ALIGN(Alignment));
/* Process locked */
__HAL_LOCK(hdac);
/* Change DAC state */
hdac->State = HAL_DAC_STATE_BUSY;
switch (Alignment)
{
case DAC_ALIGN_12B_R:
/* Get DHR12RD address */
tmpreg = (uint32_t)&hdac->Instance->DHR12RD;
break;
case DAC_ALIGN_12B_L:
/* Get DHR12LD address */
tmpreg = (uint32_t)&hdac->Instance->DHR12LD;
break;
case DAC_ALIGN_8B_R:
/* Get DHR8RD address */
tmpreg = (uint32_t)&hdac->Instance->DHR8RD;
break;
default:
break;
}
if (Channel == DAC_CHANNEL_1)
{
/* Set the DMA transfer complete callback for channel1 */
hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
/* Set the DMA half transfer complete callback for channel1 */
hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
/* Set the DMA error callback for channel1 */
hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
/* Enable the selected DAC channel1 DMA request */
SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
// /* Case of use of channel 1 */
// switch (Alignment)
// {
// case DAC_ALIGN_12B_R:
// /* Get DHR12R1 address */
// tmpreg = (uint32_t)&hdac->Instance->DHR12R1;
// break;
// case DAC_ALIGN_12B_L:
// /* Get DHR12L1 address */
// tmpreg = (uint32_t)&hdac->Instance->DHR12L1;
// break;
// case DAC_ALIGN_8B_R:
// /* Get DHR8R1 address */
// tmpreg = (uint32_t)&hdac->Instance->DHR8R1;
// break;
// default:
// break;
// }
}
else
{
/* Set the DMA transfer complete callback for channel2 */
hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
/* Set the DMA half transfer complete callback for channel2 */
hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
/* Set the DMA error callback for channel2 */
hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
/* Enable the selected DAC channel2 DMA request */
SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
// /* Case of use of channel 2 */
// switch (Alignment)
// {
// case DAC_ALIGN_12B_R:
// /* Get DHR12R2 address */
// tmpreg = (uint32_t)&hdac->Instance->DHR12R2;
// break;
// case DAC_ALIGN_12B_L:
// /* Get DHR12L2 address */
// tmpreg = (uint32_t)&hdac->Instance->DHR12L2;
// break;
// case DAC_ALIGN_8B_R:
// /* Get DHR8R2 address */
// tmpreg = (uint32_t)&hdac->Instance->DHR8R2;
// break;
// default:
// break;
// }
}
/* Enable the DMA Stream */
if (Channel == DAC_CHANNEL_1)
{
#if defined(DAC_CR_DMAUDRIE1)
/* Enable the DAC DMA underrun interrupt */
__HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
#endif /* DAC_CR_DMAUDRIE1 */
/* Enable the DMA Stream */
status = HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
}
else
{
#if defined(DAC_CR_DMAUDRIE2)
/* Enable the DAC DMA underrun interrupt */
__HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
#endif /* DAC_CR_DMAUDRIE2 */
/* Enable the DMA Stream */
status = HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
}
/* Process Unlocked */
__HAL_UNLOCK(hdac);
if (status == HAL_OK)
{
/* Enable the Peripheral */
//__HAL_DAC_ENABLE(hdac, Channel);
__HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
__HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
}
else
{
hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
}
/* Return function status */
return status;
}
/**
* @brief Disables DAC and stop conversion of channel.
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
* the configuration information for the specified DAC.
* @param Channel The selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_CHANNEL_1: DAC Channel1 selected
* @arg DAC_CHANNEL_2: DAC Channel2 selected
* @retval HAL status
*/
//HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
HAL_StatusTypeDef HAL_DACEx_Stop_DMA_Dual(DAC_HandleTypeDef *hdac, uint32_t Channel)
{
HAL_StatusTypeDef status;
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(Channel));
/* Disable the selected DAC channel DMA request */
hdac->Instance->CR &= ~(DAC_CR_DMAEN1 << (Channel & 0x10UL));
/* Disable the Peripheral */
// __HAL_DAC_DISABLE(hdac, Channel);
__HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
__HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
/* Disable the DMA Stream */
/* Channel1 is used */
if (Channel == DAC_CHANNEL_1)
{
/* Disable the DMA Stream */
status = HAL_DMA_Abort(hdac->DMA_Handle1);
#if defined(DAC_CR_DMAUDRIE1)
/* Disable the DAC DMA underrun interrupt */
__HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
#endif /* DAC_CR_DMAUDRIE1 */
}
else /* Channel2 is used for */
{
/* Disable the DMA Stream */
status = HAL_DMA_Abort(hdac->DMA_Handle2);
#if defined(DAC_CR_DMAUDRIE2)
/* Disable the DAC DMA underrun interrupt */
__HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
#endif /* DAC_CR_DMAUDRIE2 */
}
/* Check if DMA Stream effectively disabled */
if (status != HAL_OK)
{
/* Update DAC state machine to error */
hdac->State = HAL_DAC_STATE_ERROR;
}
else
{
/* Change DAC state */
hdac->State = HAL_DAC_STATE_READY;
}
/* Return function status */
return status;
}
1
2
HAL_StatusTypeDef HAL_DACEx_Start_DMA_Dual(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length,uint32_t Alignment);
HAL_StatusTypeDef HAL_DACEx_Stop_DMA_Dual(DAC_HandleTypeDef *hdac, uint32_t Channel);
main.c
文件添加变量1
2
3
4
5
6
7
8
9
10
11
//正弦波单个周期的点数
#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];
1
2
3
4
5
6
7
8
uint32_t Idx;
/* 填充正弦波形数据,双通道右对齐*/
for (Idx = 0; Idx < POINT_NUM; Idx++)
{
DualSine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]);
}
HAL_DACEx_Start_DMA_Dual(&hdac,DAC_CHANNEL_2,DualSine12bit,POINT_NUM,DAC_ALIGN_12B_R);
HAL_TIM_Base_Start(&htim2);
1
2
HAL_DAC_Start_DMA(&hdac,DAC_CHANNEL_1,DualSine12bit,POINT_NUM,DAC_ALIGN_12B_R);
HAL_DAC_Start_DMA(&hdac,DAC_CHANNEL_2,DualSine12bit,POINT_NUM,DAC_ALIGN_12B_R);