Problema de UART al recibir un char

Actualmente estoy trabajando con dos microcontroladores MSP430G2553 para un proyecto escolar y tengo que usar UART para que se comuniquen entre sí. El transmisor MSP430 es enviar un carácter cada vez que un usuario ingresa una contraseña correctamente para abrir una entrada. La puerta está siendo simulada por un servomotor en el receptor MSP430. Mi código actual funcionaba muy bien pero el servo seguía abriéndose y cerrándose; la única forma de detener esto era desconectar o apagar el MSP430. Cuando revisé el registro 'UCA0RXBUF', notamos que el carácter permanecería en el registro y no se borraría. Intentamos presionar un cero para borrar el registro sin éxito. Mi código tiene una serie de archivos .c para facilitar el uso de la inicialización del UART. adjunto está mi código actual y tal vez pueda señalar un error o un error de sintaxis,

#include <msp430g2553.h>
#include <string.h>
#include "uartMsp.h"
#include "adcMsp.h"

void door(void);
void delay(void);
void buzzer(void);
void door2(void);
void door3(void);


volatile int i, x;
char received = 0;
unsigned int mode = 1;

void main(void){
//Setup
WDTCTL = WDTPW + WDTHOLD;// Stop Watchdog Timer

//Setup Timer A0.1 and Port 1.6
P1DIR |= BIT6;//Output for SERVO PWM
P2DIR |= BIT7;//Button to shut off buzzer
P1SEL |= BIT1 + BIT6;
P1SEL2 &= ~(BIT6);//??
TA0CTL = TASSEL_2;//Setup Timer
TA0CCTL1 = OUTMOD_6;
TA0CCR0 = 20000;

//Setup DCO
DCOCTL  = CALDCO_1MHZ;    //DCO at 1MHz
BCSCTL1 = CALBC1_1MHZ;    //DCO at 1MHz

//Setup ADC
ADC10CTL0    = ADC10ON + ADC10IE;             //Turn on ADC and Enable interrupts.
ADC10CTL1    = INCH_5;              //Pick an input to sample from (Any Port 1 Pin EXCEPT P1.0 or P1.6; those belong to the LEDs)
ADC10AE0     = BIT5;                //Set your pin to analog. Hint: BITx = P1.x

__delay_cycles(500000);

clock_init();                // Set clock frequency to 1 MHz
serial_init_inter();     // Initialize UART module
_enable_interrupts(); //Enable General Interrupts. Best to do this last.

while(1) {
    received = UCA0RXBUF;
    UCA0RXBUF = 0;
    if(received == 'o'){
        received = 0;
        door();

    }
    else if(received == 'b'){
        received = 0;
        buzzer();
    }
    else if(received == 'u'){
        received = 0;
        door2();

    }
    else if(received == 'e'){
        received = 0;
        door3();

    }
    ADC10CTL0 |= ENC + ADC10SC;
}//create an infinite loop that does nothing (or goes into low power mode)
}//End of main

// ADC10 Interrupt Service Routine
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR( void ) {
x = ADC10MEM;
if((x > 700) || (x < 300)){
    P1OUT |= BIT7;
    while((P1IN & BIT4) != BIT4){}
    delay();
    delay();
    P1OUT &= ~BIT7;
}
}//End of ADC10_ISR

//Door function
void door(void){
TA0CCR1 = 1500;
TA0CTL |= MC_1;//Setup Timer
delay();
TA0CCR1 = 750;
delay();
TA0CTL |= MC_0;//
}//End of door

void delay(void){
volatile unsigned j, k;
for(j=4;j>0;j--){
    for(k=20000;k>0;k--);
}
}

void buzzer(void){
P2OUT |= BIT5;
delay();
P2OUT &= ~BIT5;
}

void door2(void){
TA0CCR1 = 1500;
TA0CTL |= MC_1;//Setup Timer
}

void door3(void){
delay();
TA0CCR1 = 750;
delay();
TA0CTL |= MC_0;//

}
Utilice siempre nombres que se expliquen por sí mismos para las variables globales. Y esto no es un servicio de depuración o revisión. Consulte Cómo preguntar y proporcionar un [mcve].
Parece que está leyendo el búfer de datos de entrada de UART sin verificar su estado rx e ignorando que tiene una rutina de interrupción en serie. El registro de entrada de datos no se borra al escribirlo: leerlo en un UART típico borra el indicador de datos rx. Luego, no vuelve a leer el registro de datos hasta que el indicador de datos rx se lo indique.
Y mientras lo pienso, tener un whileciclo esperando el estado y llamar a una delayfunción desde dentro de un ISR como el suyo __interrupt void ADC10_ISRson pecados capitales . Mejor encontrar otra forma de estructurar el código.
@WeatherVane Gracias por su aporte. Por lo tanto, el código actual no funcionaría correctamente dado que el rx no se extrae ni lee. Siento que usar el pragma ISR respectivo simplificaría el problema. ¿Estoy en lo correcto en esta suposición? también gracias por informarme de mi violación actual de la estructura. Estructuraré el código de manera más eficiente.
@Olaf Pido disculpas si esto es un inconveniente para usted. No estaba buscando a alguien que depurara mi código por mí, sino que me diera información que fuera pertinente para aprender sobre programación, para que pueda ser más eficiente en ello.
@olaf si esto no es un servicio de depuración, ¿qué demonios es?
@nicomp: lea las preguntas frecuentes, consulte Cómo preguntar . Este es un sitio de preguntas y respuestas.
@Olaf, y preguntó una Q que necesita una A. QED.
@nicomp: Olvidó verificar las restricciones. Con tu argumentación, preguntar cómo hacer un Trifle también sería perfectamente válido.
@Olaf Es una pregunta sobre UART.
@nicom Obviamente tenía una pregunta. Gracias por las pautas. No es que no los haya leído antes. Esta no es mi primera pregunta.
@MarineUTEP Copia eso. Sigue preguntando e ignora la negatividad.

Respuestas (1)

El problema principal es probablemente el hecho de que no espera a que se reciba un nuevo carácter antes de leer el UCA0RXBUFregistro. A menos que esté utilizando un enfoque basado en interrupciones, debería estar ocupado en un bucle como este:

while(!(UC0IFG & UCA0RXIFG)); /* wait for UCA0RXIFG to become set */
received = UCA0RXBUF;  /* read the received character */

Aquí no muestra el código del lado de transmisión, pero la idea es la misma: escriba para TXBUFregistrarse y luego espere hasta que se transmita el byte. O use interrupciones para obtener una operación verdaderamente asíncrona sobre el UART (la "A" significa asíncrono).

En términos más generales, creo que aquí tienes el enfoque equivocado. ¿ Por qué no usar uno de los buses síncronos ? La MCU es compatible con SPI e I2C. Normalmente cuando se interopera entre dos MCU se utiliza uno de estos protocolos, poniendo uno para el modo maestro de las MCU y el otro en modo esclavo. El intercambio de datos síncrono es generalmente más confiable y no tiene que preocuparse por cosas como la calibración de velocidad de MCU.

Todavía no hemos cubierto SPI e I2C en clase, pero definitivamente investigaré e investigaré un poco. Además, he descubierto lo que estaba haciendo mal. No estaba usando la misma configuración en el código de transmisión. Todo lo que tenía que hacer era cambiar la variable received = UCA0RXBUF;a c = UCA0RXBUF;porque eso es lo que estaba en el código de transmisión. Solucionó mi problema y pude usar Interrupt Service Routine para finalizar mi código. Muchas gracias por sus comentarios y definitivamente investigaré SPI e I2C.