This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Sending Signed Int (int16_t) via UART

Other Parts Discussed in Thread: MSP430FR5739

Hi I'm having a problem when trying to divide the int16_t into two (MSB,LSB) uint8_t numbers for transmission. It seems to occur for small negative numbers, -3, -2, -1 but recently it seems maybe only for -1. Code:

volatile int16_t countProcess = 0;
volatile uint8_t txByte = 0;
volatile uint8_t escByte = 0;

// When countProcess == 0xFF, (countProcess & 0xFF00) == 0xFF00 evaluates to 0 not 1 as (I) expected
void sendCounts(void)
{	
        // Start byte
	while((UCA1IFG & UCTXIFG) == 0);	// Wait for TX buffer to clear
	UCA1TXBUF = 0xFF;			// Start Btye
	// MSB countProcess
	if ((countProcess & 0xFF00) == 0xFF00){
		txByte = 0;
		escByte |= BIT2;                // Set MSB overflow bit
	}
	else
		txByte = ((countProcess & 0xFF00)>>8); // Load MSB of net count
	while((UCA1IFG & UCTXIFG) == 0);	// Wait for TX buffer to clear
	UCA1TXBUF = txByte;			// Send MSbyte of net count
	// LSB countProcess
	txByte = (countProcess & 0xFF);		// Load LSB of net count
        ...
}

//A different technique: when countProcess == 255, txByte = (countProcess >> 8) yields txByte = 0 not 255 as (I) expected
void sendCounts(void)
{	
        // Start byte
	while((UCA1IFG & UCTXIFG) == 0);	// Wait for TX buffer to clear
	UCA1TXBUF = 0xFF;			// Start Btye
	// MSB countProcess
	txByte = (countProcess >> 8);		// Load MSB of net count
	if (txByte == 255){
		//txByte =0;
		escByte |= BIT2;                // Set MSB overflow bit
	}
	while((UCA1IFG & UCTXIFG) == 0);	// Wait for TX buffer to clear
	UCA1TXBUF = txByte;			// Send MSbyte of net count
	// LSB countProcess
	txByte = (countProcess & 0xFF);		// Load LSB of net count
        ...
}

I'm hoping someone knows more about how signed to unsigned conversions are handled and maybe can point out what I'm missing. The chip is a MSP430FR5739.

Thanks,
Martin

  • >I'm hoping someone knows more about how signed to unsigned conversions are handled

    Using typecasting.

  • You haven't told us what the problem is. What value do you expect to see, and what do you actually get?
  • use char-struct shared with a int trick
    as a union overlap everything together so the same memory can be referenced with different names and type
    You need to use same little-endian union on the receiving side as splitting up signed int's things can go wrong easily.

    union ProcessTag {
      int count;
      struct{
        char count_low;
        char count_high;
       };
     }Process;
    int main(void){
    Process.count = -1; 
    UCA1TXBUF = Process.count_low; 
    UCA1TXBUF = Process.count_high;

    Best part, as soon you type the . the compiler gives you the 3 options from union.
    struct is anonymous but you could name it byte; for Process.byte.count_high;
    Could also make a generic two-chars-to-a-int typedef union, if code needs to do this on a few int's.

  • Yes, sorry, I should have mentioned that in one instance I tried something like this: (((uint16_t)countProcess & 0xFF00)>>8) and saw no change in the result. In the end what worked for me was in effect typecasting, but with a sledge hammer: by assigning the int16_t value to a uint16_t local variable and then dividing that into uint8_t chunks.

    uint16_t UcountProcess = countProcess;

    thanks for the suggestion.
  • Thanks for the tip! I'll give that a try. For now I got it working just by assigning the int16_t value to a local uint16_t variable and then dividing that into two uint8_t chunks: uint16_t UcountsProcess = countsProcess;

    In effect typecasting, but I'm not totally sure why masking, bit shifting and then assigning to a uint8_t doesn't do the same, but anyways it works now!
  • Next time I'll mention that the problem/expectation is embedded in the code comments. Wasn't very clear.
  • In IAR I don't see the need to do anything at all, It knows what you're going for.

    volatile int countProcess =-1;
    
    UCA0TXBUF = countProcess;
    UCA0TXBUF = countProcess>>8;
    
    IAR (optimize: high) compiles in to:
     mov.w   &countProcess,R14   ; get signed int
     mov.b   R14,&UCA0TXBUF      ; little-endian lower byte
     mov.w   &countProcess,R14   ; get signed int
     swpb    R14                 ; swap bytes, very efficient shift by 8
     mov.b   R14,&UCA0TXBUF      ; little-endian higher byte
    


    Try txByte = (char)((unsigned int)countProcess>>8);
    as right shifting signed int's it will use rra.w to keep msbit trailing with the result.
    As it thinks you are doing math (like /256) on what could be a negative number,
    but you don't want that, you want bitwise mask operation.

    On unsigned int's it will: clrc, rrc.w to shift in a zero bit.
    though should not matter when you use (char) on final result as that is same as AND 0x00FF

**Attention** This is a public forum