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.
Hello,
I'm configuring UART with BR 460800 to transmit 21000 byte from FRAM and I'm having problem getting the data on PC.
There is the code:
int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer //GPIO FOR TEST P1DIR |= BIT3; // Configure Uart P2SEL1 |= BIT0 | BIT1; // USCI_A0 UART operation P2SEL0 &= ~(BIT0 | BIT1); // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; set_MCU_frequency(DCO_16MHz); // SET DCO to 16MHz uart_init(); // UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI P1OUT |= BIT3; for(i=0;i<21000;i++) { DATI[i] = i & 0x00FF; // Write some dummy data in FRAM Variable type NOINIT } // Configure DMA (UC0TXIFG trigger) P1OUT |= BIT3; DMACTL0 = DMA0TSEL__UCA0TXIFG; // UC0TXIFG trigger __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &DATI[0]); // Source single address __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &UCA0TXBUF); // Destination array address DMA0SZ = 21000; // 32 conversions DMA0CTL = DMADT_4 + DMASRCINCR_3 + DMAEN + DMAIE + DMALEVEL + DMASRCBYTE + DMADSTBYTE; // while(!(UCA0IFG & UCTXIFG)); // Wait if UART_TXD // UCA0CTLW0 &= ~UCSWRST; __bis_SR_register(CPUOFF + GIE); // LPM0, UART_ISR will force exit __no_operation(); // << SET BREAKPOINT HERE P1OUT &= ~BIT3; return 0; } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=DMA_VECTOR __interrupt void DMA0_ISR (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(DMA_VECTOR))) DMA0_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(DMAIV,16)) { case 0: break; // No interrupt case 2: // 21000 complete data transmission P1OUT |= BIT0; UCA0CTLW0 |= UCSWRST; __bic_SR_register_on_exit(CPUOFF); // exit LPM break; // DMA0IFG case 4: break; // DMA1IFG case 6: break; // DMA2IFG case 8: break; // Reserved case 10: break; // Reserved case 12: break; // Reserved case 14: break; // Reserved case 16: break; // Reserved default: break; } }
Any help is appreciated,
Regards
What kind of problems? Missing bytes, wrong bytes, nothing at all?
Does the PC’s COM port support this high baudrate? Not all do. And then, does the PC software keep up with this? Most libraries for reading the serial port are rather clumsy and not suitable for high-speed transmissions. Especially if one uses them to read byte by byte.
Hello Jens-Michael,
thanks for your reply.
The problem was on receiving data on PC. I resolve it changing the program that received the data.
Thanks.
Hello Jens-Michael,
I have another question about ADC and DMA :)
I want to get samples from 2 channels (A3 and A4) save on memory by DMA and after to transfer these data by UART.
void adc_init(){ // Configure ADC12 ADC12CTL0 = ADC12SHT0_9 | ADC12MSC | ADC12ON; // Sampling time, S&H=384, ADC12 on, multiple conversion ADC12CTL1 = ADC12SHP | ADC12SSEL_2 | ADC12CONSEQ_3 | ADC12DIV_4; // Use sampling timer, CLK/5 ADC12CTL2 = ADC12RES_0; // 8-bit conversion results ADC12MCTL0 |= ADC12INCH_4; // A4 ADC input select; Vref=AVCC // ADC12IER0 |= ADC12IE0; // Enable ADC conv complete interrupt // ADC12CTL0 |= ADC12ENC; // Enable ADC } int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1OUT &= ~BIT0; P1DIR |= BIT0; P1DIR |= BIT5; P1OUT &= ~ BIT5; // Configure Uart P2SEL1 |= BIT0 | BIT1; // USCI_A0 UART operation P2SEL0 &= ~(BIT0 | BIT1); P1DIR &= ~BIT4; P1SEL0 |= BIT4; // Configure P1.4 for ADC P1SEL1 |= BIT4; P1DIR &= ~BIT3; P1SEL0 |= BIT3; // Configure P1.3 for ADC P1SEL1 |= BIT3; // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; set_MCU_frequency(DCO_16MHz); adc_init(); uart_init(); // Configure DMA (ADC10IFG trigger) P1OUT |= BIT5; DMACTL0 = DMA0TSEL__ADC12IFG; // ADC10IFG trigger __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC12MEM0); // Source single address __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &audio[0]); // Destination array address DMA0SZ = 16000; // 32 conversions DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAEN + DMAIE + DMASRCBYTE + DMADSTBYTE; // Rpt, inc dest, word access, // enable int after 30000 conversions // while(1) { // P1OUT |= BIT3; P1OUT |= BIT5; while (ADC12CTL1 & BIT0); // Wait if ADC12 core is active ADC12CTL0 |= ADC12ENC + ADC12SC; // Start sampling __bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit __no_operation(); // << SET BREAKPOINT HERE // P1OUT &= ~ BIT3; // __delay_cycles(5000); // Delay between conversions P1OUT ^= BIT5; DMA0CTL &= ~(DMAEN + DMAIE); UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI uart_write(audio, 16000); P1OUT ^= BIT5; } } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=DMA_VECTOR __interrupt void DMA0_ISR (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(DMA_VECTOR))) DMA0_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(DMAIV,16)) { case 0: break; // No interrupt case 2: // 40690 conversions complete // P1OUT |= BIT0; ADC12CTL0 &= ~ADC12ENC; // DMA0CTL &= ~DMAEN; __bic_SR_register_on_exit(CPUOFF); // exit LPM break; // DMA0IFG case 4: break; // DMA1IFG case 6: break; // DMA2IFG case 8: break; // Reserved case 10: break; // Reserved case 12: break; // Reserved case 14: break; // Reserved case 16: break; // Reserved default: break; } }
The goal is to receive 8000 sample from channel 3 and the other 8000 sample from channel 4.
Actually I'm getting the same data replicated.
What i'm missing on this...
Regards
Unfortunately, DMA cannot do such complex patterns on its own. You’ll have to program the DMA for the first 8000, then get an interrupt and program it for the second 8000.
Also, you can’t directly move from ADC to UART, as the ADC result is 12(16) bit and the UART takes 8 bit data. The DMA cannot split a 16 bit value into two 8 bit values, it will discard the upper 8 bit.
SO you need to fill a buffer with words first, then move them byte-wise to UART.
If you calculate the timings good enough, you might be able to do both simultaneously: sample and write one 16 bit result with one DMA channel while another one does two 8 bit transfers to the UART. In any case, you’ll need to use software (e.g. triggered by the DMA interrupt after the first 8000 transfers) to switch between the two analog inputs.
Hello, Jeans-Michael,
thanks for your reply.
The idea is to get data simultaneous from 2 different sensor (mic and camera) and send these data directly by UART without the intervention off cpu. In this way, I can get 8 bit of audio and 8 bit of image sampled by ADC and fill the buffer with interlaced data (audio+image). After that I have to send the data by UART.
By the way, I think that, if I configure the ADC & DMA with 8-bit resolution, there can't be any problem with UART TX Register.
It's not clearly to me, when I sample continuously from 2 channel (ADC12MSC & ADC12CONSEQ_3), the ADC generate the Interrupt flag after each channel conversion or after 2 conversion (channel1 and channel 2) ?
Thanks
Camera? UART?
Maximum UART clock speed is 1MBd (which only few PCs support, most end with 230400 or 460800Bd)
Which limits the transfer speed to less than 50k/s. And the MSP does not have the memory to buffer an image. So I’m not sure this is a realistic project.
MIC is no problem. Speech has <8k frequency range, so sampling with 16ksps is sufficient, which means 32k data (12bit resolution, not packed) or 16k Data per second (8 bit resolution). Which scratches the limit of a serial connection. Without any camera data.
You’re right about the 8 bit transfer. You configure the DMA to 16->8 bit transfer (which will read the ADC result as 16 bit, but discard the upper 8 bit when writing to TXBUF)
However, you can’t reliably use DMA to interchangeably transfer two results from two different ADC12MEM result registers to TXBUF. This only worked with the ADC10 where the sequence results appeared in the same memory location.
You also can’t trigger two DMA channels by the different results (assuming that TXBUF is cleared fast enough so that the next result can be written without synchronization with TXIFG). The ADC12 provides only one trigger when the sequence is complete.
However, it could be possible with some trick:
The DMA is triggered by ADC12 end of sequence (in sequence mode) and sends the two results to TXBUF. If the USCI input clock is as fast as MCLK, the USCI will move the content of TXBUF to the output shift register while the DMA fetches the second result. But then, the next sequence needs to take at least as long as the USIC requires to send both bytes (so output shift register and TXBUF are empty when the ADC has completed the next sequence) This works for two bytes only, but in your case this is sufficient for 8 bit conversion results.
Jens-Michael Gross said:Camera? UART?
Maximum UART clock speed is 1MBd (which only few PCs support, most end with 230400 or 460800Bd)
Which limits the transfer speed to less than 50k/s. And the MSP does not have the memory to buffer an image. So I’m not sure this is a realistic project.
MIC is no problem. Speech has <8k frequency range, so sampling with 16ksps is sufficient, which means 32k data (12bit resolution, not packed) or 16k Data per second (8 bit resolution). Which scratches the limit of a serial connection. Without any camera data.
Photo camera, an image 112x112 pixels - 12544 byte. The transmission is not a problem, I want to save all data (12544 byte + 8000 byte) in FRAM and after transmit the data by UART (460800Bd) on an mobile device. Where 8000byte is 1 second audio 8kbps with ADC12RES to 8 bit per data.
I do some test for the bandwidth and all seems to be OK. :)
Jens-Michael Gross said:You’re right about the 8 bit transfer. You configure the DMA to 16->8 bit transfer (which will read the ADC result as 16 bit, but discard the upper 8 bit when writing to TXBUF)
Also the ADC is configured to get 8 bits. ADC12RES can be 12,10 or 8 bit.
Jens-Michael Gross said:You also can’t trigger two DMA channels by the different results (assuming that TXBUF is cleared fast enough so that the next result can be written without synchronization with TXIFG). The ADC12 provides only one trigger when the sequence is complete.
However, it could be possible with some trick:
The DMA is triggered by ADC12 end of sequence (in sequence mode) and sends the two results to TXBUF. If the USCI input clock is as fast as MCLK, the USCI will move the content of TXBUF to the output shift register while the DMA fetches the second result. But then, the next sequence needs to take at least as long as the USIC requires to send both bytes (so output shift register and TXBUF are empty when the ADC has completed the next sequence) This works for two bytes only, but in your case this is sufficient for 8 bit conversion results.
Actually I don't want to transmit directly each sampled data by UART, I want to save it in FRAM and after to transmit all collected data by UART.
The program is:
Set ADC to sample in continuous mode on channel 1 (1 or more pixels of the image) and on channel 2 (1 audio sample) and save these data (8 bit for each sampled data) on FRAM with DMA. After getting 1 image (12544 byte) + 1 second audio (8000 byte), I will transfer these data by UART.
The ADC can set interrupt flag after each channel sampled data? So I can set DMA trigger to save this data to FRAM?
Okay, low-res photo. 256 gray scale, I assume (for 12k data). That will of course be possible. When reading ‘audio’ and ‘camera’ I thought it will be video.
For audio, you can even compress it. The old SoundBlaster cards used a delta encoding, so each sample only took two bits. It’s a straight algorithm that doesn’t take much computing power (two or three comparisons and an addition/subtraction)
As for storing data, well, you can of course use DMA to write the results to FRAM as well. However, DMA does not support different runlength for source and destination. So you cannot copy two results from ADC12 (two different ADC12MEM registers) to a buffer >2. You can only copy 1 result n times to a buffer, or n results one times to a buffer.
Since it doesn’t seem to make sense to sample the image first and then the audio (so no audio while the image is sampled), DMA won’t help you much here. But if you indeed want to take the two sequentially, then of course DMA can be used. You program the ADC in repeated single channel mode and use the DMA to move the results. Then you change the DMA channel and use DMA to move the results. And you can use a second DMA channel to move the stored data to the UART. If you use two buffers, you can even send the data with one DMA channel while receiving the next data from ADC with a second DMA channel.
The DMA from ADC will be triggered after each conversion in single channel mode, or at end of sequence in sequence mode.
However, I wonder how you want to synchronize the video data sampling to the camera output.
**Attention** This is a public forum