Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] pic18f46k22 wake up from sleep mode with serial interrupt

Status
Not open for further replies.

Valdez85

Junior Member level 1
Joined
Jan 18, 2015
Messages
16
Helped
1
Reputation
2
Reaction score
1
Trophy points
3
Activity points
125
Hey guys,

I have this code and it works fine, but i added the serial interrupt and the project stop works. I dont know what im doing wrong. Can you guys help me pls?

My pic is in sleep mode at start and wake up, take some measures and go to sleep mode again.

And now i want the same but if i press a button from keyboard the pic take the measures until i press the button again.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <usart.h>
#include <adc.h>
#include <delays.h>
#include <i2c.h>

#pragma config FOSC = HSMP
#pragma config PWRTEN = ON
#pragma config MCLRE = EXTMCLR
#pragma config HFOFST = ON
#pragma config WDTEN = SWON
#pragma config WDTPS = 2048

#define _XTAL_FREQ 8000000
#define I2C_FREQ 100000
#define  uch unsigned char                     //
#define DQ PORTCbits.RC0                                //define 18B20 data PORT
#define DQ_DIR TRISC0                         //define 18B20 D PORT direct register
#define DQ_HIGH() DQ_DIR =1                   //set data PORT INPUT
#define DQ_LOW() DQ = 0; DQ_DIR = 0           //set data PORT OUTPUT

unsigned char TLV = 0; //temperature high byte
unsigned char THV = 0; //temperature low byte
unsigned char TZ = 0; //temperature integer after convert
unsigned char TX20 = 0; //temperature decimal  after convert
unsigned int wd; //temperature BCD code  after convert
unsigned char tram;
unsigned char chuc;
unsigned char donvi;
unsigned char le;
unsigned char sec, min, hr, week_day, day, mn, year;
unsigned char stringfinal[32];
unsigned char tmp[5];
unsigned int ph;
unsigned int amo;
unsigned int clo;
unsigned char I2CData[] = {"123456"};
unsigned char dataout[30];

void readDS1307(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year) {
    StartI2C2();
    WriteI2C2(0xD0);
    WriteI2C2(0x00);
    RestartI2C2();
    WriteI2C2(0xD1);

    *sec = ReadI2C2();AckI2C2();
    *min = ReadI2C2();AckI2C2();
    *hr = ReadI2C2();AckI2C2();
    *week_day = ReadI2C2();AckI2C2();
    *day = ReadI2C2();AckI2C2();
    *mn = ReadI2C2();AckI2C2();
    *year = ReadI2C2();
    NotAckI2C2();
    StopI2C2();
}

void writeDS1307() {
    StartI2C2();
    WriteI2C2(0xD0);
    WriteI2C2(0x00);
    WriteI2C2(0x00); // sec
    WriteI2C2(0x00); //minutes
    WriteI2C2(0x00); // hours
    WriteI2C2(0x00); //week_day
    WriteI2C2(0x01); //date
    WriteI2C2(0x01); //month
    WriteI2C2(0x15); //year
    WriteI2C2(0x10); // REG 7 - Enable squarewave output pin1hz
    StopI2C2();
}

void Transform_Time(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year) {
    *sec = ((*sec & 0x70) >> 4)*10 + (*sec & 0x0F);
    *min = ((*min & 0x70) >> 4)*10 + (*min & 0x0F);
    *hr = ((*hr & 0x30) >> 4)*10 + (*hr & 0x0F);
    *week_day = (*week_day & 0x07);
    *day = ((*day & 0x30) >> 4)*10 + (*day & 0x0F);
    *mn = ((*mn & 0x70) >> 4)*10 + (*mn & 0x0F);
    *year = ((*year & 0xF0) >> 4)*10 + (*year & 0x0F);
}

void delay(int uSeconds) {
    int s;
    for (s = 0; s < uSeconds; s++);
}

void reset(void) {
    char presence = 1;
    while (presence) {
        DQ_LOW(); //MAIN MCU PULL LOW
        delay(41); //delay 503us
        DQ_HIGH(); //release general line and wait for resistance pull high general line and keep 15~60us
        delay(5); //delay 70us
        if (DQ == 1) presence = 1; // not receive responsion signal,continue reset
        else presence = 0; //receive responsion signal
        delay(40); //delay 430us
    }
}

void write_byte(uch val) {
    uch i;
    uch temp;
    for (i = 8; i > 0; i--) {
        temp = val & 0x01; //shift the lowest bit
        DQ_LOW();
        NOP();NOP();NOP();NOP();NOP(); //pull high to low,produce write time
        if (temp == 1) DQ_HIGH(); //if write 1,pull high
        delay(5); //delay 63us
        DQ_HIGH();
        NOP();NOP();
        val = val >> 1; //right shift a bit
    }
}

uch read_byte(void) {
    uch i;
    uch value = 0; //read temperature
    static bit j;
    for (i = 8; i > 0; i--) {
        value >>= 1;
        DQ_LOW();
        NOP();NOP();NOP();NOP();NOP();NOP(); //6us
        DQ_HIGH(); // pull high
        NOP();NOP();NOP();NOP();NOP(); //4us
        j = DQ;
        if (j) value |= 0x80;
        delay(5); //63us
    }
    return (value);
}

void get_temp() {
    int i;
    DQ_HIGH();
    reset(); //reset,wait for  18b20 responsion
    write_byte(0XCC); //ignore ROM matching
    write_byte(0X44); //send  temperature convert command
    for (i = 20; i > 0; i--) {
        NOP();
    }
    reset(); //reset again,wait for 18b20 responsion
    write_byte(0XCC); //ignore ROM matching
    write_byte(0XBE); //send read temperature command
    TLV = read_byte(); //read temperature low byte
    THV = read_byte(); //read temperature high byte
    DQ_HIGH(); //release general line
    TZ = ((TLV >> 4) | (THV << 4)); // & 0X3f;               //temperature integer
    TX20 = TLV << 4; //temperature decimal
    donvi = TZ % 10; //integer Entries bit
    chuc = (TZ % 100) / 10; //integer ten bit
    tram = TZ / 100;
    wd = 0;
    if (TX20 & 0x80) wd = wd + 5000;
    if (TX20 & 0x40) wd = wd + 2500;
    if (TX20 & 0x20) wd = wd + 1250;
    if (TX20 & 0x10) wd = wd + 625; //hereinbefore four instructions are turn  decimal into BCD code
    le = wd / 1000; //ten cent bit
    NOP();
    sprintf(tmp, "%d.%d", TZ, le);
}

void initDS1307(void) {
    OpenI2C2(MASTER, SLEW_OFF);
    Delay10KTCYx(25);
    SSP2ADD = (_XTAL_FREQ / (4 * I2C_FREQ)) - 1;

    StartI2C2();
    IdleI2C2();
    Delay10KTCYx(25);
    writeDS1307();
}

void analogicSensors(void) {
    SelChanConvADC(ADC_CH0);
    while (BusyADC()); //infinite loop
    ph = ReadADC(); //ReadADC();
    SelChanConvADC(ADC_CH1);
    while (BusyADC()); //infinite loop
    amo = ReadADC();
    SelChanConvADC(ADC_CH2);
    while (BusyADC()); //infinite loop
    clo = ReadADC();
}

void init24C64() {
    OpenI2C1(MASTER, SLEW_OFF);
    Delay10KTCYx(25);
    SSP1ADD = (_XTAL_FREQ / (4 * I2C_FREQ)) - 1; //set i2c clock
    Delay10KTCYx(25);
}

void write24C64(){
   StartI2C1();
   WriteI2C1(0xA0);
   WriteI2C1(0x00);
   WriteI2C1(0x00);
   for(int j=0;j<6;j++){
     WriteI2C1(I2CData[j]);
   }
   WriteI2C1(0x10);
   StopI2C1();
}

void read24C64(){
   StartI2C1();
   WriteI2C1(0xA0);
   WriteI2C1(0x00);
   WriteI2C1(0x00);
   RestartI2C1();
   WriteI2C1(0xA1);
   //for(int j=0;j<6;j++){
     //dataout[j] = ReadI2C1();
    // puts1USART(itoa(stringfinal, dataout, 10));
     dataout[0] = ReadI2C1();
     AckI2C1();
     dataout[1] = ReadI2C1();
     AckI2C1();
     dataout[2] = ReadI2C1();
     AckI2C1();
     dataout[3] = ReadI2C1();
     AckI2C1();
     dataout[4] = ReadI2C1();
     AckI2C1();
     dataout[5] = ReadI2C1();
   puts1USART(dataout);
   NotAckI2C1();
   StopI2C1();
}
/*
void interrupt RxInterrupt()
{
    unsigned char data;
    if(PIR1bits.RC1IF == 1)
    {
        data = Read1USART(); //read the byte from rx register
        if (DataRdy1USART() == 1)
            data = Read1USART();
        if (data == 's') {
            LATDbits.LD2 = 1;
        puts1USART("\nReal Time Data ON");
        readDS1307(&sec, &min, &hr, &week_day, &day, &mn, &year);
        Transform_Time(&sec, &min, &hr, &week_day, &day, &mn, &year);
        get_temp();
        analogicSensors();
        sprintf(stringfinal, "\n%02d/%02d/%02d,%02d:%02d:%02d,%s,%d,%d,%d", day, mn, year, hr, min, sec, tmp, ph, amo, clo);
        puts1USART(stringfinal);
        //Write1USART(data);
        }
        PIR1bits.RC1IF = 0; // clear rx flag
    }
}*/

void globalReset(void) {
    //ANSELA = 0x00;
    //ANSELB = 0x00;
    ANSELC = 0x00;
    ANSELD = 0x00;
    //ANSELE = 0x00;
}

void main(void) {
    globalReset();
    initDS1307();
    init24C64();
    //INTCONbits.GIE = 1; // enable global interrupts
    //INTCONbits.PEIE = 1; // enable peripheral interrupts.
    //PIE1bits.RC1IE = 1; // enable USART rx interrupt
    TRISA = 0b00000111;
    TRISDbits.TRISD2 = 0;
    LATDbits.LD2 = 0;
    CLRWDT();
    WDTCONbits.SWDTEN = 1;
    
   // ei();
    
    while (1) {

        for (int xpto = 0; xpto < 2; xpto++) {
            Close1USART();
            CloseADC();
            LATDbits.LD2 = 0;
            SLEEP();
        }

        for (int xpto = 0; xpto < 2; xpto++) {
            Open1USART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH, 51);
            OpenADC(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_20_TAD, ADC_CH0 & ADC_INT_ON, ADC_TRIG_CTMU & ADC_REF_VDD_VDD & ADC_REF_VDD_VSS);
            LATDbits.LD2 = 1;
            SLEEP();
        }

        for (int xpto = 0; xpto < 2; xpto++) {
        
        get_temp();
        Delay10KTCYx(200);
        }

        LATDbits.LD2 = 1;
        get_temp();
        readDS1307(&sec, &min, &hr, &week_day, &day, &mn, &year);
        Transform_Time(&sec, &min, &hr, &week_day, &day, &mn, &year);
        analogicSensors();
        sprintf(stringfinal, "\n%02d/%02d/%02d,%02d:%02d:%02d,%s,%d,%d,%d", day, mn, year, hr, min, sec, tmp, ph, amo, clo);
        puts1USART(stringfinal);
        write24C64();
        Delay10KTCYx(200);
        read24C64();
    }
}
 

your RxInterrupt() function is very long and includes writes to UART
interrupt routines should be kept as short as possible
have a loop in MAIN() and use a volatile global variable to signal when an interrupt has occured, e.g. something along the lines of
Code:
volatile int rxData=0;
void interrupt RxInterrupt()
{
    if(PIR1bits.RC1IF == 1)
    {
        rsData=1;
        PIR1bits.RC1IF = 0; // clear rx flag
    }

int main(void)
{
  ...
  while(1)
    {
        if(rxData)
            {
            rxData=0
            // process yor data
            ...
            
}
}
 

hello

are you really using USART interrupt ?

if you enter in RX interrupt routine, it means you allready have received a char into RCREG
Why do you read again the USART ?

do only

Code:
data=RCEG;
if (data=='s')
.......

and as Horace1 tell you, interrupt treatment must be as short as possible ,
arme a flag into the interrupt ,
test it in the main to do all the other job linked to this UART interrupt...
and add an error treatment for OERR (Overun) FERR (Frame error) to avoid blocked situation.


nota : the use of variable name like "data" is NOT RECOMMENDED .Because reserved name..
 

horace1,

I understand that and i guess you are right, but i have a problem. My pic is spleeping, so i cant generate uart interrupt.

Section 16.4.3 AUTO-WAKE-UP ON BREAK in the datasheet tells to put WUE = 1. I dont get it how to use this...
 

Try this piece of code.

Code:
TRISC = 0x80; //if PIC16F

TRISC = 0xC0; //if PIC18F

Edit: This code works fine for me.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
char uart_rd = 0, receivedFlag = 0;
 
void interrupt() {
         
    if(RC1IF_bit == 1) {
        if(OERR_bit) {
             OERR_bit = 0;
             CREN_bit = 0;
             CREN_bit = 1;
        }       
        
        uart_rd = RC1REG;
        
        receivedFlag = 1;
        
        RC1IF_bit = 0;
    }
}
 
void main() {
 
     ANSELA = 0x00;
     ANSELB = 0x00;
     ANSELC = 0x00;
     ANSELD = 0x00;
     ANSELE = 0x00;
     
     TRISA = 0xC0;
     TRISB = 0x00;
     TRISC = 0xC0;
     TRISD = 0x00;
     
     LATD = 0x00;
     
     UART1_Init(9615);
     Delay_ms(200);
     
     RC1IE_bit = 1;
     PEIE_bit = 1;
     GIE_bit = 1;
     
     RC1IF_bit = 0;
     
     UART1_Write_Text("Send S to display data");
     
     while(1) {
     
            asm sleep
            
            if(receivedFlag) {
                  if(uart_rd == 'S') {
                      LATD.F0 = 1;
                      UART1_Write_Text("\nReal Time Data ON");
                  }
                  
                  receivedFlag = 0;
            } 
     }
}

 

Attachments

  • uart.png
    uart.png
    55.5 KB · Views: 99
Last edited:

Why 2 I2C's are used one for RTC and one for EEPROM ? Both can use the same I2C bus.
 

with these changes the project does not work.

I want to use the two i2c. I know i can use one.

The sleep mode close usart so pic cant receive anything...... how can i wake up the pic with rx interrupt?
 

If it works for me it should also work for you. If you want someone to fix your XC8 code then zip and post the complete XC8 project files.
 

Dont know why, i tryed and did not work.
I attached the project.
 

Attachments

  • temperatura.X.rar
    270 KB · Views: 68

Zip and post your Circuit. If possible post it as Proteus file.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top