Перейти к содержанию
    

Здравствуйте, нужна помощь вот в каком вопросе:

пишу инициализацию усарта для 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

 

Ткните где я не прав

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ткните где я не прав
В использовании Протеуса.

В программах-моделировщиках и симуляторах можно обкатывать только программные алгоритмы. Работа с периферией проверяется в реальном железе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В использовании Протеуса.

В программах-моделировщиках и симуляторах можно обкатывать только программные алгоритмы. Работа с периферией проверяется в реальном железе.

 

а каким способом проверить на какую я скорость его все таки в железе сконфигурировал? с мегой128 на скорости 1200 мега48-я не дружит

собсно потому и полез проверять на какую скорость кто сконфижен в протеусе

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а каким способом проверить на какую я скорость его все таки в железе сконфигурировал? с мегой128 на скорости 1200 мега48-я не дружит

собсно потому и полез проверять на какую скорость кто сконфижен в протеусе

Для этого достаточно внимательно читать даташит, верить ему и также внимательно проверять написанные вами функции инициализации UART и системы тактирования. Никакой симулятор не заменит разум программиста. "Любая программа не умнее программиста, написавшего ее". ;)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если, несмотря на внимательность, прочитание и доверяние, всё-таки хочется проверять:

 

- осциллографом: быстро и красиво;

- к компьютеру подключиться через порт типа "COM", смотреть программкой типа "терминал": уверены в корректности работы приёмника;

- передавать 0b01010101, 0b00010001, 0b00000001: частота следования единичек известна, приёмник в сколько раз быстрее или медленнее их...

 

... соединять ящик А с ящиком Б унылое занятие, когда нет уверенности в работоспособности хотя бы одного из них вместе с чётким пониманием оной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В даташите черным по белому приведена таблица делителей для всех кварцев и прочая.

 

А два устройства могут не работать на одной скорости по двум десяткам причин.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не скажу за мегу48 (не работал), но у меги128 есть одна не очень приятная особенность: младший байт регистра скорости обмена USART0 принадлежит пространству ввода/вывода и читается/пишется командами IN/OUT, а старший - адресному пространству памяти, и с ним работают через LDS/STS. Для младшего байта тоже можно использовать LDS/STS, но к адресу прибавлять 0x20.

Изменено пользователем V_G

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В даташите черным по белому приведена таблица делителей для всех кварцев и прочая.

 

согласен, но про скорость 1200 там ничего не сказано

 

Даташит курил и верю ему, но хочется иметь понимание в каком случае тот же протеус привирает

Изменено пользователем HoboTech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не скажу за мегу48 (не работал), но у меги128 есть одна не очень приятная особенность...
C m48 в этом смысле - как раз "всё хорошо": все регистры USART0 доступны только через LDS/STS.

 

 

...но хочется иметь понимание в каком случае тот же протеус привирает
Если уж на МК существуют Errata, то для симуляторов, наверное, даже не стоит выискивать "особенности работы" в части работы периферии... Когда-то давно, я сам пытался составить подобный список, но довольно быстро понял, что занятие это - бессмысленное: в одном и том же симуляторе для разных МК - свои "особенности". И как только накопится небольшой список таких "особенностей" - выходит новая версия симулятора, где устранены одни ошибки и привнесены новые.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В любом случае - использовать протеус в роли отладчика - на русском языке выражения не подберешь, а в ангийском - таких и вовсе нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не скажу за мегу48 (не работал), но у меги128 есть одна не очень приятная особенность: младший байт регистра скорости обмена USART0 принадлежит пространству ввода/вывода и читается/пишется командами IN/OUT, а старший - адресному пространству памяти, и с ним работают через LDS/STS. Для младшего байта тоже можно использовать LDS/STS, но к адресу прибавлять 0x20.

Ужас... И в такой обстановке кто-то еще пишет программы на ассемблере?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зашил в мегу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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это некрасиво:

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;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

static const uint16_t ubrr = (F_CPU + 8UL * BAUD) / (16UL * BAUD) - 1UL; // эта формула верна ???

 

 

Я ж говорю - честно высмотрел на просторах интернета эту запись. В 2-х прошивках на 128 и 8 мегах работает так точно. А в 48 меге что формула из даташита, что мой вариант дают в протеусе разные скорости, очень далекие от ожидаемых. Собсно из-за этого и поднял тему.

Изменено пользователем HoboTech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как так? Формула из даташита в первом случае не дает требуемого результата, в то время как вторая формула, честно подсмотренная где-то в нете, дает почти чистенькие 1200 б/с...

Чудеса целочисленного деления/округления...

Если честно посчитаете вашу формулу на калькуляторе, как раз около 1000 и получается (1040, если точно).

В другой формуле применено округление до ближайшего целого.

Плюс, не забываем про UL, иначе при переполнении 2-байтового int вообще чёрт те что может получиться

 

PS: отставить, это коэффициент деления 1040 получился...

Значит, скорее всего второй вариант.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...