Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2148 UART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Bosicc
Вот глянул доку на LPC2148 и захотел правильно считать значение для загрузки в регистры U0DL, DIVADDVAL, MULVAL.
В деке есть формула и пример расчета коэффициентов для частоты 20MHz, а я хочу посчитать для 12 MHz.
Если считать по упроещеной формуле, без поправочных коэффициентов DIVADDVAL, MULVAL, то получается не совсем то значение baudrate. А вот из каких соображений выбираются поправочные коэффициенты я так и не понял.
Может кто сталкивался, направьте на путь истинный. Или приведите свои значение загружаемые в соответствующие регистры, для установки скорости передачи.
IV_K
что-то я не понял немного, но приведу свой пример установки baud
rate = 19200
CPU_PERIPHERAL_CLK_FREQ = 12000000
unsigned short baud
#define USART_LCR U0LCR
#define USART_DLM U0DLM
#define USART_DLL U0DLL
// установка
USART_LCR |= 0x80;
baud = (CPU_PERIPHERAL_CLK_FREQ / 16) / rate;
USART_DLM = (baud >> 8);
USART_DLL = (unsigned char)baud;
USART_LCR &=~ 0x80;


PS.. sorry.. посмотрел еще раз доку.. вопрос понятен.. DIVADDVAL, MULVAL подбираются для уменьшения ошибки в пределах допустимой
Bosicc
Попробую пояснить еще раз ситуацию.

Если посчитать по формуле из доки

Baudrate = ( PCLK / ( 16 * U0DL) ) * ( MulVal / ( MulVal + DivVal ) ) ;

PCLK = 12 000 000
U0DL = 39 (0x27)
По умолчанию MulVal = 1 и DivVal = 0 Следовательно по формуле Baudrate = 19230,77 Вместо желаемого 19200

Что б получить число максимально приближенное к желаемому, советуют использовать коэффициенты MulVal и DivVal

Если считать по упрощенной формуле

Baudrate = ( PCLK / ( 16 * U0DL) )

То для того что б получить 115200 на частоте 12MHz в регистр U0DL нужно загрузить значение 0x06

при этом получим Baudrate = 125000 вместо желаемого 115200 . Ошибка передачи будет 2-3%

Так как быть с такой задачей.
IV_K
судя по формуле, baud = (plck/(16*16*UDLL+UDLM))*(mul/(mul*div)
могу сказать, что максимальную скорость при использовании fractional baudrate generator на 12МГц можно получить 12000000/16/16 = 46875 =(( я прав?
IV_K
звиняюсь, ерунду спорол.. вроде разобрался..


12000000/16/115200 = 6.51
U0DL = 6
baud = 125000
надо подобрать ( MulVal / ( MulVal + DivVal ) = 115200/125000 = 0.92
MUL = 9, DIV = 1
baud = (12000000/16/6)*(0.9) = 112500
err = 2.3% много..
для уменьшения err уменьшим U0DL
U0DL = 4
MUL = 8, DIV = 5
baud = 115384
err = 0.15% достаточно?
bolmoe
Тут все просто, есть калькулятор от NXP для расчета этих параметров
http://www.standardics.nxp.com/support/doc.../?scope=LPC2000
а там по списку погуляете и найдете smile.gif
Bosicc
Цитата(bolmoe @ Feb 16 2007, 11:30) *
Тут все просто, есть калькулятор от NXP для расчета этих параметров

Спасибо огромное. Я Вчера 4 часа потратил пытаясь методом перебора подобрать оптимальные. А тут просто лафа.
Проблема решена, всем спасибо!
IV_K
блин.. =)))) а я на бумажке считал...
bolmoe
Цитата(Bosicc @ Feb 16 2007, 12:45) *
Цитата(bolmoe @ Feb 16 2007, 11:30) *

Тут все просто, есть калькулятор от NXP для расчета этих параметров

Спасибо огромное. Я Вчера 4 часа потратил пытаясь методом перебора подобрать оптимальные. А тут просто лафа.
Проблема решена, всем спасибо!



я тут еще когда-то баловался с этим, наманстрячил себе функшион))), правда иногда долго вычисляет ~ 1-2 мс (lpc2148 - 60 MHz), но все зависит от точности (%), ее еще можно оптимизировать......

#if SET_BAUDRATE
BOOL Set_baudrate(DWORD baudrate,DWORD com)
{
DWORD tmp,lsb,msb,dummy;
DWORD mulval;
DWORD divaddval;
DWORD max,min;
DWORD div;


msb=(( Fpclk / 16 )/baudrate) / 256;
msb*=16;
lsb=(( Fpclk / 16 )/baudrate) % 256;
dummy=lsb;


/* mulval может изменяться в диапазоне 1 .. 15*/

/*divaddval может изменяться в диапазоне 0 .. 15*/

//проценты указываются с множителем на 100, т.е. 0.5%*100=50;
max=(baudrate*50)/(100*100);
max>>=1;
min=max;
min=(baudrate-min);
max+=baudrate;



for(mulval=1;mulval<16;mulval++)
{
for(divaddval=0;divaddval<16;divaddval++)
{
div=(FDIV*mulval);
div/=(mulval+divaddval);
for(lsb=dummy;lsb>0;lsb--)
{
tmp=div/(msb+lsb);
if(tmp>max) break;
if(tmp > min || tmp==baudrate)
{
if(com)
{
U1DLL = lsb;
U1DLM = msb;
U1FDR = ((mulval<<4)|divaddval);
}
else
{
U0DLL = lsb;
U0DLM = msb;
U0FDR = ((mulval<<4)|divaddval);
}
return TRUE;
}
}
}
}

return FALSE;
}
#endif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.