剛步入大學,第一次做小車,準備用delay延時函式來控制小車,效果不佳,熬夜看了多篇關于PWM的代碼,發現并不是很詳細,所以準備分享一下我的看法和,代碼,

PWM調速是通過調節占空比來調節速度,也就是說在高電平的時候轉動,低電平時候停止轉動,由于間隙很小,所以給我們的感覺就是一直在轉動,只不過速度減慢,本來供給L298N的電壓為12V,但是調節占空比就可以得到0~12V之間任意一個電壓,
此時就應該講講L298N模塊了,L298N卸下輸出端A旁邊的跳線帽可以給單片機提供5V使能,(但是我并不建議,這樣可能電機卡死啥訓板子,可以看我小車旁邊是使用一個降壓模塊降壓以后再供給了單片機),單片機的I/O口接邏輯輸入和通道使能(下圖圖中有標識)I/O口通過給值給邏輯輸入(邏輯輸入左邊兩個介面控制左邊輸出A,右邊兩個介面控制右邊輸出B)來控制邏輯輸出的高電平或者低電平,我來解讀一下下面這個表:
IN1,IN2表示輸出端的兩個口,ENA表示輸出端A(如果在不適用PWM調速的時候就不用拔下使能端兩側的跳線帽,此時ENA默認為1,意思就是如果給他高電平他就以12V的電壓全速跑,不拔跳線帽也不用對使能端賦值,因為你也賦不了,沒有接I/O口),繼續解讀上表,在ENA=1的時候,如果IN1=1;IN2=0;也就是給電機兩端一個高電平一個低電平,假設他正轉那么IN1=0;IN2=1;就反轉IN1=0;IN2=0;此時就是兩端都為低電平,所以呢電機就不轉,使用就有人想問,如果兩端都賦值為1的話是不是也能剎車,答案是必定的,但是這容易啥訓L298N,但是都為1他的剎車效果更好(我推薦即使想要剎車效果好,但也不要使用都為1,可以采用先使電機反轉再停止)在拔下跳線帽ENA=0的時候無論如何賦值電機都不會轉動,B使能端同理,


我做的車為循跡小車,先貼下我的總代碼,后面還有一步一步決議
#include"reg52.h"
#include"intrins.h"
sbit ZUO_LUN=P2^0;
sbit ZUO1_LUN=P2^1;//左輪
sbit YOU_LUN=P2^2;
sbit YOU1_LUN=P2^ 3;//右輪
sbit ENA=P2^4;
sbit ENB=P2^5;//使能端
sbit ZUO1_XJ=P1^0;
sbit ZUO_XJ=P1^1;
sbit ZHONG_XJ=P1^2;
sbit YOU_XJ=P1^3;
sbit YOU1_XJ=P1^4;//循跡定義
unsigned int PWM_ENA=0; //左側使能時間
unsigned int PWM_ENB=0; //右側使能時間
unsigned int PWM=0; //pwm周期為200ms
unsigned int CNT,x,y ;//跑圈計數器
void delay(int x) //@11.0592MHz
{
for(y=0;y<x;y++)
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
void Timer0Init(void)//定時1ms,并使用中斷
{
TMOD= 0x01;
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
TR0 = 1;
ET0=1;
EA=1;
}
void QIAN_JING(void)
{
ZUO_LUN=1;
ZUO1_LUN=0;
YOU_LUN=1;
YOU1_LUN=0;
PWM_ENA=150;
PWM_ENB=150;
}//前進函式
void YOU_ZHUAN(void)
{
ZUO_LUN=0;
ZUO1_LUN=0;
YOU_LUN=0;
YOU1_LUN=0;
YOU_LUN=1;
YOU1_LUN=0;
PWM_ENA=0;
PWM_ENB=100;
}//右轉函式
void ZUO_ZHUAN(void)
{
ZUO_LUN=0;
ZUO1_LUN=0;
YOU_LUN=0;
YOU1_LUN=0;
ZUO_LUN=1;
ZUO1_LUN=0;
PWM_ENA=100;
PWM_ENB=0;
}//左轉函式
void STOP(void)
{
ZUO_LUN=0;
ZUO1_LUN=1;
YOU_LUN=0;
YOU1_LUN=1;
ZUO1_LUN=0;
YOU1_LUN=0;
PWM_ENA=0;
PWM_ENB=0;
}//停止函式
void XUN_JI(void)
{
if(ZUO1_XJ==0&&ZUO_XJ==0&&YOU_XJ==0&&YOU1_XJ==0)
{
QIAN_JING();
delay(5);
STOP();
delay(5);
}
if(ZUO1_XJ==0&&ZUO_XJ==1)
{
ZUO_ZHUAN();
delay(5);
STOP();
delay(5);
CNT++;
}
if(YOU1_XJ==0&&YOU_XJ==1)
{
YOU_ZHUAN();
delay(6);
STOP();
delay(5);
CNT++;
}
if(ZUO1_XJ==1&&YOU1_XJ==0&&YOU_XJ==0&&ZUO_XJ==0)
{
ZUO_ZHUAN();
delay(6);
STOP();
delay(5);
}
if(YOU1_XJ==1&&YOU_XJ==0&&ZUO_XJ==0&&ZUO1_XJ==0)
{
YOU_ZHUAN();
delay(5);
STOP();
delay(5);
}
if(ZUO1_XJ==1&&YOU1_XJ==1&&ZUO_XJ==1&&YOU_XJ==1)
{
CNT++;
delay(10);
if(CNT>14)
{
STOP();
}
else
{
QIAN_JING();
}
}
}
void main()
{
Timer0Init();
while(1)
{
XUN_JI();
}
}
void timer0()interrupt 1
{
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
if(PWM==200)
{
PWM=0;
}
if(PWM<PWM_ENA)
{
ENA=1;
}
else
{
ENA=0;
}
if(PWM<PWM_ENB)
{
ENB=1;
}
else
{
ENB=0;
}
PWM++;
}
?
sbit ZUO_LUN=P2^0;//也就是前面說的使能端A的IN1
sbit ZUO1_LUN=P2^1;//也就是前面說的使能端A的IN2
sbit YOU_LUN=P2^2;//同理也就是使能端B的IN1
sbit YOU1_LUN=P2^ 3;//同理也就是使能端B的IN1
sbit ENA=P2^4;
sbit ENB=P2^5;//使能端
?
IN1,IN2的標號為自己定義的邏輯信號的名稱,自己隨便定義就好
unsigned int PWM_ENA=0; //左側使能時間
unsigned int PWM_ENB=0; //右側使能時間
unsigned int PWM=0; //pwm初始值
這就是當時我看別人代碼很懵的地方PWM_ENA表示我對使能端的時間,每次轉彎的時間即占空比為自己定義我定義的PWM為200ms,也就是PWM從0加到200,到了200后又重新置0,先看我接下來的一段代碼我在細細解釋
void QIAN_JING(void)
{
ZUO_LUN=1;
ZUO1_LUN=0;
YOU_LUN=1;
YOU1_LUN=0;
PWM_ENA=150;
PWM_ENB=150;
}//前進函式
void timer0()interrupt 1
{
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
if(PWM==200)
{
PWM=0;
}
if(PWM<PWM_ENA)
{
ENA=1;
}
else
{
ENA=0;
}
if(PWM<PWM_ENB)
{
ENB=1;
}
else
{
ENB=0;
}
PWM++;
}
我采用的定時器中斷0,每次PWM從0每隔1ms加到200,例如前進函式我給的使能端PWM_ENA和PWM_ENB的值為150,也就是在PWM從0加到150(也就是PWM_ENA和PWM_ENB的值,當然兩邊值也可以不一樣)的時候我的使能端給他的是高電平,也就是能轉動剩下的50us給的是低電平在這50us電機就是停止的,就這樣我們調節了占空比,達到降速的作用,黃皮電機不太標準跑直線容易轉彎,我們也可以通過PWM來調節使左右轉速相同,
最后行文倉促,知識和撰寫水平均有限,難免有錯,還望大佬指出,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/375029.html
標籤:其他
