找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7269|回复: 0
收起左侧

用51单片机实现风扇转速测量的源程序+电路图

[复制链接]
ID:585441 发表于 2019-7-16 23:06 | 显示全部楼层 |阅读模式
项目功能:

将被测风扇叶片(三叶风扇)置于红外光电传感器和其反光板之间,当光电传感器接收到对面的反光板反射回来的信号时(即叶片间的空隙通过时)输出低电平,当光电传感器没收到反光板反射回的信号时(即叶片通过时)输出高电平。这样我们从光电传感器这里接受到的信号就是一串方波信号。

单片机不断接收到光电传感器的信号,同时自身内部有定时器在计时,以及计数器在计数收到方波的个数。计时器设定计时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)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表