The previous three sections talked about the various states of the independent button control of the marquee. In this section, we are going to make a robot control program. This robot can move left and right. There is a switch sensor on the far left and the far right. It can also move up and down, and there is a switch sensor at the bottom. The left and right movement is controlled by a cylinder, and the up and down movement is also controlled by a cylinder. The microcontroller controls the cylinder, essentially amplifying the signal through a triode, and then controlling the solenoid valve on the cylinder. The output and input signals of the robot drive part of this system are as follows:
2 output IO ports, controlling 2 cylinders respectively. For the cylinder that moves left and right, when the IO port is 0, it moves to the left, and when the IO port is 1, it moves to the right. For the cylinder that moves up and down, when the IO port is 0, it moves up, and when the IO port is 1, it moves down.
3 input IO ports, respectively detect 3 switch sensors. When the sensor is not triggered, the IO port detects a high level 1. When it is triggered, the IO port detects a low level 0.
This section will continue to teach you two knowledge points:
First, how to use software to perform anti-interference processing on switch sensors.
Second, how to use Switch statements to build a program framework for industrial automatic control. Again, as long as we use Switch statements as a fulcrum, we can easily write any complex and tedious program.
For details, please see the source code explanation.
(1) Hardware platform: Based on Zhu Zhaoqi's 51 single-chip microcomputer learning board. Use the S1 key in the matrix keyboard as the start independent key, use the S5 key to simulate the switch sensor on the left, use the S9 key to simulate the switch sensor on the right, and use the S13 key to simulate the switch sensor on the bottom. Remember to keep the output line P0.4 outputting a low level to simulate the trigger ground GND of the independent key.
(2) Function implementation:
When the machine is turned on, the robot arm is at the origin position on the upper left by default. After pressing the start button, the robot starts to move from the left to the right. When the robot moves to the rightmost position, it immediately starts to move down. Finally, when the robot moves to the rightmost position, it delays for 1 second and then returns to the original position in the upper left corner. Note: The start button must be triggered only when the robot is at the upper left corner.
(3)The source code is explained as follows:
#include "REG52.H"
#define const_voice_short 40 //Duration of the buzzer short call
#define const_key_time1 20 //Debounce delay time of the key
#define const_sensor 20 //Debounce delay time of the switch sensor
#define const_1s 500 //Approximate number of timer interrupts in 1 second
void initial_myself();
void initial_peripheral();
void delay_short(unsigned int uiDelayShort);
void delay_long(unsigned int uiDelaylong);
void left_to_right(); //Move from left to right
void right_to_left(); //Return from right to left
void up_to_dowm(); //Move from top to bottom
void down_to_up(); //Return from bottom to top
void run(); //Equipment automatic control program
void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
void led_update(); //LED update function
void T0_time(); //Timer interrupt function
void key_service(); //Key service application
void key_scan(); //Key scan function is placed in the timer interrupt
void sensor_scan(); //Switch sensor software anti-interference processing function, placed in the timer interrupt.
sbit hc595_sh_dr=P2^3;
sbit hc595_st_dr=P2^4;
sbit hc595_ds_dr=P2^5;
sbit beep_dr=P2^7; //Buzzer driver IO port
sbit key_sr1=P0^0; //Corresponds to the S1 key of Zhu Zhaoqi learning board
sbit left_sr=P0^1; //The switch sensor on the left corresponds to the S5 key of Zhu Zhaoqi learning board
sbit right_sr=P0^2; //The switch sensor on the right corresponds to the S9 key of Zhu Zhaoqi learning board
sbit down_sr=P0^3; //The switch sensor on the bottom corresponds to the S13 key of Zhu Zhaoqi learning board
sbit key_gnd_dr=P0^4; //Simulate the ground GND of the independent button, so it must always output a low level
unsigned char ucKeySec=0; //The number of the triggered button
unsigned int uiKeyTimeCnt1=0; //Key debounce delay
counterunsigned char ucKeyLock1=0; //Variable flag for self-locking after key triggerunsigned
char ucLeftSr=0; //Status flag of the left sensor after software anti-interference processingunsigned
char ucRightSr=0; //Status flag of the right sensor after software anti-interference processingunsigned
char ucDownSr=0; //Status flag of the lower sensor after software anti-interference processingunsigned
int uiLeftCnt1=0; //Counter variable required for software anti-interference of the left sensorunsigned
int uiLeftCnt2=0;
unsigned int uiRightCnt1=0; //Counter variable required for software anti-interference of the right sensorunsigned
int uiRightCnt2=0;
unsigned int uiDownCnt1=0; //Counter variable required for software anti-interference of the lower side
unsigned int uiDownCnt2=0;
unsigned int uiVoiceCnt=0; //Buzzer beeping duration counter
unsigned char ucLed_dr1=0; //Represents the on and off status of 16 lights, 0 represents off, 1 represents on
unsigned char ucLed_dr2=0;
unsigned char ucLed_dr3=0;
unsigned char ucLed_dr4=0;
unsigned char ucLed_dr5=0;
unsigned char ucLed_dr6=0;
unsigned char ucLed_dr7=0;
unsigned char ucLed_dr8=0;
unsigned char ucLed_dr9=0;
unsigned char ucLed_dr10=0;
unsigned char ucLed_dr11=0;
unsigned char ucLed_dr12=0;
unsigned char ucLed_dr13=0;
unsigned char ucLed_dr14=0;
unsigned char ucLed_dr15=0;
unsigned char ucLed_dr16=0;
unsigned char ucLed_update=1; //Refresh variables. Update once every time the state of the LED light is changed.
unsigned char ucLedStatus16_09=0; //Intermediate variable representing the output status of the underlying 74HC595
unsigned char ucLedStatus08_01=0; //Intermediate variable representing the output status of the underlying 74HC595
unsigned int uiRunTimeCnt=0; //Time delay counter variable in motion
unsigned char ucRunStep=0; //Step variable for motion control
void main()
{
initial_myself();
delay_long(100);
initial_peripheral();
while(1)
{
run(); //Equipment automatic control program
led_update(); //LED update function
key_service(); //Application program for key service
}
}
/* Note 1:
* The anti-interference processing of the switch sensor is essentially similar to the de-bounce processing of the button. The only difference is:
* Key de-bounce focuses on one state of the IO port, while the switch sensor focuses on two states of the IO port.
* Before the switch sensor switches from the original 1 state to the 0 state, it needs to go through the software filtering process. Once it successfully
switches to the 0 state, it needs to go through the software filtering process again when it wants to switch from the 0 state to the 1 state
. It can only switch to the 1 state after meeting the * conditions. In layman's terms, it is difficult to change the key from 1 to 0, but it is easy to change from 0 to 1.
* It is difficult for the switch sensor to change from 1 to 0, and it is also difficult to change from 0 to 1. The "difficult" here refers to the need to go through the debouncing process.
*/
void sensor_scan() //Switch sensor software anti-interference processing function, placed in the timer interrupt.
{
if(left_sr==1) //The left sensor is high level, indicating that it may not be touched. Corresponding to the S5 key of Zhu Zhaoqi's learning board
{
uiLeftCnt1=0; //In software filtering, very critical statements! ! ! Similar to the timely clearing of the key de-bounce program
uiLeftCnt2++; //Similar to the software anti-interference processing of independent key de-bounce
if(uiLeftCnt2>const_sensor)
{
uiLeftCnt2=0;
ucLeftSr=1; //Indicates that the sensor is indeed not touched
}
}
else //The left sensor is low level, indicating that it may be touched
{
uiLeftCnt2=0; //In software filtering, a very critical statement! ! ! Similar to the timely clearing of the key de-bounce program
uiLeftCnt1++;
if(uiLeftCnt1>const_sensor)
{
uiLeftCnt1=0;
ucLeftSr=0; //Indicates that the sensor is indeed touched
}
}
if(right_sr==1) //The right sensor is high level, indicating that it may not be touched Corresponding to the S9 key of Zhu Zhaoqi learning board
{
uiRightCnt1=0; //In software filtering, a very critical statement! ! ! Timely clearing of the button de-jitter program
uiRightCnt2++; // Software anti-interference processing similar to independent button de-jitter
if(uiRightCnt2>const_sensor)
{
uiRightCnt2=0;
ucRightSr=1; //Indicates that the sensor is indeed not touched
}
}
else //The right sensor is low level, indicating that it may be touched
{
uiRightCnt2=0; //In software filtering, a very critical statement! ! ! Similar to the timely clearing of key de-bounce
programuiRightCnt1++;
if(uiRightCnt1>const_sensor)
{
uiRightCnt1=0;
ucRightSr=0; //Indicates that the sensor is indeed touched
}
}
if(down_sr==1) //The lower sensor is high level, indicating that it may not be touched. Corresponding to the S13 key of Zhu Zhaoqi learning board
{
uiDownCnt1=0; //In software filtering, a very critical statement! ! ! Similar to the timely clearing of the key de-bounce program
uiDownCnt2++; //Similar to the software anti-interference processing of independent key de-bounce
if(uiDownCnt2>const_sensor)
{
uiDownCnt2=0;
ucDownSr=1; //Indicates that the sensor is indeed not touched
}
}
else //The lower sensor is low level, indicating that it may be touched
{
uiDownCnt2=0; //In software filtering, very critical statement!!! Similar to the timely clearing of the key de-bounce program
uiDownCnt1++;
if(uiDownCnt1>const_sensor)
{
uiDownCnt1=0;
ucDownSr=0; //Indicates that the sensor has indeed been touched
}
}
}
void key_scan()//The key scanning function is placed in the timer interrupt
{
if(key_sr1==1)//IO is high level, indicating that the key is not pressed, then it is necessary to clear some flag bits in time
{
ucKeyLock1=0; //Clear the key self-locking flag
uiKeyTimeCnt1=0; //Clear the key de-bounce delay counter, this line is very clever, I figured it out in actual combat.
}
else if(ucKeyLock1==0)//A key is pressed, and it is the first time it is pressed
{
uiKeyTimeCnt1++; //Accumulate the number of timer interruptsif
(uiKeyTimeCnt1>const_key_time1)
{
uiKeyTimeCnt1=0;
ucKeyLock1=1; //Set the self-locking key to avoid continuous triggeringucKeySec
=1; //Trigger key No. 1
}
}
}
void key_service() //Application program of key service
{
switch(ucKeySec) //Key service status switch
{
case 1:// Start button corresponds to the S1 key of Zhu Zhaoqi learning boardif
(ucLeftSr==0) //At the origin position in the upper left corner
{
ucRunStep=1; //Start
uiVoiceCnt=const_voice_short; //Key sound is triggered and stops after one beep.
}
ucKeySec=0; //After responding to the key service handler, the key number is cleared to avoid consistent triggering of
break;
}
}
void led_update() //LED update function
{
if(ucLed_update==1)
{
ucLed_update=0; //Clear in time to make it update only once to avoid continuous updating.
if(ucLed_dr1==1)
{
ucLedStatus08_01=ucLedStatus08_01|0x01;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0xfd;
}
if(ucLed_dr2==1)
{
ucLedStatus08_01=ucLedStatus08_01|0x02;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0xfd;
}
if(ucLed_dr3==1)
{ uc LedStatus08_01
=ucLedStatus08_01|0x04;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0xfb;
}
if (ucLed_dr4==1)
{
ucLedStatus08_01=ucLedStatus08_01|0x08;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0xf7;
}
if(ucLed_dr5==1)
{
ucLedStatus08_01=ucLedStatus08_01|0x10;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0xef;
}
if(ucLed_dr6==1)
{ uc LedStatus08_01
=ucLedStatus08_01|0x20;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0xdf;
}
if (ucLed_dr7==1)
{
ucLedStatus08_01=ucLedStatus08_01|0x40;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0xbf;
}
if(ucLed_dr8==1)
{
ucLedStatus08_01=ucLedStatus08_01|0x80;
}
else
{
ucLedStatus08_01=ucLedStatus08_01&0x7f;
}
if(ucLed_dr9==1)
{
ucLedStatus16_09=ucLedStatus16_09|0x01;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0xfe;
}
if (ucLed_dr10==1)
{
ucLedStatus16_09=ucLedStatus16_09|0x02;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0xfd;
}
if(ucLed_dr11==1)
{
ucLedStatus16_09=ucLedStatus16_09|0x04;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0xfb;
}
if(ucLed_dr12==1)
{
ucLedStatus16_09=ucLedStatus16_09|0x08;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0xf7;
}
if(ucLed_dr13== 1)
{
ucLedStatus16_09=ucLedStatus16_09|0x10;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0xef;
}
if(ucLed_dr14==1)
{
ucLedStatus16_09=ucLedStatus16_09|0x20;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0xdf;
}
if(ucLed_dr15==1)
{
ucLedStatus16_09=ucLedStatus16_09|0x40;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0xbf;
}
if(ucLed_dr16==1)
{
ucLedStatus16_09=ucLedStatus16_09|0x80;
}
else
{
ucLedStatus16_09=ucLedStatus16_09&0x7f;
}
hc595_drive (ucLedStatus16_09,ucLedStatus08_01); //74HC595 underlying driver function
}
}
void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
{
unsigned char i;
unsigned char ucTempData;
hc595_sh_dr=0;
hc595_st_dr=0;
ucTempData=ucLedStatusTemp16_09; //Send high 8 bits first
for(i=0;i<8;i++)
{
if(ucTempData >=0x80)hc595_ds_dr=1;
else hc595_ds_dr=0;
hc595_sh_dr=0; //The rising edge of SH pin sends data to register
delay_short(15);
hc595_sh_dr=1;
delay_short(15);
ucTempData=ucTempData<<1 ;
}
ucTempData=ucLedStatusTemp08_01; //Send the lower 8 bits first
for(i=0;i<8;i++)
{
if(ucTempData>=0x80)hc595_ds_dr=1;
else hc595_ds_dr=0;
hc595_sh_dr=0; //SH pin The rising edge sends the data to the register
delay_short(15);
hc595_sh_dr=1;
delay_short(15);
ucTempData=ucTempData<<1;
}
hc595_st_dr=0; //ST pin updates the data of the two registers and outputs them to the output pin of 74HC595 and latches them
delay_short(15);
hc595_st_dr=1;
delay_short(15);
hc595_sh_dr=0; //Pull low, anti-interference is enhanced
hc595_st_dr=0;
hc595_ds_dr=0;
}
void left_to_right() //Move from the left to the right
{
ucLed_dr1=1; // 1 represents the left and right cylinders move from the left to the right
ucLed_update=1; //Refresh the variable. Every time the state of the LED light is changed, it must be updated once.
}
void right_to_left() //Return from the right to the left
{
ucLed_dr1=0; // 0 represents the left and right cylinders return from the right to the left
ucLed_update=1; //Refresh the variable. Every time the state of the LED light is changed, it must be updated once.
}
void up_to_down() //Move from top to bottom
{
ucLed_dr2=1; // 1 represents the upper and lower cylinders move from top to
bottomucLed_update=1; //Refresh variables. Update every time the LED status is changed.
}
void down_to_up() //Return from bottom to top
{
ucLed_dr2=0; // 0 represents the upper and lower cylinders return from bottom to
topucLed_update=1; //Refresh variables. Update every time the LED status is changed.
}
void run() //Equipment automatic control program
{
switch(ucRunStep)
{
case 0: //The robot is at the top left corner of the origin, on standby. At this time, the start button ucRunStep=1 is triggered, which triggers a series of subsequent continuous actions.
break;
case 1: //The robot moves from the left to the right
left_to_right();
ucRunStep=2; //This is how Hong Ge flexibly controls the step variables
break;
case 2: //Wait for the robot to move to the far right until the rightmost switch sensor is triggered.
if(ucRightSr==0) //The right sensor is triggered
{
ucRunStep=3; //This is how Hong Ge flexibly controls the step variables
}
break;
case 3: //The robot moves from the upper right to the lower right, from top to bottom.
up_to_down();
ucRunStep=4; //This is how Hong Ge flexibly controls the step variables
break;
case 4: //Wait for the robot to move from the upper right to the lower right until the lower right switch sensor is triggered.
if(ucDownSr==0) //The lower right sensor is triggered
{
uiRunTimeCnt=0; //The time counter is cleared to prepare for the next 1 second
delayucRunStep=5; //This is how Hong Ge flexibly controls the step variables
}
break;
case 5: //The robot delays for 1 second at the lower rightif
(uiRunTimeCnt>const_1s) //Delay for 1 second
{
ucRunStep=6; //This is how Hong Ge flexibly controls the step variables
}
break;
case 6: //Return to the original path, and the robot moves from the lower right to the upper right.
down_to_up();
ucRunStep=7; //This is how Hong Ge flexibly controls the step variablesbreak
;
case 7: //Return to the original path and wait for the robot to move to the rightmost sensor switchif
(ucRightSr==0)
{
ucRunStep=8; //This is how Hong Ge flexibly controls the step variables
}
break;
case 8: //Return to the original path and wait for the robot to move from the right to the leftright_to_left
();
ucRunStep=9; //This is how Hong Ge's legendary step variable is flexibly controlled
break;
case 9: //Return along the original path and wait for the robot to move to the leftmost sensor switch, indicating that it has returned to the origin
if(ucLeftSr==0) //Return to the origin position in the upper left corner
{
ucRunStep=0; //This is how Hong Ge's legendary step variable is flexibly controlled
}
break;
}
}
void T0_time() interrupt 1
{
TF0=0; //Clear interrupt flag
TR0=0; //Turn off interrupt
sensor_scan(); //Switch sensor software anti-interference processing function
key_scan(); //Key scanning function
if(uiRunTimeCnt<0xffff) //Do not exceed the maximum int type range
{
uiRunTimeCnt++; //Delay counter
}
if(uiVoiceCnt!=0)
{
uiVoiceCnt--; //Each timer interrupt is decremented by 1 until it is equal to zero. beep_dr
=0; //The buzzer is controlled by a PNP transistor, and it starts to beep when the level is low.
}
else
{
; //An extra empty instruction is added here to maintain the symmetry with the number of if bracket statements, both are two instructions. It is also OK not to add it.
beep_dr=1; //The buzzer is controlled by a PNP transistor, and it stops beeping when the level is high.
}
TH0=0xf8; //Reload initial value (65535-2000)=63535=0xf82f
TL0=0x2f;
TR0=1; //Open interrupt
}
void delay_short(unsigned int uiDelayShort)
{
unsigned int i;
for(i=0;i
; //A semicolon is equivalent to executing an empty statement
}
}
void delay_long(unsigned int uiDelayLong)
{
unsigned int i;
unsigned int j;
for(i=0;i
for(j=0;j<500;j++) //Number of empty instructions in the embedded loop
{
; //A semicolon is equivalent to executing an empty statement
}
}
}
void initial_myself() //Initialize the MCU in the first area
{
/* Note 2:
* The matrix keyboard can also be used as an independent key, provided that a common output line is output at a low level.
* To simulate the triggering ground of an independent key, in this program, key_gnd_dr is output at a low level.
* S1 of Zhu Zhaoqi 51 learning board is an independent key used in this program.
*/
key_gnd_dr=0; //Simulate the ground GND of an independent key, so it must always output a low level
beep_dr=1; //Use a PNP transistor to control the buzzer, and it will not sound when the output is high level.
TMOD=0x01; //Set timer 0 to work mode 1
TH0=0xf8; //Reinstall initial value (65535-2000)=63535=0xf82f
TL0=0x2f;
}
void initial_peripheral() //Initialize the periphery in the second area
{
EA=1; //Open the general interrupt
ET0=1; //Allow the timer interrupt
TR0=1; //Start the timer interrupt
}
Conclusion:
I have spent a lot of time talking about the relationship between buttons and marquees, but I have never touched on the human-machine interface. In most practical projects, the human-machine interface is indispensable. How should the program framework of the human-machine interface be written? For details, please listen to the next analysis - the dynamic scanning program that drives the digital tube in the while loop of the main function.
Previous article:Section 24: Independent button control of the start and pause of the marquee
Next article:Section 26: Dynamic scanning program to drive the digital tube in the while loop of the main function
Recommended ReadingLatest update time:2024-11-16 20:27
- Popular Resources
- Popular amplifiers
- A review of learning-based camera and lidar simulation methods for autonomous driving systems
- Simulation and Modeling of Chemical Sensors Volume 5 Electro-Optical Sensors Part 1 Photocopy
- ADS2008 RF Circuit Design and Simulation Examples (Edited by Xu Xingfu)
- CVPR 2023 Paper Summary: Embodied Vision: Active Agents, Simulation
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- PCB Layout Guidelines
- LAUNCHXL-F28379D comprehensive routine
- 【DWIN Serial Port Screen】One of the Nucleic Acid Sampling and Registration Systems
- Live broadcast at 10 am today [TI's new generation MSP430 helps low-cost ultrasonic water meter]
- Playing with Zynq Serial 24 - Porting of User-Defined IP Cores
- [Only in Hangzhou, register now!] 12/21 (Friday) WPI Group/ON Semiconductor Industrial Internet of Things (IIoT) Application...
- Running PyBasic with CircuitPython on PyPortal
- LM3630A overcurrent abnormality detection problem
- 【Qinheng CH582】Structural analysis of Bluetooth protocol stack
- I would like to invite the great moderator eric_wang to answer what the northbound and southbound often used in NB-IOT mean