主要器件:手機電池供電,PT1301升壓到5V,以TL431輸出的2.5V為探頭的信號地,運放TL082做信號放大,數字電位器MCP41010做增益調節,NOKIA1100液晶屏做為顯示,96*65像素點,其工作所需3.3V電壓是5V電壓串聯LED后得來的。STC12C5A50S2做為核心控制,據資料介紹其ADC采樣速度可達250KHz,兩路ADC采集波形數據,一路ADC采集2.5V電壓,一路ADC采集電池電壓,兩路PWM經低通濾波后控制調理電路的偏移。探頭接口是用的雙聲道耳機接口,比較節省空間,但是通道間會有干擾。按鍵有9個,CH:選通道; Vp/Hp:主菜單選擇:POWER:開機;Vs/Hs:(本程序未用) INC:+ ,STOP:關機 SET:進彈出菜單 DEC:- ESC:退出/暫停
程序介紹:
程序中為了方便圖形操作,為液晶屏建立了內存緩沖,繪圖操做在單片機內存中進行,然后整體復制到液晶屏.由于內存不太充裕,采用了分塊的方法,以時間換取空間:
#define LCD_WIDTH 96
#define LCD_HEIGHT 8
//液晶分區數
#define LCD_PART 2
//U8 lcd_x=0;
//U8 lcd_y=0;
xdata U8 lcd_buf[LCD_HEIGHT/LCD_PART][LCD_WIDTH];//lcd顯示緩存(1/LCD_PART屏)
xdata S16 lcd_bufx0=0,lcd_bufy0=0,lcd_bufx1=0,lcd_bufy1=0;//緩沖區對應四角坐標,(去掉右邊框)
//x0 <= x < x1;y0 <= y < y1;
//-------------------------------------------------------
//選擇液晶屏區域
//s=0~LCD_PART-1
//-------------------------------------------------------
void lcd_buf_sel(U8 s)
{
if(s>=LCD_PART)return;
lcd_bufx0=0;
lcd_bufx1=LCD_WIDTH;
lcd_bufy0=LCD_HEIGHT*s/LCD_PART;
lcd_bufy1=LCD_HEIGHT*(s+1)/LCD_PART;
}
繪圖時需遍歷每個顯示緩存塊:
for(p=0;p<LCD_PART;p++)
{
lcd_buf_sel(p);
//LCD_DrawPic(0,0,160,123,0,gImage_t1);
lcd_buf_fill(0x04);
GUI_SetFont6x8();
GUI_dispnum(i,3,0,5,13,0);
GUI_PutStr(5,5,"welcome...");
GUI_SetFont8x16();
GUI_PutStr(5,25,"welcome...");
lcd_refresh();
}
程序在timer0中斷里采集波形數據,主要代碼如下:
//--------------------------------------------------
//定時器中查詢AD
//--------------------------------------------------
void timer0(void) interrupt 1 using 3 //T0中斷,用寄存器組0
{
//while(TF0==0);
//TF0=0;
U8 ad;
//static U8 fp=0;//分頻
if(T0EXC==0)
{
//mmm++;
TH0=TH0RLD;//重裝初值
TL0=TL0RLD;
T0EXC=T0EXH;
//dosamp();
while(ADC_CONTR&BIT(3));//等待通道0轉換完成
//while(!(ADC_CONTR&BIT(4)));
ad=ADC_RES;//讀通道0
if(TrigCh==0)//通道1觸發
{
if(ChEnable & BIT(1))//通道2使能
ADC_CONTR=(0xE8|ADCH2);//選通道2
else //否則選通道1
ADC_CONTR=(0xE8|ADCH1);//選通道1
ADCBuf[0][BUF_Wps]=ad;//循環存儲數據
}
else
{
if(ChEnable & BIT(0))//通道1使能
ADC_CONTR=(0xE8|ADCH1);//選通道1
else //否則選通道1
ADC_CONTR=(0xE8|ADCH2);//選通道2
ADCBuf[1][BUF_Wps]=ad;//循環存儲數據
}
//if(BUF_Wps>=ADCBUFSIZE)BUF_Wps=0;
if(SampState==0)//預采數據
{
//if(ADC_Cnt<ADCBUFSIZE)
ADC_Cnt++; //數據個數加1
BUF_Cnt++;
if(ADC_Cnt>=TrigPs)//觸發位置
{
if(TrigEdge==0)//上升沿觸發
SampState=1;
else //下降沿觸發
SampState=2;
}
}
//------------------------上升沿狀態為1-2-3,下降沿狀態為2-1-3
else if(SampState==1)
{
if(ad<=TrigLevel)//低于觸發電平
{
if(TrigEdge==0)//上升沿觸發
SampState=2;
else //下降沿觸發
SampState=3;
//if(ADC_Cnt<ADCBUFSIZE)
ADC_Cnt++;//數據個數加1
BUF_Cnt++;
}
else//否則讀取隊列,ADC_Cnt,BUF_Cnt就不加了
{
BUF_Rps++;
if(BUF_Rps>=ADCBUFSIZE)BUF_Rps=0;
}
}
else if(SampState==2)
{
if(ad>TrigLevel)//高于觸發電平
{
if(TrigEdge==0)//上升沿觸發
SampState=3;
else //下降沿觸發
SampState=1;
//if(ADC_Cnt<ADCBUFSIZE)
ADC_Cnt++;//數據個數加1
BUF_Cnt++;
}
else//否則讀取隊列,ADC_Cnt,BUF_Cnt就不加了
{
BUF_Rps++;
if(BUF_Rps>=ADCBUFSIZE)BUF_Rps=0;
}
}
else if(SampState==3)//已觸發
{
ADC_Cnt++; //數據個數加1
BUF_Cnt++;
if(ADC_Cnt>=ADCBUFSIZE)//采了足夠的數據
{
SampState=4;
TR0=0;
}
}
if((TrigMode==0)&&(SampState<3))//自動觸發處理
{
if(TrigWait==0)//等待時間低位
{
if(TrigWaitH)//等待時間高位
{
TrigWaitH--;
}
else
{
SampState=3;
}
}
TrigWait--;
}
if(TrigCh==0)//通道1觸發
{
if(ChEnable & BIT(1))//通道2使能
{
while(ADC_CONTR&BIT(3));//等待通道1轉換完成
//while(!(ADC_CONTR&BIT(4)));
ad=ADC_RES;//讀通道1
ADC_CONTR=(0xE8|ADCH1);//選通道1
ADCBuf[1][BUF_Wps]=ad;//循環存儲數據
}
}
else
{
if(ChEnable & BIT(0))//通道1使能
{
while(ADC_CONTR&BIT(3));//等待通道1轉換完成
//while(!(ADC_CONTR&BIT(4)));
ad=ADC_RES;//讀通道1
ADC_CONTR=(0xE8|ADCH2);//選通道2
ADCBuf[0][BUF_Wps]=ad;//循環存儲數據
}
}
//寫指針下移
BUF_Wps++;
if(BUF_Wps>=ADCBUFSIZE)BUF_Wps=0;
}
else
{
T0EXC--;
}
}
程序介紹:
程序中為了方便圖形操作,為液晶屏建立了內存緩沖,繪圖操做在單片機內存中進行,然后整體復制到液晶屏.由于內存不太充裕,采用了分塊的方法,以時間換取空間:
#define LCD_WIDTH 96
#define LCD_HEIGHT 8
//液晶分區數
#define LCD_PART 2
//U8 lcd_x=0;
//U8 lcd_y=0;
xdata U8 lcd_buf[LCD_HEIGHT/LCD_PART][LCD_WIDTH];//lcd顯示緩存(1/LCD_PART屏)
xdata S16 lcd_bufx0=0,lcd_bufy0=0,lcd_bufx1=0,lcd_bufy1=0;//緩沖區對應四角坐標,(去掉右邊框)
//x0 <= x < x1;y0 <= y < y1;
//-------------------------------------------------------
//選擇液晶屏區域
//s=0~LCD_PART-1
//-------------------------------------------------------
void lcd_buf_sel(U8 s)
{
if(s>=LCD_PART)return;
lcd_bufx0=0;
lcd_bufx1=LCD_WIDTH;
lcd_bufy0=LCD_HEIGHT*s/LCD_PART;
lcd_bufy1=LCD_HEIGHT*(s+1)/LCD_PART;
}
繪圖時需遍歷每個顯示緩存塊:
for(p=0;p<LCD_PART;p++)
{
lcd_buf_sel(p);
//LCD_DrawPic(0,0,160,123,0,gImage_t1);
lcd_buf_fill(0x04);
GUI_SetFont6x8();
GUI_dispnum(i,3,0,5,13,0);
GUI_PutStr(5,5,"welcome...");
GUI_SetFont8x16();
GUI_PutStr(5,25,"welcome...");
lcd_refresh();
}
程序在timer0中斷里采集波形數據,主要代碼如下:
//--------------------------------------------------
//定時器中查詢AD
//--------------------------------------------------
void timer0(void) interrupt 1 using 3 //T0中斷,用寄存器組0
{
//while(TF0==0);
//TF0=0;
U8 ad;
//static U8 fp=0;//分頻
if(T0EXC==0)
{
//mmm++;
TH0=TH0RLD;//重裝初值
TL0=TL0RLD;
T0EXC=T0EXH;
//dosamp();
while(ADC_CONTR&BIT(3));//等待通道0轉換完成
//while(!(ADC_CONTR&BIT(4)));
ad=ADC_RES;//讀通道0
if(TrigCh==0)//通道1觸發
{
if(ChEnable & BIT(1))//通道2使能
ADC_CONTR=(0xE8|ADCH2);//選通道2
else //否則選通道1
ADC_CONTR=(0xE8|ADCH1);//選通道1
ADCBuf[0][BUF_Wps]=ad;//循環存儲數據
}
else
{
if(ChEnable & BIT(0))//通道1使能
ADC_CONTR=(0xE8|ADCH1);//選通道1
else //否則選通道1
ADC_CONTR=(0xE8|ADCH2);//選通道2
ADCBuf[1][BUF_Wps]=ad;//循環存儲數據
}
//if(BUF_Wps>=ADCBUFSIZE)BUF_Wps=0;
if(SampState==0)//預采數據
{
//if(ADC_Cnt<ADCBUFSIZE)
ADC_Cnt++; //數據個數加1
BUF_Cnt++;
if(ADC_Cnt>=TrigPs)//觸發位置
{
if(TrigEdge==0)//上升沿觸發
SampState=1;
else //下降沿觸發
SampState=2;
}
}
//------------------------上升沿狀態為1-2-3,下降沿狀態為2-1-3
else if(SampState==1)
{
if(ad<=TrigLevel)//低于觸發電平
{
if(TrigEdge==0)//上升沿觸發
SampState=2;
else //下降沿觸發
SampState=3;
//if(ADC_Cnt<ADCBUFSIZE)
ADC_Cnt++;//數據個數加1
BUF_Cnt++;
}
else//否則讀取隊列,ADC_Cnt,BUF_Cnt就不加了
{
BUF_Rps++;
if(BUF_Rps>=ADCBUFSIZE)BUF_Rps=0;
}
}
else if(SampState==2)
{
if(ad>TrigLevel)//高于觸發電平
{
if(TrigEdge==0)//上升沿觸發
SampState=3;
else //下降沿觸發
SampState=1;
//if(ADC_Cnt<ADCBUFSIZE)
ADC_Cnt++;//數據個數加1
BUF_Cnt++;
}
else//否則讀取隊列,ADC_Cnt,BUF_Cnt就不加了
{
BUF_Rps++;
if(BUF_Rps>=ADCBUFSIZE)BUF_Rps=0;
}
}
else if(SampState==3)//已觸發
{
ADC_Cnt++; //數據個數加1
BUF_Cnt++;
if(ADC_Cnt>=ADCBUFSIZE)//采了足夠的數據
{
SampState=4;
TR0=0;
}
}
if((TrigMode==0)&&(SampState<3))//自動觸發處理
{
if(TrigWait==0)//等待時間低位
{
if(TrigWaitH)//等待時間高位
{
TrigWaitH--;
}
else
{
SampState=3;
}
}
TrigWait--;
}
if(TrigCh==0)//通道1觸發
{
if(ChEnable & BIT(1))//通道2使能
{
while(ADC_CONTR&BIT(3));//等待通道1轉換完成
//while(!(ADC_CONTR&BIT(4)));
ad=ADC_RES;//讀通道1
ADC_CONTR=(0xE8|ADCH1);//選通道1
ADCBuf[1][BUF_Wps]=ad;//循環存儲數據
}
}
else
{
if(ChEnable & BIT(0))//通道1使能
{
while(ADC_CONTR&BIT(3));//等待通道1轉換完成
//while(!(ADC_CONTR&BIT(4)));
ad=ADC_RES;//讀通道1
ADC_CONTR=(0xE8|ADCH2);//選通道2
ADCBuf[0][BUF_Wps]=ad;//循環存儲數據
}
}
//寫指針下移
BUF_Wps++;
if(BUF_Wps>=ADCBUFSIZE)BUF_Wps=0;
}
else
{
T0EXC--;
}
}