CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

debouncing missing out on presses!
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
temtronic



Joined: 01 Jul 2010
Posts: 9202
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Jun 08, 2019 8:22 pm     Reply with quote

http://www.ccsinfo.com/forum/viewtopic.php?t=23837

took me a bit to find it....
Jay
MassaM



Joined: 08 Jun 2019
Posts: 31

View user's profile Send private message Visit poster's website

PostPosted: Sat Jun 08, 2019 8:59 pm     Reply with quote

temtronic wrote:
http://www.ccsinfo.com/forum/viewtopic.php?t=23837

took me a bit to find it....
Jay


Great. Will check it out. Thank you.

Meanwhile, I found this by "PCM programmer" with a big Thank you! Very Happy here:

https://www.ccsinfo.com/forum/viewtopic.php?t=53600

and coded a simple test with a timer interrupt version with two buttons.

I still am going to make it into an array of switches and leds timer/interrupts based polling as per the demo i managed to code.

Tested and working full code below.

Code:


#include <18F4520.h>
#fuses INTRC_IO, BROWNOUT, PUT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

#define FOSC getenv("CLOCK")  // Get PIC oscillator frequency
#define TIMER0_PRELOAD (256 - (FOSC/4/256/100))

#define  BUTTON1   PIN_B0
#define  BUTTON2   PIN_B1

#define  LED1      PIN_D0
#define  LED2      PIN_D1

void timer0_init(void)
{
   setup_timer_0(T0_INTERNAL | T0_DIV_256 | T0_8_BIT);
   set_timer0(TIMER0_PRELOAD);
   clear_interrupt(INT_TIMER0);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
}

int8 switch1_is_down = FALSE,
     switch2_is_down = FALSE;

#int_timer0
void timer0_isr(void)
{
   int8 active_state1, previuos_state1,
        active_state2, previuos_state2;
   
   set_rtcc(TIMER0_PRELOAD); // Reload Timer0 for 10ms rate
   
   active_state1 = input(BUTTON1);  // Read the button
   active_state2 = input(BUTTON2);  // Read the button
   
   if((previuos_state1 == 1) && (active_state1 == 0))
   {
      switch1_is_down = TRUE;   
   }

   if((previuos_state2 == 1) && (active_state2 == 0))
   {
      switch2_is_down = TRUE;   
   }
   
   previuos_state1 = active_state1;  // Save current value for next time
   previuos_state2 = active_state2;  // Save current value for next time
   
}


void main()
{

   timer0_init();
   
   while(TRUE)
   {
   
   if(switch1_is_down == TRUE)
     {
         switch1_is_down = FALSE;  // Clear the switch is pushed flag
         output_toggle(LED1);     
     }
   
   if(switch2_is_down == TRUE)
     {
         switch2_is_down = FALSE;  // Clear the switch is pushed flag
         output_toggle(LED2);     
     }
   
   }
}


Hope it helps others and would appreciate any inputs and help.

MassaM
_________________
while(!dead)
{
keepLearning();
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Sun Jun 09, 2019 7:26 am     Reply with quote

Well done.
Looks quite tidy. Smile
As a comment, your flags for switchx_is_down, might as well be int1's.
The processor has inbuilt instructions for testing and branching on a bit,
so using these may well be more efficient, and will save space.
One of the things that has to be learnt on the PIC, is that you only have
a very small amount of RAM, so saving is always worthwhile.
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Sun Jun 09, 2019 8:38 am     Reply with quote

As one more comment, why are you using such an old chip?.

The 16F877A, is 'not recommended for new designs'. It came out around
about 2000, and there are newer PIC's, that use less power, have more
peripherals, are faster, have more RAM, and are cheaper!...
It's amazing how many people still carry on using such old chips.

I don't know whether you have PCH or only PCM, but the PCH chips
(PIC18's), also have a much tidier actual architecture. The 16F877A was
a reasonable chip to use 15 years ago, but now is making things harder
for yourself than they need to be...
MassaM



Joined: 08 Jun 2019
Posts: 31

View user's profile Send private message Visit poster's website

PostPosted: Sun Jun 09, 2019 9:28 am     Reply with quote

Ttelmah wrote:
Well done.
Looks quite tidy. Smile

Thank you! Smile

Ttelmah wrote:
As a comment, your flags for switchx_is_down, might as well be int1's.
The processor has inbuilt instructions for testing and branching on a bit,
so using these may well be more efficient, and will save space.
One of the things that has to be learnt on the PIC, is that you only have
a very small amount of RAM, so saving is always worthwhile.


All you mentioned are priceless, very well noted and will be put into action for future PIC adventures! Cool

With gentlemen such as yourself, and this community of course, learning PIC and CCS-C will be an easy task and I found it to be the right choice.

Bless all.

MassaM
_________________
while(!dead)
{
keepLearning();
}
MassaM



Joined: 08 Jun 2019
Posts: 31

View user's profile Send private message Visit poster's website

PostPosted: Sun Jun 09, 2019 9:37 am     Reply with quote

Ttelmah wrote:
As one more comment, why are you using such an old chip?.

The 16F877A, is 'not recommended for new designs'. It came out around
about 2000, and there are newer PIC's, that use less power, have more
peripherals, are faster, have more RAM, and are cheaper!...
It's amazing how many people still carry on using such old chips.

I don't know whether you have PCH or only PCM, but the PCH chips
(PIC18's), also have a much tidier actual architecture. The 16F877A was
a reasonable chip to use 15 years ago, but now is making things harder
for yourself than they need to be...


I agree. It's just the beginning for me and PIC, most tutorials use it, and added that I have couple of those laying in the boxes from those days! Smile

Will definitely shift to the latest ones to benefit from the features as you mentioned of course.

Cheers! Smile
_________________
while(!dead)
{
keepLearning();
}
dluu13



Joined: 28 Sep 2018
Posts: 395
Location: Toronto, ON

View user's profile Send private message Visit poster's website

PostPosted: Sun Jun 09, 2019 9:44 am     Reply with quote

Just a caution about int1:

I've experienced something where with larger projects that have more variables and more int1's scattered around, they don't work properly for some reason.

There is some brief discussion about this in the beginning of this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=57881&postdays=0&postorder=asc&start=0

So if you suddenly start to have problems with int1 flags, then this may be it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Sun Jun 09, 2019 10:04 am     Reply with quote

The issues here were with a very early V5 compiler, that was still really a
'beta' at best.
dluu13



Joined: 28 Sep 2018
Posts: 395
Location: Toronto, ON

View user's profile Send private message Visit poster's website

PostPosted: Sun Jun 09, 2019 10:06 am     Reply with quote

Ttelmah wrote:
The issues here were with a very early V5 compiler, that was still really a
'beta' at best.


Hmm... There must be something else at play for me then. I was experiencing it in 5.082. I still haven't gone to investigate that yet.
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Sun Jun 09, 2019 10:20 am     Reply with quote

Do you possibly have them in structures?.
There is an 'insidious' problem sometimes with int1's used in structures.
Seems not to happen if you use bit fields instead. So in a structure
declaration:
Code:

//instead of
struct something {
    int1 something;
}

//use
struct something {
   int8 something:1;
}
dluu13



Joined: 28 Sep 2018
Posts: 395
Location: Toronto, ON

View user's profile Send private message Visit poster's website

PostPosted: Sun Jun 09, 2019 10:25 am     Reply with quote

Ttelmah wrote:
Do you possibly have them in structures?.
There is an 'insidious' problem sometimes with int1's used in structures.
Seems not to happen if you use bit fields instead. So in a structure
declaration:
Code:

//instead of
struct something {
    int1 something;
}

//use
struct something {
   int8 something:1;
}


I may have... I don't actually remember which ones of my flags initially caused the problem. I just know that I switched them all to int8 for my current project. I will try the tip with bit fields when I have some time.
temtronic



Joined: 01 Jul 2010
Posts: 9202
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jun 09, 2019 3:51 pm     Reply with quote

I recall a 'quirky problem that dealt with bits (int1s) and the 'cure' seemed to be to have 8 int1 even though you only needed, say 5. I assuming this forced the compiler to use a whole byte and data was 'aligned'.
While this was probably fixed, I've always used the 'full' byte method.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Mon Jun 10, 2019 1:49 am     Reply with quote

This may well relate.
Using bit fields, the bits are generated as bits in a byte. Hence the 'int8'
at the start of the declaration. If you don't use all the bits, a byte as an
entity is still allocated. Now, while you perhaps would expect the int1
declaration to do the same, if it doesn't, and the 'optimiser' tries then
to save space by using 'spare' bits elsewhere, I can easily see errors
occurring (particularly perhaps with bank switching when these are accessed).
MassaM



Joined: 08 Jun 2019
Posts: 31

View user's profile Send private message Visit poster's website

Interrupts disabled during call to prevent re-entrancy
PostPosted: Mon Jun 10, 2019 1:45 pm     Reply with quote

The Problem:

A code redo for array based compiles with the two warnings below with a halt on the timer0 interrupt init on actual test! Crying or Very sad

Code:
>>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy:  (@READBITA)
>>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy:  (@WRITEBITA)


The Success:

The non-array version posted earlier compiles clean and works fine.

The Notes:

I searched and read many posts here on the subject issue, and that the CCS C compiler does not support this kind of thing, and sort of understood that they were suggesting to change the entire code routine and structure.

Below is the code here for a review and request for valuable guidances.

Code:

/*
   // ************************************************ Array version ************************************************ //
   
   Project:    Demo Controller Board - 8 Channels Relay with status LEDs and push buttons for an ON/OFF toggle
   Compiler:   CCS-C-PIC - PCWHD Version 5.076
   Author:     MassaM, June 2019
   Chip:       PIC16F877A@20Mhz
   Copyright:  No copy-rights nor copy-wrongs! :)
   Request:    Make it better and post it back on this thread, so we all learn please!
*/

#include <16F877A.h>

#fuses XT, BROWNOUT, PUT, NOWDT
#use delay(clock=20M)
#use rs232(stream=SERIAL, baud=19200, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)  // settings for Serial/Terminal outputs

#define FOSC getenv("CLOCK")  // Get PIC oscillator frequency
#define TIMER0_PRELOAD (256 - (FOSC/4/256/100))

/* ****************************************************************************************************************** */
// Array version variables
int16 switches[] = {PIN_B0,PIN_B1,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7};
int16 leds[] = {PIN_D0,PIN_D1,PIN_D2,PIN_D3,PIN_D4,PIN_D5,PIN_D6,PIN_D7};
int8 switch_is_down[] = {FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};
/* ****************************************************************************************************************** */

/* ****************************************************************************************************************** */
// Array version functions
/* ****************************************************************************************************************** */

void clearSwitches_Array()
{
   int8 i;
   for(i=0; i < 8; i++)
   {
      switch_is_down[i] = FALSE;  // Clear the switch is pushed flag
      //printf("[Cleared]:\r\n");
      //printf("Switch No: %d\r\n", switch_is_down[i]);
   }   
}

void pollSwitches_Array()
{
   int8 i;
   for(i=0; i < 8; i++)
   {
      if(switch_is_down[i] == TRUE)
      {
         switch_is_down[i] = FALSE;  // Clear the switch is pushed flag
         output_toggle(leds[i]);
         //printf("[Polled] switch No: %d\r\n", switch_is_down[i]);
      }
   }   
}

void checkStates_Array()
{
   int8 active_state[], previous_state[];
   
   int8 i;
   
   for(i=0; i < 8; i++)
   {
      active_state[i] = input(switches[i]);  // Read the button

      if((previous_state[i] == 1) && (active_state[i] == 0))
      {
         switch_is_down[i] = TRUE;   
      }
     
      previous_state[i] = active_state[i];  // Save current value for next time
     
      //printf("[Timer0] switch No: %d, previous_state %d, active_state %d\r\n", i, previous_state[i], active_state[i]);

   }
}

void timer0_init(void)
{
   setup_timer_0(T0_INTERNAL | T0_DIV_256 | T0_8_BIT);
   set_timer0(TIMER0_PRELOAD);
   clear_interrupt(INT_TIMER0);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);   
   
   //printf("[initAll]:\r\n");     // It hangs here with the array version
   //printf("T0_INTERNAL: %d\r\nT0_DIV_256: %d\r\nT0_8_BIT: %d\r\n", T0_INTERNAL , T0_DIV_256 , T0_8_BIT);
   //printf("set_timer0: %d\r\nenable_interrupts: %d\r\nGLOBAL: %d\r\n", TIMER0_PRELOAD ,INT_TIMER0, GLOBAL);
   
}

#int_timer0
void timer0_isr(void)
{   
   set_rtcc(TIMER0_PRELOAD); // Reload Timer0 for 10ms rate
   
   //printf("\r\n[timer0_isr] (%d) Waiting...\r\n", get_rtcc());
   
   checkStates_Array();       // This not working aka hangs

}

void initAll(){
   
   timer0_init();
   
   clearSwitches_Array();

}

void main()
{

   initAll();

   printf("-------------------------------------------------\r\n");
   printf("Ready!\r\n");
     
   while(TRUE)
   {
   
/*

Notes:

-> Array version compiles with the two warnings below with a halt on the timer0 interrupt init on actual test! :(
-> Non Array version posted earlier compiles clean and works fine.

>>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy:  (@READBITA)
>>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy:  (@WRITEBITA)

*/
   
   pollSwitches_Array();            // <- Warnings and notes as above

   } // while true
   
} // main


Appreciated.

MassaM
_________________
while(!dead)
{
keepLearning();
}
dluu13



Joined: 28 Sep 2018
Posts: 395
Location: Toronto, ON

View user's profile Send private message Visit poster's website

PostPosted: Mon Jun 10, 2019 1:57 pm     Reply with quote

Are you trying to use printf's to debug within your interrupts?

They are very slow and will mess with you. It is much better to set a flag in the ISR, and print in your main loop instead. A good rule for ISRs are to get in, set/check flags or increment counters, and then get out as soon as possible.

Also, in checkStates_Array():
You are using a int8 array to loop through store your switch states, when in fact you could store all of the values within a single int8 using the function input_b(). That will capture the value of all the pins on that port and store them in a single variable so you don't need to loop through.

Then you can do a bitwise comparison of previous and current states.

Another thing is that you are declaring previous_state[] inside the function, but you have not assigned anything to it. Therefore, previous_state's values can be just about anything by the next time you run checkStates_array(). You should either make that a global variable or static variable so its lifetime lasts beyond the function. Otherwise once the function returns, something else can use that memory area and you will get unexpected results.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group