找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1420|回复: 1
打印 上一主题 下一主题
收起左侧

求助,89C52计数器T0对外部方波没反应

[复制链接]
跳转到指定楼层
楼主
最近用STC89C52做一个频率计数器,用LCD1602显示,外接1kHz的方波到T0进行测试的时候,发现T0没有对方波进行计数,下面是代码,请高手帮忙看看是哪里出了问题
  1.    
  2.     #include <AT89x52.h>
  3.     #include <stdio.h>
  4.     #include <math.h>
  5.     #include <intrins.h>

  6.     float p;
  7.     char idata buff[20];
  8.     unsigned char time;
  9.     unsigned char T1inter;
  10.     unsigned char GATE = 1; //测量中断,0表示开始测量
  11.     unsigned char FLAG = 0; //是否分频选择,0不分频,1分频
  12.     unsigned char LCD_Wait(void);
  13.     void LCD_Write(bit style, unsigned char input);
  14.     void LCD_SetDisplay(unsigned char DisplayMode);
  15.     void LCD_SetInput(unsigned char InputMode);
  16.     void LCD_Initial();
  17.     void GotoXY(unsigned char x, unsigned char y);
  18.     void Print(unsigned char *str);

  19.     /****************************************
  20.     * 模块名称:LCD1602显示程序 *
  21.     *****************************************/
  22.     /***********************Port Definitions*********************/
  23.     sbit LcdRs = P1^0; //定义端口
  24.     sbit LcdRw = P1^1;
  25.     sbit LcdEn = P2^5;
  26.     sfr DBPort= 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口

  27.     /************************内部等待函数************************/
  28.     unsigned char LCD_Wait(void)
  29.     {
  30.     LcdRs=0; //寄存器选择输入端 1:数据 0:指令
  31.     LcdRw=1; _nop_(); //RW:为0:写状态;为1:读状态;
  32.     LcdEn=1; _nop_(); //使能输入端,读状态,高电平有效;写状态,下降沿有效
  33.     LcdEn=0;
  34.     return DBPort;
  35.     }
  36.     /***********************向LCD写入命令或数据*******************/
  37.     #define LCD_COMMAND 0 // Command
  38.     #define LCD_DATA 1 // Data
  39.     #define LCD_CLEAR_SCREEN 0x01 // 清屏
  40.     #define LCD_HOMING 0x02 // 光标返回原点
  41.     void LCD_Write(bit style, unsigned char input)
  42.     {
  43.     LcdEn=0;
  44.     LcdRs=style;
  45.     LcdRw=0; _nop_();
  46.     DBPort=input; _nop_();//注意顺序
  47.     LcdEn=1; _nop_();//注意顺序
  48.     LcdEn=0; _nop_();
  49.     LCD_Wait();
  50.     }
  51.     /********************设置显示模式****************************/
  52.     #define LCD_SHOW 0x04 //显示开
  53.     #define LCD_HIDE 0x00 //显示关

  54.     #define LCD_CURSOR 0x02 //显示光标
  55.     #define LCD_NO_CURSOR 0x00 //无光标

  56.     #define LCD_FLASH 0x01 //光标闪动
  57.     #define LCD_NO_FLASH 0x00 //光标不闪动

  58.     void LCD_SetDisplay(unsigned char DisplayMode)
  59.     {
  60.     LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
  61.     }
  62.     /*********************设置输入模式****************************/
  63.     #define LCD_AC_UP 0x02
  64.     #define LCD_AC_DOWN 0x00 // default

  65.     #define LCD_MOVE 0x01 // 画面可平移
  66.     #define LCD_NO_MOVE 0x00 //default

  67.     void LCD_SetInput(unsigned char InputMode)
  68.     {
  69.     LCD_Write(LCD_COMMAND, 0x04|InputMode);
  70.     }
  71.     /******************初始化LCD*********************************/
  72.     void LCD_Initial()
  73.     {
  74.     LcdEn=0;
  75.     LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵
  76.     LCD_Write(LCD_COMMAND,0x38);
  77.     LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标
  78.     LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
  79.     LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动
  80.     }

  81.     /*************************************************************/
  82.     void GotoXY(unsigned char x, unsigned char y)
  83.     {
  84.     if(y==0)
  85.     LCD_Write(LCD_COMMAND,0x80|x);
  86.     if(y==1)
  87.     LCD_Write(LCD_COMMAND,0x80|(x-0x40));
  88.     }
  89.     void Print(unsigned char *str)
  90.     {
  91.     while(*str!='\0')
  92.     {
  93.     LCD_Write(LCD_DATA,*str);
  94.     str++;
  95.     }
  96.     }
  97.     /**************************ms延时子程序********************/
  98.     void Delay(unsigned int t) //t随着数值越大,误差趋于平衡.
  99.     {
  100.     unsigned char i;
  101.     while(t--)
  102.     {
  103.     for(i=0;i<123;i++){;}
  104.     }
  105.     }
  106.     //配置计数器0,定时器1、2
  107.     void Init_timer(void)
  108.     {
  109.     TMOD=0x9D; //工作方式1 内部寄存器控制的计数功能
  110.     TH0=0x00; //T0高八位的初值
  111.     TL0=0x00; //T0低八位初值
  112.     TH1=0x00; //T1高八位的初值
  113.     TL1=0x00; //T1低八位初值
  114.     EA=1; //开启整体中断允许
  115.     ET0=1; //开启定时器0中断允许
  116.     ET1=1; //开启T1中断允许
  117.     TR0=1;
  118.     TR1=1;
  119.     EX0=1;
  120.     IT0=1;
  121.     RCAP2H=(65536-62500)/256; //在程序初始化的时候给RCAP2L和RCAP2H赋值,
  122.     RCAP2L=(65536-62500)%256; //TH2和TL2将会在中断产生时自动使TH2=RCAP2H,TL2=RCAP2L。
  123.     TH2=RCAP2H; //12M晶振下每次中断62.5ms(1s=1000ms=62.5ms×16)
  124.     TL2=RCAP2L;
  125.     ET2=1; //打开定时器2中断
  126.     TR2=1; //定时器2开始计时
  127.     }



  128.     /***************主程序**************/
  129.     void main()
  130.     {
  131.     P1_2=0;
  132.     Init_timer();
  133.     LCD_Initial(); //LCD初始化
  134.     while(1)
  135.     {;}

  136.     }
  137. //P1.2接INT0,触发中断
  138.     void Out_interrupt(void)interrupt 0
  139.     {
  140.     float t0cont,t1cont;
  141. //关闭T0、T1
  142.     TR0=0;
  143.     TR1=0;
  144.     t0cont=TH0*256+TL0;
  145.     t1cont=65535*T1inter+TH1*256+TL1;
  146.     //p=(t0cont/t1cont)*1000000;
  147.     p=t0cont;
  148.     GotoXY(0,1);
  149.     sprintf(buff,"%4.4fKHz",p);
  150.     Print(buff);
  151.     //打开T0、T1,重置初值,为下一次测量做准备
  152.     TR0=1;
  153.     TR1=1;
  154.     TH0=0x00; //T0高八位的初值
  155.     TL0=0x00; //T0低八位初值
  156.     TH1=0x00; //T1高八位的初值
  157.     TL1=0x00;
  158.     //中断后开始读数显示

  159.     }
  160.     void Timer0_isr(void)interrupt 1
  161.     {
  162.     TH0=0x00;
  163.     TL0=0x00;

  164.     }
  165.     void Timer1_isr(void)interrupt 3
  166.     { T1inter++;
  167.     TH1=0; //计数=(65535-初值) 初值0x159F=5535
  168.     TL1=0;
  169.     if(T1inter==4)
  170.     {
  171.     T1inter=0;
  172.     }
  173.     }
  174.     void timer2(void) interrupt 5 //定时器2中断(62.5ms)
  175.     {
  176.     time++;
  177.     TF2=0; //定时器2的中断标志位TF2不能够由硬件清零,所以要在中断服务程序中将其清零
  178.     if (time==4) //定时0.25s时间到
  179.     {
  180.     time=0; //计时清0
  181.     P1_2=~P1_2;//P1.2反转
  182.     }
  183.     }


复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:164602 发表于 2018-1-12 15:05 | 只看该作者
我没有看你的程序全部,只看了定时器设置那部分,你说没反应,可能就是设置的问题。
第一:如图所示:


这是STC89C52的手册说明(我没有找到你用的AT89C52的手册)
你程序中设置TMOD=0x9d,即二进制1001  1101
定时器0、1都是工作方式1——16位定时\计数器
定时器1为定时器,定时器0为计数器
“门控制”位都是1——由上图可知,当此位为1时,要开启定时\计数器,还需要外部中断。
这是不是你想要的结果?

第二:我的建议:
“门控制”位置0,即只需要TRx就可以控制定时器的开启和关闭。
你的外部脉冲,直接到定时器0。只要TR0=1,则计数器0就开始计数了,注意,你的脉冲信号要接在P34脚;只要TR1=1,定时器1就开始计时了。
同时开启两定时器,你的工作不就完成了?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表