Good afternoon community!
Someone already worked SoftUart? I need help. I am implementing a SoftUart at 115200Hz on a MSP430FR5994 microcontroller at 8MHz. with TXD at P4.1 and RXD at P4.2.
It already sends string but at the time of receiving it only receives 1s. I appreciate your help.
Below is my code..
// main.c -------------------------------------------
#include <msp430.h>
#include <stdint.h>
#include "uart.h"
int main(void)
{
// stop watchdog timer
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
SetClockMHz();
ConfigurePORTS();
PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on
__enable_interrupt(); // Enable Global Interrupts
uart_puts(" MSP430 SoftUart 115200\n\r");
while (1)
{
if (uart_getc(&Data)) {
uart_putc(Data);
__delay_cycles(4000000);
}
}
}
// uart.h --------------------------------------------
#ifndef __UART_H
#define __UART_H
#include <stdbool.h>
#include <stdint.h>
# define TXD BIT1 // TXD em P4.1
# define RXD BIT2 // RXD em P4.2
# define F8MHz 8000000 // CPU 8MHz
# define BAUDRATE 115200 // Taxa de transmissão
# define BIT_TIME (F8MHz/BAUDRATE) // Tempo de bits
# define HALF_BIT_TIME (BIT_TIME/2) // Tempo de meio bit
static volatile uint8_t bitCount=0; // Contagem de bits
static unsigned int TXByte; // Valor enviado por uart_putc()
static unsigned int RXByte; // Valor recebido
static bool isReceiving = false ; // Status dispositivo
static bool hasReceived = false ; // um byte é recebido
/* Initialize soft UART */
void SetClockMHz (void);
void ConfigurePORTS (void);
bool uart_getc(uint8_t *c);
void uart_putc(uint8_t c);
void uart_puts(const char *str);
#endif /* UART_H_ */
// uart.c ----------------------------------------
#include <msp430.h>
#include <stdbool.h>
#include "uart.h"
/* Initialize soft UART */
void SetClockMHz (void)
{
// Startup clock system with DCO ~8MHz
CSCTL0 = CSKEY; // Unlock CS registers
CSCTL1 = DCOFSEL_6; // Set DCO to 8MHz
CSCTL2 = SELA__VLOCLK|SELS__DCOCLK|SELM__DCOCLK;
CSCTL3 = DIVA__1|DIVS__1|DIVM__1; // Set all dividers
CSCTL0_H = 0; // Lock CS Registers
return;
}
void ConfigurePORTS(void)
{
// Configure TXD
P4DIR |= TXD; // P4.1 TX Output
// Configure RXD
P4DIR &= ~RXD; // P4.2 RX Input
P4OUT |= RXD; // Set internal pull-up resistor
P4REN |= RXD; // Enable internal Pull-Up Resistors
P4IES |= RXD; // High-to-low transition
P4IFG &= ~RXD; // Clear Interrupt Flag
P4IE |= RXD; // Interrupt Enable
return;
}
/* Read one character from UART non-blocking.*/
bool uart_getc(uint8_t *c)
{
if (!hasReceived) { return false; }
*c = RXByte;
hasReceived = false;
return true;
}
/* Write one chracter to the UART blocking */
void uart_putc(uint8_t c)
{
TXByte = c;
while(isReceiving); // Wait for RX completion
bitCount = 0xA; // Load Bit counter, Start + 8 bits + Stop
TXByte |= 0x100; // Add STOP bit to TXByte
TXByte = TXByte << 1; // Add START bit 0
TA0CTL = TASSEL__SMCLK + MC__CONTINOUS; // SMCLK/1 + Continuous Mode
TA0CCR0 = TA0R; // Get current timer count
TA0CCR0 += BIT_TIME; // Add Offset to TA0CCR0
TA0CCTL0 = CCIS_0 + OUTMOD_0 + CCIE + OUT; // Set signal, Enable Interrupts
while (TA0CCTL0 & CCIE); // Wait for previous TX completion
return;
}
/* Write string to the UART blocking. */
void uart_puts(const char *str) {
if(*str != 0) uart_putc(*str++);
while(*str != 0) uart_putc(*str++);
return;
}
/* ISR for PORT4 */
#pragma vector = PORT4_VECTOR
__interrupt void PORT4_ISR(void)
{
isReceiving = true;
P4IE &= ~RXD; // Disable Interrupt P4.2
P4IFG &= ~RXD; // Clear Interrupt Flag P4.2
TA0CTL = TASSEL__SMCLK + MC__CONTINOUS; // SMCLK + Continuous Mode
TA0CCR0 = TA0R; // Initialize TA0CCR0
TA0CCR0 += HALF_BIT_TIME; // Add Offset to TA0CCR0
TA0CCTL0 = OUTMOD_1 + CCIE; // Disable TX and enable interrupt Timer
RXByte = 0x00; // Initialize RXByte
bitCount = 0x9; // Load bitCounter, 8 bits + 1 start
}
/* CCR0 ISR for TXD and RXD */
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer0_A0_ISR (void)
{
TA0CCR0 += BIT_TIME; // Add Offset to TA0CCR0
if(!isReceiving) { // Transmiting
if ( bitCount == 0) { // Finish?
TA0CTL = TASSEL__SMCLK; // TASSEL_SMCLK, timer off
TA0CCTL0 &= ~CCIE; // Disable interrupt Timer
}
else {
if (TXByte & 0x01) { P4OUT |= TXD; } // P4.1 = 1
else { P4OUT &= ~TXD; } // P4.1 = 0
TXByte >>= 1;
bitCount --;
}
}
else { // Receiving
if ( bitCount == 0) { // Finish?
TA0CTL = TASSEL__SMCLK; // SMCLK, timer off
TA0CCTL0 &= ~CCIE ; // Disable Interrupt Timer
P4IE |= RXD; // Interrupt Enable P4.2
isReceiving = false;
if ((RXByte & 0x201) == 0x200) { // Validate the start and stop bit
RXByte >>= 1; // Remove start bit
RXByte &= 0xFF; // Remove stop bit
hasReceived = true;
}
}
else {
if (P4IN & RXD) { RXByte |= 0x400; } // If bit is set?
RXByte >>= 1; // Shift the bits down
bitCount --;
}
}
}