51单片机定时器的原理与使用(二)

承接上一节51单片机定时器的原理与使用,这节我们继续讲述怎么用定时器做一个电子钟,PWM脉冲和测电阻。先从实验三讲起吧!

实验三、定时器测电阻

测量如下图Rx的电阻并显示在数码管上。


测量思路为:
1、电容C1放电,P2.5与P2.6设置为输入模式,P2.7设置为推挽输出且为输出低电平0。这时候C1通过R1和P2.7放电。
2、切断C1的放电回路,将P2.7设为输入模式。
3、P2.5设为推挽输出,并且输出高电平5V,即P2.5的高电平通过Rk对C1充电。同时打开定时器Tx。
4、MCU不断读P2.7的状态,当P2.7为高,则关闭定时器。同时P2.5恢复输入模式。这个过程中定时器记录了P2.5通过Rk对C1充电直到P2.7为高电平的时间t1。
5、将P2.7设为推挽输出并输出0,即对C1再次放电。放电完成后,将P2.7恢复为输入状态。
6、P2.6设为推挽输出,并且输出高电平5V,即P2.6的高电平通过Rx对C1充电。同时打开定时器Tx。MCU不断读P2.7的状态,当P2.7为高,则关闭定时器。这个过程中定时器记录了P2.6通过Rx对C1充电直到P2.7为高电平的时间t2。
Rk/Rx = t1/t2 即 Rx = t2*Rk/t1
直接上代码:


main.c
#include "reg51.h"

unsigned int count;
extern void load_smg();
extern void res_test();
extern  void delay(unsigned int x);

void Timer1_Init()
{
	TMOD|=0x10;
	TH1=64614/256;
	TL1=64614%256;
	TR1=1;
}

void Isr_Init()
{
	EA=1;
	ET1=1;
	ET0=1;
}

void Timer0_Init()
{
	TMOD|=0x01;
	TH0=0;
	TL0=0;
	TR0=0;
}

void TF1_isr() interrupt 3		//1ms
{
	TH1=64614/256;
	TL1=64614%256;
	load_smg();

}
void main()
{
	Timer0_Init();
	Timer1_Init();
	Isr_Init();
    
	while(1)
	{
	   res_test();
	   delay(65000);
	   delay(65000);
	}
}

smg.c
 #include "reg51.h" 
  //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 char smgbuf[4]={1,2,3,4}; //从RAM的smgbuf这个地址开始连续存放4个数,并且每个数占一个单元。
 extern unsigned int count;	//外部申明,表示并不在这里申明

void fill_smgbuf() //向LED缓冲区填充数据
{
	smgbuf[0]=count/1000;  //千位
	smgbuf[1]=(count%1000)/100;  //百位
	smgbuf[2]=((count%1000)%100)/10;   //十位
	smgbuf[3]=((count%1000)%100)%10;   //个位
}

void load_smg()   //将数码管显示缓冲区的数据,显示到数码管上
 {
 	static char i;
	fill_smgbuf();
	i++;
	if(i>=4)
	{
		i=0;
	}
	P0=0xFF;   //消除上一个循环的影子
	P2 = ~(1<<i);
	P0 = seg[smgbuf[i]];	

 }
resistor.c
#include "reg51.h"
sfr P2M1=0x95; //因为reg51.h里面没有,所以自己定义
sfr P2M0=0x94;
float t1, t2;
float Rk=100; //K
float Rx;
extern unsigned int count;
sbit P2_5=P2^5;
sbit P2_6=P2^6;
sbit P2_7=P2^7;

 void delay(unsigned int x)
 {
 	while(x)   
	{
		x--;
	}	
 }

void p25_ppout() //将P2.5配置成推挽输出
{
	P2M1&=~(1<<5);
	P2M0|=(1<<5);
}

void p25_odin() //将P2.5配置成仅输入高阻
{
	P2M1|=(1<<5);
	P2M0&=~(1<<5);
}

void p26_ppout() //将P2.6配置成推挽输出
{
	P2M1&=~(1<<6);
	P2M0|=(1<<6);
}

void p26_odin() //将P2.6配置成仅输入高阻
{
	P2M1|=(1<<6);
	P2M0&=~(1<<6);
}

void p27_ppout() //将P2.7配置成推挽输出
{
	P2M1&=~(1<<7);
	P2M0|=(1<<7);
}

void p27_odin() //将P2.7配置成仅输入高阻
{
	P2M1|=(1<<7);
	P2M0&=~(1<<7);
}

void res_test()
{
	p25_odin(); p26_odin(); p27_ppout(); P2_7=0;  //C1放电
	delay(65000);
	delay(65000);
	p27_odin(); //放电完成

	p25_ppout(); P2_5=1;//P2.5通过Rk对电容C1充电
	TR0=1;	    //打开定时器0
	while(P2_7==0);//等待充电到P2.7口为高电平
	TR0=0;	     //关闭定时器0
	p25_odin();

	t1=TH0*256+TL0;
	TH0=0;
	TL0=0;

	p25_odin(); p26_odin(); p27_ppout();P2_7=0;	 //C1放电
	delay(65000);
	delay(65000);
	p27_odin(); //放电完成

	p26_ppout();P2_6=1;
	TR0=1;	    //打开定时器0
	while(P2_7==0);//等待充电到P2.7口为高电平
	TR0=0;	     //关闭定时器0
	p26_odin();

	t2=TH0*256+TL0;

	Rx=t2*Rk/t1;
	count = (unsigned int) Rx;
}

实验一、电子钟

main.c文件

#include "reg51.h"
/*实时时钟 RTC*/
char RTC[3] = {12,34,56};
extern void load_smg();
unsigned int ms1;

void Timer1_Init()
{
	TMOD|=0x10;
	TH1=64614/256;
	TL1=64614%256;
	TR1=1;
}

void Isr_Init()
{
	EA=1;
	ET1=1;
}
void Run_clock()
{
 	RTC[2]++;
	if(RTC[2]>=60)
	{
		RTC[2]=0;
		RTC[1]++;
		if(RTC[1]>=60)
		{
			RTC[1]=0;
		    RTC[0]++;
			if(RTC[0]>=24)
			{
				RTC[0]=0;
			    	
			}	
		}
	}
}
void TF1_isr() interrupt 3		//1ms
{
 	static int ms;
	TH1=64614/256;
	TL1=64614%256;
	ms++;
	ms1++;
	if(ms1>=1000)
	{
		ms1=0;
	}
	if(ms>=1000)   //1 sec
	{
		ms=0;
		Run_clock();	
		
	}
	load_smg();

}
void main()
{
	Timer1_Init();
	Isr_Init();
	while(1)
	{

	}
}
smg.c文件
 #include "reg51.h" 
  //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 char smgbuf[4]={1,2,3,4}; //从RAM的smgbuf这个地址开始连续存放4个数,并且每个数占一个单元。
// extern unsigned int count;	//外部申明,表示并不在这里申明
 extern char RTC[3];
 extern void delay(unsigned int x);
 extern unsigned int ms1;

void fill_smgbuf() //向LED缓冲区填充数据
{
	smgbuf[0]=RTC[1]/10;  //分钟十位
	smgbuf[1]=RTC[1]%10;  //分钟个位
	smgbuf[2]=RTC[2]/10;   //秒钟十位
	smgbuf[3]=RTC[2]%10;   //秒钟个位
}

void load_smg()   //将数码管显示缓冲区的数据,显示到数码管上
 {
 	static char i;
	fill_smgbuf();

 	for(i=0;i<4;i++)	
	{
		P0=0xFF;   //消除上一个循环的影子
		if(ms1<500)
		{
		   P0 = seg[smgbuf[i]]&0x7F;
		}
		else
		{
		   //P0=0xff;	//整体闪烁
		   P0 = seg[smgbuf[i]];	 //实现分钟与秒钟之间的 :闪烁
		}
		
		P2 = ~(1<<i);
		delay(200);
	} 
 }
void delay(unsigned int x)

 {
	   while(x--);
 }


实验二、产生一个周期周20ms,脉宽1-19ms可变的PWM波,脉宽可以用按键选择,输出的PWM波去点亮一个led灯,并用示波器观察效果。

main.c

#include "reg51.h"
/*用定时器1产生周期为20ms,脉宽为1-19ms*/
sbit out=P1^0; //PWM output pin
unsigned int ms;
unsigned int pwm=10;
extern void key3();

void Timer1_Init()
{
	TMOD|=0x10;
	TH1=64614/256;
	TL1=64614%256;
	TR1=1;
}

void Isr_Init()
{
	EA=1;
	ET1=1;
}

void TF1_isr() interrupt 3		//1ms
{
 	TH1=64614/256;
	TL1=64614%256;
	ms++;
	if(ms>=20)
	{
		ms=0;
	}
	//...ms=0-19
	if(ms<pwm)
	{
		out=1;
	}
	else
	{
		out=0;
	}
}
void main()
{
	Timer1_Init();
	Isr_Init();
	while(1)
	{

	    key3();
	}
}
key.c

 #include "reg51.h"
 extern unsigned int pwm;
 sbit K3=P2^6;

  void delay(unsigned int x)
 {
	   while(x--);
 }

 void key3()
 {
 	static char st;
	if(K3==0)
	{
		 if(st==0)
		 {
		 	delay(5000);
			if(K3==0)
			{
				st=1;
				pwm++;
				if(pwm>=20)
				{
					pwm=1;
				}
			}

		 }
	}
	else
	{
		st=0;
	}
 }

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值