内含PID控制、AD转换、12864显示、电机测速、控制逻辑程序
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <MOTOR.h>
- #include <ADC.h>
- unsigned int PWM=0; //pwm占空比为50%,可调占空比
- unsigned int D;
- unsigned char time = 0;
- uchar targetM=0,factM=0;
- //PID定义
- int out = 0;
- int e, e1, e2;//pid 偏差
- float uk=0, uk1=0, duk=0;//pid输出值
- float Kp = 0.1, Ki = 0.05, Kd = 0.016;//pid控制系数 10,12,1.5
- uint Inpluse = 0, num1 = 0;
- unsigned int time1 = 0;
- //-------------------------------
- //外部中断0程序-测速用的
- //-------------------------------
- void int0() interrupt 0
- {
- Inpluse++;
- }
- //-------------------------------
- // PID
- //-------------------------------
- void PIDControl() //pid偏差计算
- {
- e = targetM - factM;
- duk = (Kp*(e - e1) + Ki * e + Kd * (e - 2 * e1 + e2));
- uk = uk1 + duk;
- out = (int)uk;
- if (out > 100)
- {
- out = 100;
- }
- else if (out < 0)
- {
- out = 0;
- }
- uk1 = uk;
- e2 = e1;
- e1 = e;
- D = out;
- }
- //-------------------------------
- // 定时器、中断初始化
- //-------------------------------
- void TimeInit()
- {
- TMOD = 0X01; //定时器工作在方式1(16位定时器)
- TH0 = 0XFF; //12M晶振下定时0.1ms 65536-65436
- // TL0 = 0X9c;
- TL0 = 0Xc6; //实验
- ET0 = 1;
- TR0 = 1; //开启定时器
- EX0 = 1; //中断0允许
- IT0 = 1; //边沿触发
- EA = 1;
- INT = 1;
- e = 0;
- e1 = 0;
- e2 = 0;
- IN01=0;
- }
复制代码
- #include <reg52.h>
- #include <intrins.h>
- #include <LCD12864.h>
- #include <ADC.h>
- #include <WORDMODEL.h>
- #include <MOTOR.h>
- #define uint unsigned int
- #define uchar unsigned char
- #include <string.h>
- uchar SOC = 0, V = 0, VOLT = 0;
- //SOC
- void display0()
- {
- SOC = vol*100/255;
- temp0 = SOC / 100;
- temp1 = (SOC % 100) / 10;
- temp2 = SOC % 10;
- show_ch1(1, 0, 4 * 6, ch1 + (12 * (temp0 + 4)));
- show_ch1(1, 0, 5 * 6, ch1 + (12 * (temp1 + 4)));
- show_ch1(1, 0, 6 * 6, ch1 + (12 * (temp2 + 4)));
- }
- //车速
- void display1()
- {
- V = vol * 192 / 255;
- temp0 = V / 100;
- temp1 = (V % 100) / 10;
- temp2 = V % 10;
- show_ch1(2, 0, 3 * 6, ch1 + (12 * (temp0 + 4)));
- show_ch1(2, 0, 4 * 6, ch1 + (12 * (temp1 + 4)));
- show_ch1(2, 0, 5 * 6, ch1 + (12 * (temp2 + 4)));
- }
- //电池电压
- void display2()
- {
- VOLT = vol * 400 / 255;
- temp0 = VOLT / 100;
- temp1 = (VOLT % 100) / 10;
- temp2 = VOLT % 10;
- show_ch1(2, 2, 0 * 6, ch1 + (12 * (temp0 + 4)));
- show_ch1(2, 2, 1 * 6, ch1 + (12 * (temp1 + 4)));
- show_ch1(2, 2, 2 * 6, ch1 + (12 * (temp2 + 4)));
- }
- //目标制动力矩
- void display3()
- {
- targetM = vol * 200 / 255;
- D= vol * 100 / 255;
- temp0 = targetM / 100;
- temp1 = (targetM % 100) / 10;
- temp2 = targetM % 10;
- show_ch1(2, 4, 3 * 6, ch1 + (12 * (temp0 + 4)));
- show_ch1(2, 4, 4 * 6, ch1 + (12 * (temp1 + 4)));
- show_ch1(2, 4, 5 * 6, ch1 + (12 * (temp2 + 4)));
- }
- //实际制动力矩
- void display4()
- {
- // val=100;
- factM=num1/5 ;
- // val = vol * 192 / 255;
- temp0 = factM / 100;
- temp1 = (factM % 100) / 10;
- temp2 = factM % 10;
- show_ch1(2, 6, 3 * 6, ch1 + (12 * (temp0 + 4)));
- show_ch1(2, 6, 4 * 6, ch1 + (12 * (temp1 + 4)));
- show_ch1(2, 6, 5 * 6, ch1 + (12 * (temp2 + 4)));
- }
- void main()
- {
- InitLCD();
- TimeInit();
- ClearScreen(0);
- Set_line(0);
- //SOC显示
- show_ch1(1,0,0*6,ch1+12*1);
- show_ch1(1,0,1*6,ch1+12*2);
- show_ch1(1,0,2*6,ch1+12*3);
- show_ch1(1, 0, 3 * 6, ch1 + 12 * 0);
- show_ch1(1, 0, 7 * 6, ch1 + 12 * 14);
- //车速显示
- show_ch2(1, 0, 52, ch2 + 24 * 6);
- show_ch2(2, 0, 0 * 12, ch2 + 24 * 7);
- show_ch1(2, 0, 1 * 12, ch1 + 12 * 0);
- show_ch1(2, 0, 6*6, ch1 + 12 * 15);
- show_ch1(2, 0, 6 * 7, ch1 + 12 * 16);
- show_ch1(2, 0, 6 * 8, ch1 + 12 * 17);
- show_ch1(2, 0, 6 * 9, ch1 + 12 * 18);
- //电池电压显示
- show_ch2(1, 2, 0 * 14, ch2 + 24 * 12);
- show_ch2(1, 2, 1 * 14, ch2 + 24 * 13);
- show_ch2(1, 2, 2 * 14, ch2 + 24 * 14);
- show_ch2(1, 2, 3 * 14, ch2 + 24 * 15);
- show_ch1(1, 2, 4 * 14, ch1 + 12 * 0);
- show_ch1(2, 2, 6 * 3, ch1 + 12 * 21);
- //目标制动力矩显示
- show_ch2(1, 4, 0, ch2 + 24 * 0);
- show_ch2(1, 4, 13, ch2 + 24 * 1);
- show_ch2(1, 4, 26, ch2 + 24 * 2);
- show_ch2(1, 4, 39, ch2 + 24 * 3);
- show_ch2(1, 4, 52, ch2 + 24 * 4);
- show_ch2(2, 4, 0 * 12, ch2 + 24 * 5);
- show_ch1(2, 4, 1 * 12, ch1 + 12 * 0);
- show_ch1(2, 4, 6 * 6, ch1 + 12 * 19);
- show_ch1(2, 4, 7 * 6, ch1 + 12 * 20);
- //实际制动力矩显示
- show_ch2(1, 6, 0 , ch2 + 24 * 16);
- show_ch2(1, 6, 13, ch2 + 24 * 17);
- show_ch2(1, 6, 26, ch2 + 24 * 2);
- show_ch2(1, 6, 39, ch2 + 24 * 3);
- show_ch2(1, 6, 52, ch2 + 24 * 4);
- show_ch2(2, 6, 0 * 12, ch2 + 24 * 5);
- show_ch1(2, 6, 1 * 12, ch1 + 12 * 0);
- show_ch1(2, 6, 6 * 6, ch1 + 12 * 19);
- show_ch1(2, 6, 7 * 6, ch1 + 12 * 20);
-
- while(1)
- {
- ADDA=0;
- ADDB=0;
- ADDC=0;
- adc();
- display0();
-
- ADDA=1;
- adc();
- display1();
-
- ADDA=0;
- ADDB=1;
- adc();
- display2();
-
- ADDA=1;
- adc();
- display3();
- if (SOC>95)
- {
- targetM = 0;
- }
- if (V <20)
- {
- targetM = 0;
- }
- if (VOLT > 390)
- {
- targetM = 0;
- }
- if (targetM > 150)
- {
- targetM = 0;
- }
- else if(targetM > 100)
- {
- targetM = targetM*0.5;
- }
-
- if (time1 > 100)
- {
- time1 = 0;
- num1 = Inpluse*103/27 ;
- Inpluse = 0;
- PIDControl();
- PWM =D;
- }
- display4();
-
- }
- }
- //-------------------------------
- //定时器0
- //-------------------------------
- void Timer0(void) interrupt 1
- {
-
- // TH0 = 0XFF; //重装初值
- // TL0 = 0X9c; //标准值
- // TL0 = 0Xb8; //包含误差
- TH0=0XFF;
- TL0=0X37;
- time++;
- if (time >= 100) //PWM周期为100*0.1ms
- time = 0;
- if (time < PWM)
- IN01 = 1;
- else
- IN01 = 0;
- time1++; //转速测量周期
- }
复制代码
所有资料51hei提供下载(Proteus请使用7.5版本):
仿真、主程序.zip
(115.49 KB, 下载次数: 26)
|