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.
Hi, I got a problem with a MSP430G2553. I got a PCB with the smt version and I reproduced the bug on the launchpad. I read the errata and there is nothing about this issue so i'm considering a bug in my firmware. First, I will explain the bug showing a screen shot of it. Then, I will show you the code that generate the error.
Basically, I wanted to use 2 timers (timer0 and timer1) and 5 channel ADC. When I turn on all of these, the PWM that goes on P2.2 from the timer 1 is not what I expect. Alone, the timer runs smoothly at 50Hz as set. With the ADC or with the second timer, everything is ok.
Here's a picture since I can't explain it well.
Sometimes, the PWM stops and sometimes it stay high.
Here's a simplified version of the code I use on IAR. I tested it and it does the same glitch on the pin output. I don't understand why it does this. I initialize the modules and let it runs idle in a while(1); at the end.
#include <io430.h>
#include "types.h" //defines UInt8, UInt16, etc..
static UInt16 TSRV_LastMeasure;
static UInt32 TSRV_Timestamp;
//Init values
UInt16 ADC[5]; // Array to hold ADC values
/// <summary>
/// Main entry point of the software.
/// </summary>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD;
//Initialize MCU speed to 16MHz
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step
BCSCTL2 |= DIVS_3; // SMCLK to 2MHz
//setup 50Hz timer
UInt16 timerPeriod = 40000; //50Hz = (2Mhz)/40000
P2DIR |= BIT2; // P2.2 output
P2OUT &= ~BIT2;
P2SEL |= BIT2; // P2.2 TA options
TA1CCR0 = timerPeriod-1; // PWM Period
TA1CCTL1 = OUTMOD_7; // CCR1 reset/set
TA1CCR1 = 0; // CCR1 initialized to 0
TA1CTL = TASSEL_2 + MC_1 + ID_0 ; // SMCLK, up mode, divider by 1
//Setup ADC
ADC10CTL1 = CONSEQ_1 + ADC10SSEL_3 + INCH_4;
ADC10CTL0 = ADC10SHT_3 + MSC + ADC10ON;
ADC10DTC1 = 5;
ADC10AE0 |= BIT0+BIT1+BIT2+BIT3+BIT4;
ADC10SA = (short)&ADC[0];
ADC10CTL0 |= ENC + ADC10SC;
//Setup time service
TSRV_LastMeasure=0x0000;
TSRV_Timestamp=0x0000;
TA0CCR0 = 0xFFFF;
TA0CTL=TASSEL_2+ID_1+MC_1+TAIE; // SMCLK + Divide by 2 + Continuous mode + Enables timer interrupt.
TA0CCTL0 = CCIE; // CCR0 interrupt enabled
__bis_SR_register(GIE);
while(ADC10CTL1 & BUSY);
ADC10SA = (short)&ADC[0];
ADC10CTL0 |= ENC + ADC10SC+ ADC10ON;
TA1CCR1 = 4096;
while(1);
}
/// <summary>
/// Timer A1 interruption vector.
/// </summary>
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0_TA0IV_ISR(void)
{
switch(__even_in_range(TA0IV,14))
{
case 0x0E: // Timer overflow.
TSRV_Timestamp+=~TSRV_LastMeasure; // Adds the remaining difference.
TSRV_LastMeasure=0x0000;
break;
}
}
Since I do not have a weird configuration, I think you may help me with this problem I got.
Thanks a lot!
If you take a closer look at the pin I/O schematics in the datasheet, you’ll see that the ADC will disable the digital pin circuitry while it is sampling from a pin. When the ADC during the sequence samples the PWM output pin, it disables the digital driver. The PWM signal is generated internally as it should, but the pin output won’t follow the internal signal. So if the ADC is sampling from this pin right when the PWM pulse occurs, the pulse won’t go out. Or if it happens while the pulse is active, then the output will stay high (due to line capacitance) until the ADC is done.
Not all MSPs auto-disable the digital I/O while sampling the ADC, but the G series does. Don’t use ADC10 sequence when the sequence crosses an active output pin.
I agree with JMG's narration, but I do not think that is the cause of the problem.
P2.2 cannot be used as ADC input.
You enabled two different interrupts in TA0:
TA0CTL=TASSEL_2+ID_1+MC_1+TAIE;
TA0CCTL0 = CCIE;
But you have only one ISR:
#pragma vector=TIMER0_A0_VECTOR
__interrupt void … …
In addition, this one will try to handle the CCIE in TA0CCTL0. But you wrote this ISR in a way that should have been used to handle the TAIE in TA0CTL.
Thus one of the ways to correct your mistakes is as follows. (a) drop the +TAIE in one of the lines, and (b) change A0 to A1 in another line.
TA0CTL=TASSEL_2+ID_1+MC_1+TAIE;
…
#pragma vector=TIMER0_A1_VECTOR
__interrupt void … …
I gave you the wrong medicine! Use the following instead.
To correct your mistakes is as follows. (a) drop the line with CCIE, and (b) change A0 to A1 in the #pragme line.
TA0CCTL0 = CCIE;
#pragma vector=TIMER0_A1_VECTOR
__interrupt void … …
Thanks!! That was definitely the main issues I had: The wrong Interrupt name and 2 different interrupts enabled.
I also had another problem. The code I gave was a simplified version of the whole project. In the project, I read the ADC in the main while loop. The event apparently occurs in a bad moment. This also causes glitches on the scope. To solve this issue, I enabled the second CCR to start the ADC conversion at a moment that I'm sure there is no switching on the IO pin. That solved the third issue. I hope this can help other people out there.
Thanks a lot Jens-Michael Gross and old_cow_yellow . You guys are awesome!
**Attention** This is a public forum