Derzeit arbeite ich mit zwei MSP430G2553-Mikrocontrollern für ein Schulprojekt und muss UART verwenden, damit sie miteinander kommunizieren. Der Sende-MSP430 soll immer dann ein Zeichen senden, wenn ein Benutzer ein Passwort richtig eingibt, um einen Eingang zu öffnen. Die Tür wird durch einen Servomotor auf dem empfangenden MSP430 simuliert. Mein aktueller Code funktionierte sehr gut, aber das Servo öffnete und schloss sich weiter; Die einzige Möglichkeit, dies zu stoppen, bestand darin, den MSP430 zu trennen oder auszuschalten. Als ich das 'UCA0RXBUF'-Register überprüfte, stellten wir fest, dass das Zeichen im Register verblieb und nicht klar war. Wir haben vergeblich versucht, eine Null zu drücken, um das Register zu löschen. Mein Code enthält eine Reihe von .c-Dateien, um die Initialisierung des UART einfacher zu machen. Anbei ist mein aktueller Code und vielleicht können Sie auf einen Fehler oder Syntaxfehler hinweisen,
#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;//
}
Das Hauptproblem besteht wahrscheinlich darin, dass Sie nicht warten, bis ein neues Zeichen empfangen wird, bevor Sie das UCA0RXBUF
Register lesen. Sofern Sie keinen Interrupt-basierten Ansatz verwenden, sollten Sie eine Busy-Schleife wie folgt ausführen:
while(!(UC0IFG & UCA0RXIFG)); /* wait for UCA0RXIFG to become set */
received = UCA0RXBUF; /* read the received character */
Sie zeigen hier nicht den sendeseitigen Code, aber die Idee dort ist dieselbe - schreiben Sie in das TXBUF
Register und warten Sie dann, bis das Byte übertragen wird. Oder verwenden Sie Interrupts, um einen wirklich asynchronen Betrieb über den UART zu erhalten (das "A" bedeutet asynchron).
Allgemein denke ich, dass Sie hier einfach den falschen Ansatz haben. Warum nicht einen der synchronen Busse verwenden? Die MCU unterstützt SPI und I2C. Normalerweise wird bei der Zusammenarbeit zwischen zwei MCUs eines dieser Protokolle verwendet, wobei eines für den Master-Modus der MCUs und das andere in den Slave-Modus versetzt wird. Der synchrone Datenaustausch ist im Allgemeinen zuverlässiger und Sie müssen sich nicht um Dinge wie die MCU-Geschwindigkeitskalibrierung kümmern.
received = UCA0RXBUF;
in zu ändern c = UCA0RXBUF;
, weil das der Sendecode war. Es hat mein Problem behoben und ich konnte die Interrupt Service Routine verwenden, um meinen Code fertigzustellen. Vielen Dank für Ihr Feedback und ich werde mich auf jeden Fall mit SPI und I2C befassen.
Olaf
Wetterfahne
Wetterfahne
while
Schleife zu haben, die auf den Status wartet, und einedelay
Funktion innerhalb einer ISR wie your__interrupt void ADC10_ISR
are cardinal sins aufzurufen . Finden Sie besser einen anderen Weg, um den Code zu strukturieren.MarineUTEP
MarineUTEP
Nicomp
Olaf
Nicomp
Olaf
MarineUTEP
MarineUTEP
Nicomp