将红外模块连接外部中断0,用于记录10秒内转的圈数,定时器0计时10秒,十秒后关闭中断,计算转速(r/min)并显示在数码管上。
电机需要特别改一下,如下:
黑色小块可以吸收红外线,此时红外模块out指示灯不亮,周围白色则反射红外线回去,红外模块接收红外线,out指示灯亮,并且拉低P3^2口 ,发生中断。
材料
1、红外模块
2、51单片机
3、L298N电机驱动模块
4、5V直流电机
硬件连接
只需要一个直流电机即可,使用motorA直流电机,给L298N供电后,令L298N上IN1或IN2其中一个接Vcc就可以让直流电机转动起来。
红外模块正确供电,out接单片机P3^2口,P3^2是51单片机外部中断口。
代码
#include <REG52.H>
unsigned char code gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
sbit LSA = P2 ^ 2;//38译码器
sbit LSB = P2 ^ 3;
sbit LSC = P2 ^ 4;
sbit RAY = P3 ^ 2; // 外部中断0引脚
unsigned long cnt = 0;
unsigned int speed = 0;
//数码管显示函数,n为要显示的数
void smg_display(unsigned int n)
{
char i, j;
for (i = 7; i >= 0; i--) {
switch (i) {
case 0:
LSC = 1;
LSB = 1;
LSA = 1;
break; // 7
case 1:
LSC = 1;
LSB = 1;
LSA = 0;
break; // 6
case 2:
LSC = 1;
LSB = 0;
LSA = 1;
break; // 5
case 3:
LSC = 1;
LSB = 0;
LSA = 0;
break; // 4
case 4:
LSC = 0;
LSB = 1;
LSA = 1;
break; // 3
case 5:
LSC = 0;
LSB = 1;
LSA = 0;
break; // 2
case 6:
LSC = 0;
LSB = 0;
LSA = 1;
break; // 1
case 7:
LSC = 0;
LSB = 0;
LSA = 0;
break; // 0
}
P0 = gsmg_code[n % 10];
n = n / 10;
for (j = 0; j < 2; j++)
;
P0 = 0x00;
}
}
//外部中断0初始化
void exti0_init()
{
EA = 1;
EX0 = 1;
IT0 = 1;
}
//定时器0中断初始化
void timer0_init()
{
TMOD |= 0x01;
TH0 = 0x3c; // 定时约50ms
TL0 = 0xc4;
ET0 = 1;
EA = 1;
TR0 = 1;
}
void main()
{
exti0_init();
while (1) {
}
}
void exti0() interrupt 0
{
cnt++;
if (cnt == 1) {
timer0_init();
}
}
void timer0() interrupt 1
{
static unsigned char i;
TH0 = 0x64; // 计时会有误差,这里是根据实际情况修改过的,没有精确的计算
TL0 = 0x22;
i++; // i=200时约为10秒
if (i == 200) { //
speed = cnt * 6; // 计算转速
ET0 = 0; // 关闭timer0中断允许
TR0 = 0; // 关闭定时器0
while (1) {
smg_display(speed); /* speed 速度,单位r/min */
}
}
}
效果
注意:测量时,红外模块应正好处于面临黑色out指示灯灭,面临周围白边out指示灯亮的位置。