PIC UART causa un cambio accidental en otros registros

1

Estoy programando PIC16F886 para recibir y procesar algunos comandos AT para enviar y recibir SMS. Al principio, funciona correctamente, pero al aumentar el código (ocupaba solo el 50% de la memoria flash), el PIC inició comportamientos extraños al recibir datos en serie; A veces cambia el mordisco alto del registro RCSTA; A veces el registro T2CON cambia; A veces, el registro CCP1CON cambia y se inicia PWM (no tengo ningún código relacionado con CCP en mi proyecto). Este extraño comportamiento cambia solo agregando algo de NOP a mi código. ¿Cuál es el problema? ¡Estoy realmente confundido!
Estoy usando el compilador mikroC PRO y procesando datos seriales de 1200 bps en la rutina de interrupción. Solo hago una simple detección de comandos AT y un búfer de datos en la interrupción, el procesamiento y la respuesta se realiza en la rutina principal. Por cierto, también probé el almacenamiento en búfer en la interrupción y el procesamiento completo en la rutina principal, pero el problema no se resolvió.
Esta es una parte de mi código:

#define AT_DTMF        100 
#define AT_CMTI        101
#define AT_CMGR_TXT    102
#define AT_OK          200
#define AT_RING        201
#define AT_ERROR       202
#define AT_OtherRes    203
#define AT_TxtInput    204
#define AT_NONE        255

#define UInState_Discard            0x00
#define UInState_Result             0x10
#define UInState_Result_SecondChar  0x11
#define UInState_ResponseIdentifier 0x20
#define UInState_Response           0x40
#define UInState_Counter_Mask       0x0F
#define UInState_Type_Mask          0xF0
#define UInBuff_SIZE                  80

bit Ln2ndChar, NLCRareData;
char UInState, UInBuffPos, UInPrevChr, QoutCounter, UInCapCounter;
unsigned UInId;
volatile char UInBuff[UInBuff_SIZE], SMSSender;
volatile char resp[2], respLDI[2];
volatile unsigned CallTmr, AlertTmr, FlushTmr;
char USSDDCS;
volatile char Recip;

void SetResponse(char r, char ldi) {
  resp[1] = resp[0];
  resp[0] = r;
  respLDI[1] = respLDI[0];
  respLDI[0] = ldi;
}

char TranslateUInChar(char c) {
  if ('I' == c) return 0x1;
  if ('R' == c) return 0x2;
  if ('M' == c) return 0x3;
  if ('P' == c) return 0x4;
  if ('N' == c) return 0x5;
  if ('U' == c) return 0x6;
  if ('T' == c) return 0x7;
  if ('S' == c) return 0x8;
  if ('G' == c) return 0x9;
  //if ('' == c) return 0xa;
  if ('B' == c) return 0xb;
  if ('C' == c) return 0xc;
  if ('D' == c) return 0xd;
  if ('E' == c) return 0xe;
  if ('F' == c) return 0xf;
  return 0;
}

void Add2UInBuff(char d) {
  if (!d) UInCapCounter = 0;
  if (UInCapCounter >= UInBuff_SIZE) return;
  UInBuff[UInBuffPos] = d;
  UInBuffPos++;
  UInCapCounter++;
  if (UInBuff_SIZE == UInBuffPos) UInBuffPos = 0;
}

void interrupt() {
  char d, c;
  if (RBIF_bit) {
    RBIF_bit = 0b0;
  }
  if (RCIF_bit) {
    if (OERR_bit) {
      CREN_bit = 0b0;
      asm NOP;
      CREN_bit = 0b1;
      if (!CREN_bit) CREN_bit = 0b1;
      if (!SPEN_bit) RCSTA = 0b10010000;
    } else if (FERR_bit) {
      d = RCREG;
      if (!CREN_bit) CREN_bit = 0b1;
      if (!SPEN_bit) RCSTA = 0b10010000;
    } else {
      d = RCREG; 
      if ((13 == d) || (10 == d)) {
        c = 0;
        if ((Ln2ndChar) && (NLCRareData)) {  
          if ('0' == UInPrevChr) c = AT_OK;
          else if ('2' == UInPrevChr) c = AT_RING;
          else if ('4' == UInPrevChr) c = AT_ERROR;
          else if ((UInPrevChr > '0') && (UInPrevChr <= '9')) c = AT_OtherRes; 
          if (c) NLCRareData = 0b0;
        }
        if (NLCRareData)
          Add2UInBuff(d);
        else {
          if ((13 == UInPrevChr) || (10 == UInPrevChr)) return;
          if (UInState_Response == UInState) {
            UInState = UInState_Result;
            if (0xc415 == UInId) SetResponse(AT_CPIN, UInBuffPos);
            if (0xc2e9 == UInId) SetResponse(AT_CREG, UInBuffPos);
            if (0xd73f == UInId) SetResponse(AT_DTMF, UInBuffPos);
            if (0xc371 == UInId) SetResponse(AT_CMTI, UInBuffPos);
            if (0xc392 == UInId) {
              SetResponse(AT_CMGR, UInBuffPos);
              if (SMSSender < 10) Recip = SMSSender;
              UInState = UInState_Response;
              UInId = 1;
              NLCRareData = 0b1;
              Add2UInBuff(0);
            }
            if (1 == UInId) SetResponse(AT_CMGR_TXT, UInBuffPos);
            if (0xc4bf == UInId) SetResponse(AT_CPBF, UInBuffPos);
            if (0xc68d == UInId) SetResponse(AT_CUSD, UInBuffPos);
          } else
            UInState = UInState_Result;
          if (c) SetResponse(c, 0);
        }
      } else if (UInState_Discard != UInState) {
        if (UInState_Result == UInState) {
          if ('O' == d) UInState = UInState_Result_SecondChar;
          else if ('0' == d) SetResponse(AT_OK, 0);
          else if ('2' == d) SetResponse(AT_RING, 0);
          else if ('4' == d) SetResponse(AT_ERROR, 0);
          else if ((d > '0') && (d <= '9')) SetResponse(AT_OtherRes, 0);
          else if ('+' == d) { UInState = UInState_ResponseIdentifier; UInId = 0; } 
          else if ('>' == d) SetResponse(AT_TxtInput, 0);
          else UInState = UInState_Discard;
        } else if (UInState_Result_SecondChar == UInState) {
          if ('K' == d) SetResponse(AT_OK, 0); else UInState = UInState_Discard;
        } else if (UInState_ResponseIdentifier == (UInState & UInState_Type_Mask)) {
          c = UInState & UInState_Counter_Mask;
          if ((':' == UInPrevChr) && (' ' == d)) {
            QoutCounter = 0;
            SMSSender = 255;
            USSDDCS = 0;
            UInState = UInState_Response;
            Add2UInBuff(0);
          } else if ((':' != d) && (c < 4)) {
            UInState++;
            d = TranslateUInChar(d);
            UInId = (UInId << 4) + d;
            if (!d) UInState = UInState_Discard;
          } else if (':' != d)
            UInState = UInState_Discard;
        } else if (UInState_Response == UInState) {
          Add2UInBuff(d);
          if (('U' == d) && (5 == QoutCounter) && ('"' == UInPrevChr)) SMSSender = 254;
          if ((2 == QoutCounter) && (0xc68d == UInId) && (d >= '0') && (d <= '9')) USSDDCS = USSDDCS * 10 + (d - '0');
          if ('"' == d) {
            QoutCounter++;
            if ((6 == QoutCounter) && (254 == SMSSender)) SMSSender = UInPrevChr - '0';
            if (UInId != 1) NLCRareData = !NLCRareData;
          }
        }
      }
      Ln2ndChar = (((10 == UInPrevChr) || (13 == UInPrevChr)) && (10 != d) && (13 != d));
      UInPrevChr = d;
    }
  }
  if (TMR1IF_bit) { // every 0.1048576 second
    CallTmr++;
    AlertTmr++;
    TMR1IF_bit = 0b0;
  }
  if (TMR2IF_bit) { // every 0.0131072 second
    FlushTmr++;
    TMR2IF_bit = 0b0;
  }
}

void main() {
  bit u;
  char k, j, o, b, l, m, n;
  // setup PIC
  PORTA = 0;               // all pins low
  PORTB = 0;               // all pins low
  PORTC = 0;               // all pins low
  PORTE = 0;               // all pins low
  OPTION_REG = 0b11011111; // internal TMR0, max prescaler to WDT (~2.2 sec WDT reset period)
  ANSEL = 0;               // all pins digital
  ANSELH = 0;              // all pins digital
  TRISA = 0;               // all outputs, unused
  TRISB = 0b00110000;      // two lines input, others output
  TRISC = 0b10000001;      // RX input, others output
  TRISE = 0;               // all outputs, unused
  IOCB = 0b00110000;       // enable input lines interrupt on change
  BRG16_bit = 0b1;         // 16-bit baud rate generator  
  SPBRGH = 0x04;           // 1200 bps
  SPBRG = 0x11;            // 1200 bps
  TXSTA = 0b00100000;      // enable TX
  RCSTA = 0b10010000;      // enable serial port and reception
  T1CON = 0b00110000;      // 1:8 prescaler
  T2CON = 0b01111010;      // 16 for both scalers
  PIE1 = 0b00100011;       // enable UART recieve and timer1 and timer2 interrupts
  INTCON = 0b01000000;     // enable PortB pin change and peripheral interrupts
  // initializing
  resp[0] = AT_NONE;
  UInState = UInState_Result;
  UInBuffPos = 0;
  Ln2ndChar = 0b0;
  NLCRareData = 0b0;
  Recip = 0;
  GIE_bit = 0b1; 
  // main loop
  while (1) {
    // processing received serial data
    ...
    // serial errors check
    if (OERR_bit) {
      CREN_bit = 0b0;
      asm NOP;
      CREN_bit = 0b1;
    }
    if (FERR_bit) j = RCREG;
    if (!CREN_bit) CREN_bit = 0b1;
    if (!SPEN_bit) RCSTA = 0b10010000;
    // watchdog reset
    asm CLRWDT;
  }
}
    
pregunta Vahid

1 respuesta

1

Gracias al comentario de Bruce Abbott, encontré el problema, le dije que escribiera la respuesta, pero no lo hizo, así que lo hice yo mismo. Al usar arreglos en PIC, el compilador usa los registros INDF y FSR para acceder al elemento del arreglo. y si la matriz está almacenada en los bancos 3 o 4, el bit IRP debe establecerse antes de acceder a ella (lo que el compilador MikroC no tiene para sí mismo y debe hacerse en el código). Todo lo que hice fue organizar pequeños arreglos en los dos primeros bancos usando la palabra clave absolute y organizando mi gran conjunto en el tercer banco y configurando el bit IRP antes de acceder a mi arreglo y borrar el bit IRP después de eso.

    
respondido por el Vahid

Lea otras preguntas en las etiquetas