Re: [請益] 關於ADC0804訊號擷取的問題
※ 引述《endlessbbs ()》之銘言:
: 下面是小弟自己寫的全部程式
: #include <reg51.h>
: #include <stdlib.h>
: sbit ADCRD=P3^7 ;//設ADCRD腳位為P3.7
: sbit ADCWR=P3^6 ;//設ADCWR腳位為P3.6
: sbit ADCINTR=P3^2;//設ADCINTR腳位為P3.2
: sbit spk=P0^0;//喇叭控制定義位元
#define ADCData P2
#define LEDPort P1
#define DyBalance 64 //假設0G是64,事實上你要看你的動量感測器而定
char code ledtab[9]={0,0x1,0x3,0x7,0xf,0x1f,0x3f,0x7f,0xff};
// char code ledtab[9]={0xff;0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0};
// Invers table
: unsigned char hi, lo;
: unsigned char thi[]={0,223,229,232,233,236,238,240,241,242,244,246,247,247};
: //音階對應計時器0計數初值高位元組資料列表
: unsigned char tlo[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3};//音階對應計時器0計
: 數初值低位元組資料列表
: unsigned char song[]={3,5,5,3,2,1,2,3,5,3,2,3,5,5,3,2,1,2,3,2,1,1,100};//旋
: 律
: unsigned char len[]={1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1,100};//拍子
首先,我們來改進你的DELAY。假設你使用12MHZ,我們希望DELAY的基本單位是1/1000秒
1000=0x3e8(1000uS),所以我們知道我們要先捕捉TH1>2然後等TL1>0xe7就可已知到是
經過了精確的1mS。當然,這還有些誤差,包括比對,啟動等等得動作都有延遲。不過精
確度比較高而且每次執行也比較穩定。
/*
void delay1ms(void){
TR1=0;
TH1=0;
TL1=0;
TR1=1;
while(TH1<3); // wait TH1=3
while(TL1<0xe8); // wait TL1=0xe8
TR1=0;
}
*/
不過這樣讓CPU兜圈子似乎很浪費,那我們再來改良一下。AD轉換需要時間,而DELAY正
是讓CPU浪費時間。那位什麼不把AD轉換跟發呆一起作?
char data adtmp=0; //用來計算累計動量
void delay1ms(void){
TR1=0; TH1=0;
TL1=0; TR1=1;
ADCWR=0; ADCWR=1;
while(TH1<1); // delay 256 uS
ADCRD=0;
adtmp=adtmp+(ADCData-DyBalance); // 動量累積+(動量變化量 +64-64)
ADCRD=1;
if(adtmp<1){ // fix over flow and off LED
adtmp=0;
LEDPort=ledtab[0];
}else{ // not Zero or overflow Show LED
LEDPort=ledtab[((adtmp>>4)&0x7)+1]; //Take table 1~8 range
}
while(TH1<3); // wait TH1=3
while(TL1<0xe8); // wait TL1=0xe8
TR1=0;
}
好啦~ 我們現在有一個既能精確DELAY又能捕捉動量的DELAY程式了
: delay(int d)
: {
: int i,j;
: for(i=0;i<d;i++)
: for(j=0;j<200;j++);
: }
你這段DELAY改成這樣如何?
void delay(int d){
while(d>0){
delay1ms();
d--;
}
}
: void t0isr(void)interrupt 1
: {
: TH0=hi;
: TL0=lo;
: spk=~spk;
: }
: init_timer()
: {
:// TMOD=0x00;
TMOD=0x10; //我們需要T1用MODE1工作
: IE=0X82;
: }
: tone(char t, char l){
: hi=thi[t];
: lo=tlo[t];
: TR0=1;
: delay(100*l);
: TR0=0;
: }
: play_song(char*t,char*l)
: {
: while(1){
: if(*t==100)break;
: tone(*t++,*l++);
: delay(5);
: }
: }
老實說,你的MAIN好亂,改成這樣會不會比較簡潔?
void main(void){
init_timer();
while(1){
play_song(song,len);
delay(1000); //唱完了喔? 延遲1秒後來一次
}
}
--
作別人不願作的事,是好人!。 作別人不敢作的事,是壞人!。
作別人不能作的事,是天才!。 作別人不會作的事,是…腦殘!!
WolfLord
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.46.200.173
※ 編輯: WolfLord 來自: 114.46.200.173 (09/17 03:29)
推
09/17 11:10, , 1F
09/17 11:10, 1F
→
09/17 14:24, , 2F
09/17 14:24, 2F
→
09/17 14:25, , 3F
09/17 14:25, 3F
→
09/17 14:26, , 4F
09/17 14:26, 4F
推
09/19 11:12, , 5F
09/19 11:12, 5F
→
09/19 11:14, , 6F
09/19 11:14, 6F
→
09/19 11:14, , 7F
09/19 11:14, 7F
→
09/19 19:56, , 8F
09/19 19:56, 8F
→
09/19 19:57, , 9F
09/19 19:57, 9F
討論串 (同標題文章)
完整討論串 (本文為第 4 之 4 篇):
ASM 近期熱門文章
PTT數位生活區 即時熱門文章