項目功能: 將被測風扇葉片(三葉風扇)置于紅外光電傳感器和其反光板之間,當光電傳感器接收到對面的反光板反射回來的信號時(即葉片間的空隙通過時)輸出低電平,當光電傳感器沒收到反光板反射回的信號時(即葉片通過時)輸出高電平。這樣我們從光電傳感器這里接受到的信號就是一串方波信號。 單片機不斷接收到光電傳感器的信號,同時自身內部有定時器在計時,以及計數器在計數收到方波的個數。計時器設定計時1秒,每過1秒發生一次中斷,統計計數器中收到的方波個數,將其除以3之后就得到了每秒風扇轉過的圈數。最后通過我們設定的程序將其數值轉換為標準的轉速單位r/min的數值并且顯示在8段數碼管上,便于讓人讀出。 因為AT89C52兼容AT89C51,所以在本次的仿真試驗中,使用的是AT89C52。 
數碼管介紹: 本項目中使用的八段數碼管型號是7SEG-MPX6-CA,是共陽極數碼管。123456分別對應數碼管的從左往右的123456號數碼管。ABCDEFG,DP分別接AT89C52的P0口,123456接單片機的P1口。即用P1控制顯示哪個數碼管,用P0控制顯示的數據。
系統原理圖:


在這里我們利用方波發生器來模擬光電傳感器的輸出信號,方波發生器的參數設置如下: 如圖所示,頻率 設計為64Hz,即每秒 鐘有64個信號輸入, 轉換為一分鐘為 3840,因為風扇是三 葉片的,所以除以3 以后才是實際的風扇 轉速,結果是 3840/3=1280,而顯示 結果也是1280(如上 圖),說明單片機正 確的實現了我們所 需的功能。
在這里我們設置AT89C52的晶振頻率為11.0592Hz(設置如下圖),以滿足實際的效果,所以定時器的T0的初始值設置為TH0=10H, TL0=00H, 而定時的次數為15次,剛好是1秒鐘。 
仿真結果如下(其中視頻存放在文件夾中): 
程序的實現:
程序代碼如下,分別是C語言和匯編語言:C語言:
#include<reg51.h> //包含單片機寄存器的頭文件
#include<intrins.h> //包含_nop_()函數定義的頭文件
unsigned int v; //儲存電機轉速
unsigned char count; //儲存定時器T0中斷次數
bit flag; //計滿1秒鐘標志位
void delay1ms() //函數功能:延時1ms
{ //(3j+2)*i=(30×3+2)×10=920
unsigned char i,j; //對11.0592MHz的晶振來說大約是1ms
for(i=0;i<10;i++)
for(j=0;j<30;j++)
;
}
void delay(unsigned char n) //延時n個毫秒
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
void change(unsigned char a) //數字對應段碼的轉換
{ if(a==0) P0=0xc0;
if(a==1) P0=0xf9;
if(a==2) P0=0xa4;
if(a==3) P0=0xb0;
if(a==4) P0=0x99;
if(a==5) P0=0x92;
if(a==6) P0=0x82;
if(a==7) P0=0xf8;
if(a==8) P0=0x80;
if(a==9) P0=0x90;
}
void display_val(unsigned int x) //顯示數值
{
unsigned char i,j,k,l; //i,j,k,l分別儲存轉速的千位、百位、十位和個位
i=x/1000; //取千位
j=(x%1000)/100; //取百位
k=(x%100)/10; //取十位
l=x%10; //取個位
P1=8; //選3號數碼管
change(i);
delay1ms();
P1=4; //選4號數碼管
change(j);
delay1ms();
P1=2; //選5號數碼管
change(k);
delay1ms();
P1=1; //選6號數碼管
change(l);
delay1ms();
}
void main(void) //主函數
{
TMOD=0x51; //定時器T1工作于計數模式1,定時器T0工作于計時模式1;
TH0=0x10; //定時器T0的高8位設置初值,每66.67ms產生一次中斷
TL0=0; //定時器T0的低8位設置初值
EA=1; //開總中斷
ET0=1; //定時器T0中斷允許
TR0=1; //啟動定時器T0
count=0; //將T0中斷次數初始化為0
while(1) //無限循環
{
TR1=1; //計數器T1啟動
TH1=0; //計數器T1高8位賦初值0
TL1=0; //計數器T1低8位賦初值0
flag=0;
while(flag==0) //時間未滿1s等待
{
display_val(v); //顯示轉速
} ;
v=TL1*20; //計算速度,每周產生3個脈沖
}
}
void Time0(void ) interrupt 1 using 1 //定時器T0的中斷編號為1,使用第1組工作寄存器
{
count++; //T0每中斷1次,count加1
if(count==15) //若累計滿15次,即計滿1秒鐘
{
flag=1; //計滿1秒鐘標志位置1
count=0; //清0,重新統計中斷次數
}
TH0=0x10; //定時器T0高8位重新賦初值
TL0=0x00; //定時器T0低8位重新賦初值
}
匯編語言:
開始說明:T0是定時器,T1是計數器。50H存放定時器計數的次數,56H存放T1對輸入信號的計數值。P0控制顯示的數據,P1控制顯示哪個數碼管。
LEDBuf equ 40h ;顯示數據存放處
org 0000h
ljmp main
org 000bh
AJMP PTF00
org 0100h
main: mov sp,#60h
mov TMOD,#51H ;01010001,T1是16位計數器方式1,T0是16位定時器方式1
mov TCON,#54h ;TR1=1,TR0=1,IT1=1,即T1在下降沿計數
mov TL0,#00H ;單次66.67ms
mov TH0,#10H ;
mov TL1,#00H
mov TH1,#00H
mov IE,#8ah ;1000 1010 EA,ET0,ET1
MOV 50H,#15 ;計數15次,即66.67ms*15=1s
mov 40h,#00h ;初始化
mov 41h,#00h
mov 42h,#00h
mov 43h,#00h
mov 44h,#00h
mov 45h,#00h
dispagain:
acall display
sjmp dispagain
PTDS: MOV R1,A ;拆字子程序
ACALL PTDS1
MOV A,R1
SWAP A
PTDS1: ANL A,#0FH
MOV @R0,A
DEC R0
RET
PTF00:
push psw
push acc
SETB PSW.3
MOV TH0,#10H
MOV A,50H
DEC A
MOV 50H,A
JNZ PTFY
MOV 50H,#15
MOV A,TL1
mov 56H,a
mov TH1,#00H
mov TL1,#00H
PTFY:
pop acc
pop psw
RETI
LOOP4: CLR A ;二轉十子程序
MOV R4,A
MOV R5,A
MOV R6,A
MOV R7,#10H
LOOP5: CLR C
MOV A,52H
RLC A
MOV 52H,A
MOV A,51H
RLC A
MOV 51H,A
MOV A,R6
ADDC A,R6
DA A
MOV R6,A
MOV A,R5
ADDC A,R5
DA A
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
DJNZ R7,LOOP5
mov 53H,r4
mov 54H,r5
mov 55H,r6
RET
Delay:
mov r7, #0 ; 延時子程序
DelayLoop:
djnz r7, DelayLoop
djnz r6, DelayLoop
ret
DISPLAY:
mov a,56H
mov b,#20
mul ab
mov 51H,b
mov 52H,a
MOV R0,#45H ;將轉換結果存至45H--40H
lcall LOOP4
MOV A,55H
LCALL PTDS
MOV A,54H
LCALL PTDS
MOV A,53H
LCALL PTDS
setb 0d3h
mov r0, #LEDBuf
mov r1, #6 ; 共6個八段管
mov r2, #00100000b ; 從左往右顯示
Loop: mov p1,#0 ; 關所有八段管
mov a, @r0
mov dptr,#LEDmap
movc a,@a+dptr
mov p0, a ; 顯示一位八段管
mov p1,r2
mov r6, #1
call Delay
mov a, r2 ; 為顯示下一位做準備
rr a
mov r2, a
inc r0
djnz r1, Loop
mov p1,#0
clr 0d3h
ret
LEDMAP: ; 八段數碼管顯示段碼
;db 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07h ;共陰極段碼
;db 7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71h
db 0c0h, 0f9h, 0a4h, 0b0h, 99h, 92h, 82h, 0f8h;共陽極段碼
db 80h, 90h, 88h, 83h, 0c6h, 0a1h, 86h, 8eh
END
遇到的困難及解決辦法:
數碼管的顯示問題。
因為不知道數碼管的使用,所以先用一段程序來實驗一下數碼管。如下:
Mov P0,#0c0h //P0.0-P0.7分別接數碼管的ABCDEFG DP引腳
Mov P1,#01h //P1.5-P1.0分別接數碼管的123456引腳
結果顯示效果是六號數碼管亮,顯示數字是0。
完整的Word格式文檔51黑下載地址:
文檔.doc
(890.28 KB, 下載次數: 33)
2019-7-17 01:17 上傳
點擊文件名下載附件
轉速測量
|