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;//
}
El problema principal es probablemente el hecho de que no espera a que se reciba un nuevo carácter antes de leer el UCA0RXBUF
registro. 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 TXBUF
registrarse 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.
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.
Olaf
Veleta
Veleta
while
ciclo esperando el estado y llamar a unadelay
función desde dentro de un ISR como el suyo__interrupt void ADC10_ISR
son pecados capitales . Mejor encontrar otra forma de estructurar el código.MarinaUTEP
MarinaUTEP
nicomp
Olaf
nicomp
Olaf
MarinaUTEP
MarinaUTEP
nicomp