//用STC12C5A單片機內部AD連續采集126個數據
//將其處理后送12864液晶屏顯示
//橫坐標代表時間,縱坐標代表電壓
//延時后更新下一屏
//2014.3.7日試驗基本成功
//2014.3.10日試驗基本成功,剛上電時按下不同按鈕可取不同的采樣周期
//缺點只能測正電壓,顯示交流電半個波形
//無同步觸發功能
//按鍵掃描程序是用來調整 每次采集的時間間隔,以便適于不同頻率 如果不用,需要給m設1初值
//信號輸入引腳為p1.0
#include<STC12C5A.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar idata tempdate[126]={0};
uchar temp1,temp2,m=166;
uchar keyval,key=16;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
#define DB_DATA P0//液晶屏數據口
sbit BF=P0^7; //液晶顯示忙檢測位
sbit RS=P3^5;
sbit RW=P3^6;
sbit E=P3^4;
//sbit s1=P3^7;
sbit beep=P2^3;
sbit diola=P2^5;
sbit dula=P2^6;
sbit wela=P2^7;
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
sbit led4=P1^3;
sbit led5=P1^4;
void Delay_US(uchar us);//1延時
void Delay_MS(uchar ms);//2延時
void Delay_S(uchar s);//3 延時 本程序沒用
void adchange();//4 AD 轉換
void Chk_busy( void );//5 液晶屏忙檢測
void Write_lcd( uchar dat_cmd,uchar content);//6寫液晶屏
uchar Read_lcd(void);//7讀液晶屏
void Lcd_inital(void); //8液晶屏初始化
void CollectorDot(uchar ch);//9 采集126個數據
void Clear(void);//10 清屏
void DisplayDot(uchar Hang,uchar lie);//11 顯示1個點
void drawpicture();//12 畫曲線
void lianxu_adchange();//13 連續采集多個數據,用于高速采集 本程序沒用
void Delay_10S( );//14
void Delay_500MS( );//15
void DISPLAY(uint bb);//16數碼管顯示,可以不要
void CollectorDot100();//17本程序沒用
void keyscan();//18 按鍵掃描,可以不要
void Delay_US(uchar us)//1 延時
{
while(--us);
}
void Delay_MS(uchar ms)//2
{
do {Delay_US(246);Delay_US(247);}
while(--ms);
}
void Delay_S(uchar s)//3 本程序沒用
{
do{Delay_MS(200);Delay_MS(200);Delay_MS(200);Delay_MS(200);Delay_MS(200);}
while(--s);
}
void adchange()//4
{
ADC_CONTR=ADC_CONTR|0X80; //10000000 開啟轉換電源
//延時,等待內部電源穩定,同時調節采集周期
Delay_US(m);//500 US每次166 200US對應61 100us每次應改為27 50US對應9
Delay_US(m);
Delay_US(m);
Delay_US(m);
P1M0=P1M0|0X03; //設置p1.0和P1.1所在通道為開/漏模式
P1M1=P1M1|0X03;
ADC_CONTR=0xe0; //11100000 開啟P1.0通道開始轉換
Delay_US(m); //延時一端時間,使輸入電壓達到穩定
Delay_US(m);
ADC_RES =0x00; //清A/D轉換結果寄存器
ADC_RESL =0x00;
ADC_CONTR |= 0x08; //ADC_START=1,開始轉換
while(!(ADC_CONTR&0x10)); //0001,0000 等待A/D轉換結束
temp1=ADC_RES; //讀取轉換結果,共10位只要高8位
//temp2=ADC_RESL;
ADC_CONTR=ADC_CONTR&0xe7; //將ADC_FLAG軟件清零
Delay_US(m);
Delay_US(m);
P1M0=P1M0&0X00; //設置P1口為普通I/O模式,以便用P1口顯示數據。
P1M1=P1M1&0X40;
}
//每次采集除延時外,大約19 US
void Chk_busy(void)//5 判斷是否忙,實際是等待忙完
{
DB_DATA=0xff;
RS=0;
RW=1;
E=1;
while(BF);
E=0;
}
void Write_lcd( uchar dat_cmd,uchar content)//6 寫液晶屏(命令或數據)
{
Chk_busy();
RS=dat_cmd;//0 命令,1數據
RW=0;
E=1;
DB_DATA=content;
E=0;
}
uchar Read_lcd(void)//7 讀液晶屏
{
uchar rddata;
Chk_busy();
RS=1;
RW=1;
E=1;
rddata=DB_DATA;
E=0;
return rddata;
}
void Lcd_inital(void) //8 Lcd初始化
{
dula=1;
wela=1;
P0=0xff;
dula=0;
wela=0;
// diola=1;
Write_lcd(0,0x30); //功能設定,8位接口控制,選擇普通指令(禁止了擴展指令)
Write_lcd(0,0x30); //同一指令的動作不能同時改變RE 及DL、G,需先改變DL 或G 再改變RE 才
Write_lcd(0,0x0c); //整體顯示開,游標位置顯示關,游標位置反白關
Write_lcd(0,0x01); //清除顯示
Write_lcd(0,0x06); //畫面設定,游標右移,畫面不移動
}
void CollectorDot()//9
{
uchar i;
for(i=0;i<126;i++)
{
adchange();
tempdate[ i]=temp1;
}
}
void Clear(void)//10 清屏
{
uchar i,j,k;
k=0x80;
Write_lcd(0,0x34); //擴充功能設定,同時關繪圖顯示
for(i=0;i<32;i++)
{
Write_lcd(0,0x80+i);
Write_lcd(0,k);
for(j=0;j<16;j++)
Write_lcd(1,0x00);
}
k=0x88;
for(i=0;i<32;i++)
{
Write_lcd(0,0x80+i);
Write_lcd(0,k);
for(j=0;j<16;j++)
Write_lcd(1,0x00);
}
Write_lcd(0,0x36); //擴充功能設定,同時開繪圖顯示
Write_lcd(0,0x30);
}
void DisplayDot(uchar Hang,uchar lie)//11 行y 0-63 列x 0-127
{
uchar hang,lie1,lie2,data1,data2;
Write_lcd(0,0x34);
lie1=lie/16; //列號 0-7
lie2=lie%16; // 列內號 0-15
if(Hang<32)hang=Hang; //Y坐標32以內,行號=Y坐標
else
{
lie1+=8;
hang=Hang-32;// Y坐標32~64之間,行號=Y坐標-32
}
Write_lcd(0,0x80+hang);//寫行號
Write_lcd( 0,0x80+lie1 );//寫列號
Read_lcd();//這一句還真有點用,但不知干什么的
data1=Read_lcd( );//讀出原來數據,,除要寫點位置外,原數據不變
data2=Read_lcd( );
Write_lcd(0,0x80+hang);
Write_lcd( 0,0x80+lie1 );
if((lie2>=0)&&(lie2<=7))//1 個列地址對應兩個字節 0-7是1個字節,8-15是第2個字節
{
Write_lcd(1,data1|(0x01<<(7-lie2)));//改變第1個字節內容(插人所要畫的點)
Write_lcd(1,data2);//第二個字節內容不變
}
elseif((lie2>=8)&&(lie2<=15))
{
Write_lcd(1,data1);//第1個字節內容不變
Write_lcd(1,data2|(0x01<<(15-lie2)));//改變第2個字節內容(插人所要畫的點)
}
Write_lcd(0,0x36);
Write_lcd(0,0x30);
}
void drawpicture()//12 畫圖
{
uchar dot,x,y1,y2;
for(dot=0;dot<126;dot++)
{
x=dot;
y1=tempdate[dot]/4;
y2=63-y1;
DisplayDot(y2,x);
}
}
void Delay_500MS( )//1
{
uint bb=6667;
while(bb>0)
{
Delay_US(200);
bb--;
}
}
void main ()
{
Lcd_inital(); //初始化
diola=1;
while(key==16){keyscan();}
switch(key)
{
case 0:m=9;led2=0;break;
case 1:m=27;led3=0;break;
case 2:m=61;led4=0;break;
case 4:m=166;led5=0;break;
default:break;
}
while(1)
{
CollectorDot();//采集126個數據
//CollectorDot100();//采集100個數據并顯示所花時間
Clear(); //清屏
drawpicture(); //畫圖
Delay_500MS( );
//s1=0;
Delay_MS(250); //延時約47ms
Delay_500MS( );
}
}
void lianxu_adchange()//13 連續采集多個數據一次開啟,多次采集適合于高速
{
uchar i;
ADC_CONTR=ADC_CONTR|0X80; //10000000 開啟轉換電源
Delay_MS(1); //延時,等待內部電源穩定
//Delay_US(100);
P1M0=P1M0|0X03; //設置p1.0和P1.1所在通道為開/漏模式
P1M1=P1M1|0X03;
for(i=0;i<120;i++)
{
ADC_CONTR=0xe0; //11100000 開啟P1.0通道開始轉換
Delay_US(50); //延時一端時間,使輸入電壓達到穩定
ADC_RES =0x00; //清A/D轉換結果寄存器
ADC_RESL =0x00;
ADC_CONTR |= 0x08; //ADC_START=1,開始轉換
while(!(ADC_CONTR&0x10)); //0001,0000 等待A/D轉換結束
tempdate[ i]=ADC_RES; //讀取轉換結果,共10位只要高8位
ADC_CONTR=ADC_CONTR&0xe7; //將ADC_FLAG軟件清零
Delay_US(20);
}
P1M0=P1M0&0X00; //設置P1口為普通I/O模式,以便用P1口顯示數據。
P1M1=P1M1&0X40;
}
void CollectorDot100()//9 用于計算并顯示采集100次所花時間
{
uchar i;
uint AA;
TMOD=0X01;
TH0=0;
TL0=0;
TR0=1;
for(i=0;i<100;i++)
{
adchange();
tempdate[ i]=temp1;
}
TR0=0;
AA=TH0*256+TL0;
DISPLAY(AA);
}
void DISPLAY(uint bb)
{
uint i;
uchar b1,b2,b3,b4,b5;
b1= bb/10000%10;
b2= bb/1000%10;
b3= bb/100%10;
b4= bb/10%10;
b5= bb%10;
for(i=0;i<2000;i++)
{
wela=1;
DB_DATA=0xfe;
wela=0;
dula=1;
DB_DATA=table[b1];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xfd;
wela=0;
dula=1;
DB_DATA=table[b2];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xfb;
wela=0;
dula=1;
DB_DATA=table[b3];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xf7;
wela=0;
dula=1;
DB_DATA=table[b4];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xef;
wela=0;
dula=1;
DB_DATA=table[b5];
dula=0;
Delay_MS(10);
}
}
void keyscan()
{
uchar temp;
P3=0xef;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xed:
key=4;
break;
case 0xeb:
key=8;
break;
case 0xe7:
key=12;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0xdf;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xde:
key=1;
break;
case 0xdd:
key=5;
break;
case 0xdb:
key=9;
break;
case 0xd7:
key=13;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0xbf;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xbe:
key=2;
break;
case 0xbd:
key=6;
break;
case 0xbb:
key=10;
break;
case 0xb7:
key=14;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0x7f;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0x7e:
key=3;
break;
case 0x7d:
key=7;
break;
case 0x7b:
key=11;
break;
case 0x77:
key=15;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
} |