Reading Switches With PIC Microcontroller – MikroC
Watch the Video Tutorial
Push Buttons or Switches are digital inputs and are widely used in electronic projects as most systems need to respond to user commands or sensors. Reading a switch is very useful because a switch is widely used and can also represent a wide range of digital devices in real world like push buttons, limit sensors, level switches, proximity switches, keypads (a combination of switches) etc.
Figure 1: Two switches connected to PIC microcontroller
Connecting a switch to a microcontroller is straight forward, all we need is a pull-up or pull-down resistor.
Figure 2: A switch with a Pull-up resistor Figure 3: A switch with a Pull-down resistor
Pull-up Resistors
The pull-up or pull-down resistor is very important, if there is no resistor it will be difficult to determine the state of the pin, this is called floating.
let’s say the microcontroller pin is configured as an input. If there is nothing connected to the pin and the microcontroller program reads the state of the pin, will it be high (pulled to VCC) or low (pulled to ground)? It is difficult to tell. But with a resistor connected to VCC (pull-up) as in figure 2, or connected to ground (pull-down) as in figure 3, will ensure that the pin is in either a high or low state.
Pull-up resistors are the more common so we will focus on them.
In figure 1, if the switch is open, the input of the PIC will be high (+5V) and when the switch is closed, the input of the PIC will be low. If there was no resistor, then it could have been a short circuit.
Internal pull-up resistors can also be enabled in software if external resistors are not going to be used, refer to the datasheet to find out more.
Now we know the reasons why we should use a pull-up or pull-down resistor, the next question is what should be the value of this resistor?
The larger the resistance of this pull-up resistor, the slower the pin is to respond to voltage changes, this is because the system that feeds the input pin is essentially a capacitor coupled with the pull-up resistor, thus this forms an RC filter, and RC filters take some time to charge and discharge. So if you have a very fast changing signal (like USB), a high value pull-up resistor can limit the speed at which the pin can reliably change state.
And on the other hand if you select a lower resistance, when the switch is closed, more current will be routed to ground which is not a good idea especially if the circuit is battery powered.
Generally a value of 10KΩ should do the job fine.
Switch Debouncing
As mechanically the metal contacts of the switch are not perfectly smooth, when a switch is closed, it doesn’t perfectly close immediately, in fact in bounces open and close so fast before it can stabilise and stay open. Figure 4 below shows the operation of a bounce-less switch, when the switch is closed, it closes immediately and the current flowing through it rises immediately from 0 to maximum. In reality this kind of switch doesn’t exist, with a close-up look with an oscilloscope, it revealed that, in practice, the switch bounces close and open for a short period of time before stabising as shown on figure 5.
In normal situation, this bouncing period is so short that it won’t even be noticed, but a microcontroller can detect it, and if high speed switching is involved, the circuit won’t be accurate if this bouncing effect is not taken into consideration.
Figure 4: A Bounce-less Switch operation. Figure 5: A normal real Switch operation
There are many ways this can be eliminated in software, one can use a counting algorithm where the switch is read periodically (e.g. every 1 ms) and it can only be considered to have changed state if it has been in the new state for some number of successive samples (e.g. 10), by which time it is considered to have settled.
The other method and the easiest one is to read a switch then after a short delay, let say 10ms, read it again, if the state of the switch is still the same, then the switch is considered to have settled in that state.
MikroC Code
The TRISx register control the direction of the PORT as we have learned from the Blinking an LED Connected to a PIC Microcontroller article . If the value if the TRISx register is “1”, then the PORT/PIN becomes input, any input device like a switch can be read then.
When the value if the TRISx register is “0”, then the PORT/PIN becomes output, any output device like a diode can be controlled then. To read a switch, we need to set TRISx register of the pin where the switch is connected to ‘1’.
Example:
1. Set PORTB (all bits) to input: TRISB = 0xFF;
2. Set PORTB bit 0 only to input: TRISB0_bit = 1;
3. Set PORTB bits 0 to 3 to input and bits 4 to 7 to output: TRISB= 0x0F
4. To remove the effect of switch bouncing, we can read the switch twice with a short delay in between to make sure the switch has completely changed its status:
// if(PORTB.F0 == 0) //check if the switch connected to PORTB.0 is closed { Delay_ms(100); //wait for 100ms if(PORTB.F0 == 0) //check if the switch is still closed { // Switch is indeed closed. Do something here. } }
Example
The circuit in figure 1 shows two switches connected to PORTC.0 and PORTC.1 of the Microcontroller. Two LEDs are also connected to PORTB.0 and PORTB.1. If both switches are open, all LEDs will be switched OFF, if switch 1 is closed, then LED 1 will be ON, if switch 2 is closed, then LED 2 will be ON and if both switches are closed then both LEDs will be ON.
/* * Project name: Reading Switches (c) www.studentcompanion.net, 2018. MCU: PIC18F45K22 Oscillator: HS, 8.0000 MHz Crystal */ void main() { ANSELB = 0; // Configure PORTB pins as digital ANSELC = 0; // Configure PORTC pins as digital TRISB = 0x00; //Configure PORTB as output TRISC0_bit = 1; // set RC0 pin as input TRISC1_bit = 1; // set RC1 pin as input LATB = 0x00; // Initial PORTB value do { if(PORTC == 0b10) //If the switch1 is pressed { Delay_ms(100); //Switch Debounce if(PORTC == 0b10) //If the switch1 is still pressed { LATB.F0 = 1; //LED 1 ON LATB.F1 = 0; //LED 2 OFF } } if(PORTC == 0b01) //If the switch2 is pressed { Delay_ms(100); //Switch Debounce if(PORTC == 0b01)//If the switch2 is still pressed { LATB.F0 = 0; //LED 1 OFF LATB.F1 = 1; //LED 2 ON } } if(PORTC == 0b00) //If both switches are pressed { Delay_ms(100); //Switch Debounce if(PORTC == 0b00)//If both switches are still pressed { LATB.F0 = 1; //LED 1 ON LATB.F1 = 1; //LED 2 ON } } if(PORTC == 0b11) //If both switches are pressed { Delay_ms(100); //Switch Debounce if(PORTC == 0b11)//If both switches are still pressed { LATB.F0 = 0; //LED 1 ON LATB.F1 = 0; //LED 2 ON } } } while(1); }
You can download the full project files (MikroC Pro for PIC source code and Proteus Schematic design) below here. All the files are zipped, you will need to unzip them (Download a free version of the Winzip utility to unzip files).
Download Switch MikroC
Download mikroC Switch Proteus