找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1831|回复: 6
收起左侧

51单片机利用定时器中断产生PWM,有时无法进入中断服务程序

[复制链接]
ID:871316 发表于 2020-12-31 08:50 | 显示全部楼层 |阅读模式
我想通过51单片机控制舵机,通过一个开关与一个距离传感器控制舵机角度。程序运行后,pwm正常输出,但是经过几次角度改变后,pwm就无法产生了。请教一下是什么原因,下面是源代码,希望大家多多指教,多谢了!

#include "reg51.h"
#include "intrins.h"

#define uint unsigned int;
#define lint long int;

uint jd , count , time;
lint S;

void delay1(unsigned int i)  //长延时函数,ms级,不准确
{
  unsigned int j,k;
  for(j=i;j>0;j--)
    for(k=125;k>0;k--);
}

void delay()                                    //短延时函数,us级,相对精确,本函数为延时21us
{
        _nop_();
        _nop_();
        _nop_();
        _nop_();       
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}

void Time_init()        //两个计数器与定时器的初始化
{
        TMOD = 0x11;                     //Time1工作模式1,Time0工作模式1
        TH0 = 0xfe;      
        TL0 = 0x33;                      //设置time0计数初值,定时0.5ms
        TH1 = 0;
        TL1 = 0;                         //设置time1计数初值,等待触发
        TR0 = 1;                         //Time0开始计数
        ET0 = 1;                         //打开Time0的中断
        ET1 = 1;                        //打开Time1的中断
        EA = 1;                         //开启总中断
}

long Distence()
{
        time = TH1*256+TL1;
        TH1 = 0;
        TL1 = 0;
        S = (long)(time*0.017);     //算出来是cm
        return S;
        //if(S >= 20)
        //        return 0;
        //else
        //        return 1;
}

void Time0_Int() interrupt 1   //定时器0的中断服务程序
{
        TH0 = 0xfe;             //定时器重填,重新计时
        TL0 = 0x33;
        if(count < jd)              //判断0.5ms计时的次数
                pwm = 1;                  //PWM输出高电平,控制占空比
        else
                pwm = 0;                  //PWM输出低电平,控制占空比
        count = (count + 1);          //控制脉冲周期为20ms
        count = count%41;
        WDT_CONTR = 0x35;            //目前解决定时中断无法进入的方法是添加看门狗,此行为喂狗
}

void keyscan()              //微动开关与虚拟开关按键处理(微动开关,按下置0,松开置1)
{  
        if(D_SW == 0)               //如果超声检测到有物体
        {
                delay1(50);
                if(D_SW == 0)
                {
                        jd = 1;                 //高电平0.5ms,舵机角度为-90
                        led = 1;
                }
        }
        else if(S_SW == 0)          //微动开关触发,检测到有物体
        {
                delay1(20);
                if(S_SW == 0)
                {
                        jd = 3;                 //高电平1.5ms,舵机角度0
                        led = 0;
                }
        }
        else
        {
                jd = 1;
                led = 1;
        }
}

void main()
{
        long sw = 0;                                //变量初始化
        jd = 1;
        count = 0;
        time = 0;
        S = 0;
        Time_init();                                //定时器初始化
        WDT_CONTR = 0x35;   //看门狗初始化
        while(1)
        {
                TR0 = 1;
                ET0 = 1;
                TX = 1;
                delay();        
                TX = 0;            //使能超声波模块
                while(!RX);        //当RX为零时等待
                TR1 = 1;           //开启计数
                while(RX);         //当RX为1计数并等待
                TR1 = 0;           //关闭计数
                sw = Distence();           //计算
                if(sw >= 20)
                        D_SW = 1;
                else
                        D_SW = 0;
                keyscan();
        }
}       

回复

使用道具 举报

ID:390416 发表于 2020-12-31 10:36 | 显示全部楼层
《人人学会单片机》视频教程里面讲过了超声波测距。你应该把定时器做成1mm的长度或者10mm的长度。
回复

使用道具 举报

ID:390416 发表于 2020-12-31 10:37 | 显示全部楼层
这样,定时器中断多少次,就直接表示多少mm了。这样就不用 while(RX);这种死等代码了。
回复

使用道具 举报

ID:390416 发表于 2020-12-31 10:37 | 显示全部楼层
你写的这样的代码 最容易进入死循环。
回复

使用道具 举报

ID:871316 发表于 2020-12-31 10:51 | 显示全部楼层
人人学会单片机 发表于 2020-12-31 10:37
你写的这样的代码 最容易进入死循环。

好的,我试一下,谢谢!
回复

使用道具 举报

ID:871316 发表于 2020-12-31 10:53 | 显示全部楼层
人人学会单片机 发表于 2020-12-31 10:37
你写的这样的代码 最容易进入死循环。

我还想问一个问题,程序进入死循环,定时器中断就不起作用了吗
回复

使用道具 举报

ID:871316 发表于 2021-1-6 16:30 | 显示全部楼层
人人学会单片机 发表于 2020-12-31 10:37
你写的这样的代码 最容易进入死循环。

我试了一下,很完美!多谢多谢!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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