标题:
求助,89C52计数器T0对外部方波没反应
[打印本页]
作者:
rank
时间:
2018-1-11 17:49
标题:
求助,89C52计数器T0对外部方波没反应
最近用STC89C52做一个频率计数器,用LCD1602显示,外接1kHz的方波到T0进行测试的时候,发现T0没有对方波进行计数,下面是代码,请高手帮忙看看是哪里出了问题
#include <AT89x52.h>
#include <stdio.h>
#include <math.h>
#include <intrins.h>
float p;
char idata buff[20];
unsigned char time;
unsigned char T1inter;
unsigned char GATE = 1; //测量中断,0表示开始测量
unsigned char FLAG = 0; //是否分频选择,0不分频,1分频
unsigned char LCD_Wait(void);
void LCD_Write(bit style, unsigned char input);
void LCD_SetDisplay(unsigned char DisplayMode);
void LCD_SetInput(unsigned char InputMode);
void LCD_Initial();
void GotoXY(unsigned char x, unsigned char y);
void Print(unsigned char *str);
/****************************************
* 模块名称:LCD1602显示程序 *
*****************************************/
/***********************Port Definitions*********************/
sbit LcdRs = P1^0; //定义端口
sbit LcdRw = P1^1;
sbit LcdEn = P2^5;
sfr DBPort= 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
/************************内部等待函数************************/
unsigned char LCD_Wait(void)
{
LcdRs=0; //寄存器选择输入端 1:数据 0:指令
LcdRw=1; _nop_(); //RW:为0:写状态;为1:读状态;
LcdEn=1; _nop_(); //使能输入端,读状态,高电平有效;写状态,下降沿有效
LcdEn=0;
return DBPort;
}
/***********************向LCD写入命令或数据*******************/
#define LCD_COMMAND 0 // Command
#define LCD_DATA 1 // Data
#define LCD_CLEAR_SCREEN 0x01 // 清屏
#define LCD_HOMING 0x02 // 光标返回原点
void LCD_Write(bit style, unsigned char input)
{
LcdEn=0;
LcdRs=style;
LcdRw=0; _nop_();
DBPort=input; _nop_();//注意顺序
LcdEn=1; _nop_();//注意顺序
LcdEn=0; _nop_();
LCD_Wait();
}
/********************设置显示模式****************************/
#define LCD_SHOW 0x04 //显示开
#define LCD_HIDE 0x00 //显示关
#define LCD_CURSOR 0x02 //显示光标
#define LCD_NO_CURSOR 0x00 //无光标
#define LCD_FLASH 0x01 //光标闪动
#define LCD_NO_FLASH 0x00 //光标不闪动
void LCD_SetDisplay(unsigned char DisplayMode)
{
LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
}
/*********************设置输入模式****************************/
#define LCD_AC_UP 0x02
#define LCD_AC_DOWN 0x00 // default
#define LCD_MOVE 0x01 // 画面可平移
#define LCD_NO_MOVE 0x00 //default
void LCD_SetInput(unsigned char InputMode)
{
LCD_Write(LCD_COMMAND, 0x04|InputMode);
}
/******************初始化LCD*********************************/
void LCD_Initial()
{
LcdEn=0;
LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动
}
/*************************************************************/
void GotoXY(unsigned char x, unsigned char y)
{
if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}
void Print(unsigned char *str)
{
while(*str!='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
/**************************ms延时子程序********************/
void Delay(unsigned int t) //t随着数值越大,误差趋于平衡.
{
unsigned char i;
while(t--)
{
for(i=0;i<123;i++){;}
}
}
//配置计数器0,定时器1、2
void Init_timer(void)
{
TMOD=0x9D; //工作方式1 内部寄存器控制的计数功能
TH0=0x00; //T0高八位的初值
TL0=0x00; //T0低八位初值
TH1=0x00; //T1高八位的初值
TL1=0x00; //T1低八位初值
EA=1; //开启整体中断允许
ET0=1; //开启定时器0中断允许
ET1=1; //开启T1中断允许
TR0=1;
TR1=1;
EX0=1;
IT0=1;
RCAP2H=(65536-62500)/256; //在程序初始化的时候给RCAP2L和RCAP2H赋值,
RCAP2L=(65536-62500)%256; //TH2和TL2将会在中断产生时自动使TH2=RCAP2H,TL2=RCAP2L。
TH2=RCAP2H; //12M晶振下每次中断62.5ms(1s=1000ms=62.5ms×16)
TL2=RCAP2L;
ET2=1; //打开定时器2中断
TR2=1; //定时器2开始计时
}
/***************主程序**************/
void main()
{
P1_2=0;
Init_timer();
LCD_Initial(); //LCD初始化
while(1)
{;}
}
//P1.2接INT0,触发中断
void Out_interrupt(void)interrupt 0
{
float t0cont,t1cont;
//关闭T0、T1
TR0=0;
TR1=0;
t0cont=TH0*256+TL0;
t1cont=65535*T1inter+TH1*256+TL1;
//p=(t0cont/t1cont)*1000000;
p=t0cont;
GotoXY(0,1);
sprintf(buff,"%4.4fKHz",p);
Print(buff);
//打开T0、T1,重置初值,为下一次测量做准备
TR0=1;
TR1=1;
TH0=0x00; //T0高八位的初值
TL0=0x00; //T0低八位初值
TH1=0x00; //T1高八位的初值
TL1=0x00;
//中断后开始读数显示
}
void Timer0_isr(void)interrupt 1
{
TH0=0x00;
TL0=0x00;
}
void Timer1_isr(void)interrupt 3
{ T1inter++;
TH1=0; //计数=(65535-初值) 初值0x159F=5535
TL1=0;
if(T1inter==4)
{
T1inter=0;
}
}
void timer2(void) interrupt 5 //定时器2中断(62.5ms)
{
time++;
TF2=0; //定时器2的中断标志位TF2不能够由硬件清零,所以要在中断服务程序中将其清零
if (time==4) //定时0.25s时间到
{
time=0; //计时清0
P1_2=~P1_2;//P1.2反转
}
}
复制代码
作者:
HC6800-ES-V2.0
时间:
2018-1-12 15:05
我没有看你的程序全部,只看了定时器设置那部分,你说没反应,可能就是设置的问题。
第一:如图所示:
1.jpg
(47.84 KB, 下载次数: 33)
下载附件
2018-1-12 14:52 上传
这是STC89C52的手册说明(我没有找到你用的AT89C52的手册)
你程序中设置TMOD=0x9d,即二进制1001 1101
定时器0、1都是工作方式1——16位定时\计数器
定时器1为定时器,定时器0为计数器
“门控制”位都是1——由上图可知,当此位为1时,要开启定时\计数器,还需要外部中断。
这是不是你想要的结果?
第二:我的建议:
“门控制”位置0,即只需要TRx就可以控制定时器的开启和关闭。
你的外部脉冲,直接到定时器0。只要TR0=1,则计数器0就开始计数了,注意,你的脉冲信号要接在P34脚;只要TR1=1,定时器1就开始计时了。
同时开启两定时器,你的工作不就完成了?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1