作者WolfLord (呆呆小狼)
看板ASM
标题Re: [请益] 关於ADC0804讯号撷取的问题
时间Thu Sep 17 03:00:08 2009
※ 引述《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)
1F:推 sorkayi:改的不错 比较简洁了 09/17 11:10
2F:→ WolfLord:谢谢,不过我担心原po可能还是看不懂真正的技术症结在哪 09/17 14:24
3F:→ WolfLord:然後完全不懂怎麽修改又认为程式太敏感还是甚麽的又弄出 09/17 14:25
4F:→ WolfLord:一堆if...else 来,那我也没办法了......(笑) 09/17 14:26
5F:推 endlessbbs:程式测试时灯闪动的很快,觉得可能是只有延迟1ms的缘故 09/19 11:12
6F:→ endlessbbs:想说在else条件後面加delay(2000),请问w大我这样理解 09/19 11:14
7F:→ endlessbbs:对吗@@? 09/19 11:14
8F:→ WolfLord:这样你会得到一个当机的程式,你在想想该怎麽办 09/19 19:56
9F:→ WolfLord:我是建议能用数学解觉得东西没必要弄一堆条件式 XD 09/19 19:57