三杯式風速傳感器實驗報告 一、實驗目的
1.掌握三杯式風速傳感器的工作原理; 2.將三杯式風速傳感器測得的風速(風由風扇提供)實時顯示在液晶和上位機上; 3.進一步掌握1602液晶的使用以及串口通訊; 4.規范C的書寫格式。 二、實驗原理
三杯式風速傳感器有一個測速碼盤,當碼盤轉動并不斷地通過三杯式風速傳感器內部的光電傳感器后,就會產生脈沖信號,脈沖信號觸發單片機產生外部中斷0,外部中斷0對脈沖次數進行計數,定時器0中斷設定1s的時間,并獲取1s內的脈沖次數,然后通過公式:(脈沖次數*7)/80.0+0.1(注意:此處的80.0不能寫成80,否則將會丟失風速的小數位,因為除以80得到的是整數)就可以計算出風速,然后就可以通過單片機將風速顯示在液晶和上位機上了。
三、實驗步驟
1.查閱三杯式風速傳感器的相關資料,掌握其測速原理;
2.測三杯式風速傳感器的脈沖次數并顯示在數碼管上;
3.將風速測出并顯示在1602液晶上;
4.將風速測出并顯示在1602液晶和上位機上。
5.觀察實驗現象,總結。
四、實驗結果
1602液晶和上位機均能實時顯示三杯式風速傳感器測得的風速,且顯示一致,風速精確到了小數點后兩位。
五、實驗總結
這次實驗剛開始測脈沖次數的時候就遇到了挫折,原因是按照文檔上的接法,將紅色線和黑色線接反了,廢了一番波折將傳感器拆開后才把線接對,將脈沖次數測出來。這件事原因還是在我,不敢挑戰文檔的權威性,當時要是把紅黑線的接法對調一下就不會有后面的麻煩事了(不過這也與紅色線是重新接上去的有關系,我一直懷疑它接觸不良)。脈沖次數測出來后液晶顯示很快也順利地實現了,不過到液晶與上位機同時顯示的時候,出現了問題,究其原因是我把顯示寫在了串口中斷里,但是沒有加標志位,串口中斷接收不到脈沖次數,所以風速一直顯示是0,不過在加了標志位后,這個問題順利解決了。另外將顯示寫在主程序里通過查詢方式也實現了液晶和上位機的顯示。至于為什么沒有同時將脈沖次數顯示在數碼管上,這是因為數碼管的位選端P2口和液晶要用到的P2^0,P2^1和P2^2口發生了沖突(這里要吐槽一下,這個單片機沒有鎖存器)。
附錄1 數碼管顯示風速傳感器脈沖次數的程序 單片機源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar i;
- uint f,num;
- uchar code table[]=
- {
- 0x28,0x7e,0xa2,0x62,
- 0x74,0x61,0x21,0x7a,
- 0x20,0x60
- };//數碼表(0-9)
- void delay(uint z)//1ms延時函數
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void display()
- {
- uchar wan,qian,bai,shi,ge;
- wan=num/10000;//獲取計數值的萬位
- qian=num%10000/1000;//獲取計數值的千位
- bai=num%10000%1000/100;//獲取計數值的百位
- shi=num%10000%1000%100/10;//獲取計數值的十位
- ge=num%10000%1000%100%10;//獲取計數值的個位
- P2=0xfe;
- P0=table[wan];
- delay(2);
- P2=0xfd;
- P0=table[qian];
- delay(2);
- P2=0xfb;
- P0=table[bai];
- delay(2);
- P2=0xf7;
- P0=table[shi];
- delay(2);
- P2=0xef;
- P0=table[ge];
- delay(2);
- }
- void init()//初始化子程序
- {
- TMOD=0x01;//設置定時器0為工作方式1
- TH0=(65536-50000)/256; //定時器0裝初值
- TL0=(65536-50000)%256; //同上
- IT0=1;//外部中斷0為跳變沿觸發方式
- EA=1;//打開總中斷
- EX0=1;//打開外部中斷0
- ET0=1;//打開定時器0中斷
- TR0=1;//打開定時器0
- }
- void main()
- {
- init();
- while(1)
- {
- display();
- }
- }
- void exter0() interrupt 0 //外部中斷0子程序
- {
- f++; //脈沖計數
- }
- void timer0() interrupt 1 //定時器0中斷子程序
- {
- TH0=(65536-50000)/256; //定時器0重裝初值
- TL0=(65536-50000)%256; //同上
- i++;
- if(i==20) //定時器0計時1s
- {
- num=f;
- i=0;
- f=0;
- }
- }
復制代碼
附錄2 液晶上顯示風速的程序
附錄3 液晶和上位機同時顯示風速的程序
單片機源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar i;
- //uchar flag;//標志位
- uint a,b,c,f,num;
- uint ws_i;
- double ws_d,ws_d1;//定義風速的數據類型為雙精度型
- uchar code table1[]=" speed: ";
- uchar code table2[]=" . m/s ";
- uchar code table3[]="speed:";
- sbit RS=P2^0;
- sbit RW=P2^1;
- sbit EN=P2^2;
- void delay(uint z)//1ms延時函數
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void write_com(uchar com) //液晶寫命令子程序
- {
- RS=0;//寫入命令
- RW=0;//讀寫控制端設置為寫模式
- P0=com;//將命令送給P0口
- delay(10);
- EN=1;//將命令送給液晶顯示屏
- delay(10);
- EN=0;
- }
- void write_data(uchar dat)//液晶寫數據子程序
- {
- RS=1;//寫入數據
- RW=0;
- P0=dat;//將數據送給P0口
- delay(10);
- EN=1;//將數據送給液晶顯示屏
- delay(10);
- EN=0;
- }
- void init()//初始化子程序
- {
- write_com(0x38);//設置16*2顯示,5*7點陣,8位數據接口
- write_com(0x01);//清屏
- write_com(0x06);//寫一個字符后,地址指針加1
- write_com(0x0C);//設置開顯示,不顯示光標
- write_com(0x80);//液晶顯示屏從第一行的第一個位置開始寫入字符
- for(a=0;a<16;a++)//液晶顯示屏第一行寫入" speed: "
- {
- write_data(table1[a]);
- delay(1);
- }
- write_com(0x80+0x40);//液晶顯示屏從第二行的第一個位置開始寫入字符
- for(b=0;b<16;b++)//液晶顯示屏第二行寫入" . m/s "
- {
- write_data(table2[b]);
- delay(1);
- }
- TMOD=0x21;//設置定時器0為工作方式1,定時器1為工作方式2
- TH0=(65536-50000)/256; //定時器0裝初值
- TL0=(65536-50000)%256; //同上
- TH1=0xf3;//設置波特率為2400
- TL1=0xf3;//同上
- TR1=1;//打開定時器1
- TR0=1;//打開定時器0
- IT0=1;//外部中斷0為跳變沿觸發方式
- REN=1;//允許串口接收數據
- SM0=0;//設置串口的工作方式為1
- SM1=1;//同上
- EX0=1;//打開外部中斷0
- ET0=1;//打開定時器0中斷
- EA=1;//打開總中斷
- // ES=1;//打開串口中斷
- }
- void main()
- {
- uchar shi,ge,sf,bf,shi_1,ge_1,sf_1,bf_1;
- init();
- delay(1);
- while(1)
- {
- ws_i=(int)(ws_d1);//將雙精度類型的風速強制轉化為整型
- shi_1=ws_i/1000;//將風速的十位分離出來;
- write_com(0x80+0x40+7);
- write_data(0x30+shi_1);//液晶第二行第8個位置寫入風速的十位數
- ge_1=ws_i%1000/100;//將風速的個位分離出來
- write_com(0x80+0x40+8);
- write_data(0x30+ge_1);//液晶第二行第9個位置寫入風速的個位數
- sf_1=ws_i%1000%100/10;//將風速的十分位分離出來
- write_com(0x80+0x40+10);
- write_data(0x30+sf_1);//液晶第二行第11個位置寫入風速的十分位
- bf_1=ws_i%1000%100%10;//將風速的百分位分離出來
- write_com(0x80+0x40+11);
- write_data(0x30+bf_1);//液晶第二行第12個位置寫入風速的十分位
- delay(500);
- TI=0;//允許發送
- for(c=0;c<6;c++) //上位機接收字符串“speed:”
- {
- TI=0;//允許發送
- SBUF=table3[c];
- while(!TI);//等待發送
- delay(5);
- }
- delay(5);
- shi=ws_i/1000;
- ge=ws_i%1000/100;
- sf=ws_i%1000%100/10;
- bf=ws_i%1000%100%10;
- SBUF=0x30+shi;//上位機顯示風速的十位
- delay(5);
- SBUF=0x30+ge;//上位機顯示風速的個位
- delay(10);
- SBUF='.';
- delay(10);
- SBUF=0x30+sf;//上位機顯示風速的十分位
- delay(10);
- SBUF=0x30+bf;//上位機顯示風速的百分位
- delay(10);
- SBUF='m';
- delay(10);
- SBUF='/';
- delay(10);
- SBUF='s';
- delay(10);
- SBUF='\n';//換行
- delay(1000);
- while(!TI);//等待數據傳送
- }
- }
- void exter0() interrupt 0 //外部中斷0子程序
- {
- f++; //脈沖計數
- }
- void timer0() interrupt 1 //定時器0中斷子程序
- {
- TH0=(65536-50000)/256; //定時器0重裝初值
- TL0=(65536-50000)%256; //同上
- i++;
- if(i==20) //定時器0計時1s
- {
- num=f;
- ws_d=(num*7)/80.0+0.1;//80后面的.0不能少,少的話(num*7)/80只能得到整數
- if(ws_d>0.1) //風速大于0
- ws_d1=ws_d*100;//為了使風速顯示到小數點后兩位
- else
- ws_d1=0; //風速為0
- i=0;
- f=0;
- // flag=1;
- }
- }
- /*void ser() interrupt 4 //串口中斷函數
- {
- uchar shi,ge,sf,bf,shi_1,ge_1,sf_1,bf_1;
- if(flag==1)
- {
- ws_i=(int)(ws_d1);//將雙精度類型的風速強制轉化為整型
- shi_1=ws_i/1000;
- write_com(0x80+0x40+7);
- write_data(0x30+shi_1);
- ge_1=ws_i%1000/100;
- write_com(0x80+0x40+8);
- write_data(0x30+ge_1);
- sf_1=ws_i%1000%100/10;
- write_com(0x80+0x40+10);
- write_data(0x30+sf_1);
- bf_1=ws_i%1000%100%10;
- write_com(0x80+0x40+11);
- write_data(0x30+bf_1);
- delay(500);
- TI=0;//允許發送
- for(c=0;c<6;c++) //上位機接收字符串“speed:”
- {
- TI=0;//允許發送
- SBUF=table3[c];
- while(!TI);//等待發送
- delay(5);
- }
- delay(5);
- shi=ws_i/1000;
- ge=ws_i%1000/100;
- sf=ws_i%1000%100/10;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
三杯式風速傳感器實驗報告.docx
(23.44 KB, 下載次數: 169)
2017-12-1 22:18 上傳
點擊文件名下載附件
關于三杯式風速傳感器的液晶顯示程序 下載積分: 黑幣 -5
|