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

来源:互联网 发布:ubuntu 退出用户登录 编辑:程序博客网 时间:2024/06/08 00:08

承接上一节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; //Kfloat 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;    //打开定时器0while(P2_7==0);//等待充电到P2.7口为高电平TR0=0;     //关闭定时器0p25_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;    //打开定时器0while(P2_7==0);//等待充电到P2.7口为高电平TR0=0;     //关闭定时器0p26_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 pinunsigned 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-19if(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;} }