正点原子探索者原理图_正点原子【STM32-F407探索者】第二十六章 DAC 实验
1)資料下載:點(diǎn)擊資料即可下載
2)對(duì)正點(diǎn)原子Linux感興趣的同學(xué)可以加群討論:935446741
3)關(guān)注正點(diǎn)原子公眾號(hào),獲取最新資料更新
http://weixin.qq.com/r/hEhUTLbEdesKrfIv9x2W (二維碼自動(dòng)識(shí)別)
上幾章,我們介紹了 STM32F4 的 ADC 使用,本章我們將向大家介紹 STM32F4 的 DAC
功能。在本章中,我們將利用按鍵(或 USMART)控制 STM32F4 內(nèi)部 DAC1 來輸出電壓,
通過 ADC1 的通道 5 采集 DAC 的輸出電壓,在 LCD 模塊上面顯示 ADC 獲取到的電壓值以
及 DAC 的設(shè)定輸出電壓值等信息。本章將分為如下幾個(gè)部分:
26.1 STM32F4 DAC 簡(jiǎn)介
26.2 硬件設(shè)計(jì)
26.3 軟件設(shè)計(jì)
26.4 下載驗(yàn)證
26.1 STM32F4 DAC 簡(jiǎn)介
STM32F4 的 DAC 模塊(數(shù)字/模擬轉(zhuǎn)換模塊)是 12 位數(shù)字輸入,電壓輸出型的 DAC。DAC
可以配置為 8 位或 12 位模式,也可以與 DMA 控制器配合使用。DAC 工作在 12 位模式時(shí),
數(shù)據(jù)可以設(shè)置成左對(duì)齊或右對(duì)齊。DAC 模塊有 2 個(gè)輸出通道,每個(gè)通道都有單獨(dú)的轉(zhuǎn)換器。
在雙 DAC 模式下,2 個(gè)通道可以獨(dú)立地進(jìn)行轉(zhuǎn)換,也可以同時(shí)進(jìn)行轉(zhuǎn)換并同步地更新 2 個(gè)
通道的輸出。DAC 可以通過引腳輸入?yún)⒖茧妷?Vref+(通 ADC 共用)以獲得更精確的轉(zhuǎn)換
結(jié)果。
STM32F4 的 DAC 模塊主要特點(diǎn)有:
① 2 個(gè) DAC 轉(zhuǎn)換器:每個(gè)轉(zhuǎn)換器對(duì)應(yīng) 1 個(gè)輸出通道
② 8 位或者 12 位單調(diào)輸出
③ 12 位模式下數(shù)據(jù)左對(duì)齊或者右對(duì)齊
④ 同步更新功能
⑤ 噪聲波形生成
⑥ 三角波形生成
⑦ 雙 DAC 通道同時(shí)或者分別轉(zhuǎn)換
⑧ 每個(gè)通道都有 DMA 功能
單個(gè) DAC 通道的框圖如圖 26.1.1 所示:
圖 26.1.1 DAC 通道模塊框圖圖中 VDDA 和 VSSA 為 DAC 模塊模擬部分的供電,而 Vref+則是 DAC 模塊的參考電
壓。DAC_OUTx 就是 DAC 的輸出通道了(對(duì)應(yīng) PA4 或者 PA5 引腳)。
從圖 26.1.1 可以看出,DAC 輸出是受 DORx 寄存器直接控制的,但是我們不能直接往
DORx 寄存器寫入數(shù)據(jù),而是通過 DHRx 間接的傳給 DORx 寄存器,實(shí)現(xiàn)對(duì) DAC 輸出的控
制。前面我們提到,STM32F4 的 DAC 支持 8/12 位模式,
8 位模式的時(shí)候是固定的右對(duì)齊的,
而 12 位模式又可以設(shè)置左對(duì)齊/右對(duì)齊。單 DAC 通道 x,總共有 3 種情況:
① 8位數(shù)據(jù)右對(duì)齊:用戶將數(shù)據(jù)寫入DAC_DHR8Rx[7:0]位(實(shí)際存入DHRx[11:4]位)。
② 12 位數(shù)據(jù)左對(duì)齊:用戶將數(shù)據(jù)寫入 DAC_DHR12Lx[15:4]位(實(shí)際存入 DHRx[11:0]
位)。
③ 12 位數(shù)據(jù)右對(duì)齊:用戶將數(shù)據(jù)寫入 DAC_DHR12Rx[11:0]位(實(shí)際存入 DHRx[11:0]
位)。
我們本章使用的就是單 DAC 通道 1,采用 12 位右對(duì)齊格式,所以采用第③種情況。
如果沒有選中硬件觸發(fā)(寄存器 DAC_CR1 的 TENx 位置’0’
),存入寄存器 DAC_DHRx
的數(shù)據(jù)會(huì)在一個(gè) APB1 時(shí)鐘周期后自動(dòng)傳至寄存器 DAC_DORx。如果選中硬件觸發(fā)(寄存器
DAC_CR1 的 TENx 位置’1’),數(shù)據(jù)傳輸在觸發(fā)發(fā)生以后 3 個(gè) APB1 時(shí)鐘周期后完成。 一
旦數(shù)據(jù)從 DAC_DHRx 寄存器裝入 DAC_DORx 寄存器,在經(jīng)過時(shí)間
之后,輸出即有效,這段時(shí)間的長(zhǎng)短依電源電壓和模擬輸出負(fù)載的不同會(huì)有所變化。我們可以從
STM32F407ZGT6 的數(shù)據(jù)手冊(cè)查到
的典型值為 3us,最大是 6us。所以 DAC 的轉(zhuǎn)
換速度最快是 333K 左右。
本章我們將不使用硬件觸發(fā)(TEN=0),其轉(zhuǎn)換的時(shí)間框圖如圖 26.1.2 所示:
圖 26.1.2 TEN=0 時(shí) DAC 模塊轉(zhuǎn)換時(shí)間框圖DAC_CR 的低 16 位用于控制通道 1,而高 16 位用于控制通道 2,我們這里僅列出比較
重要的最低 8 位的詳細(xì)描述,如圖 26.1.4 所示:
圖 26.1.4 寄存器 DAC_CR 低八位詳細(xì)描述首先,我們來看 DAC 通道 1 使能位(EN1),該位用來控制 DAC 通道 1 使能的,本章我
們就是用的 DAC 通道 1,所以該位設(shè)置為 1。
再看關(guān)閉 DAC 通道 1 輸出緩存控制位(BOFF1),這里 STM32F4 的 DAC 輸出緩存做
的有些不好,如果使能的話,雖然輸出能力強(qiáng)一點(diǎn),但是輸出沒法到 0,這是個(gè)很嚴(yán)重的問
題。所以本章我們不使用輸出緩存。即設(shè)置該位為 1。
DAC 通道 1 觸發(fā)使能位(TEN1),該位用來控制是否使用觸發(fā),里我們不使用觸發(fā),
所以設(shè)置該位為 0。
DAC 通道 1 觸發(fā)選擇位(TSEL1[2:0]),這里我們沒用到外部觸發(fā),所以設(shè)置這幾個(gè)位
為 0 就行了。
DAC 通道 1 噪聲/三角波生成使能位(WAVE1[1:0]),這里我們同樣沒用到波形發(fā)生器,
故也設(shè)置為 0 即可。
DAC 通道 1 屏蔽/復(fù)制選擇器(MAMP[3:0]),這些位僅在使用了波形發(fā)生器的時(shí)候有
用,本章沒有用到波形發(fā)生器,故設(shè)置為 0 就可以了。
最后是 DAC 通道 1 DMA 使能位(DMAEN1),本章我們沒有用到 DMA 功能,故還是
設(shè)置為 0。
通道 2 的情況和通道 1 一模一樣,這里就不不細(xì)說了。在 DAC_CR 設(shè)置好之后,DAC
就可以正常工作了,我們僅需要再設(shè)置 DAC 的數(shù)據(jù)保持寄存器的值,就可以在 DAC 輸出
通道得到你想要的電壓了(對(duì)應(yīng) IO 口設(shè)置為模擬輸入)。本章,我們用的是 DAC 通道 1 的
12 位右對(duì)齊數(shù)據(jù)保持寄存器:DAC_DHR12R1,該寄存器各位描述如圖 26.1.5 所示:
圖 26.1.5 寄存器 DAC_DHR12R1 各位描述該寄存器用來設(shè)置 DAC 輸出,通過寫入 12 位數(shù)據(jù)到該寄存器,就可以在 DAC 輸出通
道 1(PA4)得到我們所要的結(jié)果。
通過以上介紹,我們了解了 STM32F4 實(shí)現(xiàn) DAC 輸出的相關(guān)設(shè)置,本章我們將使用 DAC
模塊的通道 1 來輸出模擬電壓。這里我們用到的庫函數(shù)以及相關(guān)定義分布在文件
stm32f4xx_dac.c 以及頭文件 stm32f4xx_dac.h 中。實(shí)現(xiàn)上面功能的詳細(xì)設(shè)置步驟如下:
1)開啟 PA 口時(shí)鐘,設(shè)置 PA4 為模擬輸入。
STM32F407ZGT6 的 DAC 通道 1 是接在 PA4 上的,所以,我們先要使能 GPIOA 的時(shí)
鐘,然后設(shè)置 PA4 為模擬輸入。
這里需要特別說明一下,雖然 DAC 引腳設(shè)置為輸入,但是 STM32F4 內(nèi)部會(huì)連接在 DAC
模擬輸出上,這在我們引腳復(fù)用映射章節(jié)有講解。程序如下:
__HAL_RCC_DAC_CLK_ENABLE();
//使能 DAC 時(shí)鐘
__HAL_RCC_GPIOA_CLK_ENABLE();
//開啟 GPIOA 時(shí)鐘
GPIO_Initure.Pin=GPIO_PIN_4; //PA4
GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模擬
GPIO_Initure.Pull=GPIO_NOPULL;
//不帶上下拉
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
對(duì)于 DAC 通道與引腳對(duì)應(yīng)關(guān)系,這在 STM32F4 的數(shù)據(jù)手冊(cè)引腳表上有列出,如下圖:
圖 26.1.6 DAC 通道引腳對(duì)應(yīng)關(guān)系2)初始化 DAC,設(shè)置 DAC 的工作模式。
HAL 庫中提供了一個(gè) DAC 初始化函數(shù) HAL_DAC_Init,該函數(shù)聲明如下:
HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef* hdac);
該函數(shù)并沒有設(shè)置任何 DAC 相關(guān)寄存器,也就是說沒有對(duì) DAC 進(jìn)行任何配置,它只
是 HAL 庫提供用來在軟件上初始化 DAC,也就是說,為后面 HAL 庫操作 DAC 做好準(zhǔn)備。
它有一個(gè)很重要的作用就是在函數(shù)內(nèi)部會(huì)調(diào)用 DAC 的 MSP 初始化函數(shù) HAL_DAC_MspInit,
該函數(shù)聲明如下:
void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac);
一般情況下,步驟 1 中的與 MCU 相關(guān)的時(shí)鐘使能和 IO 口配置都放在該函數(shù)中實(shí)現(xiàn)。
HAL 庫提供了一個(gè)很重要的 DAC 配置函數(shù) HAL_DAC_ConfigChannel,該函數(shù)用來配
置 DAC 通道的觸發(fā)類型以及輸出緩沖。該函數(shù)聲明如下:
HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef* hdac,
DAC_ChannelConfTypeDef* sConfig, uint32_t Channel);
第一個(gè)入口參數(shù)非常簡(jiǎn)單,為 DAC 初始化句柄,和 HAL_DAC_Init 保存一致即可。
第三個(gè)入口參數(shù) Channel 用來配置 DAC 通道,比如我們使用 PA4,也就是 DAC 通道 1,
所以配置值為 DAC_CHANNEL_1 即可。
接下來我們看看第二個(gè)入口參數(shù) sConfig,該參數(shù)是 DAC_ChannelConfTypeDef 結(jié)構(gòu)體
指針類型,結(jié)構(gòu)體 DAC_ChannelConfTypeDef 定義如下:
typedef struct
{
uint32_t DAC_Trigger;
// DAC 觸發(fā)類型
uint32_t DAC_OutputBuffer; //輸出緩沖
}DAC_ChannelConfTypeDef;
成員變量DAC_Trigger 用來設(shè)置DAC 觸發(fā)類型,DAC_OutputBuffer 用來設(shè)置輸出緩沖,
這在我們前面都有講解。DAC 初始化配置實(shí)例代碼如下:
DAC_HandleTypeDef DAC1_Handler;
DAC_ChannelConfTypeDef DACCH1_Config;
DAC1_Handler.Instance=DAC;
HAL_DAC_Init(&DAC1_Handler); //初始化 DAC
DACCH1_Config.DAC_Trigger=DAC_TRIGGER_NONE; //不使用觸發(fā)功能
DACCH1_Config.DAC_OutputBuffer=DAC_OUTPUTBUFFER_DISABLE;
HAL_DAC_ConfigChannel(&DAC1_Handler,&DACCH1_Config,DAC_CHANNEL_1);
3)使能 DAC 轉(zhuǎn)換通道
初始化 DAC 之后,理所當(dāng)然要使能 DAC 轉(zhuǎn)換通道,HAL 庫函數(shù)是:
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel);
該函數(shù)非常簡(jiǎn)單,第一個(gè)參數(shù)是 DAC 句柄,第二個(gè)用來設(shè)置 DAC 通道。
4)設(shè)置 DAC 的輸出值。
通過前面 3 個(gè)步驟的設(shè)置,DAC 就可以開始工作了,我們使用 12 位右對(duì)齊數(shù)據(jù)格式,,
就可以在 DAC 輸出引腳(PA4)得到不同的電壓值了,HAL 庫函數(shù)為:
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac,
uint32_t Channel, uint32_t Alignment, uint32_t Data);
該函數(shù)從入口參數(shù)可以看出,它是配置 DAC 的通道輸出值,同時(shí)通過第三個(gè)入口參數(shù)
設(shè)置對(duì)齊方式。
最后,再提醒一下大家,本例程,我們使用的是 3.3V 的參考電壓, 即 Vref+ 連 接
VDDA。
通過以上幾個(gè)步驟的設(shè)置,我們就能正常的使用 STM32F4 的 DAC 通道 1 來輸出不同
的模擬電壓了。
26.2 硬件設(shè)計(jì)
本章用到的硬件資源有:
1) 指示燈 DS0
2) KEY_UP 和 KEY1 按鍵
3) 串口
4) TFTLCD 模塊
5) ADC
6) DAC
本章,我們使用 DAC 通道 1 輸出模擬電壓,然后通過 ADC1 的通道 1 對(duì)該輸出電壓進(jìn)
行讀取,并顯示在 LCD 模塊上面,DAC 的輸出電壓,我們通過按鍵(或 USMART)進(jìn)行
設(shè)置。
我們需要用到 ADC 采集 DAC 的輸出電壓,所以需要在硬件上把他們短接起來。ADC
和 DAC 的連接原理圖如圖 26.2.1 所示:
圖 26.2.1 ADC、DAC 與 STM32F4 連接原理圖P12 是多功能端口,我們只需要通過跳線帽短接 P14 的 ADC 和 DAC,就可以開始做本
章實(shí)驗(yàn)了。如圖 26.2.2 所示:
圖 26.2.2 硬件連接示意圖26.3 軟件設(shè)計(jì)
打開本章實(shí)驗(yàn)工程可以發(fā)現(xiàn),我們相比 ADC 實(shí)驗(yàn),在庫函數(shù)中主要是添加了 dac 支持
的相關(guān)文件 stm32f4xx_hal_dac.c 以及包含頭文件 stm32f4xx_hal_dac.h。同時(shí)我們?cè)?
HARDWARE 分組下面新建了 dac.c 源文件以及包含對(duì)應(yīng)的頭文件 dac.h。這兩個(gè)文件用來存
放我們編寫的 ADC 相關(guān)函數(shù)和定義。打開 dac.c,代碼如下:
DAC_HandleTypeDef DAC1_Handler;//DAC 句柄
//初始化 DAC
void DAC1_Init(void)
{
DAC_ChannelConfTypeDef DACCH1_Config;
DAC1_Handler.Instance=DAC;
HAL_DAC_Init(&DAC1_Handler); //初始化 DAC
DACCH1_Config.DAC_Trigger=DAC_TRIGGER_NONE; //不使用觸發(fā)功能
DACCH1_Config.DAC_OutputBuffer=DAC_OUTPUTBUFFER_DISABLE;
//DAC1 輸出緩沖關(guān)閉
HAL_DAC_ConfigChannel(&DAC1_Handler,&DACCH1_Config,
DAC_CHANNEL_1);//DAC 通道 1 配置
HAL_DAC_Start(&DAC1_Handler,DAC_CHANNEL_1); //開啟 DAC 通道 1
}
//DAC 底層驅(qū)動(dòng),時(shí)鐘配置,引腳 配置
//此函數(shù)會(huì)被 HAL_DAC_Init()調(diào)用
//hdac:DAC 句柄
void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_DAC_CLK_ENABLE();
//使能 DAC 時(shí)鐘
__HAL_RCC_GPIOA_CLK_ENABLE();
//開啟 GPIOA 時(shí)鐘
GPIO_Initure.Pin=GPIO_PIN_4;
//PA4
GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模擬
GPIO_Initure.Pull=GPIO_NOPULL;
//不帶上下拉
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
//設(shè)置通道 1 輸出電壓
//vol:0~3300,代表 0~3.3V
void DAC1_Set_Vol(u16 vol)
{
double temp=vol;
temp/=1000;
temp=temp*4096/3.3;
HAL_DAC_SetValue(&DAC1_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,
temp);//12 位右對(duì)齊數(shù)據(jù)格式設(shè)置 DAC 值
}
此部分代碼就 2 個(gè)函數(shù),Dac1_Init 函數(shù)用于初始化 DAC 通道 1。這里基本上是按我們
上面的步驟來初始化的,我們用序號(hào)①~⑤已經(jīng)標(biāo)示這些步驟。經(jīng)過這個(gè)初始化之后,我們
就可以正常使用 DAC 通道 1 了。第二個(gè)函數(shù) Dac1_Set_Vol,用于設(shè)置 DAC 通道 1 的輸出
電壓,實(shí)際就是將電壓值轉(zhuǎn)換為 DAC 輸入值。
其他頭文件代碼就比較簡(jiǎn)單,這里我們不做過多講解,接下來我們來看看主函數(shù)代碼:
int main(void)
{
u16 adcx;
float temp;
u8 t=0;
u16 dacval=0;
u8 key;
HAL_Init();
//初始化 HAL 庫
Stm32_Clock_Init(336,8,2,7);
//設(shè)置時(shí)鐘,168Mhz
delay_init(168);
//初始化延時(shí)函數(shù)
uart_init(115200);
//初始化 USART
usmart_dev.init(84);
//初始化 USMART
LED_Init();
//初始化 LED
KEY_Init();
//初始化 KEY
LCD_Init();
//初始化 LCD
MY_ADC_Init(); //初始化 ADC1
DAC1_Init();
//初始化 DAC1
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"DAC TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2017/4/13");
LCD_ShowString(30,130,200,16,16,"WK_UP:+ KEY1:-");
POINT_COLOR=BLUE;//設(shè)置字體為藍(lán)色
LCD_ShowString(30,150,200,16,16,"DAC VAL:");
LCD_ShowString(30,170,200,16,16,"DAC VOL:0.000V");
LCD_ShowString(30,190,200,16,16,"ADC VOL:0.000V");
DAC_SetChannel1Data(DAC_Align_12b_R,dacval);//初始值為 0
while(1)
{
t++;
key=KEY_Scan(0);
if(key==WKUP_PRES)
{
if(dacval<4000)dacval+=200;
DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//設(shè)置 DAC 值
}else if(key==2)
{
if(dacval>200)dacval-=200;
else dacval=0;
DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//設(shè)置 DAC 值
}
if(t==10||key==KEY1_PRES||key==WKUP_PRES)
//WKUP/KEY1 按下了,或者定時(shí)時(shí)間到了
{
adcx=DAC_GetDataOutputValue(DAC_Channel_1);]
//讀取前面設(shè)置 DAC 的值
LCD_ShowxNum(94,150,adcx,4,16,0); //顯示 DAC 寄存器值
temp=(float)adcx*(3.3/4096);
//得到 DAC 電壓值
adcx=temp;
LCD_ShowxNum(94,170,temp,1,16,0);//顯示電壓值整數(shù)部分
temp-=adcx;
temp*=1000;
LCD_ShowxNum(110,170,temp,3,16,0X80); //顯示電壓值的小數(shù)部分
adcx=Get_Adc_Average(ADC_Channel_5,10); //得到 ADC 轉(zhuǎn)換值
temp=(float)adcx*(3.3/4096);
//得到 ADC 電壓值
adcx=temp;
LCD_ShowxNum(94,190,temp,1,16,0);
//顯示電壓值整數(shù)部分
temp-=adcx;
temp*=1000;
LCD_ShowxNum(110,190,temp,3,16,0X80); //顯示電壓值的小數(shù)部分
LED0=!LED0;
t=0;
}
delay_ms(10);
}
}
此部分代碼,我們先對(duì)需要用到的模塊進(jìn)行初始化,然后顯示一些提示信息,本章我們
通過 KEY_UP(WKUP 按鍵)和 KEY1(也就是上下鍵)來實(shí)現(xiàn)對(duì) DAC 輸出的幅值控制。
按下 KEY_UP 增加,按 KEY1 減小。同時(shí)在 LCD 上面顯示 DHR12R1 寄存器的值、DAC
設(shè)計(jì)輸出電壓以及 ADC 采集到的 DAC 輸出電壓。
26.4 下載驗(yàn)證
在代碼編譯成功之后,我們通過下載代碼到 ALIENTEK 探索者 STM32F4 開發(fā)板上,
可以看到 LCD 顯示如圖 26.4.1 所示:
圖 26.4.1 DAC 實(shí)驗(yàn)測(cè)試圖同時(shí)伴隨 DS0 的不停閃爍,提示程序在運(yùn)行。此時(shí),我們通過按 KEY_UP 按鍵,可以
看到輸出電壓增大,按 KEY1 則變小。
總結(jié)
以上是生活随笔為你收集整理的正点原子探索者原理图_正点原子【STM32-F407探索者】第二十六章 DAC 实验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 弹出窗口显示输出内容_前端加油站(3)-
- 下一篇: js实现撤销恢复_我们常用的撤销和恢复功