首先你应该知道你的转速范围是多大?每秒几十转还是几百转甚至上千转?
不同的转速对应不同的设计.
可以使用51的定时器/计数器来实现脉冲捕获计数.比如使用T0.
设置T0的工作模式,一般可用自动重装8位计数的模式2.
在T0的溢出中断中,设计二重计数cntT0.比如T0为200转溢出,则中断时再累加一次即累加了200转.
设置T1为定时器模式,可以定时1S或10ms(计为t),由你转速及程序复杂度决定.
在T1中断程序中,读取cntT0的值和T0的值(计算为rt),则转速为rt/t
开关控制指示灯显示MY8255_AEQU 0A860H;8255A口地址
MY8255_BEQU 0A861H;8255B口地址
MY8255_CEQU 0A862H;8255C口地址
MY8255_MODE EQU 0A863H;8255控制口地址
CODE SEGMENT
ASSUME CS:CODE
START: MOV DX,MY8255_MODE
MOV AL,82H
OUT DX,AL;将控制字82H写入8255控制口,A口方式0输出,B口方式0输入, C口未用到。
A1:MOV DX,MY8255_B
IN AL,DX ;读8255 B口内容
MOV DX,MY8255_A
OUT DX,AL ; 将前面读到的B口内容送到A口,即A口内容=B口内容
CALL BREAK;调用子程序BREAK
JMP A1;跳转到A1
BREAK PROC NEAR ;BREAK子程序
MOV AH,1
INT 16H
JZ RETURN ;读按键字符,ZF=1,则返回;ZF=0,则AL=字符
MOV AX,4C00H
INT 21H ;返回DOS
RETURN:RET
BREAK ENDP
CODE ENDS
END START
流水灯显示
MY8255_AEQU 0b860H;8255A口地址
MY8255_BEQU 0b861H;8255B口地址
MY8255_CEQU 0b862H;8255C口地址
MY8255_MODE EQU 0b863H;8255控制口地址
DATA SEGMENT
LA DB ?;留出1个字节
LB DB ?;留出1个字节
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
MOV DX,MY8255_MODE
MOV AL,80H
OUT DX,AL ;控制字80H送入8255控制口,A口、B口都是方式0输出,C口未用到。
MOV DX,MY8255_A
MOV AL,7FH
OUT DX,AL ;将7FH送入A口
MOV LA,AL ;将7FH送入LA存储单元
MOV DX,MY8255_B
MOV AL,0FEH
OUT DX,AL;将FEH送入B口
MOV LB,AL ;将FEH送入LB存储单元
CALL DALLY
A1:MOV AL,LA
ROR AL,1;LA内容循环右移1次
MOV LA,AL
MOV DX,MY8255_A
OUT DX,AL ;将循环右移后的LA内容送A口,其目的是让A口连接的LED灯依次向右循环点亮
MOV AL,LB
ROL AL,1 ;LB内容循环左移1次
MOV LB,AL
MOV DX,MY8255_B
OUT DX,AL ;将循环左移后的LB内容送B口,其目的是让B口连接的LED灯依次向左循环点亮
CALL DALLY ;延时,让一个LED灯发光稳定之后再点亮另一个
CALL BREAK ;调用BREAK子程序,看是否有键按下
JMP A1 ;跳转到A1
DALLY: MOV CX,3FFH ;延时子程序
D1:MOV AX,0FFFFH
D2:DEC AX
JNZ D2
LOOP D1
RET
BREAK PROC NEAR ;是否有键按下
MOV AH,06H
MOV DL,0FFH
INT 21H
JE RETURN ;若无,则转RETURN
MOV AX,4C00H
INT 21H ;返回DOS
RETURN:RET
BREAK ENDP
CODE ENDS
END START
#include <reg51.h>#include <INTRINS.H>
#define FOSC 11.0592
unsigned int speed
unsigned char key
unsigned char led_table[10]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xff,0xf6}
long speed_count,speed_count1
unsigned char speed_check
unsigned int second_flag
unsigned char speed_table[4]
unsigned char speed_table1[10]
//定时器频率1000Hz
void timer1_init(void)
{
EA=0
TMOD=0x10
//TH1=1000*FOSC/12/256
//TL1=(unsigned int)(1000*FOSC/12)%256
TH1=254
TL1=51
TR1=1
TCON|=0X04 //外部中断下降触发
EX1=1 //允许外部中断
ET1=1
EA=1
}
void int1_routine(void) interrupt 2
{
speed_count++
P1^=0X02
}
void timer1_routine(void) interrupt 3
//void timer1_routine(void)
{
TH1=254
//TH1=0xf0
TL1=51
//speed_count++
second_flag++
}
void main(void)
{
unsigned int i,j,k
// unsigned char sum
unsigned speed_table[3]
long time_id
timer1_init()
speed=0
P2=0x0f
P0=0xf0
P3=0x08
key=0
P1=0x00
speed_check=0
while(1)
{
//P1^=0XFE
j=1
//speed=1234
speed_table[0]=speed/1000
speed_table[1]=speed%1000/100
speed_table[2]=speed%100/10
speed_table[3]=speed%10
for(i=0i<4i++)
{
P2=j^0xff
j<<=1
P0=(led_table[speed_table[i]])&0xfe
for(k=0k<250k++)
}
//speed=speed_count
if(second_flag>=1000) /*中断1000次进入 */
{
second_flag=0
time_id++
speed_table1[time_id%10]=speed_count/*外部中断量转存(是很聪明的方法学习了)*/
speed_count=0
speed=(speed_table1[0]+speed_table1[1]+speed_table1[2]+speed_table1[3]+speed_table1[4]+speed_table1[5]+speed_table1[6]+speed_table1[7]+speed_table1[8]+speed_table1[9])*6/*(10X6)10秒的外部中断量乘以6就是转速了*/
//speed=speed/2+(speed_table[0]+speed_table[1]+speed_table[2])*6
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)