????????電機(jī)是我們?nèi)粘I钪斜容^常用的一個(gè)工具,我們經(jīng)常需要使用電機(jī)來(lái)轉(zhuǎn)動(dòng)和拖動(dòng),完成一些任務(wù)。本次設(shè)計(jì)便用基于51單片機(jī)完成的電機(jī)轉(zhuǎn)動(dòng)與調(diào)速,使得電機(jī)可以正常啟停、加速、減速以及正反轉(zhuǎn)。
????????文章末尾提供資源免費(fèi)下載,包括proteus仿真文件與源碼。
? ? ? ? 51單片機(jī)的最大電壓為5V,最大輸出電流為10mA??上攵覀儾豢赡芤揽繂纹瑱C(jī)引腳去驅(qū)動(dòng)電機(jī),因此我們需要借助電機(jī)驅(qū)動(dòng)芯片來(lái)完成這項(xiàng)艱難的任務(wù)。L289芯片在protues中長(zhǎng)這個(gè)樣子:
? ? ? ? ? ? ? ? ? ? ? ?
????????乍一看,這東西看著挺復(fù)雜,這么多引腳。其實(shí),仔細(xì)研究過(guò)就會(huì)知道,這東西很簡(jiǎn)單。其他博主有很詳細(xì)的介紹L298的引腳功能,這里就不講,簡(jiǎn)單說(shuō)下本次用到的。IN1和IN2是用來(lái)控制啟停和正反轉(zhuǎn)的,IN1為1,IN2為0就正轉(zhuǎn),反之則為反轉(zhuǎn),全為0或全1則制動(dòng),同時(shí),這也是PWM輸入入口,控制電機(jī)轉(zhuǎn)速。ENA引腳為1,表示可以PWM調(diào)速。VCC為工作電壓,5V,VS為驅(qū)動(dòng)電壓12V,OUT1和OUT2表示輸出,連接電機(jī)正負(fù)極,1接正,2接負(fù)。此處為網(wǎng)上找到的資源,我測(cè)試過(guò)可以用,如有紕漏,歡迎指正。
下面介紹本次設(shè)計(jì)的主角,帶編碼器的直流電機(jī)。protues中,它長(zhǎng)這個(gè)樣子:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
左右兩邊的“手”便是它的正負(fù)極,我們將他兩與L298的OUT1與OUT2相連。上面的三根頭發(fā),左右兩邊根據(jù)設(shè)定值,每圈發(fā)出固定數(shù)量的脈沖,我們根據(jù)脈沖數(shù)即可知道轉(zhuǎn)了幾圈。本次設(shè)計(jì)中,每圈輸出24個(gè)脈沖。那么在哪里修改呢?雙擊電機(jī),可以看到下圖:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
相信你看到了24了吧,該怎么改,你自己決定。那電機(jī)最中間的頭發(fā)呢?據(jù)說(shuō)是每圈一個(gè)脈沖,感興趣的同學(xué)可以試試。電機(jī)最下面的綠色屏幕就是轉(zhuǎn)速了,單位是r/min。
至于脈沖數(shù)的統(tǒng)計(jì),這里提供兩個(gè)思路,一個(gè)是計(jì)數(shù)器,一個(gè)是外部中斷。我們可以將其中一個(gè)定時(shí)器做計(jì)數(shù)器,計(jì)算脈沖,另一個(gè)計(jì)時(shí),計(jì)算轉(zhuǎn)速。另外一種是通過(guò)外部中斷統(tǒng)計(jì)脈沖數(shù),定時(shí)器計(jì)時(shí),獲得轉(zhuǎn)速。
至于PWM的生成方法,我們可以這么想。IO口有兩種狀態(tài),1和0。我用定時(shí)器計(jì)100us,70us我r讓一個(gè)IO口為1,30us為0,我不就得到了一串方波,周期100us。程序?qū)崿F(xiàn)就是設(shè)置一個(gè)變量comper,作為比較量,另一個(gè)變量count_pwm為累加量,10us加1,大于comper為1,小于為0,ok,得到了可調(diào)PWM。
下面是具體實(shí)現(xiàn),每段代碼,每個(gè)變量都有詳細(xì)注釋,同時(shí)歡迎留言詢問(wèn),源碼0error,0warning。
(1)定時(shí)器部分(timer.c)定時(shí)器T0計(jì)時(shí),T1產(chǎn)生PWM
#include <reg52.h>
/************************************
函數(shù)名:timer_Init
功能:定時(shí)器初始化,T0用作50ms定時(shí),
T1用10us定時(shí)
形參:無(wú)
返回值:無(wú)
*************************************/
void timer_Init()
{
TMOD = 0x11;
TL0 = 0xB0; //設(shè)置定時(shí)初始值50ms
TH0 = 0x3C; //設(shè)置定時(shí)初始值
TL1 = 0xF6; //設(shè)置定時(shí)初始值10us
TH1 = 0xFF; //設(shè)置定時(shí)初始值
TF0 = 0; //清除溢出標(biāo)志
TF1 = 1;
ET0 = 1; //定時(shí)中斷允許
ET1 = 1;
EA = 1; //總中斷
IT0 =1; //外部中斷
EX0 =1; //下降沿出發(fā)
TR0 = 1; //定時(shí)器開(kāi)
TR1 = 0;
}
?timer.h
#ifndef __TIMER_H
#define __TIMER_H
void timer_Init();
#endif
?(2)按鍵部分,控制電機(jī)啟停、正反轉(zhuǎn)、加速、減速
key.c
#include <reg52.h>
#include <intrins.h> //nop所在頭文件
#include "key.h" //按鍵頭文件
/***********************************
函數(shù)名:delay_key
功能:5ms延時(shí),用于按鍵消抖,此處是
為了protues仿真速度,實(shí)際應(yīng)為20ms
形參:無(wú)
返回值:無(wú)
***********************************/
void delay_key()
{
unsigned char i, j;
i = 6;
j = 211;
do
{
while (--j);
} while (--i);
}
/***********************************
函數(shù)名:key_pron
功能:按鍵處理函數(shù)(k1:開(kāi)始,k2:停止
k3:加速,k4:減速 ,k5:正轉(zhuǎn),k6:反轉(zhuǎn)
形參:無(wú)
返回值:無(wú)
*************************************/
void key_pron()
{
if(K1 == 0) //開(kāi)始
{
delay_key(); //消抖
if(K1 == 0)
{
TR1=1; //啟動(dòng)定時(shí)器
ENA = 1;
motor_flag = 0;
IN2 = 0;
comper = 50;//初始轉(zhuǎn)速
while(K1 == 0) //松手檢測(cè)
{
SMG_display();
}
}
}
if(K2 == 0) //停止
{
delay_key(); //消抖
if(K2 == 0)
{
TR1 = 0; //停止定時(shí)器
IN1 = 0;
IN2 = 0;
comper = 50; //初始轉(zhuǎn)速
while(K2 == 0) //松手檢測(cè)
{
SMG_display();
}
}
}
if(K3 == 0) //加速
{
delay_key();
if(K3 == 0)
{
comper=comper-10; //增加占空比
if(comper<0) //上限
comper = 0;
while(K3 == 0)
{
SMG_display();
}
}
}
if(K4 == 0) //減速
{
delay_key();
if(K4 == 0)
{
comper=comper+10;//減小占空比
if(comper >100)//下限
comper = 100;
while(K4 == 0)
{
SMG_display();
}
}
}
if(K5 == 0) //正轉(zhuǎn)
{
delay_key();
if(K5 == 0)
{
motor_flag = 0; //正轉(zhuǎn)標(biāo)志
ENA = 1;
IN2 = 0;
while(K5 == 0)
{
SMG_display();
}
}
}
if(K6 == 0) //反轉(zhuǎn)
{
delay_key();
if(K6 == 0)
{
motor_flag = 1; //反轉(zhuǎn)標(biāo)志
ENA = 1;
IN1 = 0;
while(K6 == 0)
{
SMG_display();
}
}
}
}
key.h
#ifndef __KEY_H
#define __KEY_H
//按鍵
sbit K1 = P1^0;
sbit K2 = P1^1;
sbit K3 = P1^2;
sbit K4 = P1^3;
sbit K5 = P1^4;
sbit K6 = P1^5;
sbit ENA = P2^5;
sbit IN1 = P2^3;
sbit IN2 = P2^4;
extern bit motor_flag;
extern void SMG_display();
void delay_key();
void key_pron();
extern char comper; //PWM占空比調(diào)節(jié)
#endif
(3)數(shù)碼管顯示部分,采取共陰四位數(shù)碼管,保留一位小數(shù)
smg.c
#include <reg52.h>
#include "seg.h"
unsigned char code SMG_NODOT[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//無(wú)小數(shù)點(diǎn)
unsigned char code SMG_DOT[10]= {0xbf,0x86,0xdb,0xcf,0x6e6,0xed,0xfd,0x87,0xff,0xef};//有小數(shù)點(diǎn)
/*************************************
函數(shù)名:SMG_Init
功能:數(shù)碼管初始化函數(shù)
形參:pos:顯示位 value:顯示值
返回值:無(wú)
**************************************/
void SMG_Init(unsigned char pos,unsigned char value)
{
unsigned char dat = 0x80;
P3 = P3&(~(dat >> pos));
P0=value;
delay(2);
P0 = 0x00;
P3 = P3|0xf0;
}
/***********************************
函數(shù)名:SMG_display
功能:數(shù)碼管顯示函數(shù)
形參:無(wú)
返回值:無(wú)
************************************/
void SMG_display()
{
SMG_Init(0,SMG_NODOT[speed/1000]);
SMG_Init(1,SMG_NODOT[(speed%1000)/100]);
SMG_Init(2,SMG_DOT[(speed%100)/10]);
SMG_Init(3,SMG_NODOT[speed%10]);
}
smg.h
#ifndef __SEG_H
#define __SEG_H
extern void delay(unsigned char t);
extern unsigned int speed;
void SMG_Init(unsigned char pos,unsigned char value);
void SMG_display();
#endif
(4)主函數(shù)main.c
/**********************************************************
Author :sakura
Time :2023/4/22
Funcation:51單片機(jī)使用L298電機(jī)芯片驅(qū)動(dòng)帶編碼器的電機(jī),
通過(guò)編碼器測(cè)量轉(zhuǎn)速,同時(shí)使用LED數(shù)碼管顯示,
按鍵可使電機(jī)正反轉(zhuǎn)并改變速度
***********************************************************/
//頭文件
#include <reg52.h> //51單片機(jī)頭文件
#include <intrins.h> //nop所在頭文件
#include "main.h" //主函數(shù)頭文件
#include "timer.h" //定時(shí)器頭文件
#include "key.h" //按鍵頭文件
#include "seg.h" //數(shù)碼管頭文件
/*************************************
函數(shù)名:main
功能:主函數(shù)入口
形參:無(wú)
返回值:無(wú)
**************************************/
void main()
{
timer_Init(); //定時(shí)器初始化
IN1 = 1;
IN2 = 1;
while(1)
{
SMG_display(); //數(shù)碼管顯示
key_pron(); //按鍵掃描
}
}
/***********************************
函數(shù)名:INT0_isr
功能:外部中斷0入口,統(tǒng)計(jì)編碼器脈沖
形參:無(wú)
返回值:無(wú)
************************************/
void INT0_isr() interrupt 0
{
count_f++;//每秒脈沖數(shù)
}
/*****************************
函數(shù)名:timer0_isr
功能:定時(shí)器0中斷入口,定時(shí)50ms
每秒計(jì)算一次轉(zhuǎn)速
形參:無(wú)
返回值:無(wú)
*****************************/
void timer0_isr() interrupt 1
{
TL0 = 0xB0; //設(shè)置定時(shí)初始值50ms
TH0 = 0x3C; //設(shè)置定時(shí)初始值
count_50ms++;
if(count_50ms == 20)
{
count_motor = count_f + count_motor;
count_f = 0;
}
if(count_50ms == 40)
{
count_50ms = 0;
count_motor = count_f + count_motor;
speed_real = (count_motor * 0.0416666);//計(jì)算每秒圈數(shù),每圈24個(gè)秒沖 //總脈沖/24 = 圈數(shù)
speed = speed_real*300;//每秒轉(zhuǎn)圈數(shù)(一位小數(shù))
count_f = 0;
count_motor = 0;
}
}
/*******************************
函數(shù)名:timer1_isr
功能:定時(shí)器1中斷入口,定時(shí)10us,
用于產(chǎn)生PWM波
形參:無(wú)
返回值:無(wú)
*******************************/
void timer1_isr() interrupt 3
{
TL1 = 0xF6; //設(shè)置定時(shí)初始值
TH1 = 0xFF; //設(shè)置定時(shí)初始值
count_pwm ++;
if(count_pwm == 100)
count_pwm = 0;
if(count_pwm>comper)
{
if(motor_flag == 0) //正轉(zhuǎn)對(duì)IN1輸出PWM
IN1 = 1;
else //反轉(zhuǎn)對(duì)IN2輸出PWM
IN2 = 1;
}
else
{
if(motor_flag == 0)
IN1 = 0;
else
IN2 = 0;
}
}
main.h
#ifndef __MAIN_H
#define __MAIN_H
#include <reg52.h>
#include <intrins.h> //nop所在頭文件
//變量
unsigned char count_f = 0; //編碼器脈沖計(jì)數(shù)
unsigned char count_50ms = 0; //50ms計(jì)數(shù)
char comper = 50; //PWM占空比調(diào)節(jié)
float speed_real = 0; //轉(zhuǎn)速中間變量
unsigned int speed = 0; //轉(zhuǎn)速,r/min
unsigned char count_pwm = 0; //pwm統(tǒng)計(jì)
bit motor_flag = 0; //正反轉(zhuǎn)標(biāo)志
unsigned char count_motor = 0; //濾波變量
//函數(shù)聲明
void delay(unsigned char t); //延時(shí)函數(shù)
/*************************************
函數(shù)名:delay
功能:t*10us延時(shí)
形參:t:延時(shí)次數(shù)
返回值:無(wú)
*************************************/
void delay(unsigned char t)
{
unsigned char i;
while(t--)
{
_nop_();
i = 2;
while (--i);
}
}
#endif
以上就是全部代碼了。仿真結(jié)果如下:
?實(shí)際轉(zhuǎn)速81.4,數(shù)碼管81.2,低速誤差是很小的。至于其他比如正反轉(zhuǎn)、加減速不好展示,歡迎大家下載資源測(cè)試,僅需您小小的一個(gè)贊。
鏈接:https://pan.baidu.com/s/1A_J6M07DGOFI9C_JDM_NPQ?pwd=ae1v?
提取碼:ae1v文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-464083.html
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-464083.html
到了這里,關(guān)于基于51單片機(jī)的電機(jī)(L298芯片,PWM調(diào)速,可加速、減速、正轉(zhuǎn)、反轉(zhuǎn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!