How to get two buttons to work with the 16f628a - C, Hi-tech comp, mplabx

Thread Starter

Bjornk

Joined Jan 28, 2013
12



I'm just began exploring my new hobby - mcu electronics. I have bought an 16f628a after reading some forumposts suggestion that is a good mcu for beginners. I have download mplabX, the hi-tech compiler and the isis program for simulating my circuit and code.
I have some knowledge from c# and java development, so I like working with their "mother language" C. I have allready created the "hello world" and "blinking led" project.

Now I want to add two buttons to my blinking led prosject (one for each led. One pin for each led and one pin for each button, everthing happening programmatically), I have been searching the Internet and found some examples and tutorials but not any that I got to work.

If any got some links to tutorials / examples, code snippets with schematics or anything else that will help me create this I would appreciate it. I can post my blinking led code and schematics if that would help. thanks
 

MrChips

Joined Oct 2, 2009
30,824
I know this is too trivial for you but maybe you need to explain your problem a bit more clearly.

pseudo code:

if (button pressed)
{
led on
}
else
{
led off
}
 

t06afre

Joined May 11, 2009
5,934
As a PIC programmer, you should take your time. To browse your you PIC header file <pic16f628a.h> Here you will see that many single bits in the register file are defined. As an example this is for PORTB
Rich (BB code):
// Register: PORTB
volatile unsigned char           PORTB               @ 0x006;
// bit and bitfield definitions
volatile bit RB0                 @ ((unsigned)&PORTB*8)+0;
volatile bit RB1                 @ ((unsigned)&PORTB*8)+1;
volatile bit RB2                 @ ((unsigned)&PORTB*8)+2;
volatile bit RB3                 @ ((unsigned)&PORTB*8)+3;
volatile bit RB4                 @ ((unsigned)&PORTB*8)+4;
volatile bit RB5                 @ ((unsigned)&PORTB*8)+5;
volatile bit RB6                 @ ((unsigned)&PORTB*8)+6;
volatile bit RB7                 @ ((unsigned)&PORTB*8)+7;
#ifndef _LIB_BUILD
volatile union {
    struct {
        unsigned RB0                 : 1;
        unsigned RB1                 : 1;
        unsigned RB2                 : 1;
        unsigned RB3                 : 1;
        unsigned RB4                 : 1;
        unsigned RB5                 : 1;
        unsigned RB6                 : 1;
        unsigned RB7                 : 1;
    };
} PORTBbits @ 0x006;
#endif
It is perfectly OK to code like this in Hi-Tech C
if(RB0) RB1=1;
else RB1=0;
 

takao21203

Joined Apr 28, 2012
3,702
As a PIC programmer, you should take your time. To browse your you PIC header file <pic16f628a.h> Here you will see that many single bits in the register file are defined. As an example this is for PORTB
Rich (BB code):
// Register: PORTB
volatile unsigned char           PORTB               @ 0x006;
// bit and bitfield definitions
volatile bit RB0                 @ ((unsigned)&PORTB*8)+0;
volatile bit RB1                 @ ((unsigned)&PORTB*8)+1;
volatile bit RB2                 @ ((unsigned)&PORTB*8)+2;
volatile bit RB3                 @ ((unsigned)&PORTB*8)+3;
volatile bit RB4                 @ ((unsigned)&PORTB*8)+4;
volatile bit RB5                 @ ((unsigned)&PORTB*8)+5;
volatile bit RB6                 @ ((unsigned)&PORTB*8)+6;
volatile bit RB7                 @ ((unsigned)&PORTB*8)+7;
#ifndef _LIB_BUILD
volatile union {
    struct {
        unsigned RB0                 : 1;
        unsigned RB1                 : 1;
        unsigned RB2                 : 1;
        unsigned RB3                 : 1;
        unsigned RB4                 : 1;
        unsigned RB5                 : 1;
        unsigned RB6                 : 1;
        unsigned RB7                 : 1;
    };
} PORTBbits @ 0x006;
#endif
It is perfectly OK to code like this in Hi-Tech C
if(RB0) RB1=1;
else RB1=0;
If you'd have used assembler for a while you'd know it is bad discipline.

If you can:

Rich (BB code):
PORTBbits.RB1=0;
if((PORTB&0x01)==0x01)PORTBbits.RB1=1;
Note also the short forms for the port bits do no longer exist on 18F PICs.
 

ErnieM

Joined Apr 24, 2011
8,377
As you can already see, even a simple task as read a button and turn on a LED can get complicated. Here's the steps you need to do:


1) define what a button down looks like. Note it may be a high or may be a low when pressed. And one day you will also need to know it has stopped bouncing (but that's for another day).

2) Define what it takes to turn on a LED. Again, note it may be a high or may be a low that turns on a LED.

3) adjust the direction of the I/O pins so the buttons go to inputs and the LEDs to outputs.

Additionally, check if anything else can interfere with the digital pin function, such as an analog function, or some other digital function. Do note that pins with an analog function default to analog when the power is applied. (I hate that too, but it must be so if the pin is to ever work effectively as an analog pin.)

4) Use the definition from #3 once to set the pin directions.

5) Make a loop to read the button inputs and drive the LED outputs.


Rich (BB code):
#include <htc.h>    // brings in specific definitions for this PIC

#define LED_ON      1       // LED is connected cathode to ground
#define LED_OFF     0

#define BUTTON_ON   0       // Button input is low when button pressed
#define BUTTON_OFF  1       // (this is how a pull-up resistor button works)

#define I_O_OUT     0       // standard TRIS definitions
#define I_O_IN      1       // zero is 0ut, one is 1n

#define SW_A        RB0     // switch A is on PORTB.0
#define SW_B        RB1
#define SW_A_TRIS   TRISB0  // switch B is on PORTB.1
#define SW_B_TRIS   TRISB1

#define LED_A       RB2     // LED A is on PORTB.2
#define LED_B       RB3     // LED B is on PORTB.3
#define LED_A_TRIS  TRISB2
#define LED_B_TRIS  TRISB3

void main(void)
{
  SW_A_TRIS  = I_O_IN;    // set up I/O pin directions
  SW_B_TRIS  = I_O_IN;
  LED_A_TRIS = I_O_OUT;
  LED_B_TRIS = I_O_OUT;
  
  // now loop forever to sense buttons
  while(1)
  {
    if (SW_A == BUTTON_ON) // test the first switch
      LED_A = LED_ON;
    else
      LED_A = LED_OFF;
      
    if (SW_B == BUTTON_ON) // test the second switch
      LED_B = LED_ON;
    else
      LED_B = LED_OFF;
      
  }
}
If you use #define statements as this to define your hardware your code becomes self-documenting. "if (SW_B == BUTTON_ON)" has much more meaning then "(RB0 == 0)"

And should you change compilers and find the defines you used are no longer defined, you can just change your definitions to suit.

In Microchip examples these defines get grouped together into a file called "HardwareProfile.h" that many code modules can share to know what the hardware looks like.

Finally, a little C magic: the ?: operator. It's a little obscure but very handy for simple if/then/else decisions like this. The while loop can be replaced by these two lines:


Rich (BB code):
    LED_A = (SW_A == BUTTON_ON) ? LED_ON : LED_OFF;   // test the first switch
    LED_B = (SW_B == BUTTON_ON) ? LED_ON : LED_OFF;   // test the second switch
 
Last edited:
Top