HoboTech 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба Здравствуйте, нужна помощь вот в каком вопросе: пишу инициализацию усарта для 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 Ткните где я не прав Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба Ткните где я не правВ использовании Протеуса. В программах-моделировщиках и симуляторах можно обкатывать только программные алгоритмы. Работа с периферией проверяется в реальном железе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HoboTech 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба В использовании Протеуса. В программах-моделировщиках и симуляторах можно обкатывать только программные алгоритмы. Работа с периферией проверяется в реальном железе. а каким способом проверить на какую я скорость его все таки в железе сконфигурировал? с мегой128 на скорости 1200 мега48-я не дружит собсно потому и полез проверять на какую скорость кто сконфижен в протеусе Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба а каким способом проверить на какую я скорость его все таки в железе сконфигурировал? с мегой128 на скорости 1200 мега48-я не дружит собсно потому и полез проверять на какую скорость кто сконфижен в протеусе Для этого достаточно внимательно читать даташит, верить ему и также внимательно проверять написанные вами функции инициализации UART и системы тактирования. Никакой симулятор не заменит разум программиста. "Любая программа не умнее программиста, написавшего ее". ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_noise 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба Если, несмотря на внимательность, прочитание и доверяние, всё-таки хочется проверять: - осциллографом: быстро и красиво; - к компьютеру подключиться через порт типа "COM", смотреть программкой типа "терминал": уверены в корректности работы приёмника; - передавать 0b01010101, 0b00010001, 0b00000001: частота следования единичек известна, приёмник в сколько раз быстрее или медленнее их... ... соединять ящик А с ящиком Б унылое занятие, когда нет уверенности в работоспособности хотя бы одного из них вместе с чётким пониманием оной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба В даташите черным по белому приведена таблица делителей для всех кварцев и прочая. А два устройства могут не работать на одной скорости по двум десяткам причин. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
V_G 11 27 декабря, 2010 Опубликовано 27 декабря, 2010 (изменено) · Жалоба Не скажу за мегу48 (не работал), но у меги128 есть одна не очень приятная особенность: младший байт регистра скорости обмена USART0 принадлежит пространству ввода/вывода и читается/пишется командами IN/OUT, а старший - адресному пространству памяти, и с ним работают через LDS/STS. Для младшего байта тоже можно использовать LDS/STS, но к адресу прибавлять 0x20. Изменено 27 декабря, 2010 пользователем V_G Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HoboTech 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 (изменено) · Жалоба В даташите черным по белому приведена таблица делителей для всех кварцев и прочая. согласен, но про скорость 1200 там ничего не сказано Даташит курил и верю ему, но хочется иметь понимание в каком случае тот же протеус привирает Изменено 27 декабря, 2010 пользователем HoboTech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 10 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба Не скажу за мегу48 (не работал), но у меги128 есть одна не очень приятная особенность...C m48 в этом смысле - как раз "всё хорошо": все регистры USART0 доступны только через LDS/STS. ...но хочется иметь понимание в каком случае тот же протеус привираетЕсли уж на МК существуют Errata, то для симуляторов, наверное, даже не стоит выискивать "особенности работы" в части работы периферии... Когда-то давно, я сам пытался составить подобный список, но довольно быстро понял, что занятие это - бессмысленное: в одном и том же симуляторе для разных МК - свои "особенности". И как только накопится небольшой список таких "особенностей" - выходит новая версия симулятора, где устранены одни ошибки и привнесены новые. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 27 декабря, 2010 Опубликовано 27 декабря, 2010 · Жалоба В любом случае - использовать протеус в роли отладчика - на русском языке выражения не подберешь, а в ангийском - таких и вовсе нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Не скажу за мегу48 (не работал), но у меги128 есть одна не очень приятная особенность: младший байт регистра скорости обмена USART0 принадлежит пространству ввода/вывода и читается/пишется командами IN/OUT, а старший - адресному пространству памяти, и с ним работают через LDS/STS. Для младшего байта тоже можно использовать LDS/STS, но к адресу прибавлять 0x20. Ужас... И в такой обстановке кто-то еще пишет программы на ассемблере? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HoboTech 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 (изменено) · Жалоба Зашил в мегу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 б/с... Изменено 28 декабря, 2010 пользователем HoboTech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Это некрасиво: 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HoboTech 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 (изменено) · Жалоба static const uint16_t ubrr = (F_CPU + 8UL * BAUD) / (16UL * BAUD) - 1UL; // эта формула верна ??? Я ж говорю - честно высмотрел на просторах интернета эту запись. В 2-х прошивках на 128 и 8 мегах работает так точно. А в 48 меге что формула из даташита, что мой вариант дают в протеусе разные скорости, очень далекие от ожидаемых. Собсно из-за этого и поднял тему. Изменено 28 декабря, 2010 пользователем HoboTech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 27 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Как так? Формула из даташита в первом случае не дает требуемого результата, в то время как вторая формула, честно подсмотренная где-то в нете, дает почти чистенькие 1200 б/с... Чудеса целочисленного деления/округления... Если честно посчитаете вашу формулу на калькуляторе, как раз около 1000 и получается (1040, если точно). В другой формуле применено округление до ближайшего целого. Плюс, не забываем про UL, иначе при переполнении 2-байтового int вообще чёрт те что может получиться PS: отставить, это коэффициент деления 1040 получился... Значит, скорее всего второй вариант. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться