承接上一节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<
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<
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
{
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;
}
}
上一篇:【51单片机】延时函数计算问题以及如何准确延时
下一篇:单片机C语言之指针变量
推荐阅读最新更新时间:2024-03-16 16:01