I am trying to communicate at 9600 baud, 8 N 1 via the Xmega32's USART. However, I can't get it to work when the system/peripheral clock is set to 32Mhz.
- When system and peripheral clock is set to 2Mhz it works. (I made the appropriate change in baudctrla and baudctrlb.)
- When I use 32Mhz clock and connect to another board with the same Atmel chip, communications succeeds. So that seems to imply that the system clock probably isn't running at 32Mhz or I'm using the wrong baudctrla and baudctrlb values.
Here's the system clock initialization:
unsigned char n; // Internal 32 kHz RC oscillator initialization // Enable the internal 32 kHz RC oscillator OSC.CTRL|=OSC_RC32KEN_bm; // Wait for the internal 32 kHz RC oscillator to stabilize while ((OSC.STATUS & OSC_RC32KRDY_bm)==0); // Internal 32 MHz RC oscillator initialization // Enable the internal 32 MHz RC oscillator OSC.CTRL|=OSC_RC32MEN_bm; // System Clock prescaler A division factor: 1 // System Clock prescalers B & C division factors: B:1, C:1 // ClkPer4: 32000.000 kHz // ClkPer2: 32000.000 kHz // ClkPer: 32000.000 kHz // ClkCPU: 32000.000 kHz n=(CLK.PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm | CLK_PSBCDIV0_bm))) | CLK_PSADIV_1_gc | CLK_PSBCDIV_1_1_gc; CCP=CCP_IOREG_gc; CLK.PSCTRL=n; // Internal 32 MHz RC osc. calibration reference clock source: 32.768 kHz Internal Osc. OSC.DFLLCTRL&= ~(OSC_RC32MCREF_bm | OSC_RC2MCREF_bm); // Enable the autocalibration of the internal 32 MHz RC oscillator DFLLRC32M.CTRL|=DFLL_ENABLE_bm; // Wait for the internal 32 MHz RC oscillator to stabilize while ((OSC.STATUS & OSC_RC32MRDY_bm)==0); // Select the system clock source: 32 MHz Internal RC Osc. n=(CLK.CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_RC32M_gc; CCP=CCP_IOREG_gc; CLK.CTRL=n; // Disable the unused oscillators: 2 MHz, external clock/crystal oscillator, PLL OSC.CTRL&= ~(OSC_RC2MEN_bm | OSC_XOSCEN_bm | OSC_PLLEN_bm); // ClkPer output: Disabled bit 7 PORTCFG.CLKEVOUT=(PORTCFG.CLKEVOUT & (~PORTCFG_CLKOUT_gm)) | PORTCFG_CLKOUT_OFF_gc;
The baudCtrlA and baudCtlB values are as defined by Atmel's baudrate_calculations Excel spreadsheet. I tried both with a bscale value of -4 and 0 using the appropriate corresponding Bsel value.
Here's the code using BSCALE of -4:
//Required Baud rate: 9600 // BAUDCTRLA and B calculated by Atmel excel spreadsheet // BSEL = 3317 = 0x0CF5 // BSCALE = -4 = 1100b = 0xC- remember the bscale is high nibble of BAUDCTRLB register so need to multiply by 0x10 // BAUDCTRLA = F5 // BAUDCTRLB = BSCALE + 0X0C // X2 = 0 (do not double clock) // ERROR% = 0.01% USARTC0.BAUDCTRLA = 0xF5; USARTC0.BAUDCTRLB = ( 0XC << USART_BSCALE_gp) | 0X0C;
Here's the other attempt using BSCALE of 0 and appropriate BSEL:
//Required Baud rate: 9600 // BAUDCTRLA and B calculated by Atmel excel spreadsheet // BSEL = 207 = 0xCF // BSCALE = 0 // BAUDCTRLA = 0XCF // BAUDCTRLB = 0 // X2 = 0 (do not double clock) // ERROR% = 0.16% // USARTC0.BAUDCTRLA = 0xCF; // USARTC0.BAUDCTRLB = 0;
As I mentioned, I can get it to work using a clock of 2Mhz or by connecting two Xmega's together.