找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1020|回复: 7
收起左侧

51单片机的计数器问题,电机圈数怎么达不到停止条件?

[复制链接]
ID:1005338 发表于 2022-5-23 18:51 | 显示全部楼层 |阅读模式
通过T0计数器对减速直流电机轴的转动圈数进行累计(直流电机带有编码器),转到一定圈数后让电机停止,但不知道为什么,程序运行后,电机一直转,不会停,不知道为什么?求大侠们帮忙指点指点:

单片机源程序如下:
#include "reg52.h"

typedef unsigned int u16;        //对系统默认数据类型进行重定义
typedef unsigned char u8;

sbit MOTOR1_A=P0^0;          //直流电机的正极
sbit MOTOR1_B=P0^1;          //直流电机的负极

u16 s1=10;                //设定电机旋转圈数
u16 count=0;               //电机圈数

/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能                 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ten_us
* 输    出             : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
        u16 i,j;
        for(i=ms;i>0;i--)
                for(j=110;j>0;j--);
}

/*******************************************************************************
* 函 数 名       : time0_init
* 函数功能       : 定时器0中断配置函数,通过设置TH和TL即可确定计数值
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/

void counter0_init(void)
{
        TMOD|=0X05;                //选择为计数器0模式,工作方式1
        TH0=0xFC;                  //电机编码器867个脉冲,减速器轴转一圈,初值设置为FC9D
        TL0=0x9D;      
        TF0=0;
        TR0=1;        //打开计数器
        ET0=1;        //打开计数器0中断允许
        EA=1;        //打开总中断
}

/*******************************************************************************
* 函 数 名       : contor0
* 函数功能       : 定时器0中断函数,通过设置TH和TL即可确定计数值,并对减速器轴圈数进行累加
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/

void conter0() interrupt 1 //定时器0中断函数
{
        TH0=0xfC;        //给计数器赋初值
        TL0=0x9D;
        count++;                 //对电机转动圈数进行累加
}


/*******************************************************************************
* 函 数 名       : main
* 函数功能       : 主函数
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/
void main()
{      
        u16 k;                                //缓冲变量
        k=count;      

        counter0_init();        //计数器0中断配置

        MOTOR1_A=1;                   //直流电机开始正转
        MOTOR1_B=0;
        do
        {
                ;
        }
        while(k<s1);                  //检测编码器计数是否达到设定值s1
        TR0=0;                                //计数器停止计数
        MOTOR1_A=1;                            //电机停止
        MOTOR1_B=1;
        delay_ms(5000);         
}
回复

使用道具 举报

ID:844772 发表于 2022-5-24 09:13 | 显示全部楼层
1、把while(k<s1);    改成while(count<s1); 2、把 delay_ms(5000);  改成while(1);3、  另外电机停止应该都置低位吧。
回复

使用道具 举报

ID:979299 发表于 2022-5-24 10:51 | 显示全部楼层
信号线接好,这样改一下,如果还不行就用最下面的方法先试一下
    MOTOR1_A=1;                   //直流电机开始正转
    MOTOR1_B=0;
        while(1)
        {
                if(k>s1)  
                {                //检测编码器计数是否达到设定值s1
                        TR0=0;                                //计数器停止计数
                        MOTOR1_A=0;                            //电机停止
                        MOTOR1_B=0;
                        delay_ms(5000);
                }
        }

另一种试验
#include "reg52.h"

typedef unsigned int u16;        //对系统默认数据类型进行重定义
typedef unsigned char u8;

sbit MOTOR1_A=P0^0;          //直流电机的正极
sbit MOTOR1_B=P0^1;          //直流电机的负极

u16 s1=10;                //设定电机旋转圈数
//u16 count=0;               //电机圈数



void counter0_init(void)
{
    TMOD|=0X05;                //选择为计数器0模式,工作方式1
    TH0=0xFF;                  //电机编码器867个脉冲,减速器轴转一圈,初值设置为FC9D
    TL0=0xF5;      
    TF0=0;
    TR0=1;        //打开计数器
    ET0=1;        //打开计数器0中断允许
    EA=1;        //打开总中断
}
main()
{
        counter0_init();
    MOTOR1_A=1;                   //直流电机开始正转
    MOTOR1_B=0;
        while(1);
}


void conter0() interrupt 1 //定时器0中断函数
{
    TH0=0xFF;        //给计数器赋初值
    TL0=0xF5;
    MOTOR1_A=0;                            //电机停止
        MOTOR1_B=0;               //对电机转动圈数进行累加
}
回复

使用道具 举报

ID:979299 发表于 2022-5-24 11:21 | 显示全部楼层
下面的方法  
TH0=0xFC;        //计数器赋初值,和初值设置,用这个初值只能转一转
TL0=0x9D;
TH0=0xDE;        //计数器赋初值,和初值设置,用这个初值转十转
TL0=0x22;
回复

使用道具 举报

ID:735831 发表于 2022-5-24 11:39 | 显示全部楼层
我觉得楼主的主要问题在于k=count没有附上导致do while没有办法跳出,count已为全局变量,所以无需缓冲也可以用于判断,另外主函数不带while的话应该不会重复跑把,可以的话还是加一个大循环,通过大循环来保持mcu的持续运行
回复

使用道具 举报

ID:1005338 发表于 2022-5-24 11:52 | 显示全部楼层

1,改成cuont<s1解决问题,k只在开始时等于了count,后面就失去作用了
2,改成while(1)可以一直停止下去,用delay_ms(5000)停止5秒又继续转了,在此我不明白,main主程序执行完了还会从头开始再来吗?
3,主要我用了个直流电机驱动模块,真值表上说都置高位是刹车,也可以停止
回复

使用道具 举报

ID:1005338 发表于 2022-5-24 11:54 | 显示全部楼层
兴安xa 发表于 2022-5-24 11:21
下面的方法  
TH0=0xFC;        //计数器赋初值,和初值设置,用这个初值只能转一转
TL0=0x9D;

一转的控制精度高些,10转走的太远了
回复

使用道具 举报

ID:844772 发表于 2022-5-24 14:51 | 显示全部楼层

嵌入系统主程序是不能返回的,结果不可测,我觉得没必要研究究竟会跑飞还是软启动,因为这要看编译器和芯片设计情况。
两个高位没有刹车作用,短路两极才刹车。我不大习惯程序结束了还置高位。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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