DAC 实验
STM32F4 的 DAC 模塊(數(shù)字/模擬轉(zhuǎn)換模塊)是 12 位數(shù)字輸入,電壓輸出型的 DAC。DAC 可以配置為 8 位或 12 位模式,也可以與 DMA 控制器配合使用。DAC 工作在 12 位模式時, 數(shù)據(jù)可以設(shè)置成左對齊或右對齊。DAC 模塊有 2 個輸出通道,每個通道都有單獨(dú)的轉(zhuǎn)換器。 在雙 DAC 模式下,2 個通道可以獨(dú)立地進(jìn)行轉(zhuǎn)換,也可以同時進(jìn)行轉(zhuǎn)換并同步地更新 2 個 通道的輸出。DAC 可以通過引腳輸入?yún)⒖茧妷?Vref+(通 ADC 共用)以獲得更精確的轉(zhuǎn)換 結(jié)果。
STM32F4 的 DAC 模塊主要特點(diǎn)有:
① 2 個 DAC 轉(zhuǎn)換器:每個轉(zhuǎn)換器對應(yīng) 1 個輸出通道
② 8 位或者 12 位單調(diào)輸出
③ 12 位模式下數(shù)據(jù)左對齊或者右對齊
④ 同步更新功能
⑤ 噪聲波形生成
⑥ 三角波形生成
⑦ 雙 DAC 通道同時或者分別轉(zhuǎn)換
⑧ 每個通道都有 DMA 功能
?圖中 VDDA 和 VSSA 為 DAC 模塊模擬部分的供電,而 Vref+則是 DAC 模塊的參考電壓。DAC_OUTx 就是 DAC 的輸出通道了(對應(yīng) PA4 或者 PA5 引腳)。 DAC 輸出是受 DORx 寄存器直接控制的,但是我們不能直接往 DORx 寄存器寫入數(shù)據(jù),而是通過 DHRx 間接的傳給 DORx 寄存器,實(shí)現(xiàn)對 DAC 輸出的控制。STM32F4 的 DAC 支持 8/12 位模式,8 位模式的時候是固定的右對齊的, 而 12 位模式又可以設(shè)置左對齊/右對齊。單 DAC 通道 x,總共有 3 種情況:
① 8位數(shù)據(jù)右對齊:用戶將數(shù)據(jù)寫入DAC_DHR8Rx[7:0]位(實(shí)際存入DHRx[11:4]位)。 ?
② 12 位數(shù)據(jù)左對齊:用戶將數(shù)據(jù)寫入 DAC_DHR12Lx[15:4]位(實(shí)際存入 DHRx[11:0] 位)。
③ 12 位數(shù)據(jù)右對齊:用戶將數(shù)據(jù)寫入 DAC_DHR12Rx[11:0]位(實(shí)際存入 DHRx[11:0] 位)。
如果沒有選中硬件觸發(fā)(寄存器 DAC_CR1 的 TENx 位置’0’),存入寄存器 DAC_DHRx 的數(shù)據(jù)會在一個 APB1 時鐘周期后自動傳至寄存器 DAC_DORx。如果選中硬件觸發(fā)(寄存器 DAC_CR1 的 TENx 位置’1’),數(shù)據(jù)傳輸在觸發(fā)發(fā)生以后 3 個 APB1 時鐘周期后完成。 一 旦數(shù)據(jù)從 DAC_DHRx 寄存器裝入 DAC_DORx 寄存器,在經(jīng)過時間 之后,輸出即有效,這段時間的長短依電源電壓和模擬輸出負(fù)載的不同會有所變化。我們可以從 STM32F407ZGT6 的數(shù)據(jù)手冊查到 的典型值為 3us,最大是 6us。所以 DAC 的轉(zhuǎn)換速度最快是 333K 左右。
當(dāng) DAC 的參考電壓為 Vref+的時候,DAC 的輸出電壓是線性的從 0~Vref+,12 位模式 下 DAC 輸出電壓與 Vref+以及 DORx 的計(jì)算公式如下:
DACx 輸出電壓=Vref*(DORx/4095)
1)開啟 PA 口時鐘,設(shè)置 PA4 為模擬輸入。
STM32F407ZGT6 的 DAC 通道 1 是接在 PA4 上的,所以,先要使能 GPIOA 的時鐘,然后設(shè)置 PA4 為模擬輸入。 這里需要特別說明一下,雖然 DAC 引腳設(shè)置為輸入,但是 STM32F4 內(nèi)部會連接在 DAC 模擬輸出上。
?
?2)使能 DAC1 時鐘。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能 DAC 時鐘3)初始化 DAC,設(shè)置 DAC 的工作模式。
該部分設(shè)置全部通過 DAC_CR 設(shè)置實(shí)現(xiàn),包括:DAC 通道 1 使能、DAC 通道 1 輸出 緩存關(guān)閉、不使用觸發(fā)、不使用波形發(fā)生器等設(shè)置。這里 DAC 初始化是通過函數(shù) DAC_Init 完成的:
void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct);
跟前面一樣,首先我們來看看參數(shù)設(shè)置結(jié)構(gòu)體類型 DAC_InitTypeDef 的定義:
typedef struct
{
uint32_t DAC_Trigger;
uint32_t DAC_WaveGeneration;
uint32_t DAC_LFSRUnmask_TriangleAmplitude;
uint32_t DAC_OutputBuffer;
}DAC_InitTypeDef;
第一個參數(shù) DAC_Trigger 用來設(shè)置是否使用觸發(fā)功能。 第二個參數(shù) DAC_WaveGeneratio 用來設(shè)置是否使用波形發(fā)生。 第三個參數(shù) DAC_LFSRUnmask_TriangleAmplitude 用來設(shè)置屏蔽/幅值選擇器,這個變量只在使用波形發(fā)生器的時候才有用,這里設(shè)置為 0 即可,值為 DAC_LFSRUnmask_Bit0。 第四個參數(shù) DAC_OutputBuffer 是用來設(shè)置輸出緩存控制位,因?yàn)槭褂幂敵鼍彺鎸⒉荒茌敵?,所以我們不使用。
DAC_InitTypeDef DAC_InitType; DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用觸發(fā)功能 TEN1=0 DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形發(fā)生 DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0; DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1 輸出緩存關(guān)閉 DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化 DAC 通道 14)使能 DAC 轉(zhuǎn)換通道 初始化 DAC 之后,要使能 DAC 轉(zhuǎn)換通道:
DAC_Cmd(DAC_Channel_1, ENABLE); //使能 DAC 通道 15)設(shè)置 DAC 的輸出值。 通過前面 4 個步驟的設(shè)置,DAC 就可以開始工作了,我們使用 12 位右對齊數(shù)據(jù)格式, 所以通過設(shè)置 DHR12R1,就可以在 DAC 輸出引腳(PA4)得到不同的電壓值了。設(shè)置 DHR12R1 的庫函數(shù)是:
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12 位右對齊數(shù)據(jù)格式設(shè)置 DAC 值第一個參數(shù)設(shè)置對齊方式,可以為 12 位右對齊 DAC_Align_12b_R,12 位左對齊 DAC_Align_12b_L 以及 8 位右對齊 DAC_Align_8b_R 方式。 第二個參數(shù)就是 DAC 的輸入值了,這個很好理解,初始化設(shè)置為 0。
還可以讀出 DAC 對應(yīng)通道最后一次轉(zhuǎn)換的數(shù)值,函數(shù)是: DAC_GetDataOutputValue(DAC_Channel_1)
硬件連接:
我們使用 DAC 通道 1 輸出模擬電壓,然后通過 ADC1 的通道 1 對該輸出電壓進(jìn)行讀取,并打印,DAC 的輸出電壓,我們通過按鍵(或 USMART)進(jìn)行設(shè)置。 我們需要用到 ADC 采集 DAC 的輸出電壓,所以需要在硬件上把他們短接起來。
P12 是多功能端口,只需要通過跳線帽短接 P14 的 ADC 和 DAC,就可以了。?
?程序:
//DAC 通道 1 輸出初始化 void Dac1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;DAC_InitTypeDef DAC_InitType;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能 PA 時鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能 DAC 時鐘GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模擬輸入GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 GPIODAC_InitType.DAC_Trigger=DAC_Trigger_None;//不使用觸發(fā)功能 TEN1=0DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形發(fā)生DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0; //屏蔽、幅值設(shè)置DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ;/輸出緩存關(guān)閉DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化 DAC 通道 1DAC_Cmd(DAC_Channel_1, ENABLE); //使能 DAC 通道 1DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12 位右對齊數(shù)據(jù)格式 } //設(shè)置通道 1 輸出電壓 //vol:0~3300,代表 0~3.3V void Dac1_Set_Vol(u16 vol) {double temp=vol;temp/=1000;temp=temp*4096/3.3;DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12 位右對齊數(shù)據(jù)格式 }main函數(shù)
int main(void) { u16 adcx;float temp;u8 t=0; u16 dacval=0;u8 key; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置系統(tǒng)中斷優(yōu)先級分組2delay_init(168); //初始化延時函數(shù)uart_init(115200); //初始化串口波特率為115200LED_Init(); //初始化LED Adc_Init(); //adc初始化KEY_Init(); //按鍵初始化Dac1_Init(); //DAC通道1初始化 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按下了,或者定時時間到了{(lán) adcx=DAC_GetDataOutputValue(DAC_Channel_1);//讀取前面設(shè)置DAC的值printf("DAC:%d\t",adcx); //顯示DAC寄存器值temp=(float)adcx*(3.3/4096); //得到DAC電壓值printf("DAC_V:%.2f\t",temp); //顯示電壓值整數(shù)部分adcx=Get_Adc_Average(ADC_Channel_5,10); //得到ADC轉(zhuǎn)換值 temp=(float)adcx*(3.3/4096); //得到ADC電壓值printf("ADC_V:%.2f\r\n",temp); LED0=!LED0; t=0;} delay_ms(10); } }運(yùn)行結(jié)果:
第一個為設(shè)置的DAC的值,第二個為設(shè)置的電壓值,第三個為ADC測量的電壓值。
DAC實(shí)驗(yàn)
總結(jié)
- 上一篇: uIP介绍
- 下一篇: 手把手教你怎样简单利用GitHub实现合