Макросом дробный делитель сложновато считать. У меня кодом считается при необходимости:
CODE
#ifdef USE_CALC_FRACTIONAL_DIVIDER
//расчёт дробного делителя UART для минимизации процента ошибок.
//19200 и 115200 позволяет использовать с 0 ошибкой для кварца 11,0592.
static void uart_calc_divisors(uint_fast32_t baudrate, int *pDiv, int *pAddDiv, int *pMul, int *error)
{
uint_fast32_t uClk;
uint_fast32_t calcBaudrate = 0;
uint_fast32_t temp = 0;
int mulFracDiv, dividerAddFracDiv;
int diviser = 0;
int mulFracDivOptimal = 1;
int dividerAddOptimal = 0;
int diviserOptimal = 0;
int relativeError = 0;
int relativeOptimalError = 10000;
uClk = CPU_PERIPH_CLOCK >> 4; // div by 16
// In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers
// The formula is :
// BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
// It involves floating point calculations. That's the reason the formulae are adjusted with
// Multiply and divide method.
// The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
// 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15
for (mulFracDiv = 1; mulFracDiv <= 15;mulFracDiv++)
{
for (dividerAddFracDiv = 0; dividerAddFracDiv <= 15;dividerAddFracDiv++)
{
temp = (mulFracDiv * uClk) / ((mulFracDiv + dividerAddFracDiv));
diviser = temp / baudrate;
if ((temp % baudrate) > (baudrate / 2))
diviser++;
if ((diviser > 2) && (diviser < 65536))
{
calcBaudrate = temp / diviser;
if (calcBaudrate <= baudrate)
relativeError = baudrate - calcBaudrate;
else
relativeError = calcBaudrate - baudrate;
if ((relativeError < relativeOptimalError))
{
mulFracDivOptimal = mulFracDiv;
dividerAddOptimal = dividerAddFracDiv;
diviserOptimal = diviser;
relativeOptimalError = relativeError;
if (relativeError == 0)
break;
}
}
}
if (relativeError == 0)
break;
}
*pDiv = diviserOptimal;
*pAddDiv = dividerAddOptimal;
*pMul = mulFracDivOptimal;
*error = relativeOptimalError;
}
#else //!USE_CALC_FRACTIONAL_DIVIDER
//UART baudrate formula : PCLK / (16 * UART1_MAIN_DIV * (1 + (FRACTIONAL_UART1_DIV / FRACTIONAL_UART1_MUL)))
//For 11.0592 MHz , CCLK = 99532800, PCLK = 24883200
//Baudrate = 115200
#if (UART1_BAUDRATE == 115200)
#define FRACTIONAL_UART1_DIV 1
#define FRACTIONAL_UART1_MUL 2
#define UART1_MAIN_DIV 9
#endif
//Baudrate = 19200
#if (UART1_BAUDRATE == 19200)
#define FRACTIONAL_UART1_DIV 0
#define FRACTIONAL_UART1_MUL 1
#define UART1_MAIN_DIV 81
#endif
//wrong baudrate
#if ((UART1_BAUDRATE != 115200) && (UART1_BAUDRATE != 19200))
#error "Wrong UART1 baudrate"
#endif
#endif //USE_CALC_FRACTIONAL_DIVIDER
Сообщение отредактировал IgorKossak - Jun 20 2013, 09:51
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!