USI UART accroding to AVR307

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I am trying to use USI of ATmega169 as a UART according to AVR307. It works but not in Power Save mode, only in Idle mode. The USI UART driver can be downloaded from Atmel website so I only post my code. I should mention that all the USI UART receiver functions and ISRs are disabled because I only need transmitter. In my code one byte is sent every 3 second. Timer2 is used with help of an external 32.768kHz crystal. The baudrate of UART is 9600.

extern volatile char gPowerSaveTimer;    // external Counter from "RTC.c"
char PowerSaveTimeout = 3;
volatile char PowerSave = FALSE;         

// send a byte every 3 second
__C_task void main( void )
{   
    OSCCAL_calibration();
    clock_init_8MHz();
    RTC_init();
    
    USI_UART_Flush_Buffers();
    __enable_interrupt();                                                   // Enable global interrupts
       
    for( ; ; )                                                              // Run forever
    {
      if (PowerSave == FALSE)
      {
        OSCCAL_calibration();
        USI_UART_Transmit_Byte(0x5A);
        PowerSave = TRUE;
      }    
      else 
      {
        //SMCR = (3<<SM0) | (1<<SE);      // Enable Power-save mode
        SMCR = (1<<SE);                 // Enable idle mode
        __sleep();                      // Go to sleep
      }            
      SMCR = 0;
    }    
}

void OSCCAL_calibration(void)
{
    unsigned char calibrate = FALSE;
    int temp;
    unsigned char tempL;

    CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable
    // set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
    CLKPR = (1<<CLKPS1) | (1<<CLKPS0);
    
    TIMSK2 = 0;             //disable OCIE2A and TOIE2

    ASSR = (1<<AS2);        //select asynchronous operation of timer2 (32,768kHz)
    
    OCR2A = 200;            // set timer2 compare value 

    TIMSK0 = 0;             // delete any interrupt sources
        
    TCCR1B = (1<<CS10);     // start timer1 with no prescaling
    TCCR2A = (1<<CS20);     // start timer2 with no prescaling

    while((ASSR & (0x01 | 0x04)));       //wait for TCN2UB and TCR2UB to be cleared

    //Delay(1000);    // wait for external crystal to stabilise
    __delay_cycles(1000000);
    while(!calibrate)
    {
        __disable_interrupt();  // disable global interrupt
        
        TIFR1 = 0xFF;   // delete TIFR1 flags
        TIFR2 = 0xFF;   // delete TIFR2 flags
        
        TCNT1H = 0;     // clear timer1 counter
        TCNT1L = 0;
        TCNT2 = 0;      // clear timer2 counter
           
        while ( !(TIFR2 & (1<<OCF2A)) );   // wait for timer2 compareflag
    
        TCCR1B = 0; // stop timer1

        __enable_interrupt();  // enable global interrupt
    
        if ( (TIFR1 & (1<<TOV1)) )
        {
            temp = 0xFFFF;      // if timer1 overflows, set the temp to 0xFFFF
        }
        else
        {   // read out the timer1 counter value
            tempL = TCNT1L;
            temp = TCNT1H;
            temp = (temp << 8);
            temp += tempL;
        }
    
        if (temp > 6250)
        {
            OSCCAL--;   // the internRC oscillator runs to fast, decrease the OSCCAL
        }
        else if (temp < 6120)
        {
            OSCCAL++;   // the internRC oscillator runs to slow, increase the OSCCAL
        }
        else
            calibrate = TRUE;   // the interRC is correct
    
        TCCR1B = (1<<CS10); // start timer1
    }
   
    RTC_init();
    __disable_interrupt();
    clock_init_8MHz();
    __enable_interrupt();
}

/******************************************************************************
*
*   Function name:  RTC_init
*
*   returns:        none
*
*   parameters:     none
*
*   Purpose:        Start Timer/Counter2 in asynchronous operation using a
*                   32.768kHz crystal.
*
*******************************************************************************/
void RTC_init(void)
{
    //Delay(1000);            // wait for 1 sec to let the Xtal stabilize after a power-on,

    __disable_interrupt();  // disabel global interrupt

    cbi(TIMSK2, TOIE2);             // disable OCIE2A and TOIE2

    ASSR = (1<<AS2);        // select asynchronous operation of Timer2

    TCNT2 = 0;              // clear TCNT2A
    TCCR2A |= (1<<CS22) | (1<<CS20);             // select precaler: 32.768 kHz / 128 = 1 sec between each overflow
    
    while((ASSR & (0x01 | 0x04)));       // wait for TCN2UB and TCR2UB to be cleared

    TIFR2 = 0xFF;           // clear interrupt-flags
    sbi(TIMSK2, TOIE2);     // enable Timer2 overflow interrupt
 
    __enable_interrupt();                 // enable global interrupt
}

/******************************************************************************
*
*   Timer/Counter2 Overflow Interrupt Routine
*
*   Purpose: Increment the real-time clock
*            The interrupt occurs once a second (running from the 32kHz crystal)
*
*******************************************************************************/
#pragma vector = TIMER2_OVF_vect
__interrupt void TIMER2_OVF_interrupt(void)
{
  gPowerSaveTimer++;
  if (gPowerSaveTimer == PowerSaveTimeout)
  {
    gPowerSaveTimer = 0;
    PowerSave = FALSE;
  }
}

void clock_init_8MHz(void)
{
  CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable
    
  // set prescaler = 8, Inter RC 8Mhz / 1 = 8Mhz
  CLKPR = 0; 
}

Thanks
Owen

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You may want to go to the project section here and download a copy of "Buttload" by abcminiuser. In that Dean has routines for the mega169 to do the UART connection to the PC that works very well.