自己動手做個智能小車(5)


自己動手做個智能小車(5)

——用程序來控制輪子

PWM控制電路完工了,接下來得把電路接到單片機,由單片機進行控制了。回想電路圖:

這個圖中,輸入有3根組,A,B,C,其中,A入口,我們可以當成PWM控制線,B,C為正反轉、停止控制線,整個狀態可以羅列為下面表格:

A控制

B控制

C控制

Q1

Q2

Q3

Q4

電機狀態

X

0

0

0/導通

0/導通

0/截止

0/截止

剎車

PWM

1

0

1/截止

0/導通

PWM

0/截止

正轉

PWM

0

1

0/導通

1/截止

0/截止

PWM

反轉

0

1

1

1/截止

1/截止

0/截止

0/截止

惰行

1

1

1

1/截止

1/截止

1/導通

1/導通

剎車

 

為了方便代碼管理,我們在工程中建一個car.c和car.h文件,專門編寫控制小車的程序:

 

程序開始,引入相應頭文件:

#include<reg52.h>

#include "common.h"

#include "car.h"

 

定義好PWM電路的接入引腳:

sbit Ctl_R1=P2^4; //右輪控制端1

sbit Ctl_R2=P2^5; //右輪控制端2

sbit PWM_R=P2^3; //右輪PWM

 

sbit Ctl_L1=P2^2; //左輪控制端1

sbit Ctl_L2=P2^1; //左輪控制端2

sbit PWM_L=P2^0; //左輪PWM

 

為了代碼清楚,我們將car這個(對象),整成2個函數:

void InitCar()

{

}

 

void CarGo(int left,int right)

{

}

將兩個函數的函數體寫入到car.c中,將函數的定義,寫入到car.h中。

兩個函數分別意義為:InitCar為小車初使化,CarGo為小車控制,參數left、right分別代表左右輪,然后值為-100~100,當為0時,則停止,當為負數時,則反轉,數值大小代表轉動速度,值越大越快。

好了,測試工作總是逐步的,而不是一步到位,我們先來試一下基本的正反轉及停,調速的后面再來。

void InitCar()

{

CarGo(0,0);

PWM_R = 1;

PWM_L = 1;

}

void CarGo(int left,int right)

{

if ( right >0)

{

Ctl_R1=0;

Ctl_R2=1;

}

else if (right ==0)

{

Ctl_R1=0;

Ctl_R2=0;

}

else if (right<0)

{

Ctl_R1=1;

Ctl_R2=0;

}

 

if ( left >0)

{

Ctl_L1=0;

Ctl_L2=1;

}

else if (left ==0)

{

Ctl_L1=0;

Ctl_L2=0;

}

else if (left<0)

{

Ctl_L1=1;

Ctl_L2=0;

}

}

好了,簡單的程序,應該很容易能看懂,測試么,得寫個main函數咯。

#include "car.h"

#include "common.h"

 

void main()

{

//小車初使化

InitCar();

CarGo(100,0);

Delay(2000);

CarGo(0,100);

Delay(2000);

CarGo(-100,0);

Delay(2000);

CarGo(0,-100);

Delay(2000);

CarGo(0,0);

}

經常會用到一些通用函數,如里面的delay之類的,所以我們又建一個common.c和common.h文件,將一些通用的方法寫入,比如這里的:

/*****************************************************

* 函數功能:延時若干毫秒

* 入口參數:n

***************************************************/

void Delay(unsigned int i)

{

unsigned int j;

for(;i>0;i--) //變量i由實際參數傳入一個值,因此i不能賦初值

for(j=0;j<125;j++)

{;}

}

 

整個程序也容易看清的,每隔2秒后,可以看到電機會變換一個狀態。將程序燒寫到單片機中,運行,觀察吧。

如果發現狀態不對,那就得debug了。

  1. 如果發現某個狀態不對,可以把程序單獨調這個狀態,然后跟據上面的表格,從單片機輸出,到場效管引腳,用萬用表一步步量,就可以看到哪步上有問題。
  2. 如果發現正反轉不對,反了。那就簡單,可以把 CarGo 函數控制0和1的地方反寫一下即可。

 

一切調通后,就剩下PWM了,上一章中,我們知道速度通過占空比來實現的。

換句話說,我們要針對PWM引腳要連續的輸出0和1變換值。所以這里我們得引入單片的計數器和中斷。

TH0和TL0是計數器0的高8位和低8位計數器,計算辦法:TL0=(65536-C)%256;TH0=(65536-C)/256,其中C為所要計數的次數即多長時間產生一次中斷;TMOD是計數器工作模式選擇,0X01表示選用模式1,它有16位計數器,最大計數脈沖為65536,最長時間為1ms*65536=65.536ms

#define V_TH0 0XFE

#define V_TL0 0XF6

#define V_TMOD 0X01

unsigned char ZKB1,ZKB2;

void InitCar()

{

CarGo(0,0);

 

/*定時器初始化 */

TMOD=V_TMOD;

TH0=V_TH0;

TL0=V_TL0;

TR0=1;

ET0=1;

EA=1;

 

ZKB1 = 0;

ZKB2 = 0;

}

 

 

/*中斷函數 */

void timer0(void) interrupt 1 using 2

{

static uchar click=0; //中斷次數計數器變量

TH0=V_TH0; //恢復定時器初始值

TL0=V_TL0;

++click;

if (click>=100)

click=0;

 

if (click<=ZKB1) //當小於占空比值時輸出低電平,高於時是高電平,從而實現占空比的調整

PWM_R=0;

else

PWM_R=1;

 

if (click<=ZKB2) //當小於占空比值時輸出低電平,高於時是高電平,從而實現占空比的調整

PWM_L=0;

else

PWM_L=1;

}

 

說明:iitcar中對定時器進行初使化。timer0函數中不對的計數,當click計值到ZKB1時,把PWM值反轉一下。這個ZKB1在就是在CarGo中賦值的left,right值的絕對值。

OK,到此,這個Car.c文件,就可以收功了,后面只需要調用一下這里面的函數,就可以相應的來控制小車的電機了。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM