|
USART baud rate |
|
|
|
Dec 27 2010, 09:43
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Здравствуйте, нужна помощь вот в каком вопросе: пишу инициализацию усарта для Mega48PA Код .equ SYSCLK = 20000000;System Clock [Hz] .equ BaudSpeed0=1200 ;speed of UART .equ bauddivider = (SYSCLK/(16*BaudSpeed0))-1
;************************************************************************ ; USART0_Init ; lds R16,PRR andi R16,255-(1<<PRUSART0);USART0 wake up sts PRR,R16
ldi R16,0b00000000 ;RXCn, TXCn, UDREn, FEn, DORn, UPEn, U2Xn, MPCMn sts UCSR0A,R16
ldi R16,0b00011000 ;RXCIE,TXCIE,UDRIE,RXEN,TXEN,UCSZn2,RXB8,TXB8 sts UCSR0B,R16
ldi R16,0b00000110 ;-, UMSELn, UPMn1, UPMn0, USBSn, UCSZn1, UCSZn0, UCPOLn sts UCSR0C,R16
ldi R16,High(bauddivider) sts UBRR0H,R16 ldi R16,Low(bauddivider) sts UBRR0L,R16 ;BaudRate Gen. при симуляции в протеусе получаю: Код (AVR USART 0)Baud rate = 54212 b/s частота 20МГц выставлена и для контроллера и для кварца. Решил написать инициализацию усарта для 128 меги на С под ИАРом. Скорость установилась как и ожидалось - 1200 Ткните где я не прав
|
|
|
|
|
Dec 27 2010, 09:58
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(HoboTech @ Dec 27 2010, 17:43)  Ткните где я не прав В использовании Протеуса. В программах-моделировщиках и симуляторах можно обкатывать только программные алгоритмы. Работа с периферией проверяется в реальном железе.
|
|
|
|
|
Dec 27 2010, 10:07
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Цитата(rezident @ Dec 27 2010, 15:58)  В использовании Протеуса. В программах-моделировщиках и симуляторах можно обкатывать только программные алгоритмы. Работа с периферией проверяется в реальном железе. а каким способом проверить на какую я скорость его все таки в железе сконфигурировал? с мегой128 на скорости 1200 мега48-я не дружит собсно потому и полез проверять на какую скорость кто сконфижен в протеусе
|
|
|
|
|
Dec 27 2010, 11:31
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Цитата(DpInRock @ Dec 27 2010, 15:21)  В даташите черным по белому приведена таблица делителей для всех кварцев и прочая. согласен, но про скорость 1200 там ничего не сказано Даташит курил и верю ему, но хочется иметь понимание в каком случае тот же протеус привирает
Сообщение отредактировал HoboTech - Dec 27 2010, 11:36
|
|
|
|
|
Dec 27 2010, 12:45
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(V_G @ Dec 27 2010, 17:12)  Не скажу за мегу48 (не работал), но у меги128 есть одна не очень приятная особенность... C m48 в этом смысле - как раз "всё хорошо": все регистры USART0 доступны только через LDS/STS. Цитата(HoboTech @ Dec 27 2010, 17:31)  ...но хочется иметь понимание в каком случае тот же протеус привирает Если уж на МК существуют Errata, то для симуляторов, наверное, даже не стоит выискивать "особенности работы" в части работы периферии... Когда-то давно, я сам пытался составить подобный список, но довольно быстро понял, что занятие это - бессмысленное: в одном и том же симуляторе для разных МК - свои "особенности". И как только накопится небольшой список таких "особенностей" - выходит новая версия симулятора, где устранены одни ошибки и привнесены новые.
|
|
|
|
|
Dec 28 2010, 06:14
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Зашил в мегу8: Код #include <ioavr.h>
#define F_CPU 14745600 #define BAUD 1200
void USART_Init() { UCSRB = (1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN); //enable interrupts during recieve/transmit, enable recieve, enable transmit UCSRC = (1<<UCSZ1)|(1<<UCSZ0); //asynchronous mode, 8 data, 1 stop bit
UBRRH = ((F_CPU/(16*BAUD)-1)>>8); UBRRL = ((F_CPU/(16*BAUD)-1)&0xFF); }
int main( void ) { USART_Init(); asm("sei"); for(;;) { while ( !( UCSRA & (1<<UDRE)) ) ; UDR = 0xAA; for(long i = 0; i<7372;i++); }
} Тыкаю осциллографом в это тельце и вижу: длительность одного бита - 1мс. Почесал репу, заменил формулу для расчета UBRR на Код UBRRH = ((((F_CPU) + 8UL * (BAUD)) / (16UL * (BAUD)) -1UL) >> 8); UBRRL = ((((F_CPU) + 8UL * (BAUD)) / (16UL * (BAUD)) -1UL) & 0xff); Опять тыкаю осциллографом в это тельце и вижу: длительность одного бита примерно 840мкс (1200 б/с). Как так? Формула из даташита в первом случае не дает требуемого результата, в то время как вторая формула, честно подсмотренная где-то в нете, дает почти чистенькие 1200 б/с...
Сообщение отредактировал HoboTech - Dec 28 2010, 06:14
|
|
|
|
|
Dec 28 2010, 06:44
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Это некрасиво: Цитата(HoboTech @ Dec 28 2010, 12:14)  Код UBRRH = ((((F_CPU) + 8UL * (BAUD)) / (16UL * (BAUD)) -1UL) >> 8); UBRRL = ((((F_CPU) + 8UL * (BAUD)) / (16UL * (BAUD)) -1UL) & 0xff); Вот так без тавтологии будет. Код #define BYTE0(X) ((uint8_t)((X)>>0)) #define BYTE1(X) ((uint8_t)((X)>>8)) #define BYTE2(X) ((uint8_t)((X)>>16)) #define BYTE3(X) ((uint8_t)((X)>>24))
void uart_init_tx_8n1(void) { static const uint16_t ubrr = (F_CPU + 8UL * BAUD) / (16UL * BAUD) - 1UL; // эта формула верна ???
UCSRA = 0; UCSRB = 0; UCSRC = (1<<UCSZ0)|(1<<UCSZ1);
UBRRH = BYTE1(ubrr); UBRRL = BYTE0(ubrr);
UCSRB = (1<<TXEN); }
void uart_tx_byte(uint8_t x) { while (!( UCSRA & (1<<UDRE))) {;}
UDR = x; }
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 28 2010, 07:00
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Цитата(demiurg_spb @ Dec 28 2010, 11:44)  Код static const uint16_t ubrr = (F_CPU + 8UL * BAUD) / (16UL * BAUD) - 1UL; // эта формула верна ??? Я ж говорю - честно высмотрел на просторах интернета эту запись. В 2-х прошивках на 128 и 8 мегах работает так точно. А в 48 меге что формула из даташита, что мой вариант дают в протеусе разные скорости, очень далекие от ожидаемых. Собсно из-за этого и поднял тему.
Сообщение отредактировал HoboTech - Dec 28 2010, 07:03
|
|
|
|
|
Dec 28 2010, 07:08
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(HoboTech @ Dec 28 2010, 12:14)  Как так? Формула из даташита в первом случае не дает требуемого результата, в то время как вторая формула, честно подсмотренная где-то в нете, дает почти чистенькие 1200 б/с... Чудеса целочисленного деления/округления... Если честно посчитаете вашу формулу на калькуляторе, как раз около 1000 и получается (1040, если точно). В другой формуле применено округление до ближайшего целого. Плюс, не забываем про UL, иначе при переполнении 2-байтового int вообще чёрт те что может получиться PS: отставить, это коэффициент деления 1040 получился... Значит, скорее всего второй вариант.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Jan 10 2011, 18:57
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(Метценгерштейн @ Jan 11 2011, 00:53)  Из-за чего проблема? Что 8,5% искажения? "Ну а сам-то как думаешь ?" (с) Цитата Надо подбирать кварц для 0% искажений? По крайней мере 2% желательно, если уж нет возможности выбрать из стандартного ряда 3.6864-7.3728-...
|
|
|
|
|
Jan 10 2011, 20:04
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(Метценгерштейн @ Jan 11 2011, 00:53)  Из-за чего проблема? Что 8,5% искажения? Надо подбирать кварц для 0% искажений? Чтобы было 0% искажений, то надо подбирать кварц с такой частотой, чтобы она НАЦЕЛО (т.е. без остатка) делилась на нужную вам частоту в бодах 115200. Если это условие будет соблюдено, то МК сможет выбрать целочисленный делитель (а дробного у него не может быть), чтобы из кварцованной частоты получить рабочую. А если нацело не разделится, то частное придется округлить до целого делителя, и тогда рабочая частота будет получаться не точно, а с искажением. Например, кварцевые частоты 3.6864 МГц и 7.3728 МГц отлично делятся без остатка не только на 115200, но и на все более низкие бодовые частоты: 3686400 / 115200 = 32 7372800 / 115200 = 64 А раз так, то частоту 115200 можно получить из частоты кварца после деления ее на 32 или 64. При этом результат 115200 получится точно. Но вот мы берем кварц на 4 МГц и обнаруживаем, что: 4000000 / 115200 = 34.72 тогда как делитель может быть только целочисленный. Придется тогда нам округлить 34.72 до ближайшего целого, т.е. до 35. Однако с таким делителем вместо нужной вам частоты 115200, получится частота: 4000000 / 35 = 114285 которая на те 8% меньше нормы. А если бы округлили в меньшую сторону - до 34, то тогда искажение стало бы еще больше, только в сторону увеличения: 4000000 / 34 = 117647 Т.е. куда не кинь, всюду клин. Я когда-то тоже не знала про эту кухню и сильно удивлялась, отчего кварцы делают на такие "кривые" частоты  . А как стала с USART работать, так сразу поняла причину. Впрочем, с ошибкой до 2% обычно всё устойчиво работает, хотя в даташите требуют не более пол процента. Ну а 8% - это, конечно, перебор.
|
|
|
|
|
Jan 11 2011, 04:22
|
Группа: Новичок
Сообщений: 8
Регистрация: 8-02-08
Пользователь №: 34 865

|
При скорости 114285 ошибка будет 0,8%, при 117647 - чуть больше 2%.
В принципе ничего криминального.
|
|
|
|
|
Jan 11 2011, 08:45
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Marchello @ Jan 11 2011, 12:22)  При скорости 114285 ошибка будет 0,8%, при 117647 - чуть больше 2%.
В принципе ничего криминального. Это ошибка битового интервала, но в UART синхронизация посимвольная. На символьном интервале ваши числа нужно умножать на длину символа. Типично длина симовла 10-11 бит (старт-бит, 8 бит данных, стоп-бит, иногда еще и бит parity). Вот и получается ошибка на символьном интервале -7,9% и 21% соответственно. Чисто теоретически на некоторых типах UART ошибка на символьном интервале может достигать 50%, но зависит это от конкретной реализации UART и реальной погрешности тактовых генераторов на обеих сторонах линии связи.
|
|
|
|
|
Jan 11 2011, 10:09
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Xenia @ Jan 11 2011, 02:04)  Но вот мы берем кварц на 4 МГц и обнаруживаем, что: 4000000 / 115200 = 34.72 тогда как делитель может быть только целочисленный и, в данном случае, кратный степени 2 Цитата Придется тогда нам округлить 34.72 до 32 Цитата Однако с таким делителем вместо нужной вам частоты 115200, получится частота: 4000000 / 32 = 125000 Цитата которая на те 8% больше нормы. ну и т.д. ... 2 rezident: относительная ошибка останется одинаковой и на битовом, и на символьном интервале. 2 Метценгерштейн: как вариант, убрать кварц и калибровать внутренний генератор по COM-порту. Где-то в аппнотах был пример по auto-baud.
|
|
|
|
|
Jan 11 2011, 17:52
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(xemul @ Jan 11 2011, 18:09)  2rezident: относительная ошибка останется одинаковой и на битовом, и на символьном интервале. Отнюдь! Ошибки битового интервала на символьном интервале суммируются. Считаем время передачи символа из 10 бит 10/114285=87,5мкс 10/115200=86,8мкс (86,8мкс-87,5мкс)*115200*100%= -8% к концу 10-го битового интервала (стоп-бит). А следом за ним (без какой-либо паузы) может идти очередной старт-бит следующего символа. Цитата(ViKo @ Jan 11 2011, 20:42)  Дело не в символьной синхронизации, а в том, что синхронизируется UART по стартовому биту в начале приема символа. А это не то же самое? Однократная синхронизация на периоде времени приема всего символа это разве не (по)символьная синхронизация? Цитата(ViKo @ Jan 11 2011, 20:42)  Еще нужно учесть, что обычно выборок бита берется несколько, сдвинутых по времени, и бит определяется мажоритарным способом. Не во всех типах UART используется именно такой способ. Поэтому я и сделал оговорку ранее.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|