problema de UART al recibir un char

1

Actualmente estoy trabajando con dos microcontroladores MSP430G2553 para un proyecto escolar y tengo que usar UART para que se comuniquen entre sí. El MSP430 de transmisión 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 MSP430 receptor. Mi código actual estaba funcionando 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 verifiqué el registro 'UCA0RXBUF', notamos que el personaje permanecería en el registro y no estaba claro. 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 de UART. adjunto está mi código actual y tal vez pueda señalar un error, o un error de sintaxis, que pueda haber omitido.

#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;//

}
    
pregunta MarineUTEP

1 respuesta

1

El problema principal es probablemente el hecho de que no espere a que se reciba un nuevo carácter antes de leer el registro UCA0RXBUF . A menos que esté utilizando un enfoque basado en interrupciones, debe realizar un ciclo como este:

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

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

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

    
respondido por el kfx

Lea otras preguntas en las etiquetas