本此设计选择STC89C52单片机作为主控芯片,选取带有光电编码器的直流电机作为被控对象,利用单片机的T0定时器产生PWM信号并送到直流电机。在Proteus仿真环境下搭建了L298N直流电机驱动电路、矩阵键盘扫描电路以及LCD12864显示电路。实现了直流电机的启动、加速、正转、反转、制动等功能。同时,采用PID控制算法可实现电机速度在特定的场合实现自动切换。具体见附件。
单片机源程序如下:
- #include<reg51.h>
- #include<intrins.h>
- #include<math.h>
- #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<L_Duty)
- MotorL_Control();
- else
- MotorL_Stop();
-
- if( pwm_t<R_Duty)
- 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;
- }
复制代码 |