Hi everyone,
I'm new to the forums and I look for help on a problem with a software UART implementation.
I'm using an MSP430F4270 and I modified TI's software UART examples to have a voltage INVERTED software UART.
Here are the interesting pieces of code:
void sendRequestSetup(void)
{
sent = 0;
UART_TXconfig();
_bis_SR_register(GIE);
UARTsendChar('?');
UARTsendChar(0x0D);
}
void receiveDataSetup(void)
{
received = 0;
iM = 0; //reset buffer tail pointer
UART_RXconfig();
_bis_SR_register(GIE);
}
void setup(void)
{
WDTCTL = WDTPW + WDTHOLD; //stop watchdog
FLL_CTL0 |= XCAP14PF; //set crystal load capacitance
}
void portConfig(void)
{
P1SEL = UART_TXD + UART_RXD; //timer function for TX/RX pins
P1DIR = UART_TXD; //pins configured as output
}
void clearTimerA(void)
{
TACTL = 0;
TACCTL0 = 0;
}
void UART_TXconfig(void)
{
TACTL = TASSEL_2 + MC_2;
TACCTL0 = 0;
TACCTL0 |= CCIE;
}
void UART_RXconfig(void)
{
rxBitCounter = 8; //number of bits to receive
rxBuffer = 0;
TACCTL0 = SCS + CM_1 + CCIS_1 + OUTMOD0 + CAP + CCIE;// capture positive edge (Inverted UART!), default output mode LOW (Inverted UART!)
TACTL = TASSEL_2 + MC_2; //clock SMCLK, start in continuous mode up
}
void UARTsendChar(unsigned char byte)
{
while(TACCTL0 & CCIE); //wait while interrupt flag is enabled - last character sent?
TACCR0 = TAR; //start from current counter value
TACCR0 += UART_TBIT;
TACCTL0 = OUTMOD_5; //output LOW for start (Inverted UART!)
TACCTL0 |= CCIE; //interrupt enabled
txBuffer = ~byte; //byte values are negated (Inverted UART!)
txBuffer &= 0x0FF; //after MSB is all zeros - stop bits are 2 zeros (Inverted UART!)
txBuffer <<= 1; //add room for start bit
txBuffer += 0x01; //start bit is 1 (data will move from LSB to MSB) (Inverted UART!)
lastByte = byte & 0x7F; //save copy
while(TACCTL0 & CCIE); //only move to the next when the previous was sent
}
#pragma vector = TIMERA0_VECTOR
__interrupt void timer_A0_ISR(void)
{
static unsigned char txBitCounter = 11;
TACCR0 += UART_TBIT; //timer offset for next bit
//RX
if(TACCTL0 & CCIS0){ //ready to receive or transmit?
P1OUT |= TEST_POINT2;
if(TACCTL0 & CAP){ //capture mode for start bit edge
TACCTL0 &= ~CAP;
TACCTL0 &= ~OUTMOD0;
TACCR0 += UART_HALF_TBIT;
}else{
rxBuffer >>= 1; //advance buffer for next bit
if(TACCTL0 & SCCI) //get bit waiting in receive latch
rxBuffer |= 0x80;
rxBitCounter--;
if(rxBitCounter == 0){ //all bits received?
rxBuffer = ~rxBuffer; //negate the outcome (Inverted UART!)
mBuffer[iM++] = rxBuffer; //save character
if(((rxBuffer & 0x7F) == 0x0D) | (iM >= M_BUFFER_SIZE)){//all characters received? - check for last character <CR> or buffer overflow
TACCTL0 = 0;
received = 1;
_bic_SR_register_on_exit(GIE); //disable global interrupts
}else{
rxBitCounter = 8; //number of bits to receive
rxBuffer = 0;
TACCTL0 |= CAP; //get ready to receive another character
}
}
}
P1OUT &= ~TEST_POINT2;
}else{//TX
P5OUT |= TEST_POINT;
if(txBitCounter == 0){ //something to transmit?
TACCTL0 &= ~CCIE; //disable interrupt
txBitCounter = 11; //re-load bit counter
if(lastByte == 0x0D){ //check for last character <CR>
sent = 1;
}
}else{
if(txBuffer & 0x01) {
TACCTL0 = OUTMOD_7; //to make the transition between modes without producing a glitch that changes to OUTMOD_0!!!
TACCTL0 &= ~OUTMOD_5; //output LOW (Inverted UART!)
}else{
TACCTL0 = OUTMOD_7;
TACCTL0 &= ~OUTMOD_1; //output HIGH (Inverted UART!)
}
TACCTL0 |= CCIE;
txBuffer >>= 1;
txBitCounter--;
}
P5OUT &= ~TEST_POINT;
}
}
My problem is more exactly in the fact that I only get the capture working with these settings (from function UART_RXconfig):
TACCTL0 = SCS + CM_1 + CCIS_1 + OUTMOD0 + CAP + CCIE;
which makes OUTMODx=001 -> which is mode SET, and produces a HIGH state when the TX pin is idle (TX needs to idle in LOW state since it's an voltage inverted UART).
My question is then, is there a dependence between the CAPTURE mode and the OUTPUT settings on TIMER_A?
Looking at the block diagram of the capture/compare blocks in the datasheet I don't seem to find one...
Thanks,
David