You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am playing with baud rate compensation based on the factory stored error compensation values in the Sigrow.
So I need to know at compile time if the OSC20M will be set for 16 or 20 MHz. The setting of the fuse is done during the UPDI upload, so the core knows how to set it.
I looked in the reference for core defines to see if there is a define that I can use with a #if statement. I can't find it. So now the only thing I could come up with is to check F_CPU and derive from that if the OSC20M is set for 16 or 20 MHz.
I like to determine at compile time and not waste flash by reading the OSCCFG register in my program and then applying the right compensation.
I could use the ADC to determine the VCC and automate the 5V vs 3V selection by itself, but that is maybe for later.
This is my test sketch so far:
#include <util/delay.h> //do not use standard delay(). It will hang.
//#define USE_ALTERNATE_TXD // uncomment if you want to use the alternate TXD* / RXD* pins
//#define TUNE_BAUD 3 // Uncomment for baudrate tuning at 3 Volt
#define TUNE_BAUD 5 // Uncomment for baudrate tuning at 5 Volt
int main(void) {
F_CPU_init ();
USART_init(2400); //Call the USART initialization code and choose ( baudrate )
char printbuffer[16]; //The ASCII of the integer will be stored in this char array
static char Sometext[] = " is the USART0_BAUD value.\r\n"; // A string array with some fixed text
while (1) { //Infinite loop
utoa(USART0_BAUD, printbuffer, 10); //(unsigned integer, yourBuffer, base)
USART_putstring(printbuffer); // print the
USART_putstring(Sometext);
_delay_ms(5000); //Delay for 5 seconds
}
}
void F_CPU_init () {
// reconfigure CPU clock prescaler
#if (F_CPU == 20000000) | (F_CPU == 16000000)
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
#elif (F_CPU == 10000000) | (F_CPU == 8000000) // 20/16MHz prescaled by 2
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc));
#elif (F_CPU == 5000000) | (F_CPU == 4000000) // 20/16MHz prescaled by 4
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc));
#elif (F_CPU == 2000000) // 16MHz prescaled by 8
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_8X_gc));
#elif (F_CPU == 1000000) // 16MHz prescaled by 16
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_16X_gc));
#else
#ifndef F_CPU
#error "F_CPU not defined"
#else
#error "F_CPU defined as an unsupported value for untuned internal oscillator"
#endif
#endif
}
void USART_init(uint32_t BAUDRATE) {
int32_t baud_reg_val = (F_CPU * 4LL / BAUDRATE); // initial BAUD register value
/* Baud rate compensated with factory stored frequency error */
#if (TUNE_BAUD == 5) & ((F_CPU == 20000000) | (F_CPU == 10000000) | (F_CPU == 5000000)) // 5V and 20MHz OSC
baud_reg_val *= (1024 + SIGROW_OSC20ERR5V); // Sum resolution + error
baud_reg_val /= 1024; // Divide by resolution
#elif (TUNE_BAUD == 3) & ((F_CPU == 20000000) | (F_CPU == 10000000) | (F_CPU == 5000000)) // 3V and 20MHz OSC
baud_reg_val *= (1024 + SIGROW_OSC20ERR3V); // Sum resolution + error
baud_reg_val /= 1024; // Divide by resolution
#elif (TUNE_BAUD == 5) & ((F_CPU == 16000000) | (F_CPU == 8000000) | (F_CPU == 4000000) | (F_CPU == 2000000) | (F_CPU == 1000000))
baud_reg_val *= (1024 + SIGROW_OSC16ERR5V); // Sum resolution + error
baud_reg_val /= 1024; // Divide by resolution
#elif (TUNE_BAUD == 3) & ((F_CPU == 16000000) | (F_CPU == 8000000) | (F_CPU == 4000000) | (F_CPU == 2000000) | (F_CPU == 1000000))
baud_reg_val *= (1024 + SIGROW_OSC16ERR3V); // Sum resolution + error
baud_reg_val /= 1024; // Divide by resolution
#else
#warning "Reminder: you have no baudrate tuning selected"
#endif
USART0_BAUD = (int16_t) baud_reg_val; // Set tuned baud rate
#ifdef USE_ALTERNATE_TXD
PORTMUX_CTRLB = PORTMUX_USART0_bm; // activate alternate RXD* / TXD* pins
// VPORTA_DIR |= PIN1_bm; // set pin PA1 as output (select manually to save flash)
pinModeFast(PIN_HWSERIAL0_TX_PINSWAP_1, OUTPUT); // let the core to figure out the pin (uses 100 bytes more memory)
#else
// VPORTB_DIR |= PIN2_bm; // set pin PB2 as output (select manually to save flash)
// VPORTA_DIR |= PIN6_bm; /* set pin 6 of PORT A (TXd) as output*/
pinModeFast(PIN_HWSERIAL0_TX, OUTPUT); // if you want the core to figure out the pin (uses 100 bytes more memory)
#endif
USART0_CTRLB |= USART_TXEN_bm ; //enable tx only
}
void USART_send(unsigned char data) {
while (!(USART0_STATUS & USART_DREIF_bm));
USART0_TXDATAL = data;
}
void USART_putstring(char* StringPtr) {
while (*StringPtr != 0x00) {
USART_send(*StringPtr);
StringPtr++;
}
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I am playing with baud rate compensation based on the factory stored error compensation values in the Sigrow.
So I need to know at compile time if the OSC20M will be set for 16 or 20 MHz. The setting of the fuse is done during the UPDI upload, so the core knows how to set it.
I looked in the reference for core defines to see if there is a define that I can use with a #if statement. I can't find it. So now the only thing I could come up with is to check F_CPU and derive from that if the OSC20M is set for 16 or 20 MHz.
I like to determine at compile time and not waste flash by reading the OSCCFG register in my program and then applying the right compensation.
I could use the ADC to determine the VCC and automate the 5V vs 3V selection by itself, but that is maybe for later.
This is my test sketch so far:
Beta Was this translation helpful? Give feedback.
All reactions