Stepper motor control system + LCD status display

Functions

The functions realized are as follows.

  1. realizing forward and reverse rotation of the motor.

  2. realizing motor speed change within a certain range.

  3. controlling motor start, stop, forward and reverse rotation, acceleration and deceleration, modification of time and zeroing of speed setting through 2x4 keyboard, and displaying system operation status with LCD screen.

  4. Display the current status of motor operation, including (start, stop, forward rotation, reverse rotation, acceleration, deceleration, modification of hours, modification of minutes, etc.).

(5) LCD display Beijing time, adjustable hours and minutes (seconds can not be modified), can be added or subtracted.

(6) equipped with motor operation indicator, when the motor is running, the indicator lights up, when the motor stops, the indicator lights off, used to indicate whether the motor is running.

(7) equipped with reset button, can be manually reset when the operation is wrong.

Proteus hardware circuit schematic drawing

20200605091615453

Source code and comments

#include "reg51.h" //header file
#include <string.h> //character manipulation
 
#define uchar unsigned char //macro definition
#define uint unsigned int
 
uchar time[] = "23:59:56";//time string
uchar state[] = " hello ";//state string
 
char code tab[2][4]={{'0','1','2','3'},
		     {'4','5','6','7'}}; // 8 key plants from 0 to 7
uint num=0;//judge whether to 1 second
uchar speed=100;//used to delay the speed control
bit time_flag=0; //modify the time flag bit, modify the hour or minute
bit turn_flag=0;//the speed direction flag bit
bit turn_stop=0;//Start/stop flag bit
uchar key;//Key value
sbit E=P2^2;//Enable E to send signal in the form of pulse
sbit RS=P2^1;//0: command 1: character
sbit RW=P2^0;//0: write 1: read
sbit led=P2^3;//motor running status light
 
		     
void keyscan();//used in the interrupt keyboard scan
void key_gn();//key function
void moto();//motor driver
				
void delay(uint x)//delay
{
	uint i;
	i=x*100;
	while(i--);	
}
 
void LCD_1602_Cmd(uchar cmd)//lcd write instruction
{
	RS=0; //timing is RS, RW, E
	RW=0;
	P1=cmd;
	E=1; //one pulse, one enable signal
	delay(2);
	E=0;
}
 
void LCD_1602_Data(uchar dat)//lcd write character
{
	RS=1;
	RW=0;
	P1=dat;
	E=1;
	delay(2);
	E=0;
}
void LCD_1602_init()//lcd initialization
{
	LCD_1602_Cmd(0X38);//open display: 8-bit line, 5x7 display dot matrix	
	LCD_1602_Cmd(0X06);//add one to the pointer after each character is written, i.e., the cursor moves one to the right
	LCD_1602_Cmd(0X0c);//open display but not display cursor
	LCD_1602_Cmd(0X01);//clear the screen
}
 
 
void display(uint l,uchar *p)//;cdisplay string
{
	uint i;
	for(i=0;i<l;i++)
		LCD_1602_Data(p[i]);
}
 
 
void int0() interrupt 1 using 1 //t0 interrupt update display time, timer
{
   unsigned int shi;//hour
   unsigned int fen;//minutes
   unsigned int miao; //seconds
   
   num++;//num to 20 proves that a second has been reached
   TR0 = 0;//Stop timing
   TL0=0xB0; //assign initial value, 50ms delay
   TH0=0x3C;
	
    if(num == 20)//reached one second
    {
       shi = (time[0]-48)*10+time[1]-48;//difference between Askew code and number 48,0 Askew code is 48, take out the number of hours in the string
      fen = (time[3]-48)*10+time[4]-48;//take out the number of minutes
      miao = (time[6]-48)*10+time[7]-48;//take out the number of seconds
       num = 0;//return to 0
       miao++;//seconds + 1
       if(miao == 60)//whether it reaches one minute
       {
	  miao = 0;//clear the number of seconds 0
	  fen = fen + 1;//fraction + 1
       }
       if(fen >= 60)//whether to reach one minute
       {
	  fen = 0;//fraction clear 0
	  shi = shi + 1;//hour + 1
       }
       if(shi >= 24)//whether it reaches 24 hours
       {
	  shi = 0;//hours clear 0
       }
       
       time[0] = shi / 10 + 48;//update the tenth digit of the hour in the time string, +48 is the corresponding Asics code
       time[1] = shi % 10 + 48;//update the hour in the time string to the single digit
       time[3] = fen / 10 + 48;//update the tenth digit of the minute in the time string
       time[4] = fen % 10 + 48;//update the minutes in the time string
       time[6] = miao / 10 + 48;//update the tenths of the seconds in the time string
       time[7] = miao % 10 + 48;//update the time string to the second digit
        
    }
    TR0 = 1;//continue timing
 
}
 
void INTERR(void) interrupt 0//Use external interrupt to determine if a key is pressed, no query, save system time
{
	keyscan();//judge which key is pressed
}
 
void start(void) interrupt 2//Use external interrupts to determine if a key is pressed, no need to query, saves system time
{
	turn_stop=1;
	  strcpy(state, "start");//strcpy string copy function, copy 'start' to state, easy to display
	  led = 0;//the light is on
	speed = 100;//prevent the operation when not started, start with the default rotation speed
}
 
void keyscan()
{
 	unsigned char hang,lie;//rows and columns
	delay(5);//delay for a while
	if((P3&0x03)! =0x03)//judge whether the key is pressed
		{
		switch(P3&0x03)//judge which line's key pressed
				{
				case 0x01:hang=1;break;//the second line pressed
				case 0x02:hang=0;break;//The first line is pressed
				}
		P3=P3&0xfc;//P3's low two pull low to determine which column
		P2=P2|0xf0;//the high four bits of P2 pull high
		while((P3&0x03)! =0x00);//P3's low two bits pull low and continue
		switch(P2&0xf0)//read P2 high four bits
				{
				case 0xe0:lie=3;break;//the fourth column
				case 0xd0:lie=2;break;//third column
				case 0xb0:lie=1;break;//second column
				case 0x70:lie=0;break;//first column
				}
		P2=P2&0x0f;//pull down the high four bits of P2
		P3=P3|0x03;//pull up P3 low two
		while((P2&0xf0)! =0x00);//pull down the high four bits of P2 and then continue
		key=tab[hang][lie];//judge which key is pressed, assign the corresponding value to all variables key, to facilitate further operations
		key_gn();//key's function function
		}
	else
		key=0;//default value no key pressed
 
}
 
 
void key_gn() //key's function
{
   uint time_temp;//time modified to temporary value
   if(key!=0)//if a key is pressed
   {
      state[0]="\0";//the state display information on the lcd is cleared, because the \0 escape character represents the end, no better way to find
      switch(key)//switch branch statement, execute the function of the key
      {
	 case '0'://the first pressed
	    strcpy(state, "reset");//strcpy string copy function, copy 'reset' to state, easy to display
	    speed = 100;//default speed
	    break;
	 case '1'://second key pressed, stop
	    strcpy(state, "stop");//same as
	    turn_stop = 0;//start flag position 0
	    led = 1;//light off
	    break;
	 case '2'://Third key pressed, accelerate
	    strcpy(state, "speed up");
	    if((speed >= 50))//the maximum speed set
	       speed = speed - 20;//speed is the delay time and speed is inversely proportional
	    break;
	 case '3'://the fourth key pressed, slow down
	    strcpy(state, "slow down");
	 if((speed <= 150))//the minimum speed set
	       speed = speed + 20;//speed is the delay time and speed is inversely proportional
	    break;
	 case '4'://the fifth key pressed, reverse
	    turn_flag = ~turn_flag;//turn flag bit reversed
	 if(turn_flag == 1)//flag bit is 0 positive turn
	    strcpy(state, "left");
	 else//flag bit is 1 inverse
	    strcpy(state, "right");
	    break;
	 case '5'://the sixth key is pressed, the time adjustment flag bit, modify the hour or minute
	    time_flag=~time_flag;//reverse
	 if(time_flag==0)//If the flag bit is 0, adjust the minutes
	    strcpy(state," minute ");
	 else//If the flag bit is 0, adjust the hour
	    strcpy(state," hour ");
	    break;
	 case '6'://the seventh key pressed, time +
	    TR0 = 0; //stop timing
	    if(time_flag==0)//judge adjust hour or minute
	    {
	       strcpy(state, "minute+");//display state
	       time_temp = (time[3]-48)*10+time[4]-48;//read current minute value
	       time_temp = time_temp + 1;//minute + 1
	       if(time_temp >= 60)//If greater than 60, set 0
		  time_temp = 0;
	       time[3] = time_temp / 10 + 48;//modify string time
	       time[4] = time_temp % 10 + 48;
	    }
	    else
	    {
	       strcpy(state, "hour+");//display state, hour+
	       time_temp = (time[0]-48)*10 + time[1]-48;//read hour value
	       time_temp = time_temp + 1;//hour + 1
	       if(time_temp >= 24)//set 0 if hour is greater than 23
		  time_temp = 0;
	       time[0] = time_temp / 10 + 48;//modify string time
	       time[1] = time_temp % 10 + 48;
	    }
	    TR0 = 1;//continue timing
	    break;
	case '7'://eighth key pressed, time -
	    TR0 = 0;//Stop timing
	    if(time_flag==0)//the same to determine whether it is hours or minutes
	    {
	       strcpy(state, "minute- ");//same reasoning, not in detail
	       time_temp = (time[3]-48)*10+time[4]-48;
	       time_temp = time_temp - 1;
	       if(time_temp > 100)
		  time_temp = 59;
	       time[3] = time_temp / 10 + 48;
	       time[4] = time_temp % 10 + 48;
	    }
	    else
	    {
	       strcpy(state, "hour-");
	       time_temp = (time[0]-48)*10 + time[1]-48;
	       time_temp = time_temp - 1;
	       if(time_temp > 100)
		  time_temp = 23;
	       time[0] = time_temp / 10 + 48;
	       time[1] = time_temp % 10 + 48;
	    }
	    TR0 = 1;
	    break;
	    
      }
   }
}
 
void moto()//stepper motor drive
{
   uchar code fan[] = {0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//positive rotation
   uchar code zheng[] = {0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//reverse
   uchar i;
   if(turn_stop==1)//If it is start state
   {
      if (turn_flag==0)//judge forward and reverse
      {
	 for(i=0;i<8;i++)
	 {
	    P0 = zheng[i];//positive rotation
	    delay(speed); //delay, adjust speed
	 }
      }
      else
      {	
	 for(i=0;i<8;i++)
	 {
	    P0 = fan[i];//reverse rotation
	       delay(speed);//delay, adjust speed
	 }
      }
   }
}
 
void main()//main function part
{
 
	TMOD=0x01;//Timer 0, mode 1
	TL0=0xB0; //assign initial value
	TH0=0x3C;
	
	ET0=1;//allow t0 interrupt
	TR0=1;//Start timing
	IT0=1; //IT0=1 for lower edge trigger
	EX0=1; //Open external interrupt 0
		IT1=1; //IT0=1 for lower edge trigger
	EX1=1; //Open external interrupt 0
 
   EA=1;//open total interrupt
   LCD_1602_init();//lcd initialization
 
   led = 1;//default light off
   key = 0;//key is 0
   P2=P2&0x0f;//pull down P2 high four bits
   while(1)
   {
      moto();//motor drive
		 
      LCD_1602_Cmd(0X80); //first line display time 
     display(8,time);//display time
    LCD_1602_Cmd(0X80+0X40); //The second line shows the state
     display(9,state);//display state
   }	
}