這是一個簡易數字示波器的程序 前面的程序都不用 主要是后面main函數的邏輯看不懂 求大神幫忙看看
#include <AT89X52.h>
#include <intrins.h>
//12864控制引腳定義
sbit DI = P2 ^ 2; //數據D\指令I選擇引腳
sbit RW = P2 ^ 1; //讀R\寫W選擇引腳
sbit E= P2 ^ 0; //讀\寫使能引腳
sbit CS1 = P2 ^ 4; //片選1引腳
sbit CS2 = P2 ^ 3; //片選2引腳
sbit BUSY= P1 ^ 7; //忙標志位
//按鍵控制定義
sbit Y1 = P3 ^ 0;
sbit Y2 = P3 ^ 1;
sbit X1 = P3 ^ 3;
sbit X2 = P3 ^ 7;
//ADC0832控制引腳
sbit START=P3^4;
sbit OE=P3^6;
sbit EOC=P3^5;
unsigned int ADdata; //AD采集值
unsigned int Ldata; //控制命令
unsigned char ye,lei,shu; //頁 列 數
unsigned char ADViewdata[91]; //AD顯示數據存儲區 存儲AD值
char code FrameData[]={ //提示字符存儲區
0x00,0x00,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x01,0x00,
0x01,0x00,0x11,0x10,0x11,0x08,0x21,0x04,0x41,0x02,0x81,0x02,0x05,0x00,0x02,0x00, //示
0x00,0x20,0x20,0x20,0x10,0x20,0x13,0xFE,0x82,0x22,0x42,0x24,0x4A,0x20,0x0B,0xFC,
0x12,0x84,0x12,0x88,0xE2,0x48,0x22,0x50,0x22,0x20,0x24,0x50,0x24,0x88,0x09,0x06, //波
0x00,0x00,0x3E,0x7C,0x22,0x44,0x22,0x44,0x3E,0x7C,0x01,0x20,0x01,0x10,0xFF,0xFE,
0x02,0x80,0x0C,0x60,0x30,0x18,0xC0,0x06,0x3E,0x7C,0x22,0x44,0x22,0x44,0x3E,0x7C, //器
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //" "
};
//AD轉換軟件
void ADCChage()
{
START=1;
START=0;
while(EOC==0) //等待轉換完成
{
OE=1;
}
ADdata = P0; //讀取AD數據
OE=0;
}
//檢查12864液晶狀態
void CheckState()
{
DI=0;
RW=1;
do
{
E=1;
E=0;
//僅當第7位為0時才可操作(判別busy信號)
}while(BUSY==1);
}
//向12864寫入一個字節的命令
void WriteCommand(unsigned char cmd)
{
CheckState(); //檢查當前的12864狀態
DI = 0;
RW = 0;
P1 = cmd; //送出相應的命令
E = 1;
E = 0;
}
//向12864寫入一個字節的數據
void WriteData(unsigned char dat)
{
CheckState(); //檢查當前的12864狀態
DI = 1;
RW = 0;
P1 = dat; //送出相應的數據
E = 1;
E = 0;
}
//12864液晶的選擇控制引腳 選擇左屏 還是右屏幕 CS1=0,CS2=0 全屏 CS=1,CS2=0 右屏
void LCMCSControl(unsigned int csl)
{
if(csl==1) //根據參數不同判斷當前的12864控制引腳狀態 選擇左邊
{
CS1=0,
CS2=1;
}
if(csl==2) //選擇右邊
{
CS1=1,
CS2=0;
}
if(csl==3) //全選
{
CS1=0,
CS2=0;
}
}
//12864顯示函數
void LCMView()
{
LCMCSControl(Ldata); //先發送控制命令
WriteCommand(ye); //選頁 10111xxx(頁地址) 0xB(不定)
WriteCommand(lei); //選列 01xxxxxx(列地址) 0x(不)(定)
WriteData(shu); //然后發送數據
}
//12864的清屏函數
void CleanScreen()
{
unsigned char page,i;
LCMCSControl(3); //左右屏幕選擇 3全選
for(page=0xb8;page<=0xbf;page++) //0xb8 10111 000-10111 111 8頁全部掃描一遍
{
WriteCommand(page);
WriteCommand(0x40); //0x40 0100 0000 第0列
for(i=0;i<64;i++)
{
WriteData(0x00); //清零
}
}
LCMCSControl(1); // 左半屏
lei=0x40; //列 0100 0000
for(ye=0xb8;ye<0xbf;ye++) // 10111 000 第0頁 -10111 111 第7頁
{
shu=0xff; //全1
LCMView(); //顯示
}
ye=0xb8;
for(lei=0x40;lei<=0x7f;lei++)
{
shu=0x80;
LCMView();
}
ye=0xbf;
for(lei=0x40;lei<=0x7f;lei++)
{
shu=0x01;
LCMView();
}
LCMCSControl(2);
ye=0xb8;
for(lei=0x40;lei<=0x5b;lei++)
{
shu=0x80;
LCMView();
}
ye=0xbf;
for(lei=0x40;lei<=0x5b;lei++)
{
shu=0x01;
LCMView();
}
lei=0x5b;
for(ye=0xb9;ye<=0xbe;ye++)
{
shu=0xff;
LCMView();
}
}
//12864的初始化函數
void InitLCM(void)
{
WriteCommand(0xc0); // 1100 0000 啟始行
WriteCommand(0x3f); // 0011 1111 屏幕開
}
//50us的延時函數
void Delay50us(unsigned int t)
{
unsigned char j;
for(;t>0;t--)
for(j=19;j>0;j--);
}
//刷新12864液晶
void RefreshLCM()
{
unsigned char i;
for(i=0xb9;i<=0xbe;i++)
{
ye=i;
shu=0x00;
LCMView();
}
}
//主函數
void main()
{
unsigned int r,j,q,k;
unsigned int Xaxis =0;
unsigned int Yaxis = 1;
unsigned char l;
unsigned char d1,d2,d3,d4,d5;
CleanScreen(); //清屏
InitLCM(); //初始化 開屏幕 設置初始行第0行
LCMCSControl(2); // 選擇右屏幕
l=0xb8; //啥玩意啊
for(k=0;k<4;k++,l=l+0x02) //首先顯示右側的提示 顯示“示波器 ”
{
ye=l;
lei=0x70; // 01(標識) 110000 第48列
for(r=0;r<16;r++)
{
shu=FrameData[2*r+1+32*k];
LCMView();
lei++;
}
ye=l+0x01; //第二頁
lei=0x70;
for(r=0;r<16;r++)
{
shu=FrameData[2*r+32*k];
LCMView();
lei++;
}
}
while(1) //重頭戲來了
{
while(X2==0) //調節X軸 外部按鍵控制X軸 +是延遲橫向掃描時間
{
while(X2==0); //放開后才加
Xaxis = Xaxis + 1; //X軸
}
while(X1==0)
{
while(X1==0);
if(Xaxis!=0)
{
Xaxis = Xaxis - 1; // 縮短橫向掃描時間
}
}
while(Y1==0) //調節Y軸
{
while(Y1==0);
Yaxis = Yaxis + 1;
}
while(Y2==0)
{
while(Y2==0);
if(Yaxis!=1) //調整顯示幅度DIV
{
Yaxis=Yaxis-1;
}
}
for(j=0;j<90;j++) //AD采樣最大值 只是為了得到最大值
{
ADCChage(); //開啟轉換
ADViewdata[j]=ADdata; //采集的數據存入數表
if(ADViewdata[j]>ADViewdata[91]) //選擇最大值
{
ADViewdata[91]=ADViewdata[j]; //選到的最大值存到91的位置
}
Delay50us(Xaxis);
}
while(ADdata!=ADViewdata[91]) //如果采集值不相等,則繼續 直至掃到最大值
{
ADCChage();
}
for(j=0;j<90;j++) //連續采樣90次 要準備用來顯示了
{
ADCChage();
ADViewdata[j]=ADdata; //注意 只存到89 。91千萬不能碰
Delay50us(Xaxis);
}
lei=0x41; //01(標識) 000001 第1列
for(r=0,j=0;r<90;r++,j++) // 一個特別醒目的問題 一起加1
{ //這個括號直接到整個程序結束的
if(j<63) // 如果是前64個數 則用左屏幕顯示
{
Ldata=1;
}
if(j==63) //第64個數 用中間行顯示
{
lei=0x40;
}
if(j>=63) //后面的數 用右屏幕顯示
{
Ldata=2;
}
RefreshLCM(); //刷新當前顯示
if(ADViewdata[j>=127])//正電壓
{
ADdata=(ADViewdata[j]-127)*0.196/Yaxis; //計算電壓值 0.196什么意思?
if(ADdata<=7) //小于7 沒超過
{
ye=0xbb; // 10111(標識) 011 第A3頁 從上往下數是第四頁
shu=(0x80>>ADdata); // 1000 0000 右移
}
else if(ADdata<=15) // 大于7小于15
{
ye=0xba; // 10111(標識) 010 第A2頁 從上往下第三頁
shu=(0x80>>(ADdata-8));
}
else if(ADdata<=23) // 小于23
{
ye=0xb9; // 10111 001 第A1頁 從上往下第二頁
shu=(0x80>>(ADdata-16));
}
else if(ADdata<=31)
{
ye=0xb9; //還是A1頁
shu=(0x80>>(ADdata-24));
}
}
if(ADViewdata[j]<127) //負電壓
{
ADdata=(127-ADViewdata[j])*0.196/Yaxis; //計算電壓值
if(ADdata<=7)
{
ye=0xbc; // 10111 100 第A4頁
shu=(0x01<<(ADdata));
}
else if(ADdata<=15)
{
ye=0xbd; //A5頁
shu=(0x01<<(ADdata-8));
}
else if(ADdata<=23)
{
ye=0xbe; //A6頁
shu=(0x01<<(ADdata-16));
}
else if(ADdata<=31)
{
ye=0xbe; //A7頁
shu=(0x01<<(ADdata-24));
}
}
if(r==0)//判斷正負 上面一大串 其實只是為了得到一個顯示的點應該放在哪個位置
{
d1=shu;
d2=ye; //存放位置信號 而且r==0 是啟始點
}
if(r!=0) //不是第一個點
{ // 這個括號到快結束
d3=shu;
d4=ye;
if(ye==d2) //如果相等,則判斷是否顯示完成 跟第一個數是同一頁嗎
{
if(shu>d1) //是同一頁的話 如果數比第一個數大 PS:同一位 位移的數越多 越大
{
d5=shu; //確實比較大的話 給d5
d5=d5>>1; // 右移一位 除以2
while(d5!=d1) //跟初始值比 一樣的話沒事 不一樣的話 再除以2
{
d5=d5>>1;
shu=shu|(shu>>1);
}
}
if(shu<d1) //同頁 但比較小
{
d5=shu;
d5=d5<<1;
while(d5!=d1)
{
d5=d5<<1;
shu=shu|(shu<<1);
}
}
}
if(ye<d2)
{
for(q=0;q<7;q++)
{
shu=shu|(shu<<1);
}
LCMView();
ye++;
while(ye<d2)
{
shu=0xff;
LCMView();
ye++;
}
if(ye==d2)
{
shu=0x01;
if(shu<d1)
{
d5=shu;
d5=d5<<1;
while(d5!=d1)
{
d5=d5<<1;
shu=shu|(shu<<1);
}
}
}
}
if(ye>d2)
{
for(q=0;q<7;q++)
{
shu=shu|(shu>>1);
}
LCMView();
ye--;
while(ye>d2) {shu=0xff,LCMView(),ye--;}
if(ye==d2)
{
shu=0x80;
if(shu>d1)
{
d5=shu;
d5=d5>>1;
while(d5!=d1)
{
d5=d5>>1;
shu=shu|(shu>>1);
}
}
}
}
}
if(r!=0)
{
d1=d3;
d2=d4;
}
LCMView();
if(lei!=0x7f) //000 11111 最后一列
{
lei++;
}
}
}
}
|