完整版 电路图和程序代码 下载地址
https://pan.baidu.com/s/1RfYvweDxuF1L-OIg3cxVMA?pwd=8888
部分代码展示
#include<reg52.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
uchar i=0;
sbit AddSpeed=P1^0;//加速按键置位
sbit SubSpeed=P1^1;//减速按键置位
sbit Turn=P1^2;//正转按键置位
sbit Stop=P1^3;//停止按键置位
sbit IN1=P3^6;
sbit IN2=P3^7;//控制电机正反转和停止状态
sbit PWM_FC=P1^7;//输出PWM口
bit ENA=1;
sbit E=P2^7; //1602使能引脚 仿真
sbit RW=P2^6; //1602读写引脚
sbit RS=P2^5; //1602数据/命令选择引脚
float pid_p=0.5,pid_i=0.1,pid_d=0;//0.002 //PID三个参数 初值
unsigned int lastError=0;
long int sumError=0;//sum偏差和
int out=0; //PWM高电平时间控制标志位
int SpeedSet=0;//速度初值
uint cnt=0; //PWM的周期标志位
uint Inpluse=0,num=0;//脉冲计数
int pid_val_mid=0;//脉冲宽度
//void PIDControl();//PID控制子函数
void SystemInit();//定时器和中断初始化子函数
void delay(uchar x); //延时子函数
void delayus (uchar x);
void PWMOUT(); //PWM输出子函数
void SetSpeed(); //按键进行速度和转向控制子函数
void SegRefre(); //显示刷新子函数
void delay(uchar x);
void L1602_Write_char(uchar hang,uchar lie,char sign);
void L1602_init(void);
void L1602_Write_string(uchar hang,uchar lie,uchar *p);
void L1602_Write_Com(uchar del);
/**************主函数************/
void main() //定时器和中断初始化
{
SystemInit();
L1602_init();
L1602_Write_string(1,1,"spdset: ");
L1602_Write_string(2,1,"speed: ");
while(1)
{
SetSpeed(); //按键设定速度
SegRefre(); //显示器显示刷新
if(SpeedSet==0)
{
ENA=0;
}
}
}
/***************pid偏差计算子函数 ***************/
unsigned int PID()
{
int dError=0,Error=0,B;
Error=SpeedSet-num;//当前误差
sumError=Error+sumError;//误差和
dError=Error-lastError;//误差偏差
lastError=Error;
if(Error>10)
{
B=100;
}
else if (Error<-10)
{
B=0;
}
else
{
B=pid_p*Error+pid_i*sumError+pid_d*dError;
}
if(B>100) pid_val_mid=100;
if(B<0) pid_val_mid=0;
if(B>=0&&B<=100)
pid_val_mid=B;
return(0);
}
/**************延时子函数**************/
void delay(uchar x)//延时子函数平
{
uint i,j;
for(i=x;i>0;i--)
for(j=50;j>0;j--);
}
void delayus(uchar x)
{
uchar i;
while(x--)
for(i=0;i<110;i++);
}
/************PWM输出子函数*************/
void PWMOUT() //输出PWM脉冲子函数,进行PWM高低电平时间的判别
{
if(cnt<pid_val_mid) //高电时间为PID输出PWMTime
{
PWM_FC=1;
}
else
{
PWM_FC=0;
}
if(cnt>=100)
cnt=0; //100次定时器T1中断触发时间为一个PWM周期为1ms,故所取PWM频率为1k
}
/****************定时器和中断初始化子函数*************************/
void SystemInit()//定时器和中断初始化子函数
{
TMOD=0X11;//TOMD寄存器设置,T0为16位定时器,T1为8位自动重装定时器
TH0=(65536-2000)/256;
TL0=(65536-2000)%256; //定时器T0定时2ms
TH1=0xfc;
TL1=0X66; //定时器T1定时10us
ET1=1; //T1中断允许
ET0=1; //T0中断允许
TR0=1; //启动定时器T0
TR1=1; //启动定时器T0
EX0=1; //允许外部中断0,中断0用来测量转速
IT0=1; //跳变沿触发方式计数
EA=1; //全局中断允许
IN1 = 1; //默认电机初始转向为正向
IN2 = 0;
}
/**************按键进行速度和转向控制子函数**************/
void SetSpeed() //按键进行速度和转向控制子函数
{
if(AddSpeed==0) //加速按键按下
{
delay(200); //按键消抖处理
if(AddSpeed==0)
{
SpeedSet=SpeedSet+50;
if(SpeedSet>500)
{
SpeedSet=500;
}
while(AddSpeed==0);
}
}
if(SubSpeed==0) //减速按键按下
{
delay(200); //按键消抖处理
if(SubSpeed==0)
{
SpeedSet=SpeedSet-50;
if(SpeedSet<=0)
{
SpeedSet=0;
}
while(SubSpeed==0);
}
}
if(Turn==0) //正/反转按键按下
{
delay(200); //按键消抖处理
if(Turn==0) //实现电机正反转切换
{
IN1 = ~IN1;
IN2 = ~IN2;
while(Turn==0);
}
}
if(Stop==0) //停止按键按下
{
delay(200); //按键消抖处理
if(Stop==0) //实现电机停止
{
ENA=~ENA;
while(Stop==0);
}
}
}