PIC16F Programming

Thread Starter

Gajyamadake

Joined Oct 9, 2019
310
Hi
I don't think I am at the level to write program for micro-controller. I am doing focus on small building blocks

Switch : I am working on the function that should check the status of switch

Does it make sense ?

Code:
#define TRUE       1
#define Debounce   30

#define  SWITCH_PRESSED        1
#define  SWITCH_NOT_PRESSED    0

  int CheckSwitch(void)
{
    int ReturnValue =  SWITCH_NOT_PRESSED;

    if(Switch == TRUE)
    {
        DebounceDelay(Debounce);
 
        if(Switch == TRUE)
        {
            ReturnValue = SWITCH_PRESSED;
        }
    }
    return ReturnValue ;
Updated : After post of AlbertHall
 

Attachments

Last edited:

hexreader

Joined Apr 16, 2011
581
Disclaimer - my opinion only, and I am a hobby programmer only..

Yes, your program makes good sense to me, and must have been satisfying to write.

Everything is very clear (despite lack of commenting)

On the down side.....

1) That is the most complicated button-press code I have ever seen (but good for educational value). The code could be simplified.

2) De-bounce delay may, or may not affect main program performance. Not a problem if you are aware of the limitations.

3) Simpler code, commented well might be better than the (IMHO excessive) definitions of TRUE/PRESSED/NOT_PRESSED. But this is a matter of style - others might like your way better than mine.

4) TRUE in C code is normally any value other than zero (FALSE), not necessarily limited to just "1" - but again, a matter of style, as long as you understand, and are consistent.

5) The best code has entry/exit commenting just before the function code IMHO.

6) "Switch" is not defined.

7) A whole function might (or might not) be over the top. A simple check such as (maybe) something like "if(PORTB.B0){ ..do something; }" might (or might not) be all that you need - depending on surrounding code.

8) Why not change "int CheckSwitch(void)" to "unsigned char CheckSwitch(void)" and save one whole byte of memory :)



On the up side....

You clearly care more than most programmers, and clearly have a good understanding. My comments above are very picky and subjective.

Just my thoughts... feel free to ignore
 
Last edited:

AlbertHall

Joined Jun 4, 2014
12,345
I would expect the two 'if SWITCH' lines to be both checking for the same value. If you check and the switch is closed then wait a while and if it is still closed the bounce has finished.
 

AlbertHall

Joined Jun 4, 2014
12,345
I am sure program follow that condition. Does my program follow that condition ?
It does now.
You are checking for the switch pin to be true when pressed so the switch must pull the pin up to supply voltage and then there must be a pull down resistor to get it back to 0V when the switch isn't pressed. That will work just fine.

It more common for the switch to pull the pin down to 0V but it is not a requirement for the program/circuit to function correctly.
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
310
It does now.
You are checking for the switch pin to be true when pressed so the switch must pull the pin up to supply voltage and then there must be a pull down resistor to get it back to 0V when the switch isn't pressed. That will work just fine.

It more common for the switch to pull the pin down to 0V but it is not a requirement for the program/circuit to function correctly.
Time Delay function : I have seen we mostly use delay function in Embedded System

I have written two delay functions and they both gives same result

Time delay with for loop

C:
#include<stdio.h>

void TimeDelay( int x);

int main (void)           /*start program */
{
    int count = 5;       /* asign  value 5 to  integer i */
    
    TimeDelay(count);            /*call Delay function */

    return 0;
}

void TimeDelay( int x)       /*pass value 5 */
   {
       int i = 0;
      
       for ( i = 0; i < x; i++)
       {
          printf("Wait : %d \n", i);   
       }
   }
Time Delay with while loop

C:
#include<stdio.h>

void Delay( int x);

int main (void)     /*start program */
{
    int i = 5;     /* asign  value 5 to  integer i */
    
    Delay(i);    /*call Delay function */

    return 0;
}

void Delay( int x)       /*pass value 5 */
   {
    
      while(x--)          /* decrements value by one */     
       {
          printf("Wait : %d \n", x);   
       }
   }
Can you tell me which one is more useful and why it is useful ? I can't figure out which one is more suitable ?
 

AlbertHall

Joined Jun 4, 2014
12,345
Either will do the job - and that's really the only rule.
You will not know exactly how long the delay will be though and the processor cannot do anything else during the delay. That may or may not matter in a particular program.

If you use the Microchip compiler XC8, it has the functions '__delay_ms(xx)' and '__delay_us(xx)' which allow you to specify the time of the delay but still have the problem of tying up the processor.

Alternatively you can set up a timer interrupt to give a known delay and also allow the processor to get on with other stuff during the delay.
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
310
Alternatively you can set up a timer interrupt to give a known delay and also allow the processor to get on with other stuff during the delay.
I understand what you mean but can you describe the situation where you used timer interrupt to generate a delay?

I have seen in many tutorials they use timer interrupt to flash LED.

There are two types of delay Hardware delay

1) software delay : I have shown two examples are the software delay
2) Hardware Delay : We use the timer of micro-controller to generate delay
 

djsfantasi

Joined Apr 11, 2010
9,156
Time Delay function : I have seen we mostly use delay function in Embedded System

I have written two delay functions and they both gives same result

Time delay with for loop
C:
#include<stdio.h>

void TimeDelay( int x);

int main (void)           /*start program */
{
    int count = 5;       /* asign  value 5 to  integer i */
  
    TimeDelay(count);            /*call Delay function */

    return 0;
}

void TimeDelay( int x)       /*pass value 5 */
   {
       int i = 0;
    
       for ( i = 0; i < x; i++)
       {
          printf("Wait : %d \n", i); 
       }
   }
Time Delay with while loop
C:
#include<stdio.h>

void Delay( int x);

int main (void)     /*start program */
{
    int i = 5;     /* asign  value 5 to  integer i */
  
    Delay(i);    /*call Delay function */

    return 0;
}

void Delay( int x)       /*pass value 5 */
   {
  
      while(x--)          /* decrements value by one */   
       {
          printf("Wait : %d \n", x); 
       }
   }
Can you tell me which one is more useful and why it is useful ? I can't figure out which one is more suitable ?

Just to be clear, you do know that delay is a built-in function in C? While you can write your own, the standard function in much more accurate. Plus, if you write your own and you use the code on another processor, the delay likely will not be the and your code may not work.
 

djsfantasi

Joined Apr 11, 2010
9,156
Either will do the job - and that's really the only rule.
You will not know exactly how long the delay will be though and the processor cannot do anything else during the delay. That may or may not matter in a particular program.

If you use the Microchip compiler XC8, it has the functions '__delay_ms(xx)' and '__delay_us(xx)' which allow you to specify the time of the delay but still have the problem of tying up the processor.

Alternatively you can set up a timer interrupt to give a known delay and also allow the processor to get on with other stuff during the delay.
Alternatively, you can calculate the future time when your delay should finish and go about with whatever your program needs to do. As long as you check routinely if the time has passed the end time.

This sample code addresses a problem with microprocessors. Counting millisseconds in a fixed length variable has a rollover problem. While perhaps it is complex, this code works during a rollover.

C:
unsigned long startTime = 0;
unsigned long myDelay = 50; // 50 ms delay
boolean waitforDelay = TRUE;

startTime = millis();
While ( waitforDelay) {
    if ((millis()-startTime) >= myDelay) {
        // do other stuff
        }
else {
        // delay has expired
        // execute desired action
        waitforDelay = FALSE;
        } 
// rest of program
}
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
310
@djsfantasi @AlbertHall

I have looked in many tutorials they use timer interrupt to flash LED. I found interrupt is more useful in context of response time and priority of task.

I am sorry but Can you give example of interrupt other then led where do you think interrupt is more suitable ? perhaps it would be easy if you can tell me where did you use interrupt in your project and why did you feel that you should use interrupt ?
 

jpanhalt

Joined Jan 18, 2008
11,087
I am sorry but Can you give example of interrupt other then led where do you think interrupt is more suitable ? perhaps it would be easy if you can tell me where did you use interrupt in your project and why did you feel that you should use interrupt ?
I cannot show you anything in C language, but think about a process in which you are sampling something periodically and don't want the processor tied up polling that event waiting for it to happen. Here are two specific examples:

1) Say you want to send RS-232 type of transmission at 9600 baud. Each "bit" is 104 us. So, you set up an interrupt that happens every 104 us (adjusted for "housekeeping"). With a clock of 8 MHz, one could do almost 200 instructions instead of waiting.
2) My current project is a recording cooking thermometer based on a thermocouple. If I sample every second using an interrupt, I can do thousands of instructions instead of wasting that time waiting. During that time, I process the data, do some ancillary calculations, display it on a GLCD. I can draw a complete screen in less than 6 ms, so that allows ample time for the screen to scroll.
 

AlbertHall

Joined Jun 4, 2014
12,345
I am in the process of writing an IR receiver in 'C'. It uses IOC (interrupt on change) to detect the edges of the received IR signal. The interrupt records the value of TMR1. The TMR1 overflow is set to generate an interrupt to indicate a timeout on waiting for edges.

I used an interrupt for capturing the edges to get good timing accuracy. I think you would also get reasonable accuracy by polling the IR pin using well written assembler but I do prefer 'C'.
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
310
I can get the status of one switch it's pressed or unpressed Problem is What happen if there are many switch buttons (16 switches) .

Code:
#define TRUE       1
#define Debounce   30

#define  SWITCH_PRESSED        1
#define  SWITCH_NOT_PRESSED    0

  int CheckSwitch(void)
{
    int ReturnValue =  SWITCH_NOT_PRESSED;

    if(Switch == TRUE)
    {
        DebounceDelay(Debounce);

        if(Switch == TRUE)
        {
            ReturnValue = SWITCH_PRESSED;
        }
    }
    return ReturnValue ;
}
I have understanding of for loop and function and I believe they will use to read the 16 buttons

What would be simple logic to read 16 buttons
 
Last edited:

AlbertHall

Joined Jun 4, 2014
12,345
Let's suppose eight of the switches are connected to one port and the other eight are connected to a different port. Then you can get the state of all 16 switches by two port reads. You then have to process the two read bytes to determine the actions for the program.
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
310
Let's suppose eight of the switches are connected to one port and the other eight are connected to a different port. Then you can get the state of all 16 switches by two port reads. You then have to process the two read bytes to determine the actions for the program.
Assume We have only 16 buttons A B C D E F G H I J K L M N O P ( assume keyboard of 16 buttons )

User can press any button How would you know which button it has been pressed

This is my idea but It's fail to read all switches

C:
void main()
{
    while(1)
    {
        s1 = CheckSwitch1 ();
        s2 = CheckSwitch2 ();      
        .....................
        .....................
       
        s16 = CheckSwitch16 ();
    }
}

int CheckSwitch1(void)
{
    return ReturnValue1 ;
}

int CheckSwitch2(void)
{
    return ReturnValue2 ;  
}

.......................

int CheckSwitch16(void)
{
    return ReturnValue16 ;
}
 

atferrari

Joined Jan 6, 2004
4,764
Reading 16 buttons.

I solved that many years ago, considering such a mass of switches as a keyboard. Wrote my own routine jointly with a keyboard manager.

For any new application I start, I just tailor this last to the switches I use. Those not installed are ignored de facto.

I work in Assembly.

While It could look too advanced for you (It is not) you could have a keyboard allowing "qualifiers", that is, more than one key pressed down at the same time to get additional codes (pretty much like the Ctrl key codes in a PC).

By the way, try by all means stop using on-line delays unless they are actually needed. You do not want your processor tied waiting if you can avoid it.

After learning how to use interrupts I got an ample degree of freedom for any kind of timing.
 

AlbertHall

Joined Jun 4, 2014
12,345
In what way does it fail?
Note that you have no storage of a keypress. When you release a key the S1 etc will return to the 'not pressed' state.
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
310
Reading 16 buttons.
I solved that many years ago, considering such a mass of switches as a keyboard. Wrote my own routine jointly with a keyboard manager.
@AlbertHall @atferrari
Assume we have bellow 16 buttons like this each label A B C D E F G H I J K L M N O P

I know the basics of c programming so how to use basic concept to read the all buttons. remember I am not talking about coding. I am asking for logic

It's really hard me to solve the problem I don't have idea whatever I had in mind I have already explained
1573556429986.png1573556443484.png1573556451802.png1573556469108.png
 
Top