51单片机 AD转换
扫描二维码
随时随地手机看文章
在数逻的课程中,已经学习过AD转换的概念:将模拟信号采样、量化、编码后转换为数字信号。但是未学习过通过单片机编程,显示结果。
编码分有舍有入、只舍不入两种,量化误差前者更小。=2Vm/(2^n+1- 1 )
注意,为了达到精确度高、稳定性好的目的,最好将所有器件的模拟地和数字分别连接,最后将模拟地和数字地仅在一点相连。
此处,使用的是STC12C5A60S2内部的AD转换。
1 /* 功能:使用12C5A60S2内部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数据口 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 //大致延时1mS
38 DelayUs2x(245);
39 DelayUs2x(245);
40 }
41 }
42 /*------------------------------------------------
43 判忙函数
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 写入数据函数
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 清屏函数
83 ------------------------------------------------*/
84 void LCD_Clear(void)
85 {
86 LCD_Write_Com(0x01);
87 DelayMs(5);
88 }
89 /*------------------------------------------------
90 写入字符串函数
91 ------------------------------------------------*/
92 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)//y为行数,x为横坐标,最后一个是字符
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 写入字符函数
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 初始化函数
125 ------------------------------------------------*/
126 void LCD_Init(void)
127 {
128 LCD_Write_Com(0x38); /*显示模式设置*/
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); /*显示关闭*/
136 LCD_Write_Com(0x01); /*显示清屏*/
137 LCD_Write_Com(0x06); /*显示光标移动设置*/
138 DelayMs(5);
139 LCD_Write_Com(0x0C); /*显示开及光标设置*/
140 }
141
142 /*------------------------------------------------
143 ADC函数
144 ------------------------------------------------*/
145 void InitADC()//初始AD寄存器
146 {
147 P1ASF=0x03; //0xff设置P1口全部为ADC通道,P10 P11为输出口
148 ADC_RES=0x00; //清除高8位缓冲数据
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: 定时器0,interrupt3:定时器3
171 {
172 TH0=(65536-20000)/256; //高八位,(需要表示Xms的定时,计数器由65536-X数到65536,由于16位,只能分高低位)
173 TL0=(65536-20000)%256; //低八位
174 InitADC();
175
176 }
177
178 void adc_isr() interrupt 5 //FLAG标志位置位触发中断,没有设优先级,但是同优先级下定时器0更高
179 {
180
181 //V_5REF=V_1REF*256/da_ref;
182 if(ADC_Chanul_Turn%3==0) //外部基准电压
183 {
184 da1=ADC_RES; //获取转换结果
185 Data=((double)da1/256)*5; //取八位计算基准电压Data,
186 c =Data;
187 }
188 if(ADC_Chanul_Turn%3==1)
189 {
190 da2=ADC_RES; //获取转换结果
191 Data=((double)da2/256)*5; //取八位计算实际值Data,
192 c =Data;
193 }
194 if(ADC_Chanul_Turn%3==2)
195 {
196 da3=ADC_RES; //获取转换结果
197 Data=((double)da3/256)*5; //取八位计算实际值Data,
198 c =Data;
199 }
200
201 a[0]=((int)c%10+0x30);//个位(电压<5,仅有个) //0x30: