Re: [請益] 關於ADC0804訊號擷取的問題

看板ASM (組合語言)作者 (呆呆小狼)時間15年前 (2009/09/17 03:00), 編輯推噓2(207)
留言9則, 3人參與, 最新討論串4/4 (看更多)
※ 引述《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
謝謝,不過我擔心原po可能還是看不懂真正的技術癥結在哪
09/17 14:24, 2F

09/17 14:25, , 3F
然後完全不懂怎麼修改又認為程式太敏感還是甚麼的又弄出
09/17 14:25, 3F

09/17 14:26, , 4F
一堆if...else 來,那我也沒辦法了......(笑)
09/17 14:26, 4F

09/19 11:12, , 5F
程式測試時燈閃動的很快,覺得可能是只有延遲1ms的緣故
09/19 11:12, 5F

09/19 11:14, , 6F
想說在else條件後面加delay(2000),請問w大我這樣理解
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
我是建議能用數學解覺得東西沒必要弄一堆條件式 XD
09/19 19:57, 9F
文章代碼(AID): #1AiJMyKA (ASM)
文章代碼(AID): #1AiJMyKA (ASM)