Jump to content
43oh

Internal ref for stable PWM with unregulated Vcc


Recommended Posts

Using a g2553:

 

Any suggestions for doing PWM using the internal reference for the high so that Vcc doesn't need to be regulated? Battery powered application so not using a regulator is desirable.

 

Only way I can come up with is use P1.4 as the PWM output, after setting up the reference, toggling ADC10AE.4 in software, otherwise configuring the pin for output and a value of 0. It works, but it is kinda ugly, so a more elegant solution would be nice.

 

The application is driving an analog meter movement, so the current is in the ballpark of 200uA full scale.

Link to post
Share on other sites

Ok. That woulld allow me to use hardware PWM. Any ideas on a level shifter that will go down to 1.5V? Not sure if I love needing another device, but would definitely simplify the software.

TI TXB0101 (or any of the TXB01xx series).  I had the voltage rails backwards too, VccA is the low side and VccB is the high side.

 

VccA = 1.2-3.6V, VccB = 1.65-5.5V range.  VccA must be <= VccB at all times.

Link to post
Share on other sites

Never had a need to look at the one-bit level shifters before. handy little buggers, they appear to be. Ordered a couple different flavours to play with.

 

In the mean time, what I have is not quite making sense, and I figure I am missing something in the documentation. What I am seeing is that, if I set REFOUT in the ADC10CTL register, while the appropriate ADC10AE bit is not set, the output hangs at a stiff 750mV rather than being pulled low as the P1OUT bit specifies. Doesn't even float. It is stiff against 500uA. My initial thought was modulate the ADC10AE bit to switch between the P1.4 output value and the reference. Instread, I need to also modulate REFOUTT in the control register.

 

This is two kinds of ugly: 1) the code is kludgy, and 2) when going high (switching the pin to analog and enebling REFOUT), there is a roughly 1us spike to Vcc, and the output hangs at 750mV for the time between the two operations (about 5us at the default 1MHz clock) due to the lack of synch. The weirdest part is that if I swap the order of the state assignments so that the hang is on the falling edge, the output actually goes just about to zero before going back up to 750mV, holds there for 5us, then the second part of the state is set and to ground it goes.

 

Does issue 2) cause a real problem? no. The energy in the spike and in the 750mV hang is too low to have an effect on the analog movement being driven. But, aesthetically, it bugs me.

 

Hence, my asking...

 

 

BTW, this just cycles from bottom to top of range to test the analog movement.

/*
 * Software PWM on p1.4 using the internal voltage ref as high
 */


/* led's port 0, bits 0 and 6 */
#define led1 0x01

#define button 0x08 /* launchpad pushbutton bit 3 */



#define PWM_CYCLE_TIME 0x8000       /* approx 1/30 sec */
#define PERIOD (0x0080) /* PWM interrupt period */ /* was 0x0100 */
#define PWM_CYCLE (PWM_CYCLE_TIME/PERIOD) /* number of periods per cycle */



volatile unsigned int cycleflag=0; // flag for start of new PWM cycle

volatile unsigned int period=PWM_CYCLE; // period counter for PWM cycles

volatile unsigned int PW=1;    // current output pulse width

#define PWM_ONE   (SREF_1 | REFON | REFOUT) /* reference is on at 1.5V and ADC select is for internal ref, set p1.4 to ref voltage */
#define PWM_ZERO  (SREF_1 | REFON) /* reference is on at 1.5V and ADC select is for internal ref, set p1.4 to ref voltage */

volatile unsigned int nextout=0;
volatile unsigned int nextADC=PWM_ZERO;

/*
 * main.c
 */
int main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    // clock default ~1MHZ


    P1DIR = ~(button); //  P1.x all outputs except pushbutton
    P1OUT=button;       //  setup for pushbutton to be input, all other P1 are low
    P1REN=button;




    // to minimize issues with floating I/O
    P2DIR |= 0xff;// P2 all out
    P2OUT =0;

    ADC10CTL0=PWM_ONE;


    // set up timer
    // USE MCLK at 1MHz (default)

    CCR0 = PERIOD; // period

    TACTL = MC_1|TASSEL_2|TACLR;    // set up timer
    		//MC_1: up mode    TACLR: reset counter to 0   TASSEL_2: source SMCLK
    CCTL0 = CCIE; // enable interrupt for timer on compare 0; interrupt on final count


    _BIS_SR( GIE); // enable interrupt


    unsigned int lifectr=0;

    while (1) {

      if (!(P1IN & button)) { //
    	  PW=PWM_CYCLE; // full on
    	  continue; // do no PWM calcs
      }
      if (cycleflag) { // calculate new cycle
        cycleflag = 0; // indicate cycle detected


        if (lifectr++ & 0x80) {P1OUT|=led1;} else {P1OUT &= ~(led1);} // flash led1 periodically


        PW++;
        if (PW>=PWM_CYCLE) {PW=0;}


      } // if cycleflag
    } // while inf loop

}



//Timer A0 interrupt svc routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{

	// output the new state. Doing it here, at the interrupt time, gives decent synchronization
        // either order spikes on rise, but this order hangs on rise, the other order hangs on fall
	ADC10CTL0=nextADC;
        ADC10AE0=nextout; // set bits with analog enable

	if (--period ==0) { period = PWM_CYCLE; cycleflag=1;  } // count off this interval; if new cycle, flag for main


	if (period < PW) { // set next state
                nextout=0x10;  // 0x10
                nextADC=PWM_ONE;
	} else{
		nextout=0x00;
		nextADC=PWM_ZERO;
	}

} // interrupt handlerTIMER_A


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...