Hi,
I want to trigger ADC10 using Watchdog timer every 2 msec and want the average value of 64 samples. Once the average is obtained, i want to reflect same in the duty cycle of TIMER_A1 . The change in the duty cycle can be seen as the LED brightness change connected to P2.1.
But, when i am running the code, it is toggling between
if(ADC_flag) AND if (Reading_Captured)
Please see what may be the issue with the code. I am NOT able to find out the solution ever after giving so much try.
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
CLOCK_Init(); // Initialize clocks for 16 MHz
__delay_cycles (80000000);
ConfigPins();
__delay_cycles (500); //Random delay
Timer_Init();
__bis_SR_register(GIE); // Enable global interrupt
WDT_Init();
ADC_Init();
while(1)
{
if(ADC_flag)
{
ADC_flag=0;
__bis_SR_register(CPUOFF); // MSP430 waits in LPM0 to save power until ADC10 conversion complete
// ADC10_ISR will force exit from any LPMx on return.
while (ADC10CTL1 & ADC10BUSY); //Wait for conversion. 13 ADC10CLK cycle = 2.6 usec
ADC10SA = (unsigned int)&ADC_Readings; // Transfer adc readings to an array
ADC10CTL0 &= ~ENC; //The ENC bit must be clear so that most bits in ADC10CTL0 and ADC10CTL1 can be changed.
// sequence of conversions complete
Voltage_Sum += ADC_Readings;
Reading_Captured = 1;
Avg_ctr ++;
}
if (Reading_Captured)
{
Reading_Captured = 0;
if (Avg_ctr == ctr_th)
{
ADC_Update();
if(Voltage > 0)
{
Duty = Voltage;
// P1OUT |= BIT0;
}
}
// Reset all the ADC values
Avg_ctr = 0;
Voltage_Sum = 0;
}
}
}
void CLOCK_Init(void)
{
//if we want DCO=MCLK=SMCLK,then just configure DCOCTL and BCSCTL1
//16Mhz @ maximum device frequency
if (CALBC1_16MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation*/
}
void ConfigPins(void)
{
P1DIR |= BIT0; // output
P1OUT = 0; // clear output pin
}
void ADC_Init(void)
{
ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE;
ADC10CTL1 = INCH_1 + SHS_0 + ADC10SSEL_0 + ADC10DIV_0 + CONSEQ_0;
ADC10AE0 |= BIT1; // Select port pins function as input Analog channels
ADC10DTC1 = 0x001; // 1 conversion per sequence
}
void WDT_Init (void)
{
// Watchdog timer is used to generated interrupts for taking ADC readings
// DCO/SMCLK clock source used in this example for the WDT clock source
WDTCTL = WDT_MDLY_32; // WDT 32ms, for SMCLK = 1Mhz,here SMCLK = 16Mhz so timer interval = 2ms
IE1 |= WDTIE; // Enable WDT interrupt
}
// Watchdog Timer interrupt service routine
#pragma vector = WDT_VECTOR
__interrupt void WDT_ISR(void)
{
/* Here for each interrupt, it triggers ADC to take readings
* WDTIFG interrupt flag is automatically cleared */
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
ADC_flag =1; //set ADC flag to process adc data
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
//ADC10IFG interrupt flag is automatically cleared
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(Status Register)
}
void Timer_Init(void)
{
/*TIMER_A1 as PWM generation
*/
P2DIR |= BIT1|BIT2; //set as output pin
P2SEL |= BIT1|BIT2; //pin selected for pwm operations (P2.1/TA1.1) and (P2.2/TA1.1)
TA1CTL |= TASSEL_2 + MC_1; //SMCLK and up mode count till ccr register
TA1CCR0 |= 1600 - 1; //pwm frequency 10 khz; DCO = MCLK = SMCLK = 16 Mhz
TA1CCR1 |= Duty; //Duty cycle
TA1CCTL1 |= OUTMOD_7; //set/reset mode
//_BIS_SR(LPM0_bits + GIE); //For low power mode and global interrupt
// TAKE DUTY AS A VARIBLE TO CHANGE THE DUTY CYCLE
}
void ADC_Update(void)
{
/* Here ctr_th = 64 . i.e average of 64 ADC readings is calculated.
* Once is every 1 ms a set of ADC readings is taken
* So loop time is approximately 64 * 2 = 128 ms
*/
Voltage = Voltage_Sum / ctr_th;
}
THANK YOU ....