基于網上的資料,整理而成。
/**
* 51單片機 1602+ADC0832顯示程式,用proteus 7.8仿真通過。
*/
#include <reg52.h>
#include <intrins.h>
#include <math.h>
#include <stdio.h>
char data str[]=" ";
/**********LCD1602接口程式**********/
#define DD P2
sbit Rs = P3^0;
sbit Rw = P3^1;
sbit E = P3^2;
void delay_1ms(unsigned char i) //最小延時1ms
{
unsigned char j;
while(i--)
for(j=0;j<125; j++);
}
void delay_10us(unsigned char i) //最小延時10us
{
unsigned char j;
while(i--)
for(j=0;j<10; j++);
}
void write_com(unsigned char com) //寫指令
{
delay_10us(5);
E=0;
Rs=0;
Rw=0;
DD=com;
delay_10us(50); //>40us
E=1;
delay_1ms(2); //>150us
E=0;
delay_10us(4); //>25+10us
}
void write_data(unsigned char DATA) //寫資料
{
delay_10us(50);
E=0;
Rs=1;
Rw=0;
DD=DATA;
delay_10us(50);
E=1;
delay_10us(50);
E=0;
delay_10us(4);
}
void addr_x_y(unsigned char x,bit y) //寫坐标,定位置
{
unsigned char temp=0x80; //預設最高位:D7為1 即以0x80開始。
if(y) //y :0為第一行 1為第二行
{
temp|=0x40;
}
temp|=x;
write_com(temp);
}
//在指定位置顯示一個字元。
void Show_Char(unsigned char x,bit y,unsigned char p)
{
addr_x_y(x,y);
write_data(p);
}
void Show_String(unsigned char x,bit y,char *ptr)
{
unsigned char i;
for (i=0;i<16;i++)
Show_Char(x++,y,*(ptr+i));//循環顯示16個字元
}
//1602初始化代碼
void init(void)
{
delay_1ms(1500);
write_com(0x38);
delay_1ms(5);
write_com(0x38);
delay_1ms(5);
write_com(0x38);
delay_1ms(5);
write_com(0x38);
write_com(0x08);
write_com(0x06);
write_com(0x0c);
write_com(0x01);
}
void xs_int(unsigned int shuju,bit t) //資料顯示
{
unsigned char huancun[6]={0};
unsigned char biaozhi=0,i;
if (shuju < 10) biaozhi = 1;
else if(shuju < 100) biaozhi = 2;
else if(shuju < 1000) biaozhi = 3;
else if(shuju < 10000) biaozhi = 4;
else if(shuju < 65535) biaozhi = 5;
switch(biaozhi) //這裡沒有break,是以從辨別比對的入口直接執行到最後,完成整數各位的提取到數組。
{
case 5:
huancun[5] = shuju/10000;
case 4:
huancun[3] = shuju%10000/1000;
case 3:
huancun[2] = shuju%1000/100;
case 2:
huancun[1] = shuju%100/10;
case 1:
huancun[0] = shuju%10;
break;
default:
break;
}
for(i=0;i<6;i++)
{
if(i==1)
Show_Char(i,1,'.'); /* 加入小數點,縮小了10000倍,是以AD采樣後的值需要乘上10000*5V/256=196(V) */
else
Show_Char(i,t,0x30+huancun[6-i-1]);
}
Show_Char(6,t,'V');
}
/**********ADC0832接口程式************************************/
sbit ADC_CS =P3^4;
sbit ADC_CLK=P3^5;
sbit ADC_DO =P3^6;
sbit ADC_DI =P3^7;
void Delay(unsigned char j)
{
unsigned char i;
for(i=0;i<j;i++); //延時,脈沖一位持續的時間
}
unsigned char ADC0832(void) //把模拟電壓值轉換成8位二進制數并傳回
{
unsigned char i,data_c;
data_c=0;
ADC_CS=0;
ADC_CLK=1;
ADC_DO=0;//片選,DO為高阻态
//ADC_DI=0; //先拉低
for(i=0;i<10;i++)
{;}
ADC_CLK=0;
Delay(2);
ADC_CLK=1;
ADC_DI=1; //啟始位
Delay(2);
ADC_CLK=0; //第一個脈沖下降沿,DI=1為起始位?
Delay(2);
ADC_CLK=1;
ADC_DI=1;//1
Delay(2);
ADC_CLK=0; //第二個脈沖下降沿,DI=1
Delay(2);
ADC_DI=1;//1 若為0則選擇CH0
ADC_CLK=1;
Delay(2);
ADC_CLK=0; //第三個脈沖下降沿,DI=1,選擇 ADC0832 的CH1(1 1)
Delay(2);
ADC_DI=1; //已不關心
ADC_DO=1; //高阻
ADC_CLK=1;
Delay(2);
for (i=0; i<8; i++)
{
ADC_CLK=0; //第四個開始讀資料
Delay(2);
data_c=(data_c<<1)|ADC_DO;//在每個脈沖的下降沿DO輸出一位資料,最終ch為8位二進制數
ADC_CLK=1;
Delay(2);
}
ADC_CS=1;//取消片選,一個轉換周期結束
return(data_c);//把轉換結果傳回
}
void main(void)
{
unsigned int data_temp=0;
while(1)
{
data_temp=ADC0832();
sprintf(str,"The voltage is:"); //the first line
init();
Show_String(0,0,str);
xs_int(196*data_temp,1); /* 10000*5V/256=196(V),把采樣值放大10000倍後再處理,移動小數點4位。
4位有效數字,其實用不到,因為8位采樣精度為:0.019V */
delay_1ms(1500);
}
}
proteus仿真原理圖如下: