Hi team,
Here's an issue from the customer may need your help:
A 2-kHz sinusoidal signal is generated with a 1-v amplitude from the signal source, then the signal is acquired through ADC10 of the MSP430G2553, and the acquired data is sent via UART to the matlab for waveform restoration. But the recovered signal always has a glitch (sometimes it's OK). The customer would like to know is there anything wrong with the program? (The signal from the source is accurate and has been tested).
The following figure shows two conditions for glitches:
Normal is as the following figure:
#include <msp430.h>
#include "stdint.h"
#define nn 100;
uint16_t adcbuff[100] = {0}; //An array of nn lengths
uint8_t combuff[20]={0}; //Used to save the commands accepted by the serial port
uint8_t iscomend =0 ;//End of command? Used to determine if a complete command has been received successfully
/**
* main.c
*/
void InitSystemClock(void)
{
DCOCTL = CALDCO_16MHZ;
BCSCTL1 = CALBC1_16MHZ;
BCSCTL2 &= ~SELS; //Select the source of SMCLK
BCSCTL2 &= ~(DIVS0 | DIVS1); //Set the division factor
}
void InitUART(void)
{
UCA0CTL1 |= UCSWRST; //set UCSWRST
//Initialize all UCSI registers
UCA0CTL0 &= ~(UCMODE1 | UCMODE0); //Configure UCSI mode 00 to UART mode
UCA0CTL0 &= ~UCSYNC; //Select asynchronous mode
UCA0CTL1 |= (UCSSEL1 | UCSSEL0); //Configure clock sources 10 and 11 as SMLCK
//Configure the baud rate, look at UCOS16, and then look in the user manual for table 15.4 UCBRx UCBRSx UCBRFx The last two are actually in UCAxMCTL
UCA0BR0=0x82;
UCA0BR1=0x06;
UCA0MCTL |= (UCBRS1| UCBRS2);
//Configure the port
P1SEL |= BIT1 + BIT2;
P1SEL2 |= BIT1 + BIT2;
//Clear reset to enable UART
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0RXIE; //Turn on the receive interrupt of the serial port
IFG2 &= ~UCA0RXIFG ;// Clear the receive interrupt flag
}
void InitADCTrigByTimerA(void)
{
ADC10CTL1 |= ADC10SSEL_2;//Select the clock source
ADC10CTL1 |= SHS0; //Select Timer A out1 SHSx for sampling and hold source 01 for Timer_A out1 00 for ADC10SC bit
ADC10CTL1 |= CONSEQ1; //Select conversion sequence 00 to single-channel single-conversion 01 to channel sequence
ADC10CTL0 |= SREF_1;//Set the reference, external or internal?
ADC10CTL0 |= ADC10SHT_1; //Set the ADC10 sample hold time to 16 CLK
ADC10CTL0 &= ~ADC10SR; //ADC10 sample rate
ADC10CTL0 |= REF2_5V; //ADC reference selection 2.5 V
ADC10CTL0 |= REFON; //Turn on the reference
ADC10CTL1 |= INCH_4;//Select the ADC input channel A4
ADC10AE0 |= 1 << 4;//Allows A4 analogue input
//DTC transfer mode
ADC10DTC0 |= ADC10CT;//At 1, the data is transmitted continuously, and the operation of the DTC only stops when ADC10CT is cleared or ADC10SA is written
ADC10DTC1 = nn; //The total number of transfers is 50
ADC10SA = (uint16_t)(adcbuff); //ADC10SA to determine the start address, which forces the first address of adcbuff to a 16-bit integer
/*turn on ADC*/
ADC10CTL0 |= ADC10ON;
/*Allow conversion */
ADC10CTL0 |= ENC;
}
void InitTimerA()
{
TA0CTL |=TASSEL1; //Configure the clock bit SMLCk
TA0CTL |= MC0; // Up mode, 01 is up, and up is up to TA0CCR0, 10 is continuous mode and the timer counts to 0FFFFh
//11 Up/Down mode is the timer increases to TACCR0 and then decreases to 0000h
TA0CCR0 =0x004F;// configure TA0CCR0 bit 0x004F
TA0CCR1= 0x002F;//set duty cycle (TACCR0-TACCR1)/TARRC0 At this time, the duty cycle is 1/2, frequency = SMCLK/(TACCR0+1)/2 SMCLK is set in the clock. For example, 16 MHz/80/2 is approximately 100 k, approximately the sampling frequency, and the maximum sampling frequency
TA0CCTL0 &= ~CAP;
TA0CCTL1 &= ~CAP;
TA0CCTL1 |= OUTMOD_6;
//Set IO multiplexing
P1SEL |= BIT6;//
P1DIR |= BIT6;//
}
int main(void)
{
uint16_t cnt = 0;
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
InitSystemClock();
InitUART();
InitADCTrigByTimerA();
InitTimerA();
__bis_SR_register(GIE);//Turn on global interrupts
while(1)
{
if(iscomend)
{
iscomend =0;
for(cnt = 0; cnt<100;cnt ++)
{
while(UCA0STAT & UCBUSY);
UCA0TXBUF=*(adcbuff+cnt)/256; //The data in adcbuff is sent out, 8 bits high first
__delay_cycles(30000);
while(UCA0STAT & UCBUSY);
UCA0TXBUF=*(adcbuff+cnt)%256; //And then 8 bits lower
__delay_cycles(30000);
}
}
}
return 0;
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void UART_Receive_ISR(void)
{
static uint8_t cnt2 = 0;
if(IFG2 & UCA0RXIFG)//Detects if the receive interrupt is USCI_A0, and the receive interrupt shares the same amount for USCI_A0 and USIC_B0
{
IFG2 &= ~UCA0RXIFG;//Clear the flag bit
combuff[cnt2++] = UCA0RXBUF;//Save the command
cnt2 %= 20;//Prevents cnt greater than 20, causing buffer overflow
if(combuff[cnt2 - 1] == '#')//If a command end character is detected (end of command with '#')
{
cnt2 = 0;//Reset the counter
iscomend = 1;//Command received
}
}
}
Note: It's equivalent to using the G2553 as an oscilloscope.
Could you help check this case? Thanks.
Best Regards,
Cherry