Switch and PIC

Discussion in 'Programmer's Corner' started by Skyferia, Jul 4, 2010.

  1. Skyferia

    Thread Starter New Member

    May 5, 2010
    20
    0
    What is the best way to code in order to utilize switch control?

    For example, I want:
    Switch1(RB5): Displays "Hello!" on LCD when pressed once
    Switch2(RB6): Displays "Hey There!" on LCD when pressed once
    Switch3(RB7): Toggles blinking when pressed once

    The idea I have is like this:

    Code ( (Unknown Language)):
    1. while(RB5){
    2.     while(!RB5)
    3.     {
    4.          [code for display on LCD here]
    5.     }
    6. }
    Unfortunately this is not a good idea since it does not work every time (because of the instruction cycle clock).

    I'm sure there is a much more efficient way.

    Please advise.

    Sincerely me.
     
  2. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    can you draw a simple schematic of how your switch is connected. Do you have any debounce circuit?
     
  3. Skyferia

    Thread Starter New Member

    May 5, 2010
    20
    0
    Hey it's you. Thanks for the help the other day.

    Instead of drawing, I hope my explanation will help. If not, please inform.

    = EXPLANATION =

    - The LCD is connected appropriately to the PIC16F877A
    - A tact switch is connected to RB5, RB6 and RB7, each of them having their own pull-up resistors

    = EXPLANATION ENDS =


    That's about it. I... don't know what a debounce circuit is.
     
  4. Eng_Bandar

    Active Member

    Feb 27, 2010
    50
    1
    I wrote code in MikroC compiler and you can see it below

    Code ( (Unknown Language)):
    1.  
    2. char *text1 = "Hello!";
    3. char *text2 = "Hey There!";
    4. void main(){
    5. TRISB=0;
    6. TRISC=0;
    7. TRISD=0xff;
    8. PORTB=0;
    9. PORTC=0;
    10. while(1){
    11.        if(portd.f0==0){
    12.                        Lcd_Init(&PORTB);
    13.                        Lcd_Cmd(LCD_CURSOR_OFF);
    14.                        Lcd_Out(1,1,text1);
    15.                        delay_ms(1000);
    16.                       }
    17.        if(portd.f1==0){
    18.                        Lcd_Init(&PORTB);
    19.                        Lcd_Cmd(LCD_CURSOR_OFF);
    20.                        Lcd_Out(2,1,text2);
    21.                       }
    22.        if(portd.f2==0){
    23.                        portc.f0=0;
    24.                        delay_ms(500);
    25.                        portc.f0=1;
    26.                        delay_ms(500);
    27.                       }
    28.         }
    29. }
    30.  
    and also I simulated it in proteus and it is work correctly

    see it below

    [​IMG]

    Frist action
    [​IMG]

    Second action

    [​IMG]

    Third action

    [​IMG]


    finally, whole project in attachment ( code file and simulation file)
     
    • ww.zip
      File size:
      45.5 KB
      Views:
      20
    Skyferia likes this.
  5. Skyferia

    Thread Starter New Member

    May 5, 2010
    20
    0
    Wow! You really put in a lot of effort there, I sincerely thank you. MikroC looks a lot easier than Hi Tech C.

    The thing is, what if you have a more complex code, and then you press and lift the RD0 switch when the PIC is at the point where it is running other instructions?

    For example, using your code:
    Code ( (Unknown Language)):
    1.  
    2. char *text1 = "Hello!";
    3. char *text2 = "Hey There!";
    4. void main(){
    5. TRISB=0;
    6. TRISC=0;
    7. TRISD=0xff;
    8. PORTB=0;
    9. PORTC=0;
    10. while(1){
    11.        if(portd.f0==0){
    12.                        Lcd_Init(&PORTB);
    13.                        Lcd_Cmd(LCD_CURSOR_OFF);
    14.                        Lcd_Out(1,1,text1);
    15.                        delay_ms(1000);
    16.                       }
    17.        if(portd.f1==0){            [color=green]// You press RB0 button when PIC runs instruction at this point onwards[/color]
    18.                        Lcd_Init(&PORTB);
    19.                        Lcd_Cmd(LCD_CURSOR_OFF);
    20.                        Lcd_Out(2,1,text2);
    21.                       }
    22.        if(portd.f2==0){
    23.                        portc.f0=0;
    24.                        delay_ms(500);
    25.                        portc.f0=1;
    26.                        delay_ms(500);
    27.                       }
    28.         }
    29. }
    30.  
    I hope you understand my question.
     
  6. coldpenguin

    Active Member

    Apr 18, 2010
    165
    9
    In order to do what you want there (your second question), you are probably going to have to employ interrupts.
    On the 877a (from memory) as it happens, there is the ability to define RB4-7 as a single interrupt input, allowing your code's main loop to be paused, go into the interrupt routine, check which interrupt, then check which pin on that interrupt, then continue from its last position.
     
    Skyferia likes this.
  7. Skyferia

    Thread Starter New Member

    May 5, 2010
    20
    0
    Ah I wasn't aware. Thank you.

    So continuing on, if say I want to use an external interrupt(INT/RB0) to further initiate interrupts from RB4-RB7, will that work?
     
  8. retched

    AAC Fanatic!

    Dec 5, 2009
    5,201
    312
    Kind of. You will jump to a separate area of code during the interrupt, so you can "trigger" other interrupts (Why I do not know) or just simply jump to other areas of code once again.

    What I dont know, is if you can interrupt an interrupt.

    i.e. Signal causes an interrupt, during the interrupt code being executed, another interrupt is triggered. Do you set priority for the interrupts or does the uC wait until it returns from the first interrupt to check the status of other possible interrupts?
     
  9. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    you can do that with logic gates. I assume your ports goes low then the switchs are down. So what would be 4 input NOR gate (can be made by combine 2 input NOR gates). But it would be almost the same programming using the interrupt-on-change feature.
     
  10. Eng_Bandar

    Active Member

    Feb 27, 2010
    50
    1
    I hope understood your question.
    Firstly, remember task of while(1) this mean endless loop.
    Secondly, If you press RD.0 and hold it, the condition (if(portd.f0==0)) will be satisfied and it will execute its work, in this instant if you press for example RD.1 and hold it, in this case also PIC will execute the condition. What is mean that? If you press all switches together all conditions will be satisfied. Why? Because in the code I don’t put command stop code if for example press RD.0 stop others. I told code satisfy from any switch and also if all switches together pressed execute the action. If you try the code and simulation will be clear to you.
    If you press RD.0 and RD.1 together here will be find problem, Why? PIC will display two messages at the same time and this will cause confusion ( message Hello! And message Hey There! ).
    You can solve this problem by put second message in second row in LCD and first message in first row or you need to change your code. This is depend on your project.
     
  11. Harrington

    New Member

    Dec 19, 2009
    86
    3
    Its better to handle switches in an interrupt then in Main deal with the switch states and output to your LCD You also need place a flag in the interrupt to indicate when your interrupt is over and you need to place another flag in the main where you deal with the routine for dealing with switch states and have finished outputting to LCD

    I have always found this the best way to obtain accurate switch states You also tend to avoid switch debounce this way as well
     
  12. Harrington

    New Member

    Dec 19, 2009
    86
    3
    Reading on finite state machines would prove to be an advantage Very helpful when programming PIC see attached UML on Finite state machines I hope this helps you
     
    Last edited: Jul 7, 2010
Loading...