本此設計選擇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;
- }
復制代碼 |