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.

MSP430G2553: Using ADC10 DTC to send result via UART

Other Parts Discussed in Thread: MSP430G2553

I'm having some trouble figuring out if the following is even possible. The MSP430G2553 has the ADC10 peripheral with Data Transfer Controller (DTC). I'd like to use the DTC to copy the ADC10MEM directly to the USCI's Transmit Buffer (UCA0TXBUF) so it will be sent via UART. The idea is to sample as quickly as possible. I thought that one could possibly achieve a reasonable data rate by using the DTC to copy data directly to the UART, with carefully tuned baud rates and sample rates.
The UCA0TXBUF is an 8-bit register at address 0x0067, whereas ADC10MEM is a 16-bit register. Will the DTC even transfer data to an 8-bit register? I don't mind the register at 0x0068 to be overwritten as well. Unfortunately, I didn't find any discussion about valid DTC destinations in the Family User's Guide.

I attach my basic example code below. For ease of debugging, just one sample is captured and then the MCU enters an infinite loop. Unfortunately, I currently can't hook an oscilloscope to the UART pins. I'm using the MSP430G2553 on a Launchpad Rev 1.5.
- UART works, when the MCU starts, it will send an 'a'. I receive the 'a'.
- The ADC works, as ADC10MEM is copied to adcResult for debug purposes
- The DTC works when I point it to a variable in RAM (e.g. adcResult)

I expect to receive an 'a' and then some 8-bit value afterwards. However, I just receive the 'a' and then nothing happens.

I'm using the latest TI Compiler with CCSv6. The disassembly shows that the compiler generates the correct code:
106       ADC10SA = (unsigned short) &UCA0TXBUF;
c1b0:   40B2 0067 01BC      MOV.W   #0x0067,&ADC10_ADC10SA

So, my question is: Am I doing something wrong or will the ADC10's DTC not write to 8-bit registers?

#include <msp430.h> 
#include <inttypes.h>

/*
 * main.c
 */
// MCU: msp430g2553
 
volatile uint16_t adcResult = 0;

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer

    init_clock();
    init_uart();
    UCA0TXBUF = 'a';		// test if uart works
    while(UCA0STAT & UCBUSY);
    init_adc();
    for(;;) {
    	while(ADC10CTL1 & ADC10BUSY);
    	adcResult = ADC10MEM;		// copy result into memory for debug purposes
    	for(;;);	// stop here
    }
	return 0;
}


void init_clock(void) {
	DCOCTL = 0;
	DCOCTL = CALDCO_16MHZ;
	BCSCTL1 = CALBC1_16MHZ;
}

void init_uart(void) {
	// select UART peripheral for pins P1.1 and P1.2
    P1SEL |= BIT1 | BIT2;
    P1SEL2 |= BIT1 | BIT2;

    // init uart clock
    UCA0CTL1 |= UCSSEL_2;
    // 9600/8/N/1
    // ucbrx = 1666, ucbrs = 6   -> uca0br0 = 130   uca0br1 = 6
	UCA0BR0 = 130;
	UCA0BR1 = 6;

	UCA0MCTL = UCBRS_6;

	UCA0CTL0 = 0;

	// enable UART
	UCA0CTL1 &= ~UCSWRST;
}

void init_adc(void) {
	ADC10CTL1 = INCH_5 | ADC10DIV_7 | ADC10SSEL_2;
	ADC10AE0 = BIT5;
	ADC10CTL0 = ADC10ON;

	// configure DTC
	ADC10DTC0 = ADC10CT;
	ADC10DTC1 = 1;
	ADC10SA = (unsigned short) &UCA0TXBUF;

	// start conversion
	ADC10CTL0 |= ENC | ADC10SC;
}

  • This is a great hack (if it works). My reading is the same as yours -- and 22.2.7.1 does say "anywhere". Unfortunately, my spare G2 Launchpad seems to be dead, so I can't try it.

    One suggestion: Jumper the UART TX/RX lines together to make it loop back. That will eliminate variables such as bit rate mismatch and Host-program intolerance of non-ASCII. It will also let you see whether anything (even if mangled) came in by looking at RXIFG.

  • I had access to my oscilloscope and measured a bit.

    I inserted some code that sets a pin before the ADC is initialized, and unsets the pin when the ADC10BUSY flag of ADC10CTL1 is cleared.

    I expect to see the initial UART transmission ('a'), then the pin will be set high, then the pin will be set low and another UART transmission will occur. This second UART transmission will be initiated by the ADC10's DTC that copies ADC10MEM to UCA0TXBUF.

    As you can see from the pictures (UART TX=Channel 1, yellow; Pin = Channel 2, blue), there is no second UART transmission. Just nothing happens.

    The pin is held high for roghly 12us, which translates to about 192 clock cycles at 16 MHz. The ADC initialization does not take that long, so I'm absolutely sure that a conversion is actually taking place, which should trigger the DTC.

  • Another shot in the dark: Try targeting 0x66 (UCA0RXBUF) rather than 0x67. If you succeed, that will suggest that you're dealing with a word-alignment thing. (Writing RXBUF should of course be harmless.)

    Unfortunately, if you succeed you will also be demonstrating that you can only send the high byte this way, which is probably less useful than the low byte. But at least you (and we) will know.
  • Unfortunately, this doesn't change anything. It still doesn't work.
  • I was wondering whether there was some unwritten rule, but I looked again and I'm afraid it is written:

    SLAU144J sec 22.3.9 (ADC10SA) says that the DTC address low bit is always 0, i.e. always word aligned (I forgot about this). Sec 1.4.3 says "If word data is written to a byte module [below 0xFF] only the low byte is written into the peripheral register, ignoring the high byte".

    So it was/is always writing to 0x66 (RXBUF, i.e. no effect), but Only to 0x66, which doesn't get you to 0x67 (TXBUF).

    Maybe someone smarter will contradict me, but these two effects together seem to present a significant obstacle. Sorry.

**Attention** This is a public forum