USART startup problem (32A4)

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

After initializing the C1 USART on this part, the first two transmit commands don't do anything (the output pin doesn't change). Third and subsequent transmits do cause the pin to change. Any ideas what I'm doing wrong? Relevant code below. I put main() first for readability. I only include up to LCD_Init() as that's where the problem appears. The first two SendUSART() calls there are the ones that have no effect. Thanks for your help.

int main(void)
{
    unsigned int x;
    ClockConfig();
    PortInit();
    USART_Init();       // Initialize USARTS C0 and C1
    LCD_Init();


void ClockConfig(void)
{

// Load the Protect IO Register signature into the Configuration Change Protection 
// register.

    CPU.CCP = CCP_IOREG_gc; 

// Enable 32MHz internal oscillator

    OSC.CTRL |= OSC_RC32MEN_bm;          

// Wait for oscillator to stabilize

    while (!( OSC.STATUS & OSC_RC32MRDY_bm));  

// Load the Protect IO Register signature into the Configuration Change Protection 
// register.

    CPU.CCP = CCP_IOREG_gc; 

// Select 32MHz internal oscillator

    CLK.CTRL = CLK_SCLKSEL_RC32M_gc;     

// Load the Protect IO Register signature into the Configuration Change Protection 
// register.

    CPU.CCP = CCP_IOREG_gc; 

// Disable 32 KHz internal oscillator.

    OSC.CTRL &= (~OSC_RC2MEN_bm);   
}

void PortInit(void)
{
    PORTE.OUTSET = 0xf0;    // Keep power supply relay off
    PORTD.OUTCLR = 1;

// PE0 = output for LED (1 = on, 0 = off), PE3 = output (for power relay), PE2 = 
// input (for pushbutton).

    PORTE.DIR = 0xf9;       

// PC3 = USARTC0 TxD0 for USARTC0.  PC7 = USARTC0 TxD0 for USARTC1.  PC0 connected 
// to ultrasonic sensor (in/out).

    PORTC.OUTSET = 0x88;    
    PORTC.DIR = 0xff;       // Output
    PORTD.DIR = 0xff;       // Output
}

void USART_Init(void)
{
    // Set baud rate to 9600 for both USARTs.  Two different values, but they 
    // both produce 9600 bps.  Xmega baud rate alculator:   
    // http://prototalk.net/forums/showthread.php?t=188

    USARTC0.BAUDCTRLA = 106;
    USARTC0.BAUDCTRLB = (1 << USART_BSCALE0_bp);
    USARTC1.BAUDCTRLA = 46;
    USARTC1.BAUDCTRLB = 205;

    // Set operating mode to asynch, 8 data btis, no parity, 1 stop bit

    USARTC0.CTRLC |= (USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc |
                      USART_CHSIZE_8BIT_gc & (~USART_SBMODE_bm));
    USARTC1.CTRLC |= (USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc |
                      USART_CHSIZE_8BIT_gc & (~USART_SBMODE_bm));

    // Enable transmitter

    USARTC0.CTRLB |= USART_TXEN_bm;
    USARTC1.CTRLB |= USART_TXEN_bm;
    Delay(500);    // Wait a second for configuration to set.
}

void LCD_Init(void)
{
    SendUSART(0xfe, 1);  // Clear screen with 0xfe, 0x51.
    SendUSART(0x51, 1);
    SendUSART(0xfe, 1);  // Set display contrast
    SendUSART(0x52, 1);
    SendUSART(25, 1);    // Contrast 0 - 50, 25 best.
}

// Send a byte through usart (USARTs:  C0 = 0, C1 = 1, D0 = 2, D1 = 3, E0 = 4)

void SendUSART(unsigned char byte, unsigned char usart)
{
    switch (usart)
    {
        case 0:

// Wait for xmit buffer to empty

            while (!(USARTC0.STATUS & USART_DREIF_bm));
            USARTC0.DATA = byte;
            break;
        case 1:

// Wait for xmit buffer to empty

            while (!(USARTC1.STATUS & USART_DREIF_bm));
            USARTC1.DATA = byte;
            break;
        case 2:

// Wait for xmit buffer to empty

            while (!(USARTD0.STATUS & USART_DREIF_bm));     
            USARTD0.DATA = byte;
            break;
        case 3:

// Wait for xmit buffer to empty

            while (!(USARTD1.STATUS & USART_DREIF_bm)); 
            USARTD1.DATA = byte;
            break;
        case 4:

// Wait for xmit buffer to empty

            while (!(USARTE0.STATUS & USART_DREIF_bm));     
            USARTE0.DATA = byte;
            break;
        default:
            break;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lautman wrote:

    USARTC0.BAUDCTRLA = 106;
    USARTC0.BAUDCTRLB = (1 << USART_BSCALE0_bp);
    USARTC1.BAUDCTRLA = 46;
    USARTC1.BAUDCTRLB = 205;

Those numbers looks odd to me. When I calculate baud values for 9600@32MHz with the formulas in the data sheet I get
F_CPU = 32000000, desired baud rate = 9600, u2x = 0
bscl bsel  abaud   error%
  7     1    7812  -18.62  
  6     2   10416    8.50  
  5     6    8928   -7.00  
  4    12    9615    0.16 OK 
  3    25    9615    0.16 OK 
  2    51    9615    0.16 OK 
  1   103    9615    0.16 OK 
  0   207    9615    0.16 OK 
 -1   415    9592   -0.08 OK 
 -2   829    9603    0.03 OK 
 -3  1659    9598   -0.02 OK 
 -4  3317    9600    0.00 OK  <---
 -5  4095   15507   61.53  
 -6  4095   30776  220.58  
 -7  4095   60620  531.46  

The best is bsel = 3317 and bscale = -4, so maybe something like

	// 9600 @ 32MHz, bsel = 3317, bscale = -4
	USARTC0.BAUDCTRLA = (uint8_t) 3317;
	USARTC0.BAUDCTRLB = (-4 << 4) |  (3317 >> 8);

will work better? (It works for me, but I prefer the macros from the app.note).

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

snigelen:

Yeah, 3317 is ideal in theory, but I had to fine-tune it on my particular chip. In any event, I don't think that's what's causing the first couple of transmissions to be ignored.