找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机有没有办法用一个定时器来完成对两个步进电机的控制

[复制链接]
回帖奖励 60 黑币 回复本帖可获得 20 黑币奖励! 每人限 1 次
ID:368637 发表于 2019-5-5 14:32 | 显示全部楼层 |阅读模式
我是用51单片机来控制两个步进电机的运动,同时还要用串口通讯发送数据给串口助手显示,但是单片机的两个定时器都被步进电机占用了,有什么解决办法吗。程序如下:
#include<reg52.h>
#include<stdio.h>
#include "PCF8591.H"
#define uchar unsigned char
#define uint  unsigned int
#define del   2 //速度调节
#define ydl   5 //移动量调节
#define  PCF8591 0x90    //PCF8591 地址

uint   s=0,x=0;   //s表示上,x表示下
uint   z=0,y=0;    //
uint   sx=0,zy=0;

sbit ENTER = P3^3;
sbit UP = P3^4;
sbit DOWN = P3^5;
sbit LEFT = P3^6;
sbit RIGHT = P3^7;
sbit LED1 = P1^2;
sbit LED2 = P1^3;
uchar Motor_Up[4]={0x08,0x04,0x02,0x01};
uchar Motor_Down[4]={0x01,0x02,0x04,0x08};

uchar Motor_Left[4]={0x10,0x20,0x40,0x80};
uchar Motor_Right[4]={0x80,0x40,0x20,0x10};

unsigned char AD_CHANNEL;

uchar AD_Up,AD_Down,AD_Left,AD_Right;
uchar i,j,k;
uchar Table[4];
uint alt,alt1;

//延时函数
void Delay_ms(uint jj)
{
        uint ii;
        while(jj--)
                for(ii=0;ii<125;ii++);
}
void delay(unsigned int time)
{
  unsigned int o,p;
        for(o=0;o<1000;o++)
        for(p=0;p<time;p++);
}
void UART_Init(void)
{
     TMOD = 0x11;   //定时器模式选择               
     TH0 = (65535-50000)%256;   
     TL0 = (65535-50000)/256;
        ET0=1;         //使能定时器0
        TR0 = 1;                //启动定时器1
       
        TH1 = (65535-50000)%256;   
  TL1 = (65535-50000)/256;
        ET1=1;         //使能定时器0
        TR1 = 1;                //启动定时器1       
   EA=1;         //开启总中断

}
/********************************************************************
* 名称   : PSend_Hex()
* 功能   : 发送字符串函数,可控制发送长度
* 变量   : 无
* 返回值 : 无
********************************************************************/
void Send_Hex(unsigned char *p,unsigned char num)
{
           while(num--)   //剩余发送的字符数
        {
        SBUF = *p; //将要发送的数据赋给串口缓冲寄存器
                while(!TI);//等待发送结束
                TI = 0;    //软件清零
                p++;       //指针加一
        }       
}
void main()           //函数功能:主函数
{          

       
        Delay_ms(200);
        UART_Init();
        SCON = 0x50;    //串口方式1,允许接收
        TMOD = 0x20;    //定时器1定时方式2
        TCON = 0x40;    //设定时器1开始计数
        TH1 = 0XFD;     //11.0592MHz 9600波特率
        TI = 1;
        TR1 = 1;        //启动定时器       
        while(1)
        {
               
                if(!ENTER)
                {
                        Delay_ms(20);
                        while(!ENTER);
                        k++;       
                }
               
                if(k%2 == 0)
                {
                LED1 = 1;
                LED2 = 0;
                for(i=0;i<8;i++)
                {
                        switch(AD_CHANNEL)
                        {
                                case 0: PCF8591_ISendByte(PCF8591,0x41);
                                AD_Up=PCF8591_IRcvByte(PCF8591)*2;  //模拟输入口1A/D转换
                                break;  
                               
                                case 1: PCF8591_ISendByte(PCF8591,0x42);
                                AD_Down=PCF8591_IRcvByte(PCF8591)*2;  //模拟输入口2A/D转换
                                break;  
                                case 2: PCF8591_ISendByte(PCF8591,0x43);
                                AD_Left=PCF8591_IRcvByte(PCF8591)*2;  //模拟输入口3A/D转换
                                break;  
                               
                                case 3: PCF8591_ISendByte(PCF8591,0x40);
                                AD_Right=PCF8591_IRcvByte(PCF8591)*2;  //模拟输入口4A/D转换
                                break;
                        }

                        Send_Hex(Table,4);
                        if(++AD_CHANNEL>3)
                        {
                         AD_CHANNEL=0;
                         Table[0] = AD_Up;
                        Table[1] = AD_Down;
                        Table[2] = AD_Left;
                        Table[3] = AD_Right;
                         }
                }
                }
               
                if(k%2 == 1)
                {
                        LED1 = 0;
                        LED2 = 1;
                        AD_Up = 0;        //上
                        AD_Down = 0;//下
                        AD_Left = 0;//左
                        AD_Right = 0;//右       
                }       
                zy=y-z;
                zy=zy*5.625;
                sx=x-s;
                sx=sx*5.625;
                printf("fangxiang:%d\n",zy);
                printf("fujjiao:%d\n",sx);
                delay(100);
               
            
        ///////////////////////////
          
               
               
                ////////////////////////////////////
                //Delay_ms(100);//延时,可适当修改
        }
}
void timer0() interrupt 1
{
        TH0 = (65535-50000)%256;   
  TL0 = (65535-50000)/256;
        alt++;
        if(alt==3)
        {
                alt=0;
                if(((AD_Up<AD_Down)&&(AD_Down-AD_Up>10))||(!UP))//上转
                {
                        for(i=0;i<ydl;i++)
                        {
                                for(j=0;j<4;j++)
                                {
                                        P2=Motor_Up[j];
                                        Delay_ms(del);
                                }       
       s=s+1;                                       
                        }       
                }
                //////////////////////////////////////
                if(((AD_Up>AD_Down)&&(AD_Up-AD_Down>10))||(!DOWN))//下转
                {
                        for(i=0;i<ydl;i++)
                        {
                                for(j=0;j<4;j++)
                                {
                                        P2=Motor_Down[j];
                                        Delay_ms(del);
                                }               
                                x=x+1;
                        }
                }
        }
}

void timer1() interrupt 3
{
        TH1 = (65535-50000)%256;   
  TL1 = (65535-50000)/256;
        alt1++;
        if(alt1==3)
        {
                alt1=0;
                /////////////////////////////
                if(((AD_Left<AD_Right)&&(AD_Right-AD_Left>10))||(!LEFT))//左转
                {
                        for(i=0;i<ydl;i++)
                        {
                                for(j=0;j<4;j++)
                                {
                                        P2=Motor_Left[j];
                                        Delay_ms(del);
                                }       
                                z=z+1;                               
                        }
               
                }
                //////////////////////////////////////
                if(((AD_Left>AD_Right)&&(AD_Left-AD_Right>10))||(!RIGHT))//右转
                {
                        for(i=0;i<ydl;i++)
                        {
                                for(j=0;j<4;j++)
                                {
                                        P2=Motor_Right[j];
                                        Delay_ms(del);
                                }       
                                y=y+1;                               
                        }
                }
        }
}

回复

使用道具 举报

ID:525068 发表于 2019-5-5 23:29 | 显示全部楼层
能用两个还是用两个好,用一个的话可以设置两个变量,在中断里不断递加或不断递减到一个数值
回复

使用道具 举报

ID:528003 发表于 2019-5-6 00:55 | 显示全部楼层
功能双设、扩展定时、并联分布?
回复

使用道具 举报

ID:512205 发表于 2019-5-6 08:28 | 显示全部楼层
我想应该可以的,要多少路就设置多少路的变量 ,然后都放在定时器里面执行.
回复

使用道具 举报

ID:528313 发表于 2019-5-6 11:09 | 显示全部楼层
放几个变量就可以了,看下OS里面的多定时器设计,一个硬件定时器可以延伸N个软件定时器,当然用到回调函数的概念。
回复

使用道具 举报

ID:345562 发表于 2019-5-6 12:18 | 显示全部楼层
一个硬件定时代N多个软定时,可代N多个步进。
回复

使用道具 举报

ID:528677 发表于 2019-5-6 16:52 | 显示全部楼层
在中断函数里每个电机设两个变量,一个控制是否转,另一个控制正反转。通过操作这4个变量来控制两个电机。
回复

使用道具 举报

ID:303841 发表于 2019-5-8 17:54 | 显示全部楼层
可以的,关键要看以什么作为触发源
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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