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

PIC18LF47K42 doesn't awake when receives data by UART.

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



Joined: 27 Mar 2018
Posts: 25

View user's profile Send private message

PIC18LF47K42 doesn't awake when receives data by UART.
PostPosted: Fri Oct 30, 2020 5:34 am     Reply with quote

I use PIC18LF47K42 for the first time.

I'm not able to awake the PIC when it receives a character by the UART1 using interrupts once it is asleep.

I'm forgetting something...

...This PIC has two UART but previous PIC's I've been used had EUART with 'E'?

...fuses?

The same code works fine with other PICs like PIC18LF47K40.

Could someone help me?

Thank you in advance!

Code:

// MPLABX version: 5.40
// CCS version: 5.096


#CASE   // Case sensetive compiler

#include <18LF47K42.h>

#FUSES NOBROWNOUT

#use delay(clock = 16MHZ, internal)

#pin_select U1TX = PIN_C6
#pin_select U1RX = PIN_C7

//The PIN_SELECT stuff must be before you use the UART
#use rs232 (UART1, baud = 9600)

#define LED PIN_C4   // OUT high = led on

#INT_RDA
void serial_isr()
{
   putc(getc());
}

void main(void)
{
   output_high(LED);     // Led on
   delay_ms(300);
   output_toggle(LED);   // Led off
   delay_ms(300);
   output_toggle(LED);   // Led on
   delay_ms(300);
   output_toggle(LED);   // Led off

   output_low(PIN_A0);
   output_low(PIN_A1);
   output_low(PIN_A2);
   output_low(PIN_A3);
   output_high(PIN_A4);
   output_low(PIN_A5);
   output_low(PIN_A6);
   output_low(PIN_A7);
   
   output_low(PIN_B0);
   output_low(PIN_B1);
   output_low(PIN_B2);
   output_low(PIN_B3);
   output_low(PIN_B4);
   output_low(PIN_B5);
   output_low(PIN_B6);
   output_low(PIN_B7);
   
   output_low(PIN_C0);   
   output_low(PIN_C1);
   output_low(PIN_C2);
   output_low(PIN_C3);
   output_low(PIN_C4);
   output_low(PIN_C5);
   //output_high(PIN_C6);   // TX pin 44
   //output_high(PIN_C7);   // RX pin 1
   
   output_low(PIN_D0);
   output_low(PIN_D1);
   output_low(PIN_D2);
   output_low(PIN_D3);
   output_low(PIN_D4);
   output_low(PIN_D5);
   output_low(PIN_D6);
   output_low(PIN_D7);
   
   output_low(PIN_E0);
   output_low(PIN_E1);
   output_high(PIN_E2);   
   output_high(PIN_E3);

   putc('>');
   delay_ms(1);
   
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

//   while(TRUE)   // With this loop at VDD=3.0V current consumption is 3000uA. Receives RX data OK.
//   {
//   }
     
//   while(TRUE)   // With this loop at VDD=3.0V current consumption is 0.3uA. Doesn't receive any RX data. Is OK.
//   {
//      sleep();
//      delay_cycles(1);
//   }
 
   while(TRUE)   // Whith this loop I'm not able to awake the PIC to receive data! Help needed here!
   {             // With this loop at VDD=3.0V current consumption is 0.3uA.
      setup_uart(UART_WAKEUP_ON_RDA);
      sleep();
      delay_cycles(1);
  }

}

Josep Robert



Joined: 27 Mar 2018
Posts: 25

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 5:55 am     Reply with quote

I have done more tests without success.

Code:

   while(TRUE)   // Whith this loop I'm able to awake the PIC to receive data but with a lot of errors!
   {             // With this loop at VDD=3.0V current consumption is very high, 1900uA.
     
      setup_uart(UART_WAKEUP_ON_RDA);

      sleep(SLEEP_IDLE); // #define SLEEP_IDLE 1  // Clock and peripherals don't stop

      delay_cycles(1);
  }
temtronic



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

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 6:36 am     Reply with quote

Ok, I don't consider 1900ua (1.9ma) to be 'very high' but then I'm a dinosaur that had 40AMP, +5 PSUs for my equipment.
To reduce power consumption, you need to disable any/all internal peripherals that you're not using. Items like ADC, comparators, etc. I don't use that PIC, but modern PICs have a LOT of peripherals and most will be enabled by default.
As for the 'errors', what are they ? If data, do you buffer the incoming data, have you 'errors' in the #use RS232(...options...). What is the other RS232 'device', what baudrate ? Is it 3 volt device. What level translators are you using? Cable type, length, etc. Proper ground between PIC and 'device' ?

If the PIC is NOT asleep, is the data 100% ?

At 3 volts, are you using a battery ?
Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 8:42 am     Reply with quote

You do understand you can't receive the character that wakes you?.

You also have to send a 'break' character to wake the chip.
The chip does not receive this, just wakes.
So the sequence is 'send break', pause for a moment, then send the
characters you want received. The PIC has to stay awake once the break
is seen till the packet is complete.

So you won't wake on any old character being received, and even if you
did, the actual character that wakes you is never received.
Josep Robert



Joined: 27 Mar 2018
Posts: 25

View user's profile Send private message

PostPosted: Tue Nov 03, 2020 7:18 am     Reply with quote

Thanks for your answer temtronic.

I need an average consumption current of 100uA. I want the two AA (Vdd 3.0V...1.8V) batteries last more than 2 years.

With all peripherals disabled I have consumption less than 1uA.

I don't used 'errors' in the #use RS232(...options...).

The rs232 communicates with a Bluetooth module at 9600. No need level translators.

When the PIC is not asleep the data is OK.
temtronic



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

View user's profile Send private message

PostPosted: Tue Nov 03, 2020 7:30 am     Reply with quote

You need to add 'ERRORS'. Without it, if the PIC receives 3 or more characters and you don't read the UART buffer, the UART will shutdown due to 'overrun'. Like having a mailbox and NOT getting your mail, the box gets 'stuffed' and you're in trouble !
As it's a battery powered device, remember that batteries do NOT like getting cold ! Their energy output is greatly reduced.
Josep Robert



Joined: 27 Mar 2018
Posts: 25

View user's profile Send private message

PostPosted: Tue Nov 03, 2020 7:31 am     Reply with quote

Thanks for your answer Ttelmah.

You are right again.
Sorry for asking a question that I know that you are answering almost every day during more than a decade.
Once I have studied and understood the AUTO-WAKE-UP ON BREAK (PIC18LF47K42 31.17.3 AUTO-WAKE-UP ON BREAK pag.496) I will make a test code and I will post it.
If the PIC doesn’t go to sleep a UART works in 5 minutes but if you need low consumption (sleep) things are more complicated.
Josep Robert



Joined: 27 Mar 2018
Posts: 25

View user's profile Send private message

PostPosted: Tue Nov 17, 2020 2:15 am     Reply with quote

PIC consumes < 1uA.
Receives a 5 bytes order plus a heading break byte.
The PIC starts consuming 2500uA while receiving the order and transmitting the answer.
PIC goes to sleep again consuming < 1uA.

How can I improve this code with ",timeout" ",errors" in "#use rs232 ()" ?
Code:

// AUTO-WAKE-UP ON BREAK
//
// TX: 00 01 02 03 04 05 => RX 01 02 03 04 05 (0x00 = break)
//
// TX: ff 01 02 03 04 05 => RX 01 02 03 04 05 (0xff = break)
//
//                               0  1  2  3  4  0  1  2  3  4
// order to receive:     00(brk) 01 02 03 04 05                       from PC terminal to RX PIC
// order resend                                 01 02 03 04 05        from PIC TX to PC terminal
// PIC _____sleep______> <awake-------------------------awake> <___sleep___
//          <1uA                      2500uA                       <1uA
//
// MPLABX version: 5.40
// CCS version: 5.096

#CASE   // Case sensetive compiler

#include <18LF47K42.h>

#FUSES NOBROWNOUT
#FUSES NOWDT

#use delay(clock = 16MHZ, internal)

#pin_select U1TX = PIN_C6   // U1RXPPS portC 0x3ae5 = 0x17
#pin_select U1RX = PIN_C7

#use rs232 (UART1, baud = 9600)   // The PIN_SELECT stuff must be before you use the UART
// ,timeout   ???
// ,errors    ???

#define NO  0
#define YES 1

#define LED PIN_C4   // OUT high = led on

#byte U1ERRIR = 0x3DF9
#bit TXMTIF = U1ERRIR.7

#byte U1UIR = 0x3DF8
#bit WUIF = U1UIR.7

#byte U1FIFO = 0x3df7
#bit RXIDL = U1FIFO.3 

#byte U1CON2 = 0x3DF4

#byte U1CON1 = 0x3df3
#bit WUE = U1CON1.4

#byte INTCON0 = 0x3FD2
#bit GIE = INTCON0.7

#byte U1CON0 = 0x3DF2

#byte U1TXB = 0x3dea;   // 0x3dea   U1TXB:  UART TRANSMIT REGISTER
#byte U1RXB = 0x3de8;   // 0x3de8   U1RXB:  UART RECEIVE REGISTER

#byte PIR3 = 0x39A3
#bit  U1RXIF = PIR3.3   // UART1 Receive Interrupt Flag bit.

#byte PIE3 = 0x3993
#bit  U1IE = PIE3.6
#bit  U1RXIE = PIE3.3

int8 rxIndex = 0;
int1 goToSleep = YES;
int1 orderReceived = NO;
int8 rxBuffer[5] = {0xff, 0xff, 0xff, 0xff, 0xff};
       
#INT_RDA
// When the wake-up event ocours the UART module generates a U1UIR.WUIF interrupt (0x3DF8.7).
void serial_isr(void)
{
   rxBuffer[rxIndex++] = getc();

   if (rxIndex >= 5)
   {
      rxIndex = 0;
      orderReceived = YES;
   }

   WUIF = 0;   // U1UIR.WUIF  0x3DF8.7 Wake-up Interrupt bit. The interrupt condition is cleared here by software.
               // U1UIR: UART GENERAL INTERRUPT REGISTER
               // bit 7 WUIF: Wake-up Interrupt bit
               //       1 = Idle to non-idle transition on RX line detected when WUE is set. Also sets U1IF. (WUIF must be cleared by software to clear U1IF)
               //       0 = WUE not enabled by software or no transition detected
   
   // PIR3.U1RXIF 0x39a3.3 bit cleared by compiler.
   // PIR3: PERIPHERAL INTERRUPT REGISTER 3
   // bit 3 U1RXIF: UART1 Receive Interrupt Flag bit
   //       1 = Interrupt has occurred
   //       0 = Interrupt event has not occurred

}

void main(void)
{   
   int8 i;
   
   output_high(LED);     // Led on
   delay_ms(300);
   output_toggle(LED);   // Led off
   delay_ms(300);
   output_toggle(LED);   // Led on
   delay_ms(300);
   output_toggle(LED);   // Led off
   
   output_low(PIN_A0);
   output_low(PIN_A1);
   output_low(PIN_A2);
   output_low(PIN_A3);
   output_low(PIN_A4);
   output_low(PIN_A5);
   output_low(PIN_A6);
   output_low(PIN_A7);
   
   output_low(PIN_B0);
   output_low(PIN_B1);
   output_low(PIN_B2);
   output_low(PIN_B3);
   output_low(PIN_B4);
   output_low(PIN_B5);
   output_low(PIN_B6);
   output_low(PIN_B7);
   
   output_low(PIN_C0);   
   output_low(PIN_C1);
   output_low(PIN_C2);
   output_low(PIN_C3);
   output_low(PIN_C4);   // LED low = off
   output_low(PIN_C5);
   //output_high(PIN_C6);   // TX pin 44 output
   //output_high(PIN_C7);   // RX pin 1  input
   
   output_low(PIN_D0);
   output_low(PIN_D1);
   output_low(PIN_D2);
   output_low(PIN_D3);
   output_low(PIN_D4);
   output_low(PIN_D5);
   output_low(PIN_D6);
   output_low(PIN_D7);
   
   output_low(PIN_E0);
   output_low(PIN_E1);
   output_low(PIN_E2);
   output_high(PIN_E3);   // MCLR

   putc('>');
   delay_ms(1);

   U1IE = 1;   // PIE3.U1IE, 0x3993.6 = 1. PERIPHERAL INTERRUPT ENABLE REGISTER 3.
               // bit 6 U1IE: UART1 Interrupt Enable bit
               //       1 = Enabled
               //       0 = Disabled
   
   enable_interrupts(INT_RDA);   // PIE3.U1RXIE, 0x3993.3 = 1. PERIPHERAL INTERRUPT ENABLE REGISTER 3.
                                 // bit 3 U1RXIE: UART1 Receive Interrupt Enable bit
                                 //       1 = Enabled
                                 ///      0 = Disabled
   
   enable_interrupts(GLOBAL);    // 0x3df2 | 0b11000000   INTCON0: INTERRUPT CONTROL REGISTER 0
                                 //            bit 7 GIE/GIEH: Global Interrupt Enable bits
                                 //             bit 6 GIEL: Global Low Priority Interrupt Enable bit

   while (TRUE)
   {
      output_toggle(LED);
      output_toggle(LED);
     
      if (goToSleep == YES)
      {
         setup_uart(UART_WAKEUP_ON_RDA);   // U1CON1.WUE, 0x3DF3.4 = 1. U1CON1: UART CONTROL REGISTER 1
                                           //  bit 4 WUE: Wake-up Enable bit
                                           //        1 = Receiver is waiting for falling RX input edge which will set the UxIF bit. Cleared by hardware on wake event. Also requires UxIE
                                           //        0 = Receiver operates normally
         sleep();
         delay_cycles(1);
         
         goToSleep = NO;
      }
      else
      {
         if (orderReceived == YES)   
         {
            orderReceived = NO;
           
            for (i = 0; i < 5; i++)
               putc(rxBuffer[i]);

            while(TXMTIF == 0);   // 3DF9h.7    U1ERRIR.TXMTIF: Transmit Shift Register Empty Interrupt Flag bit
                                  //                    1 = Transmit shift register is empty (Set at end of Stop bits)
                                  //                    0 = Transmit shift register is actively shifting data
            goToSleep = YES;      // Entering sleep with last 2 characters sent correctly.
         }
      }
   }
}

Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Tue Nov 17, 2020 3:34 am     Reply with quote

'ERRORS' should always be used with a hardware UART. It really should
be made the default by CCS. Without this if a character does get missed,
the UART can become completely hung.
TIMEOUT, would not do anything for you. You never sit 'waiting' on the
UART, so no effect from this. TIMEOUT doesn't generate an interrupt.
If you want a timeout, you are going to have to write it yourself. So
(for example), start a timer when you wake from the break, and when this
expires, if you have not received a complete 'packet', throw away what you
have received and go back to sleep.
temtronic



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

View user's profile Send private message

PostPosted: Tue Nov 17, 2020 6:25 am     Reply with quote

If 'improve' means use less power, consider a faster baudrate. while doubling it( 9600> 19200) won't reduce power by 1/2, there will be a slight reduction. Same holds true with the PIC 'clock'. Running it faster for a shorter time, will reduce power.
Microchip had an 'appnote' very early ( AN606 ???, it's OLD...) that had charts and numbers about batteries/clocks/tricks to reduce power . It's only 10-15 pages long but well worth the effort to find and read it.

Also
instead of...
Quote:

output_low(PIN_A0);
output_low(PIN_A1);
output_low(PIN_A2);
output_low(PIN_A3);
output_low(PIN_A4);
output_low(PIN_A5);
output_low(PIN_A6);
output_low(PIN_A7);

try...
Code:
 output_A(0b00000000);

It makes for shorter and faster code, even if some bits have to be '1's. Instead of 16 lines of code, only 2 or 3.
I know, it only gets executed once BUT it's a 'tweak' that does reduce overall power consumption.
Adding a small 'supercap' in parallel to the battery could help.
When using 'batteries only', EVERY trick or tweak, has to be tested.
Josep Robert



Joined: 27 Mar 2018
Posts: 25

View user's profile Send private message

PostPosted: Wed Nov 18, 2020 4:23 am     Reply with quote

Thanks for your reply temtronic.

The 'appnote' you recommend is very interesting:

AN606 Low Power Design Using PICmicro™ Microcontrollers

https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en024865
temtronic



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

View user's profile Send private message

PostPosted: Wed Nov 18, 2020 5:40 am     Reply with quote

Thank you ! for taking the time, finding it and posting a 'link' to it !! I used to have the real databooks here on the shelf for quick reference, sigh, that was a long, long time ago.... Kind interesting that I remember the apnote number, bet there's a 'few' more added since then.

Another 'fun' read are the 'Tips & Tricks' books. Though code is in assembler, they can easily be adapted to C.

Jay aka Temtronic
Josep Robert



Joined: 27 Mar 2018
Posts: 25

View user's profile Send private message

PostPosted: Thu Nov 19, 2020 12:18 am     Reply with quote

Thanks to you temtronic.

The Microchip Compiled Tips ‘N Tricks Guide is quite old but very interesting to have in mind while designing.

http://ww1.microchip.com/downloads/en/DeviceDoc/01146B.pdf
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