/* ========================= * ===== Sercom UART * ========================= */ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { initClockNVIC(); resetUART(); //Setting the CTRLA register sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | SERCOM_USART_CTRLA_SAMPR(sampleRate); //Setting the Interrupt register sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete SERCOM_USART_INTENSET_ERROR; //All others errors if ( mode == UART_INT_CLOCK ) { uint16_t sampleRateValue; if (sampleRate == SAMPLE_RATE_x16) { sampleRateValue = 16; } else { sampleRateValue = 8; } // Asynchronous fractional mode (Table 24-2 in datasheet) // BAUD = fref / (sampleRateValue * fbaud) // (multiply by 8, to calculate fractional piece) uint32_t baudTimes8 = (SystemCoreClock * 8) / (sampleRateValue * baudrate); sercom->USART.BAUD.FRAC.FP = (baudTimes8 % 8); sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8); } }
/* ========================= * ===== Sercom UART * ========================= */ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { #if (SAML21) // On the SAML21, SERCOM5 is on PD0, which is a low power domain on a different bridge than the other SERCOMs. // SERCOM5 does not support SAMPLE_RATE_x8 or SAMPLE_RATE_x3. if (sercom == SERCOM5) { sampleRate = SAMPLE_RATE_x16; } #endif initClockNVIC(); resetUART(); //Setting the CTRLA register sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | SERCOM_USART_CTRLA_SAMPR(sampleRate); //Setting the Interrupt register sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete SERCOM_USART_INTENSET_ERROR; //All others errors if ( mode == UART_INT_CLOCK ) { uint16_t sampleRateValue; if (sampleRate == SAMPLE_RATE_x16) { sampleRateValue = 16; } else { sampleRateValue = 8; } #if 0 // Asynchronous arithmetic mode // 65535 * ( 1 - sampleRateValue * baudrate / SercomClock); // 65535 - 65535 * (sampleRateValue * baudrate / SercomClock)); // sercom->USART.BAUD.reg = 65535.0f * ( 1.0f - (float)(sampleRateValue) * (float)(baudrate) / (float)(SercomCoreClock)); // this pulls in 3KB of floating point math code // make numerator much larger than denominator so result is integer (avoid floating point). uint64_t numerator = ((sampleRateValue * (uint64_t)baudrate) << 32); // 32 bits of shifting ensures no loss of precision. uint64_t ratio = divide64(numerator, SercomClock); uint64_t scale = ((uint64_t)1 << 32) - ratio; uint64_t baudValue = (65536 * scale) >> 32; sercom->USART.BAUD.reg = baudValue; #endif // Asynchronous fractional mode (Table 24-2 in datasheet) // BAUD = fref / (sampleRateValue * fbaud) // (multiply by 8, to calculate fractional piece) uint32_t baudTimes8 = (SercomClock * 8) / (sampleRateValue * baudrate); sercom->USART.BAUD.FRAC.FP = (baudTimes8 % 8); sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8); }
/* ========================= * ===== Sercom UART * ========================= */ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { initClockNVIC(); resetUART(); //Setting the CTRLA register sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | SERCOM_USART_CTRLA_SAMPR(sampleRate); //Setting the Interrupt register sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete SERCOM_USART_INTENSET_ERROR; //All others errors if ( mode == UART_INT_CLOCK ) { uint16_t sampleRateValue ; if ( sampleRate == SAMPLE_RATE_x16 ) { sampleRateValue = 16 ; } else { if ( sampleRate == SAMPLE_RATE_x8 ) { sampleRateValue = 8 ; } else { sampleRateValue = 3 ; } } // Asynchronous arithmetic mode // 65535 * ( 1 - sampleRateValue * baudrate / SystemCoreClock); // 65535 - 65535 * (sampleRateValue * baudrate / SystemCoreClock)); sercom->USART.BAUD.reg = 65535.0f * ( 1.0f - (float)(sampleRateValue) * (float)(baudrate) / (float)(SystemCoreClock)); } }