标题:
单片机+H桥控制直流电机调速程序+Proteus仿真电路
[打印本页]
作者:
娜娜的小磨盘
时间:
2020-5-20 15:35
标题:
单片机+H桥控制直流电机调速程序+Proteus仿真电路
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
Snipaste_2020-05-20_15-31-22.png
(18.97 KB, 下载次数: 58)
下载附件
2020-5-20 15:33 上传
单片机源程序如下:
#include <reg51.h>
#include "lcd1602.h"
#define THC0 0xf9
#define TLC0 0x0f //
/***********端口定义**************/
//按键
sbit StopAndStart =P0^0;
sbit KeyTurnForward =P0^1;
sbit KeyTurnBackward=P0^2;
sbit KeyAddSpeed =P0^3;
sbit KeySubSpeed =P0^4;
//电机
sbit CONT1=P2^3;
sbit CONT2=P2^4;
sbit EN =P2^5;
//
sbit LED1 = P2^0;
sbit LED2 = P2^1;
sbit LED3 = P2^2;
/*^^^^^^^^转态变量^^^^^^^^^^*/
unsigned char motoEn;
unsigned char motoDirection;
/***********变量定义**************/
unsigned int SpeedSet = 100; //速度设置
unsigned int Impluse = 0; //脉冲计数
unsigned int num = 0; //速度显示
unsigned int cnt = 0;
unsigned int PWMTime=500; //脉冲宽度
int e,e1,e2;
float uk,uk1,duk; //PID输出值
float Kp=15,Ki=12,Kd=1.6;
int out=0;
/*^^^^^^^^延时函数^^^^^^^^^^*/
void delay_xms(unsigned char ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<333;j++);
}
}
/*########系统初始化########*/
void SystemInit()
{
//外部中断0
IT0 = 1; //下降沿触发
EX0 = 1; //开外部中断
EA = 1; //开总中断
//定时器0 1
ET0=1; //开定时器中断
TMOD=0X21;//T0方式2 T1方式2
TH0 = THC0;
TL0 = TLC0;
TR0 = 1; //启动定时器0
TH1=0x10;
TL1=0x10;
ET1=1;
TR1=1;
e = 0;
e1 = 0;
e2 = 0;
motoEn=0;
motoDirection=1;
//LCD
LCD1602_Init();
}
/*########按键扫描##########*/
void key_scan()
{
//启/停
if(StopAndStart == 0) //判断按下
{
delay_xms(10);
if(StopAndStart == 0)
{
while(StopAndStart == 0 ); //判断松手
//执行按键功能
motoEn=~motoEn;
//EN=1;
}
}
//正转
if(KeyTurnForward == 0) //判断按下
{
delay_xms(10);
if(KeyTurnForward == 0)
{
while(KeyTurnForward == 0 ); //判断松手
//执行按键功能
motoDirection=1;
//CONT1 = 1;
//CONT2 = 0;
}
}
//反转
if(KeyTurnBackward == 0) //判断按下
{
delay_xms(10);
if(KeyTurnBackward == 0)
{
while(KeyTurnForward == 0 ); //判断松手
//执行按键功能
motoDirection=0;
//CONT1 = 0;
//CONT2 = 1;
}
}
//加速
if(KeyAddSpeed == 0)
{
delay_xms(10);
if(KeyAddSpeed == 0) //判断按下
{
unsigned char i=0;
while(KeyAddSpeed == 0 && i<255){delay_xms(1);i++;} //判断松手
//执行按键功能
SpeedSet += 5;
if(SpeedSet>300)
{
SpeedSet = 300;
}
}
}
//减速
if(KeySubSpeed == 0) //判断按下
{
delay_xms(10);
if(KeySubSpeed == 0)
{
unsigned char i=0;
while(KeySubSpeed == 0 && i<255){delay_xms(1);i++;} //判断松手
//执行按键功能
SpeedSet -= 5;
if(SpeedSet<0)
{
SpeedSet = 0;
}
}
}
}
/*##########电机状态动作###########*/
void MotoControl()
{
if(motoEn == 0)
{
EN=0;
CONT1=0;
CONT2=0;
LED1 = 1;
}
else
{
EN=1;
LED1 = 0;
if(motoDirection == 1)
{
CONT1=1;
CONT2=0;
LED2 = 0;
LED3 = 1;
}
else
{
CONT1=0;
CONT2=1;
LED2 = 1;
LED3 = 0;
}
}
}
/*########LCD显示###########*/
void LCDDis()
{
LCD1602_4num(0,8,num);
LCD1602_4num(1,8,SpeedSet);
}
/*^^^^^^^^PWM 输出^^^^^^^^^*/
void PWMOUT()
{
if(motoDirection == 1)
{
if(cnt<PWMTime)
{
CONT1=1;
}
else
{
CONT1=0;
}
}
else
{
if(cnt<PWMTime)
{
CONT2=1;
}
else
{
CONT2=0;
}
}
if(cnt>1000) cnt = 0;
}
/*########PID调速############*/
void PIDControl() //pid偏差计算
{
e=SpeedSet-num;
duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/50;
uk=uk1+duk;
out=(int)uk;
if(out>1000)
{
out=1000;
}
else
if(out<0)
{
out=0;
}
uk1=uk; //变量值偏移位
e2=e1;
e1=e;
PWMTime=out;
}
/********************/
void main()
{
SystemInit();
while(1)
{
key_scan();//按键扫描
LCDDis();//LCD显示
MotoControl();//根据按键扫描出的结果做出响应
PWMOUT();
}
}
/*@@@@@@@@@@外部中断0@@@@@@@@@@@@@@*/
void inter0() interrupt 0
{
Impluse++; //采集外部脉冲数据
}
/*@@@@@@@@@@定时器中断0@@@@@@@@@@@@@@*/
void inter1() interrupt 1
{
static unsigned int time=0;
TH0=THC0;
TL0=TLC0;
time++; //转速测量周期
if(time>100)
{
time=0;
num=Impluse*5;
Impluse=0;
PIDControl();
}
}
void inter3() interrupt 3
{
cnt++;
if(motoDirection == 1)
{
if(cnt<PWMTime)
{
CONT1=1;
}
else
{
CONT1=0;
}
}
else
{
if(cnt<PWMTime)
{
CONT2=1;
}
else
{
CONT2=0;
}
}
if(cnt>1000) cnt = 0;
}
复制代码
全部资料51hei下载地址:
直流调速.zip
(94.76 KB, 下载次数: 149)
2020-5-20 15:34 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1