|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Jun 20 2013, 08:33
|
Знающий
   
Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163

|
Макросом дробный делитель сложновато считать. У меня кодом считается при необходимости: 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] - для короткого!!!
|
|
|
|
|
Jun 20 2013, 09:54
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(andrewlekar @ Jun 20 2013, 12:33)  Макросом дробный делитель сложновато считать. У меня кодом считается при необходимости: С кодом то понятно, просто jcxz утверждает, что ВСЕ прескалеры макросами получаются. Может есть какой то "красивый" способ. Цитата(jcxz @ Jun 20 2013, 11:40)  В моих проектах все частоты (UART, SPI и т.п.) задаются дефайнами, от которых макросами рассчитываются необходимые делители, прескалеры, делители PCLK и пр. Если данную частоту невозможно обеспечить физически, принимается ближайшая большая/меньшая или выводится #error компиляции (по ситуации). вот и интересен пример такого макроса для этого вида UART
|
|
|
|
|
Jun 20 2013, 10:27
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (jcxz @ Jun 20 2013, 16:40)  Ну вообще-то только так и надо делать. В моих проектах все частоты (UART, SPI и т.п.) задаются дефайнами, от которых макросами рассчитываются необходимые делители, прескалеры, делители PCLK и пр. Нет, Вы меня не правильно поняли  Когда я написал формулами и без препроцессора, я подразумевал, что всё считается в коде, как показал andrewlekar Места в нынешних контроллерах до фига, смысла экономить на спичках нет
--------------------
Выбор.
|
|
|
|
|
Jun 20 2013, 12:35
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 12-09-05
Пользователь №: 8 478

|
Спасибо за ответы. Не обязательно что калькуляторы ошибочные. Был сайт с калькулятором где можно было задать частоту и необходимую скорость обмена все работало. Сейчас не могу вспомнить где он был. Взял программу по расчету скорости UART. Настроил UART до скорости 480600 частота 24МГц. Но 921600 никак не хочет синхронизироваться.
|
|
|
|
|
Jun 21 2013, 06:40
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 12-09-05
Пользователь №: 8 478

|
Умножение 16 * 921600 = 14 745 600 что меньше 24 000 000.
|
|
|
|
|
Jun 22 2013, 10:58
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 12-09-05
Пользователь №: 8 478

|
Частота кварца 12 000 000 Частота процессора 48 000 000 Частота переферии 24 000 000
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|