本此设计选择STC89C52单片机作为主控芯片,选取带有光电编码器的直流电机作为被控对象,利用单片机的T0定时器产生PWM信号并送到直流电机。在Proteus仿真环境下搭建了L298N直流电机驱动电路、矩阵键盘扫描电路以及LCD12864显示电路。实现了直流电机的启动、加速、正转、反转、制动等功能。同时,采用PID控制算法可实现电机速度在特定的场合实现自动切换。
单片机源程序如下:
#include
#include
#include
#include "lcd.h"
#include "Key.h"
#include "Motor.h"
#include "LCD12864.h"
#include "KeyBoard.h"
#include "LCD12864.h"
#include "LcdShow.h"
#include "PID.h"
extern uchar State_Flag;
extern uchar Fwd_Flag;
extern uchar Rev_Flag;
unsigned int KeyValue;
unsigned int idata pwm_t;//周期
unsigned int idata Impluse,Time_Count,ImpluseR;
uchar idata Stop_Flag,Run_Flag,Curve_Flag;
uint idata Set_Speed; // 设定转速
unsigned char idata Sz_Flag,Sr_Flag; // 记录A相触发后 ,B相高低电平的标志
float idata L_Speed,R_Speed,ReaSpeed;
uint idata PWM_Out,R_Duty,L_Duty,Turn_now;
sbit LSB_L = P1^0; // LSB_L
sbit LSB_R = P1^1; // LSB_R
void TimerInit(void) //@11.0592MHz
{
TMOD=0x01; //定时器模式
TL0 = 0x18; //初值 1ms
TH0 = 0xFC; //初值
IT0 = 1; //设置下降沿触发 还是低电平触发 0低电平
IT1 = 1; //设置下降沿触发 还是低电平触发 0低电平
EA = 1;
EX0 = 1;
EX1 = 1;
ET0 = 1;
TR0 = 1;
}
void main()
{
LED = 0;
Stop_Flag = 0;
Lcd_Initial();
TimerInit();
Set_Speed = 0;
Lcd_Clear();
while(1)
{
KeyValue = Get_Keyvalue(); // 矩阵键盘扫描
if(KeyValue == 14) // 输入速度
{
Set_Speed = SpeedInput();
KeyValue = 16;
}
Key_Process();
if(Run_Flag)
{
Set_Speed = 80;
Run_Flag = 0;
}
if(State_Flag && ~Stop_Flag)
{
PWM_Out = PID_Calculate(Set_Speed,abs(ReaSpeed));
R_Duty = PWM_Out + Turn_now;
L_Duty = PWM_Out - Turn_now;
}
else
PWM_Out = 0; // 停止
Lcd_Show();
}
}
//定时器0中断
void timer0() interrupt 1
{
static int i;
TL0 = 0x18; //初值
TH0 = 0xFC; //初值
pwm_t++;
Time_Count++;;
if(pwm_t == 500) //500ms
{
pwm_t = 0;
if(Stop_Flag)
{
i++;
L_Duty = 0;
R_Duty = 0;
if(i<31)
{
LED = ~LED;
if(i == 30)
{
Stop_Flag = 0;
i = 0;
Set_Speed = 30;
}
}
}
}
if( pwm_t MotorL_Control(); else MotorL_Stop(); if( pwm_t MotorR_Control(); else MotorR_Stop(); /*---------M法 测速------------*/ if(Time_Count == 100 ) // 100ms { Control(); Time_Count = 0; Impluse = 0; ImpluseR = 0; } } void int0() interrupt 0 { Impluse++; if(LSB_L == 1) Sz_Flag = 1; // 正反转标志位 A相下降沿,B相高电平 else Sz_Flag = 0; LSB_L = 1; } void int1() interrupt 2 // 外部中断1 用于测 右轮的速度 { ImpluseR++; if(LSB_R == 1) Sr_Flag = 1; // 正反转标志位 A相下降沿,B相高电平 else Sr_Flag = 0; LSB_R = 1; }
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』