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 CCS Technical Support

Help: Trouble storing settings in data eeprom with 18f26k22

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
fmartinezs



Joined: 16 Aug 2006
Posts: 19

View user's profile Send private message

Help: Trouble storing settings in data eeprom with 18f26k22
PostPosted: Fri Aug 25, 2017 12:26 pm     Reply with quote

Hi:

I'm having trouble with something seemingly simple, but which has me scratching my head. I'm working on a serial comm device, which has 2 modes of operation and works at 1200, 2400 and 4800 bps. Both settings should be selectable by the user with pushbuttons, and their current state shown with LEDs. Also, these settings should be stored in eeprom, so they remain as default as the equipment is turned off and on again.

So far, i haven't been able to accomplish this with PIC 18f26k22. I can toggle both mode and speed, but the settings are not getting stored in eeprom. I stripped my code to the bare minimum and it still doesn't work! I'm using compiler v5.015 by the way. My code is as follows:
Code:

#include <18f26k22.h>
#fuses HSH,NOWDT,NOPROTECT,PUT,NOPLLEN,NOCPD
#use delay(clock=20000000)
#use rs232(UART1, stream = TEST1, baud=1200, parity=N, bits=8, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use rs232(UART2, stream = TEST2, baud=1200, parity=N, bits=8, xmit=PIN_B6, rcv=PIN_B7, ERRORS)
#use standard_io(A)
#use standard_io(B)
#use standard_io(C)


/////////////////
// Definitions //
/////////////////

#define nop delay_cycles(1)

#byte PORTB = 0x0F81

#define V_1200_1 output_high(PIN_C1)
#define V_1200_0 output_low(PIN_C1)

#define V_2400_1 output_high(PIN_C2)
#define V_2400_0 output_low(PIN_C2)

#define V_4800_1 output_high(PIN_C3)
#define V_4800_0 output_low(PIN_C3)

#define MODE_A_1 output_high(PIN_C4)
#define MODE_A_0 output_low(PIN_C4)

#define MODE_B_1 output_high(PIN_C5)
#define MODE_B_0 output_low(PIN_C5)


/////////////
// Globals //
/////////////

int speed_ctr = 0;
int mode = 0;   


////////////////
// Interrupts //
////////////////

#INT_EXT
void speed_isr()
{
   speed_ctr++;

   if(speed_ctr>2)
      speed_ctr = 0;

   write_eeprom(0,speed_ctr);
   
   switch(speed_ctr)
   {
      case 0:
      {
         set_uart_speed(1200,TEST1);
         V_1200_1;
         V_2400_0;
         V_4800_0;
         break;
      }

      case 1:
      {
         set_uart_speed(2400,TEST1);      
         V_1200_0;
         V_2400_1;
         V_4800_0;
         break;
      }

      case 2:
      {
         set_uart_speed(4800,TEST1);      
         V_1200_0;
         V_2400_0;
         V_4800_1;
         break;
      }
   }

   delay_ms(250);
}


#INT_EXT1
void bypass_isr()
{
   write_eeprom(1,mode);

   if(!mode)
   {
      mode = 1;
      MODE_B_1;
      MODE_A_0;
   }
   else
   {
      mode = 0;
      MODE_B_0;
      MODE_A_1;   
   }

   delay_ms(250);
}


//////////////////
// main routine //
//////////////////

void main()
{
   //Set external interrupts edge
   ext_int_edge(0,H_TO_L);
   ext_int_edge(1,H_TO_L);

   //Enable necessary interrupts
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_EXT1);

   // Determine initial settings of the device

   speed_ctr = read_eeprom(0);

   switch(speed_ctr)
   {
      case 0:
      {
         set_uart_speed(1200,TEST1);
         V_1200_1;
         V_2400_0;
         V_4800_0;
         break;
      }

      case 1:
      {
         set_uart_speed(2400,TEST1);      
         V_1200_0;
         V_2400_1;
         V_4800_0;
         break;
      }

      case 2:
      {
         set_uart_speed(4800,TEST1);      
         V_1200_0;
         V_2400_0;
         V_4800_1;
         break;
      }

      default:
      {
         speed_ctr = 0;
         set_uart_speed(1200,TEST1);
         V_1200_1;
         V_2400_0;
         V_4800_0;
         break;
      }
   }   


   mode = read_eeprom(1);

   if(mode)
   {
      MODE_B_1;
      MODE_A_0;
   }
   else
   {
      MODE_B_0;
      MODE_A_1;   
   }

   //Infinite loop
   while(1)
   {
   }
}

*INT0 -> changes uart speed -> indicates current speed with pins C1 (1200), C2 (2400) and C3 (4800) respectively.

*INT1 -> toggles mode of operation -> indicates with pins C4 and C5 respectively.

I used the same code with a PIC18F252, and it worked just fine, so I have no idea why this apparently simple code doesn't work.

I tested storing data in eeprom with another short program, and using the same fuses, and that worked just fine, so I'm even more lost here.

Any help will be very appreciated. Thanks in advance!

Best regards,
Fernando
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 25, 2017 1:43 pm     Reply with quote

What external circuits do you have on pins B0 and B1 ? Do you have
pull-up resistors on these two pins ? These pins are used to receive the
external interrupts.


Also you claim this program ran fine on an 18F452. But the 18F452 has
only 1 hardware UART. The 18F26K22 has two hardware UARTS.
These are not similar PICs.
temtronic



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

View user's profile Send private message

PostPosted: Fri Aug 25, 2017 2:52 pm     Reply with quote

couple big nonos....

1) having delays within any ISR. might be ok for a quick test but not in the real world.

2) writing to eeprom within any ISR. again, same reason

Jay
fmartinezs



Joined: 16 Aug 2006
Posts: 19

View user's profile Send private message

PostPosted: Fri Aug 25, 2017 5:07 pm     Reply with quote

@PCM Programmer: Yes, i have 10 k pullups in both pins; i'm trying to port a working code running in a 18f252 to the 18f26k22, and the second usart will be used for management; i"m just discovering how different these pics are...

@temtronic: 1) how should i debounce my inputs more optimally? 2) should raise a flag and write the eeprom within the main loop?

Thanks both for your answers! Is there a chance my version of the compiler is acting up?

Best regards,
Fernando
temtronic



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

View user's profile Send private message

PostPosted: Sat Aug 26, 2017 5:28 am     Reply with quote

re : debounce
When using mechanical switches, you should have a scope to 'see' what is happening. It's a 'get what you pay for' product. The inexpensive ones will really bounce, pay $$ for hard gold plated contacts to minimize bounce. They all wear out, so read the spec for number of operations AND at what current level. Reducing the current will greatly extend the life BUT they need a certain amount to 'self clean'. Compromise, like life...switches involve compromise.

two options

1) hardware solutions include...
a) add a small cap across the switch. I use a .68mfd as I have 3500-4000 of them on a reel here.... you want a value that 'quenches' or 'absorbs' most of the spikey energy caused when the mechanical switch 'bounces'. This is easy to see on a scope.
b) add a schmitt buffer or opamp window comparator between switch and PIC. Both of these control what is a '1' and a '0'.But bigger part, more space, more cost.
c) use solid state switches. They give perfect '1's and '0's at a cost !
d) transistor buffer.Old school, they work great but does anyone use them anymore ??

all add cost,board space.and R&D time

2) software solutions
a) use a timer and poll the switches
b) use a counter, say 3 highs in a row = a 'one'

add add cost to code(R&D time) but NO hardware changes

There are dozens of methods and there was a recent( 1-2 weeks ago) thread about this. Try using the 'search' window here, put in 'debounce' and see what comes up. It's a very common topic, maybe a candidate for a 'sticky'?

I use a combination of both hardware and software. Kinda 'old school', like a reasonably good signal to go to the PIC, have software 'clean it up' before committing to next process.

One 'trick' in using mechanical switches is that you need to ensure no debounce but allow quick button presses.Another compromise. I use one of those 3by4 matrixmembrane 'domed' keypads for data entry and only use a 10ms software delay. It works fine, no errors. I can't type fast so speed isn't needed,reliabilty is.

Just some points to ponder...
Jay
guy



Joined: 21 Oct 2005
Posts: 297

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

PostPosted: Sat Aug 26, 2017 7:43 am     Reply with quote

Hi fmartinezs. If I understand your problem, it seems the EEPROM doesn't store your info and so the UART settings are not set properly.
I suggest to divide this into two - first make sure the EEPROM settings are written and read back correctly. If so, check that the set_uart_speed works correctly by looking at the hardware registers. It doesn't always do what it's told...
Other coding remarks mentioned earlier also apply of course.
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Sat Aug 26, 2017 8:45 am     Reply with quote

Three things (comments inline for two):
Code:

   //Set external interrupts edge
   ext_int_edge(0,H_TO_L);
   ext_int_edge(1,H_TO_L);
   //You should always clear interrupts after changing the active edge
   //This can lead to them being incorrectly triggered
   clear_interrupt(INT_EXT);
   clear_interrupt(INT_EXT1);

   speed_ctr = read_eeprom(0);
   //realistically I'd have expected to read the value
   //before starting the interrupt code. Otherwise if the interrupt does
   //trigger before the read completes you have an indeterminate value
   //in the variable....

   //Enable necessary interrupts
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_EXT1);


Then debounce is definitely a likely problem. Is the keypad an actual one you have tested with the older chip, or just 'the same type'?. Assume you are running at 5v?. Honestly, yes, far better to debounce, and only perform an actual write, once the value is what you want. The EEPROM write is typically slightly faster on the new chip. If might just be that this change is causing a problem...
fmartinezs



Joined: 16 Aug 2006
Posts: 19

View user's profile Send private message

PostPosted: Sun Aug 27, 2017 6:11 am     Reply with quote

Thanks for your answers guys! I'll try your suggestions on Monday and let you know about the results.

Best regards,
Fernando
fmartinezs



Joined: 16 Aug 2006
Posts: 19

View user's profile Send private message

PostPosted: Mon Aug 28, 2017 11:24 am     Reply with quote

Quick update:

It seems that with your help i managed to sort this problem out! Basically, i used temtronic's suggestion, of a counter that checks if the pin is still low after 3 timer interrupts; if so, i raise a flag and perform the write_eeprom routine within the while(TRUE).

I'll post the code later, as it may be useful for someone else.

Thanks for your help!

Best regards,
Fernando
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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