51單片機(jī) AD轉(zhuǎn)換
在數(shù)邏的課程中,已經(jīng)學(xué)習(xí)過(guò)AD轉(zhuǎn)換的概念:將模擬信號(hào)采樣、量化、編碼后轉(zhuǎn)換為數(shù)字信號(hào)。但是未學(xué)習(xí)過(guò)通過(guò)單片機(jī)編程,顯示結(jié)果。
編碼分有舍有入、只舍不入兩種,量化誤差前者更小。=2Vm/(2^n+1- 1 )
注意,為了達(dá)到精確度高、穩(wěn)定性好的目的,最好將所有器件的模擬地和數(shù)字分別連接,最后將模擬地和數(shù)字地僅在一點(diǎn)相連。
此處,使用的是STC12C5A60S2內(nèi)部的AD轉(zhuǎn)換。
1 /* 功能:使用12C5A60S2內(nèi)部AD讀取外部電壓,顯示在1602上 */
2
3 #include "STC12C5A60S2.H"
4 #include
5 sbit RS = P2^6; //1602定義口 //HZ:EN=P2.2 RS=P2.0 RW=P2.1
6 sbit RW = P2^5;
7 sbit EN = P2^7;
8 #define uchar unsigned char;
9 #define uint unsigned int;
10
11 #define RS_CLR RS=0
12 #define RS_SET RS=1
13 #define RW_CLR RW=0
14 #define RW_SET RW=1
15 #define EN_CLR EN=0
16 #define EN_SET EN=1
17
18 #define DataPort P0 //連接1602數(shù)據(jù)口 P0
19
20 uchar da1=0,da2=0,da3=0;
21 double Data,c;
22 char a[5]="";
23 uchar ADC_Chanul_Turn=0;
24
25
26 void DelayUs2x(unsigned char t)
27 {
28 while(--t);
29 }
30
31
32 void DelayMs(unsigned char t)
33 {
34
35 while(t--)
36 {
37 //大致延時(shí)1mS
38 DelayUs2x(245);
39 DelayUs2x(245);
40 }
41 }
42 /*------------------------------------------------
43 判忙函數(shù)
44 ------------------------------------------------*/
45 bit LCD_Check_Busy(void)
46 {
47 DataPort= 0xFF;
48 RS_CLR;
49 RW_SET;
50 EN_CLR;
51 _nop_();
52 EN_SET;
53 return (bit)(DataPort & 0x80);
54 }
55 /*---------
56 ------------------------------------------------*/
57 void LCD_Write_Com(unsigned char com)
58 {
59 while(LCD_Check_Busy()); //忙則等待
60 RS_CLR;
61 RW_CLR;
62 EN_SET;
63 DataPort= com; //
64 _nop_();
65 EN_CLR;
66 }
67 /*------------------------------------------------
68 寫(xiě)入數(shù)據(jù)函數(shù)
69 ------------------------------------------------*/
70 void LCD_Write_Data(unsigned char Data)
71 {
72 while(LCD_Check_Busy()); //忙則等待
73 RS_SET;
74 RW_CLR;
75 EN_SET;
76 DataPort= Data;
77 _nop_();
78 EN_CLR;
79 }
80
81 /*------------------------------------------------
82 清屏函數(shù)
83 ------------------------------------------------*/
84 void LCD_Clear(void)
85 {
86 LCD_Write_Com(0x01);
87 DelayMs(5);
88 }
89 /*------------------------------------------------
90 寫(xiě)入字符串函數(shù)
91 ------------------------------------------------*/
92 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)//y為行數(shù),x為橫坐標(biāo),最后一個(gè)是字符
93 {
94 if (y == 0)
95 {
96 LCD_Write_Com(0x80 + x); //表示第一行
97 }
98 else
99 {
100 LCD_Write_Com(0xC0 + x); //表示第二行
101 }
102 while (*s)
103 {
104 LCD_Write_Data( *s);
105 s ++;
106 }
107 }
108 /*------------------------------------------------
109 寫(xiě)入字符函數(shù)
110 ------------------------------------------------*/
111 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
112 {
113 if (y == 0)
114 {
115 LCD_Write_Com(0x80 + x);
116 }
117 else
118 {
119 LCD_Write_Com(0xC0 + x);
120 }
121 LCD_Write_Data( Data);
122 }
123 /*------------------------------------------------
124 初始化函數(shù)
125 ------------------------------------------------*/
126 void LCD_Init(void)
127 {
128 LCD_Write_Com(0x38); /*顯示模式設(shè)置*/
129 DelayMs(5);
130 LCD_Write_Com(0x38);
131 DelayMs(5);
132 LCD_Write_Com(0x38);
133 DelayMs(5);
134 LCD_Write_Com(0x38);
135 LCD_Write_Com(0x08); /*顯示關(guān)閉*/
136 LCD_Write_Com(0x01); /*顯示清屏*/
137 LCD_Write_Com(0x06); /*顯示光標(biāo)移動(dòng)設(shè)置*/
138 DelayMs(5);
139 LCD_Write_Com(0x0C); /*顯示開(kāi)及光標(biāo)設(shè)置*/
140 }
141
142 /*------------------------------------------------
143 ADC函數(shù)
144 ------------------------------------------------*/
145 void InitADC()//初始AD寄存器
146 {
147 P1ASF=0x03; //0xff設(shè)置P1口全部為ADC通道,P10 P11為輸出口
148 ADC_RES=0x00; //清除高8位緩沖數(shù)據(jù)
149 if(ADC_Chanul_Turn%2==0)
150 {
151 ADC_CONTR=0xF0; //P10口
152 _nop_();
153 _nop_();
154 _nop_();
155 _nop_();
156 ADC_CONTR=0xE8;
157
158 }
159 if(ADC_Chanul_Turn%2==1) //P11口
160 {
161 ADC_CONTR=0xF1;
162 _nop_();
163 _nop_();
164 _nop_();
165 _nop_();
166 ADC_CONTR=0xE9;
167 }
168 }
169
170 void timer0() interrupt 1 //interrupt 1: 定時(shí)器0,interrupt3:定時(shí)器3
171 {
172 TH0=(65536-20000)/256; //高八位,(需要表示Xms的定時(shí),計(jì)數(shù)器由65536-X數(shù)到65536,由于16位,只能分高低位)
173 TL0=(65536-20000)%256; //低八位
174 InitADC();
175
176 }
177
178 void adc_isr() interrupt 5 //FLAG標(biāo)志位置位觸發(fā)中斷,沒(méi)有設(shè)優(yōu)先級(jí),但是同優(yōu)先級(jí)下定時(shí)器0更高
179 {
180
181 //V_5REF=V_1REF*256/da_ref;
182 if(ADC_Chanul_Turn%3==0) //外部基準(zhǔn)電壓
183 {
184 da1=ADC_RES; //獲取轉(zhuǎn)換結(jié)果
185 Data=((double)da1/256)*5; //取八位計(jì)算基準(zhǔn)電壓Data,
186 c =Data;
187 }
188 if(ADC_Chanul_Turn%3==1)
189 {
190 da2=ADC_RES; //獲取轉(zhuǎn)換結(jié)果
191 Data=((double)da2/256)*5; //取八位計(jì)算實(shí)際值Data,
192 c =Data;
193 }
194 if(ADC_Chanul_Turn%3==2)
195 {
196 da3=ADC_RES; //獲取轉(zhuǎn)換結(jié)果
197 Data=((double)da3/256)*5; //取八位計(jì)算實(shí)際值Data,
198 c =Data;
199 }
200
201 a[0]=((int)c%10+0x30);//個(gè)位(電壓<5,僅有個(gè)) //0x30: