? AD轉(zhuǎn)換就是模數(shù)轉(zhuǎn)換,顧名思義,就是把模擬信號轉(zhuǎn)換成數(shù)字信號。我們所用的模數(shù)轉(zhuǎn)換芯片是ADC0809。
ADC0809 8通道8位a/d轉(zhuǎn)換器,ADC0809是帶有8位A/D轉(zhuǎn)換器、8路多路開關(guān)以及微處理機兼容的控制邏輯的CMOS組件。它是逐次逼近式A/D轉(zhuǎn)換器,可以和單片機直接接口。ADC0809由一個8路模擬開關(guān)、一個地址鎖存與譯碼器、一個A/D轉(zhuǎn)換器和一個三態(tài)輸出鎖存器組成。多路開關(guān)可選通8個模擬通道,允許8路模擬量分時輸入,共用A/D轉(zhuǎn)換器進行轉(zhuǎn)換。三態(tài)輸出鎖器用于鎖存A/D轉(zhuǎn)換完的數(shù)字量,當OE端為高電平時,才可以從三態(tài)輸出鎖存器取走轉(zhuǎn)換完的數(shù)據(jù)。如圖3.1所示。
?
? 圖3.1 ADC0809的內(nèi)部結(jié)構(gòu)和引腳定義
? 如何學會使用一個自己曾經(jīng)沒有用過的芯片,最重要的是要學會看它的芯片手冊,以及它的時序圖。下面我們將看看是如何根據(jù)它的時序圖完成對芯片的驅(qū)動的。
? 圖3.2 ADC0809時序圖
原理(好好理解一下,這樣才能很好的根據(jù)時序圖寫出代碼。):START為轉(zhuǎn)換啟動信號。當START上跳沿時,所有內(nèi)部寄存器清零;下跳沿時,開始進行A/D轉(zhuǎn)換;在轉(zhuǎn)換期間,START應保持低電平。EOC為轉(zhuǎn)換結(jié)束信號。當EOC為高電平時,表明轉(zhuǎn)換結(jié)束;否則,表明正在進行A/D轉(zhuǎn)換。OUTPUTENABLE為輸出允許信號,用于控制三條輸出鎖存器向單片機輸出轉(zhuǎn)換得到的數(shù)據(jù)。OE=1,輸出轉(zhuǎn)換得到的數(shù)據(jù);OE=0,輸出數(shù)據(jù)線呈高阻狀態(tài)。D7-D0為數(shù)字量輸出線。CLK為時鐘輸入信號線。因ADC0809的內(nèi)部沒有時鐘電路,所需時鐘信號必須由外界提供,通常使用頻率為500KHZ(程序中會有體現(xiàn))。
Verilog HDL實現(xiàn)
實現(xiàn)步驟請參照?【連載】 FPGA Verilog HDL 系列實例--------8-3編碼器。這里就不再贅述。
設計文件輸入Verilog HDL代碼。
?
1 //------------------------------------------------------------------------------------------------- 2 // 3 // File : ADC0809.v 4 // Generated : 2011-07-21 5 // Author : wangliang 6 // 7 //------------------------------------------------------------------------------------------------- 8 `timescale 1 ns / 1 ps 9 10 11 module ADC0809 ( seven_seg ,ale ,OE ,D ,EOC ,clk ,abc_in ,abc_out ,start ,rst ); 12 13 input clk ; //系統(tǒng)時鐘 14 input [2:0] abc_in ; //外部控制的通道選擇信號 15 input [7:0] D ; //ADC0809傳進來的數(shù)據(jù) 16 input EOC ; //ADC0809轉(zhuǎn)換完成信號標志 17 input rst ; //系統(tǒng) 復位 18 19 output [15:0] seven_seg ; //FPGA給數(shù)碼管的數(shù)據(jù) 20 output ale ; //FPGA給ADC0809的地址鎖存信號 21 output OE ; //FPGA給ADC0809的使能信號 22 output [2:0] abc_out ; //FPGA給ADC0809的通道選擇信號 23 output start ; //ADC0809 轉(zhuǎn)換開始信號 24 25 parameter st0 = 3'b000, 26 st1 = 3'b001, 27 st2 = 3'b010, 28 st3 = 3'b011, 29 st4 = 3'b100, 30 st5 = 3'b101, 31 st6 = 3'b110 ; 32 33 reg [2:0] p_state ; 34 reg [2:0] n_state ; 35 reg ale_r ; 36 reg OE_r ; 37 reg start_r ; 38 reg [7:0] reg1 ; 39 reg [7:0] qq ; 40 wire [2:0] state ; 41 42 assign state = p_state ; 43 44 always @ (posedge clk or negedge rst) 45 begin 46 if ( rst== 1'b0 ) begin 47 p_state <= st0 ; 48 qq <= 8'b0 ; 49 50 end 51 else begin 52 qq <= qq + 1'b1; 53 if ( ( qq >= 8'b0100_0010) && ( clk == 1'b1 ) ) begin 54 qq <= 8'b0; 55 p_state <=#1 n_state; 56 end 57 58 end 59 end 60 61 assign ale = ale_r ; 62 assign OE = OE_r ; 63 assign start = start_r ; 64 65 assign abc_out = abc_in ; 66 67 always @ ( EOC ,p_state ) 68 begin 69 case ( p_state ) 70 st0 :begin 71 ale_r <= #1 1'b0; 72 start_r <= #1 1'b0; 73 OE_r <= #1 1'b0; 74 n_state <=#1 st1; 75 end 76 st1 :begin 77 ale_r <= #1 1'b1; 78 start_r <= #1 1'b0; 79 OE_r <= #1 1'b0; 80 n_state <=#1 st2; 81 end 82 st2 :begin 83 ale_r <= #1 1'b0; 84 start_r <= #1 1'b1; 85 OE_r <= #1 1'b0; 86 n_state <=#1 st3; 87 end 88 st3 :begin 89 ale_r <= #1 1'b0; 90 start_r <= #1 1'b0; 91 OE_r <= #1 1'b0; 92 if ( EOC == 1'b1 ) 93 n_state <=#1 st3; 94 else 95 n_state <=#1 st4; 96 97 end 98 st4 :begin 99 ale_r <= #1 1'b0;100 start_r <= #1 1'b0; 101 OE_r <= #1 1'b0; 102 if ( EOC == 1'b0 )103 n_state <=#1 st4; 104 else105 n_state <=#1 st5; 106 end 107 st5 :begin 108 ale_r <= #1 1'b0;109 start_r <= #1 1'b0; 110 OE_r <= #1 1'b1; 111 n_state <=#1 st6; 112 end 113 st6 :begin 114 ale_r <= #1 1'b0;115 start_r <= #1 1'b0; 116 OE_r <= #1 1'b1; 117 reg1 <=#1 D ; 118 n_state <=#1 st0; 119 end 120 default :begin 121 ale_r <= #1 1'b0;122 start_r <= #1 1'b0; 123 OE_r <= #1 1'b0; 124 n_state <=#1 st0; 125 end 126 endcase 127 128 end 129 130 /******************** 數(shù)碼管顯示譯碼部分 ***********************************/131 reg [7:0] Y_r_1; 132 reg [7:0] Y_r_2; 133 134 assign seven_seg[7:0] ={1'b1,(~Y_r_1[6:0])};135 assign seven_seg[15:8] = {1'b1,(~Y_r_2[6:0])};136 137 always @(reg1[3:0] ) 138 begin 139 Y_r_1 = 7'b1111111;140 case (reg1[3:0] ) 141 4'b0000: Y_r_1 = 7'b0111111; // 0142 4'b0001: Y_r_1 = 7'b0000110; // 1143 4'b0010: Y_r_1 = 7'b1011011; // 2144 4'b0011: Y_r_1 = 7'b1001111; // 3145 4'b0100: Y_r_1 = 7'b1100110; // 4146 4'b0101: Y_r_1 = 7'b1101101; // 5147 4'b0110: Y_r_1 = 7'b1111101; // 6148 4'b0111: Y_r_1 = 7'b0000111; // 7149 4'b1000: Y_r_1 = 7'b1111111; // 8150 4'b1001: Y_r_1 = 7'b1101111; // 9151 4'b1010: Y_r_1 = 7'b1110111; // A152 4'b1011: Y_r_1 = 7'b1111100; // b153 4'b1100: Y_r_1 = 7'b0111001; // c154 4'b1101: Y_r_1 = 7'b1011110; // d155 4'b1110: Y_r_1 = 7'b1111001; // E156 4'b1111: Y_r_1 = 7'b1110001; // F157 default: Y_r_1 = 7'b0000000;158 endcase 159 end 160 161 always @( reg1[7:4] ) 162 begin 163 Y_r_2 = 7'b1111111;164 case ( reg1[7:4] ) 165 4'b0000: Y_r_2 = 7'b0111111; // 0166 4'b0001: Y_r_2 = 7'b0000110; // 1167 4'b0010: Y_r_2 = 7'b1011011; // 2168 4'b0011: Y_r_2 = 7'b1001111; // 3169 4'b0100: Y_r_2 = 7'b1100110; // 4170 4'b0101: Y_r_2 = 7'b1101101; // 5171 4'b0110: Y_r_2 = 7'b1111101; // 6172 4'b0111: Y_r_2 = 7'b0000111; // 7173 4'b1000: Y_r_2 = 7'b1111111; // 8174 4'b1001: Y_r_2 = 7'b1101111; // 9175 4'b1010: Y_r_2 = 7'b1110111; // A176 4'b1011: Y_r_2 = 7'b1111100; // b177 4'b1100: Y_r_2 = 7'b0111001; // c178 4'b1101: Y_r_2 = 7'b1011110; // d179 4'b1110: Y_r_2 = 7'b1111001; // E180 4'b1111: Y_r_2 = 7'b1110001; // F181 default: Y_r_2 = 7'b0000000;182 endcase 183 end 184 185 endmodule
?
上面一長串代碼,剛接觸的人一看可能會頭大,但要是仔細分析一下,就會很好理解了。本實現(xiàn)有三部分組成:
1.第44行~第59行:時鐘分頻,系統(tǒng)時鐘為50MHZ,ADC0809的驅(qū)動頻率不需要這么快,所以需要分頻。一般在500KHZ左右,實例中用的是750KHz。
2.第67行~第128行:對ADC0809時序的實現(xiàn)。自己好好理解下哦。一次模數(shù)轉(zhuǎn)換經(jīng)過6個步驟完成。第3步和第4步需要查看EOC的狀態(tài)來確定是否將模擬數(shù)據(jù)轉(zhuǎn)換完畢。
3.第137行~第183行:將模擬數(shù)據(jù)轉(zhuǎn)化到的數(shù)字數(shù)據(jù)輸出到2個數(shù)碼管上。圖3.3是ADC0809的外部接口。
? 圖3.3 ADC0809的外部接口
?分配引腳:
clk接系統(tǒng)時鐘,rst接復位信號,abc_in[2..0]接三個按鍵,seven_seg[15..0]接2個七段數(shù)碼管,其余的是ADC0809上的型號,這是由硬件連線決定的,只要搞清楚它們是輸入還是輸出就行了。
實驗結(jié)果:
將三個按鍵都關(guān)閉,選擇0通道,這樣,當旋轉(zhuǎn)按鈕的時候,在2個七段數(shù)碼管上就能顯示數(shù)值。這就完成了將模擬數(shù)據(jù)轉(zhuǎn)化為數(shù)字量的驗證。
審核編輯:劉清
評論
查看更多