找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于计算脉冲频率的问题(STC8G单片机)

[复制链接]
跳转到指定楼层
楼主
ID:721008 发表于 2020-12-18 10:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
想利用霍尔传感器测一个电机的实时频率,超出规定的18.72Hz,单片机P5^5口就输出高电平,低于18.72Hz就输出低电平,因为电机的频率一直是在变化的,所以直接测霍尔传感器输出的一个脉冲的周期,然后用1秒钟除以这个周期的时间得到频率,现在单片机编程内容如下,但是发现电机频率无论怎么变化,单片机的输出一直是高电平,实在不知道程序错在什么地方,还请大神赐教。单片机频率为12MHz。
#include "stc8g.h"
#include "COMMON.H"

uint int0_count = 0;
uint th0_tl0=0;
float freq =0;
sbit out=P5^5;

void int0_init()
{
  IT0 = 0;            //为 1 是下降沿; 为 0 是低电平
  EX0 = 0;                //为 1 允许中断; 为 0 是禁止中断
}

void t0_init()  //@12MHz
{
    AUXR &= 0x7F;        //定时器时钟12T模式
        TMOD &= 0xF0;        //设置定时器模式
        TL0 = 0x00;                //设置定时初值
        TH0 = 0x00;                //设置定时初值
        TF0 = 0;                //清除TF0标志
        ET0 = 1;                //允许T0中断
        TR0 = 0;                //定时器0停止计时
}

void test()
{
switch(int0_count)
{
  case 1:TR0=1;
  case 2:
  case 3:TR0=0;th0_tl0=TH0*256+TL0;freq=1000000/(float)th0_tl0;TL0=0X00;TH0=0X00;
  default:break;
}
if(freq>18.72)
{out=1;}
else
{out=0;}
}

void main()
{
stc_init();
int0_init();
t0_init();
out=0;
EA=1;
while(1)
{
EX0=1;
test();
}
}

void int0() interrupt 0         
{
if(int0_count>=3)
{int0_count = 0;}
int0_count++;        
}

void t0() interrupt 1
{

}


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

使用道具 举报

沙发
ID:824490 发表于 2020-12-18 15:55 | 只看该作者
18.72Hz,这么低的频率,测其脉冲宽度可能会更准确点。
回复

使用道具 举报

板凳
ID:824490 发表于 2020-12-18 15:59 | 只看该作者
switch(int0_count)
{
  case 1:
   TR0=1;
   break;
  case 2:
   break;
  case 3:
TR0=0;
th0_tl0=TH0*256+TL0;
freq=1000000/(float)th0_tl0;
TL0=0X00;
TH0=0X00;
break;
  default:break;
}

每一个CASE,都要有一个break,不然的话,程序会从第一个CASE运行到最后一个CASE .
回复

使用道具 举报

地板
ID:748788 发表于 2020-12-18 21:17 | 只看该作者
调试程序的时候应该用可调频率发生器代替霍尔传感器吧
回复

使用道具 举报

5#
ID:213173 发表于 2020-12-19 07:39 | 只看该作者
18.72Hz,频率太低,测脉冲周期更合适,程序也更简单。
  1. #include <STC8.H>

  2. #define thre 534 //53.4ms(周期=1s/18.72Hz=0.0534188034188034)

  3. sbit out=P5^5;

  4. unsigned int count;        //100微秒中断计数变量
  5. unsigned int time;        //暂存变量

  6. void Timer0Init()                //100微秒@12.000MHz
  7. {
  8.         AUXR |= 0x80;                //定时器时钟1T模式
  9.         TMOD &= 0xF0;                //设置16位自动重装模式
  10.         TL0 = 0x50;                        //设置定时初值
  11.         TH0 = 0xFB;                        //设置定时初值
  12.         TF0 = 0;                                //清除TF0标志
  13.         TR0 = 1;                                //启动定时器
  14.         ET0 = 1;          //使能定时器中断
  15. }

  16. void main()
  17. {
  18.         Timer0Init();                //初始化定时器
  19.         IT0 = 1;          //使能INT0下降沿中断
  20.         EX0 = 1;          //使能INT0中断
  21.         EA = 1;                                //开总中断
  22.        
  23.         while(1)
  24.         {
  25.                 if(time>thre)
  26.                         out=1;
  27.                 else out=0;
  28.         }
  29. }
  30. //定时器0中断服务函数
  31. void TM0_Isr() interrupt 1
  32. {
  33.     count++;
  34. }
  35. //外部中断0服务函数
  36. void INT0_Isr() interrupt 0
  37. {
  38.         time=count;//暂存
  39.         count=0;        //清0
  40. }

复制代码

回复

使用道具 举报

6#
ID:721008 发表于 2020-12-21 09:11 | 只看该作者
wulin 发表于 2020-12-19 07:39
18.72Hz,频率太低,测脉冲周期更合适,程序也更简单。

您好,很感谢您给出的建议,一开始我也是把测频率转换成测周期的思想,因为定时器工作在12T模式、16位自动重做载的时候最大定时时间也就是65.536ms,我程序的思想是在发生第一个边沿中断的时候启动定时器定时,在第三个边沿中断的时候停止定时器计时,因此这段时间就是一个脉冲的时间,但是我程序却实现不了把THx和TLx转换成时间(ms),因为我经验少,不确定这样子做的可行性。另外我也注意到了脉冲周期超出最大定时时间范围时,当前的频率肯定小于18.72Hz,我就直接可以在定时服务中断函数里让单片机输出低电平了。
回复

使用道具 举报

7#
ID:721008 发表于 2020-12-21 09:12 | 只看该作者
名字不是重点 发表于 2020-12-18 15:59
switch(int0_count)
{
  case 1:

好的,感谢您的建议,我已经采取
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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