終于逮了個忙里偷閑的機會,就再學一下LPC1768的外圍功能吧,循序漸進是學習的基本規則,也許LPC1768的DAC與8位單片機16位單片機里面集成的DAC操作類似,但是既然這是懶貓的學習日志,就順便把DAC再好好復習一下了,或許能品出個什么味來^_^DAC是Digital to Analog Converter的縮寫,中文名就是數模轉換器,D/A轉換器一般由數碼寄存器、模擬電子開關電路、解碼網絡、求和電路及基準電壓等幾部分組成。如下圖所示:
圖1-1 DAC原理框圖 數字量以串行或并行方式輸入,存儲于數碼寄存器中,數碼寄存器輸出的名位數碼分別控制對應的模擬開關,使數碼為1的位在位權網絡上產生與其值成正比的電流值或電壓值,再由求和電路將各權值相加,即得到數字量對應的模擬量。按解碼網絡結構不同可以將DAC轉換器分成T 型電阻網絡D/A轉換器、倒T型電阻網絡D/A轉換器、權電流D/A轉換器、權電阻網絡轉換器。 1、 T型電阻網絡D/A轉換器,其簡單模型如下圖所示:
圖1-2 T型電阻網絡D/A轉換器模型 2、 倒T型電阻網絡D/A轉換器簡易模型
圖1-3 倒T型電阻網絡D/A轉換器 3、 權電流D/A轉換器簡易模型如下圖所示: 圖1-4 權電流D/A轉換器簡易模型 4、 權電阻網絡轉換器簡易模型如下圖所示: 圖 1-5 權電阻網絡轉換器簡易模型 按模擬電子開關的電路的不同,也可以將D/A轉換器分為CMOS開關型D/A轉換器(速度要求不高),雙極型D/A轉換器。而雙極型D/A轉換器雙可以劃分為電流開關型(速度要求較高)與ECL電流開關型(轉換速度更高)兩種。如果對歐姆定律不陌生的話,我想上面各個模型是如何輸出電壓的應該就可以理解了,在這里就不總結公式了,因為這只是模型,對應,實際電路與模型是有所出入的,在實際應用中要著重關注一下以下幾個參數: 1、 分辨率 D/A轉換器的分辨率用最小分辨電壓VLSB與滿量程輸出電壓VFSV的比值來表示: 從上式可以看出D/A轉換器的分辨率只與輸入二進制數的位數n有關,因此大部分情況下我們直接把n做為分辨率如8位,10位,12位等,由此我們也可以知道分辨率值越小,分辨能力越高。 2、 轉換精度 在D/A轉換器中,一般用轉換誤差來描述轉換精度。DAC轉換誤差是指實際輸出模擬電壓值與理想值的最大偏差。轉換誤差是一個綜合性的靜態指標,主要由三部分構成: 1)非線性誤差:一般是由于模擬電子開關的導通電阻和導通壓降及R、2R電阻值的偏差引起。 2)漂移誤差:一般是由于運算放大器的零點漂移引起。 3)增益誤差:一般是由于參考電壓偏離標準值、運放增益不穩定引起。 3、 轉換速度 轉換速度一般由建立時間決定,從輸入由全0突變全1起,到輸出電壓穩定(最大輸出電壓正負二分之一最小輸出電壓)止,稱為DAC轉換時間。它是DAC最大響應時間。例如,DAC 5G7520響應時間不大于500ns。 除了以上三個常見的指標D/A轉換器的指標還包括電源抑制比、功率消耗、溫度系數以及輸入高、低邏輯電平的數值等技術指標。關于D/A的應用,應該說在電子系統中應用相當廣泛,除了在微機系統中將數字量轉換為模擬量典型應用之外,還常用于波形生成,名種數字式的或編程應用等。 好了,關于D/A轉換器的知識暫時總結到這,更深入的知道還需要翻一下模電,信號與線性系統(好像里面有奈奎斯特定理,與采樣有關),微電子,放大器等方面的書籍。下面簡單總結一下LPC1768內部集成的D/A轉換器。LPC1768內部集成的是10位模數轉換器,它是電阻串聯結構的,并且帶有緩沖輸出,最大輸出頻率為1MHz。電阻串聯結構模型如下圖所示: 圖 1-6 電阻串聯結構 涉及到D/A的引腳主要有DAC輸出腳P0.26,參考電壓引腳,用來給D/A轉換器提供參考電壓,模擬電源與數字電源VDD/VSS,這個兩個電源要分開提供,再不使用DAC時也要將這兩個引腳連接到電源,不能懸空,不然系統會不穩定。 DAC的配置也很簡單,首先就是將P0.26設置為DAC模式,再一個就是配置DAC控制寄存器DACDR。DAC的控制寄存器DACDR的6-15位是DAC的輸出電壓數字值,這個數字決定了要輸出的電壓大小,DAC輸出電壓的計算方法是: 公式中VDAC即指AC的控制寄存器DACDR的6-15位的值,VREF指的是參考電壓,在這次實驗電路中用的是3.3V。LPC1768的DAC功能還有DAM中斷和定時控制功能,它采用又緩沖方式輸出。在這里簡單總結一下DAM模式,所謂的DAM模式也就是Direct Memory Access,漢語的意思就是直接內存訪問,是一種不經過CPU而直接從內存存取數據的數據交換模式。在DMA模式下,CPU只須向DMA控制器下達指令,讓DMA控制器來處理數據的傳送,數據傳送完畢再把信息反饋給CPU,這樣就很大程度上減輕了CPU資源占有率,可以大大節省系統資源。DMA模式又可以分為Single-Word DMA(單字節DMA)和Multi-Word DMA(多字節DMA)兩種,其中所能達到的最大傳輸速率也只有16.6MB/s。DMA有兩個技術特征,首先是直接傳送,其次是塊傳送。 DMA工作過程 ⑴ 當進程要求設備輸入數據時,CPU把準備存放輸入數據的內存起始地址以及要傳送的字節數分別送入DMA控制器中的內存地址寄存器和傳送字節計數器。 ⑵ 發出數據傳輸要求的進行進入等待狀態。此時正在執行的CPU指令被暫時掛起。進程調度程序調度其他進程占據CPU。 ⑶ 輸入設備不斷地竊取CPU工作周期,將數據緩沖寄存器中的數據源源不斷地寫入內存,直到所要求的字節全部傳送完畢。 ⑷ DMA控制器在傳送完所有字節時,通過中斷請求線發出中斷信號。CPU在接收到中斷信號后,轉入中斷處理程序進行后續處理。 ⑸ 中斷處理結束后,CPU返回到被中斷的進程中,或切換到新的進程上下文環境中,繼續執行。 DMA與中斷的區別 ⑴ 中斷方式是在數據緩沖寄存器滿之后發出中斷,要求CPU進行中斷處理,而DMA方式則是在所要求傳送的數據塊全部傳送結束時要求CPU 進行中斷處理。這就大大減少了CPU進行中斷處理的次數。 ⑵ 中斷方式的數據傳送是在中斷處理時由CPU控制完成的,而DMA方式則是在DMA控制器的控制下,不經過CPU控制完成的。這就排除了CPU因并行設備過多而來不及處理以及因速度不匹配而造成數據丟失等現象。 在DMA方式中,由于I/O設備直接同內存發生成塊的數據交換,因此I/O效率比較高。由于DMA技術可以提高I/O效率,因此在現代計算機系統中,得到了廣泛的應用。許多輸入輸出設備的控制器,特別是塊設備的控制器,都支持DMA方式。 通過上述分析可以看出,DMA控制器功能的強弱,是決定DMA效率的關鍵因素。DMA控制器需要為每次數據的傳送做大量的工作,數據傳送單位的增大意味著傳送次數的減少。另外,DMA方式竊取了時鐘周期,CPU處理效率降低了,要想盡量少地竊取時鐘周期,就要設法提高DMA控制器的性能,這樣可以較少地影響CPU出理效率。 好了,關于DAM的知識先總結到這,要想使用LPC1768的DAM功能,需要配置D/A轉換控制寄存器DACCTRL與DAC轉換計數寄存器DACCNTVAL。這次實驗只是簡單的學習怎樣使用DAC,所以沒有用到DAM。下面說一下實驗電路,就是把DAC轉換的電壓通過放大器輸出到Speaker,電壓值不同,則Speaker的響度就不一樣,如下圖所示: 圖 1-7 DAC實驗電路圖 關于LM386M已經是爛大街的芯片,關于它的應用網上有成大堆的資料可供參考,這里就不總結它的用法了,下面貼上這次實驗的程序: 關于LM386M已經是爛大街的芯片,關于它的應用網上有成大堆的資料可供參考,這里就不總結它的用法了,下面貼上這次實驗的程序: 一、dac.c程序源代碼
主程序:
- /*********************************************************************************
- 工程名稱:lesson5
- 功 能: 學習使用LPC1768的DAC功能
- 編譯環境: MDKV4.12
- 時 鐘: 外部12Mhz
- 日 期: 11/09/08
- 作 者: 懶貓愛飛
- 版本 號:V1R0
- ---------------------------------------------------------------------------------
- 修改內容:NULL
- 修改日期:
- 修改人員:
- ---------------------------------------------------------------------------------
-
- **********************************************************************************/
- /*********************************************************************************
- 文件名稱:mian.c
- 功 能: 主要調度函數及應用函數
- 編譯環境: MDKV4.12
- 時 鐘: 外部12Mhz
- 日 期: 11/09/08
- 作 者: 懶貓愛飛
- 備 注:NULL
- ---------------------------------------------------------------------------------
- 修改內容:NULL
- 修改日期:XXXX年xx月xx日 xx時xx分
- 修改人員:xxx xxx xxx
-
- **********************************************************************************/
- #include"includes.h"
-
- volatile unsigned long SysTickCnt; /* 用于系統時鐘計數 */
- unsigned char LedOnMeg[] = "Led 1 On!\r\n";
- unsigned char LedOffMeg[] = "Led all Off!\r\n";
- unsigned char KeyMeg[] = "key push down \r\n";
- unsigned char DacVal[] = "the voltage is: 0.0 V \r\n";
- unsigned char OpenString[][50] = {
- "**********************************************\r\n",
- "**** --歡迎光臨-- ****\r\n",
- "**** 小野獸的小草窩^_^ ****\r\n",
- "**** http://blog#ednchina#com/ytfdhb/ ****\r\n",
- "**** 我是懶貓愛飛,我的口號是: ****\r\n",
- "**** 每天進步一點點,開心多一點^_^ ****\r\n",
- "**********************************************\r\n"
- };
- unsigned int key_sta = 0; /* 按鍵狀態 */
- unsigned int key_pre = 1; /* 按鍵當前狀態值 */
- unsigned int key_old = 1; /* 按鍵前一個狀態值 */
- unsigned int led_flag = 0;
- unsigned int StepCnt = 0; /* 狀態計數 */
- /********************************************************************************
- * 函數名稱 :void SysTick_Handler (void)
- * 函數功能 : 系統節拍定時器中斷函數,每1ms計數一次
- * 入口參數 : 無
- * 出口參數 : 無
- * 備 注 :無
- *******************************************************************************/
- void SysTick_Handler (void)
- {
- SysTickCnt++;
- }
- /********************************************************************************
- * 函數名稱 :void Delay (unsigned long tick)
- * 函數功能 : 毫秒級延時函數
- * 入口參數 : unsigned long tick -- 延時時長
- * 出口參數 : 無
- * 備 注 :無
- *******************************************************************************/
- void DelayMs (unsigned long tick)
- {
- unsigned long systickcnt;
- systickcnt = SysTickCnt;
- while ((SysTickCnt - systickcnt) < tick);
- }
- /********************************************************************************
- * 函數名稱 :void PortInit(void)
- * 函數功能 : 端口初始化
- * 入口參數 : 無
- * 出口參數 : 無
- * 備 注 :無
- *******************************************************************************/
- void PortInit(void)
- {
- GPIO1->FIODIR = 0xB0000000; /* LEDs on PORT1 defined as Output */
- GPIO2->FIODIR = 0x0000007C; /* LEDs on PORT2 defined as Output */
- LedAllOff(); /* 初始化時熄滅所有的燈 */
- }
- /********************************************************************************
- * 函數名稱 :void KeyScan(void)
- * 函數功能 : 按鍵掃描
- * 入口參數 : 無
- * 出口參數 : 無
- * 備 注 :現在只掃描一個按鍵
- *******************************************************************************/
- void KeyScan()
- {
- key_pre = KEY_EN ;
- if(!KEY_EN ) /* 如果按鍵按下 */
- {
- if(key_old)
- {
- if(key_pre == 0) /* 下降沿有效 */
- {
- key_sta = 1; /* 記錄按鍵狀態 */
- }
- }
- }
- key_old = key_pre;
- }
- /********************************************************************************
- * 函數名稱 :void KeyHandle(void)
- * 函數功能 : 按鍵處理函數
- * 入口參數 : 無
- * 出口參數 : 無
- * 備 注 :無
- *******************************************************************************/
- void KeyHandle(void)
- {
- if(key_sta == 1)
- {
- StepCnt++; /* 執行下一步*/
- if(StepCnt == 9)
- {
- UART0_SendString (LedOffMeg); /* 顯示LED狀態信息 */
- }
- if(StepCnt < 9)
- {
- LedOnMeg[4] = StepCnt+0x30; /* 轉換成字符 */
- UART0_SendString (LedOnMeg); /* 顯示LED狀態信息 */
- }
- key_sta = 0; /* 按鍵狀態清零,保證只執行一次 */
- }
- }
- /********************************************************************************
- * 函數名稱 :void LedHandle()
- * 函數功能 : LED燈處理函數
- * 入口參數 : 無
- * 出口參數 : 無
- * 備 注 :無
- *******************************************************************************/
- void LedHandle()
- {
- switch(StepCnt)
- {
- case 1:Led1On(); /* LED1 點亮*/
- break;
- case 2:Led2On(); /* LED2 點亮*/
- break;
- case 3:Led3On(); /* LED3 點亮*/
- break;
- case 4:Led4On(); /* LED4 點亮*/
- break;
- case 5:Led5On(); /* LED5 點亮*/
- break;
- case 6:Led6On(); /* LED6 點亮*/
- break;
- case 7:Led7On(); /* LED7 點亮*/
- break;
- case 8:Led8On(); /* LED8 點亮*/
- break;
- case 9:LedAllOff(); /* 熄滅所有的LED燈*/
- StepCnt = 0; /* 重新開始 */
- break;
- default:break;
- }
- }
- /********************************************************************************
- * 函數名稱 :void DacConver(unsigned int val)
- * 函數功能 : DAC轉換函數
- * 入口參數 : unsigned int val -- 要轉換的電壓值,單位mv
- * 出口參數 : 無
- * 備 注 :無
- *******************************************************************************/
- void DacConver(unsigned int val)
- {
-
- unsigned int hi = 0;
- unsigned int low = 0;
- hi = val/1000; /* 求電壓的整數部分 */
- low = val%1000/100; /* 求電壓的小數部分 */
- DacVal[16]= (unsigned char)hi + 0x30; /* 將電壓值轉換成字符,方便從串口發送 */
- DacVal[18]= (unsigned char)low + 0x30;/* 將電壓值轉換成字符,方便從串口發送 */
- DacOut(val); /* 賦給DAC控制寄存器DACDR的值*/
- UARTSend(0,DacVal,25); /* 發送轉換信息 */
- }
- /********************************************************************************
- * 函數名稱 :int main(void)
- * 函數功能 : 主函數
- * 入口參數 : 無
- * 出口參數 : 無
- * 備 注 :無
- *******************************************************************************/
- int main(void)
- {
- unsigned int i = 0;
- SystemInit(); /* 系統初始化,函數在system_LPC17xx.c文件夾中定義 */
- SysTick_Config(SystemFrequency/1000 - 1);/* 配置節拍定時器中斷,每1ms中斷一次 */
-
- PortInit(); /* 端口初始化 */
- DACInit();
- UARTInit(0,19200); /* 設置串口0波特率 */
- for(i=0;i<7;i++)
- {
- UARTSend(0,OpenString[i],50); /* 發送歡迎信息 */
- }
- /* 下面的函數是測試DAC的,分別輸出2.0V、2.5V、3.0V與3.3V*/
- DacConver(2000); // 2.0v
- DacConver(2500); // 2.5v
- DacConver(3000); // 3.0v
- DacConver(3300); // 3.0v
- //LedOnMeg[4] = 4+0x30; /* 轉換成字符 */
- //UART0_SendString (KeyMeg);
- while(1)
- {
- KeyScan(); // 按鍵掃描
- KeyHandle(); // 按鍵處理
- LedHandle(); // Led處理程序
- }
- }
復制代碼
程序很簡單,就是簡單的測試,能從Speaker聽到響聲,同時我也把結果發送到了串口顯示,下面是實驗的結果: 
圖 1-8 實驗執行結果
每天進步一點點,開心多一點^_^ 完整程序源代碼工程文件下載地址:
SW110908.rar
(218.91 KB, 下載次數: 27)
2015-5-27 19:29 上傳
點擊文件名下載附件
|