找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1974|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

關(guān)于單片機(jī)舵機(jī)控制

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:900557 發(fā)表于 2021-4-27 12:49 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
用51單片機(jī)控制兩個舵機(jī),設(shè)置按鈕控制舵機(jī)轉(zhuǎn)動角度,4個按鈕,一個控制轉(zhuǎn)到-90,一個轉(zhuǎn)到0,第三個控制一個舵機(jī)逆時針轉(zhuǎn)一個小角度一個舵機(jī)順時針轉(zhuǎn)動一個小角度,最后一個和第三個相反,為什么第三個和第四個順時針轉(zhuǎn)動的舵機(jī)轉(zhuǎn)到90度之后就沒辦法在增加角度了,我改了下程序發(fā)現(xiàn)舵機(jī)是可以轉(zhuǎn)到正90的,外部電源共地也用上了,希望得到解決。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:883167 發(fā)表于 2021-4-27 13:13 | 只看該作者
這個沒有看到具體程序,也不好判斷,最好分段注釋掉,每一步在里面調(diào)試,看出在哪個代碼上有問題!

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復(fù)

使用道具 舉報

板凳
ID:900557 發(fā)表于 2021-4-27 13:30 | 只看該作者
林大俠 發(fā)表于 2021-4-27 13:13
這個沒有看到具體程序,也不好判斷,最好分段注釋掉,每一步在里面調(diào)試,看出在哪個代碼上有問題!

這是具體程序
#include "reg51.h"

#define uint8        unsigned char    //無符號字符型
#define uint16        unsigned short int
#define uint32        unsigned long

sbit SERVO0=P3^6;                        //控制舵機(jī)的PWM輸出口
sbit SERVO1=P3^5;
sbit kaishi=P1^1;
sbit jieshu=P1^2;
sbit jiare=P3^3;
sbit jianre=P3^4;

uint16 Servo0PwmDuty0=1500;        //PWM脈沖寬度   1.5ms脈沖寬度
uint16 Servo0PwmDuty1=1500;
/***********************************************************
* 名    稱: DelayMs(uint16 ms)
* 功    能: 延時ms毫秒
* 入口參數(shù): ms        毫秒
* 出口參數(shù): 無
* 說    明:                                          
/**********************************************************/
void DelayMs(uint16 ms)
{
        uint16 i,j;
        for(i=0;i<85;i++)                //89單片機(jī)用85,12系列單片機(jī)用800
                for(j=0;j<ms;j++);
}
/***********************************************************
* 名    稱:InitTimer0()
* 功    能:時鐘0初始化
* 入口參數(shù):無
* 出口參數(shù):無
* 說    明:12M晶振,12分頻,所以計數(shù)器每遞增一個數(shù)就是1微秒,完全滿足舵機(jī)控制的精度要求
                        因為定時器是TH0,TL0都要全部計數(shù)到0xFF后在計1個數(shù)就會產(chǎn)生中斷,所以要想產(chǎn)生
                        x毫秒的中斷,那么TH0,TL0就應(yīng)該賦值(0xFFFF-x)        從這個值開始計數(shù)產(chǎn)生定時中斷                                         
/**********************************************************/
void InitTimer0(void)
{

        TMOD = 0x11;                //設(shè)置定時器模式
        TL0 = 0x00;                        //設(shè)置定時初值
        TH0 = 0x00;                        //設(shè)置定時初值
        TF0 = 0;                        //清除TF0標(biāo)志
        TR0 = 1;                        //定時器0開始計時
        ET0 = 1;
        TL1 = 0x00;                        //設(shè)置定時初值
        TH1 = 0x00;                        //設(shè)置定時初值
        TF1 = 0;                        //清除TF0標(biāo)志
        TR1 = 1;                        //定時器0開始計時
        ET1 = 1;                        //開定時器0中斷
}
/***********************************************************
* 名    稱:Timer0Value(uint16 pwm)  
* 功    能:給定時器0計數(shù)器賦值產(chǎn)生定時中斷
* 入口參數(shù):pwm                控制舵機(jī)的PWM脈沖寬度值(范圍:500~2500)
* 出口參數(shù):無
* 說    明:12M晶振,12分頻,所以計數(shù)器每遞增一個數(shù)就是1微秒,完全滿足舵機(jī)控制的精度要求
                        因為定時器是TH0,TL0都要全部計數(shù)到0xFF后在計1個數(shù)就會產(chǎn)生中斷,所以要想產(chǎn)生
                        pwm毫秒的中斷,那么TH0,TL0就應(yīng)該賦值(0xFFFF-pwm)        從這個值開始計數(shù)產(chǎn)生定時中斷                                          
/**********************************************************/
void Timer0Value(uint16 pwm)
{
        uint16 value;
        value=0xffff-pwm;       
        TR0 = 0;
        TL0=value;                        //16位數(shù)據(jù)給8位數(shù)據(jù)賦值默認(rèn)將16位數(shù)據(jù)的低八位直接賦給八位數(shù)據(jù)
    TH0=value>>8;                //將16位數(shù)據(jù)右移8位,也就是將高8位移到低八位,再賦值給8位數(shù)據(jù)       
        TR0 = 1;
}

void Timer1Value(uint16 pwm)
{
        uint16 value;
        value=0xffff-pwm;       
        TR1 = 0;
        TL1=value;                        //16位數(shù)據(jù)給8位數(shù)據(jù)賦值默認(rèn)將16位數(shù)據(jù)的低八位直接賦給八位數(shù)據(jù)
    TH1=value>>8;                //將16位數(shù)據(jù)右移8位,也就是將高8位移到低八位,再賦值給8位數(shù)據(jù)       
        TR1 = 1;
}
/***********************************************************
* 名    稱: main()
* 功    能: 入口函數(shù)
* 入口參數(shù): 無
* 出口參數(shù): 無
* 說    明:                                          
/**********************************************************/
void main(void)
{

        InitTimer0();        //定時器0初始化
        EA = 1;                        //開總中斷
        while(1)                //大循環(huán)
        {       
                if(kaishi==0)
                {
                  Servo0PwmDuty0 = 1500;Servo0PwmDuty1 = 1500;
                  DelayMs(1000);
                }
                if(jieshu==0)
                {
                  Servo0PwmDuty0 = 500;Servo0PwmDuty1 = 500;
                  DelayMs(1000);
                }
                if(jiare==0)
                {
                  Servo0PwmDuty0=Servo0PwmDuty0+100;Servo0PwmDuty1=Servo0PwmDuty1-100;
                  DelayMs(1000);
                  if(Servo0PwmDuty0>=2500){Servo0PwmDuty0=2500;}
                  if(Servo0PwmDuty1<=500){Servo0PwmDuty1=500;}
                }
                if(jianre==0)
                {
                  Servo0PwmDuty0=Servo0PwmDuty0-100;Servo0PwmDuty1=Servo0PwmDuty1+100;
                  DelayMs(1000);
                  if(Servo0PwmDuty1>=2500){Servo0PwmDuty1=2500;}
                  if(Servo0PwmDuty0<=500){Servo0PwmDuty0=500;}
                }

        }
}


void Timer_0(void) interrupt 1 using 1
{
        static uint16 i = 1;        //靜態(tài)變量:每次調(diào)用函數(shù)時保持上一次所賦的值,
                                                        //跟全局變量類似,不同是它只能用于此函數(shù)內(nèi)部
        switch(i)
        {
                case 1:
                        SERVO0 = 1;        //PWM控制腳高電平
                        //給定時器0賦值,計數(shù)Pwm0Duty個脈沖后產(chǎn)生中斷,下次中斷會進(jìn)入下一個case語句
                        Timer0Value(Servo0PwmDuty0);       
                        break;
                case 2:
                        SERVO0 = 0;        //PWM控制腳低電平
                        //高脈沖結(jié)束后剩下的時間(20000-Pwm0Duty)全是低電平了,Pwm0Duty + (20000-Pwm0Duty) = 20000個脈沖正好為一個周期20毫秒
                        Timer0Value(20000-Servo0PwmDuty0);
                        i = 0;       
                        break;         
        }
        i++;
}

void Timer_1(void) interrupt 3 using 1
{
        static uint16 j = 1;        //靜態(tài)變量:每次調(diào)用函數(shù)時保持上一次所賦的值,
                                                        //跟全局變量類似,不同是它只能用于此函數(shù)內(nèi)部
        switch(j)
        {
                case 1:
                        SERVO1 = 1;        //PWM控制腳高電平
                        //給定時器0賦值,計數(shù)Pwm0Duty個脈沖后產(chǎn)生中斷,下次中斷會進(jìn)入下一個case語句
                        Timer1Value(Servo0PwmDuty1);       
                        break;
                case 2:
                        SERVO1 = 0;        //PWM控制腳低電平
                        //高脈沖結(jié)束后剩下的時間(20000-Pwm0Duty)全是低電平了,Pwm0Duty + (20000-Pwm0Duty) = 20000個脈沖正好為一個周期20毫秒
                        Timer1Value(20000-Servo0PwmDuty1);
                        j = 0;       
                        break;         
        }
        j++;
}
回復(fù)

使用道具 舉報

地板
ID:516455 發(fā)表于 2021-4-27 16:18 | 只看該作者
通過pwm的四個通道可以同時驅(qū)動幾個舵機(jī),引腳需要自己查芯片手冊

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復(fù)

使用道具 舉報

5#
ID:516455 發(fā)表于 2021-4-27 16:18 | 只看該作者
定時器的不同通道就可以驅(qū)動不同的舵機(jī),具體引腳需要查看數(shù)據(jù)手冊

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復(fù)

使用道具 舉報

6#
ID:900557 發(fā)表于 2021-4-27 16:44 | 只看該作者
我仿真是可以的,不知道實物為什么不行
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表