100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > c语言 测转速程序 用51单片机实现风扇转速测量的源程序+电路图

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

时间:2021-10-27 00:20:53

相关推荐

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

项目功能:

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

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

#include //包含_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

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

AJMPPTF00

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 1010EA,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

sjmpdispagain

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

JNZPTFY

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:

djnzr7, DelayLoop

djnzr6, 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

movp0, a ; 显示一位八段管

mov p1,r2

mov r6, #1

callDelay

mov a, r2 ; 为显示下一位做准备

rr a

mov r2, a

inc r0

djnzr1, Loop

movp1,#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, 下载次数: 23)

-7-17 01:17 上传

点击文件名下载附件

转速测量

下载积分: 黑币 -5

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。