Mega2560, быстрая библиотека для UART (типа CyberLib)

Тема в разделе "Arduino & Shields", создана пользователем Vovka, 20 ноя 2019.

Метки:
  1. Vovka

    Vovka Гик

    Столкнулся с такой ситуацией: в CyberLib нет работы с UART, а стандартная библиотека не подходит, нужно что-то максимально быстрое, чтобы принять из одного UART-а, сделать вычисления и передать в другой UART.
    Может кто уже дополнил эту библиотеку или написал свою - поделитесь пожалуйста!
    PS. Там есть ссылка на улучшенную версию, но на Гитхабе этой библиотеки уже нет :(
     
  2. parovoZZ

    parovoZZ Гуру

    А на фига там вообще библиотека? Пару регистров проинициализировать?
    (код защищен от копирования путем копипасты!)
    uart.png
    В меге названия регистров надо смотреть в даташите. Возможно, что различаются!
     
    timon и Daniil нравится это.
  3. SergeiL

    SergeiL Оракул Модератор

    Вот предсказуемо, ждал выхода @parovoZZ.
    А почему только инициализация? Где вектора? :)
     
    Airbus, Vovka и issaom нравится это.
  4. parovoZZ

    parovoZZ Гуру

    В заголовочнике на МК надо смотреть. Возможно, есть в даташите, но это не точно) Мне лень опять грузить AS, переключать МК и смотреть его. Сами вполне способны проделать эти операции.
     
  5. Vovka

    Vovka Гик

    Крутая защита: картинка :)
    Посмотришь форум, так все крутые программеры, советы раздаю направо и налево, а как до конкретики, так
    Может кто реально с Мегой и с портами работал, и поделится...
     
  6. DetSimen

    DetSimen Guest

    А наскока надо быстро? У мня обычная UNO на 256'000 бит шарашит и хоть бы хрен по деревне
    003.jpg
    004.jpg
     
    Последнее редактирование модератором: 21 ноя 2019
    Andrey12 нравится это.
  7. parovoZZ

    parovoZZ Гуру

    А своя голова на что? Скажи, что не понимаешь?
     
  8. akl

    akl Гуру

    насколько я смог разобраться в стандартной ардуиновой работе с уартом, там вроде все нормально организовано, на прерываниях, с кольцевыми буферами. Может и нету этого в прокачанных альтернативах потому что убыстрять особо нечего :oops:
     
  9. timon

    timon Гик

    Не понимает что такое регистры МК и почему они в разных МК могут называться по разному. Глубина понимания упирается в библиотеку. Что ниже библиотеки - уже колдовство и туда не надо.

    Уважаемый Vovka, мой вам совет как от не программиста к не программисту:
    • возьмите код Паровоза, он сгодится как пример что бы понять про регистры.
    • откройте даташит на ваш МК и посмотрите как называются регистры USART-a (страница 200, раздел 22), в частности 22.5 USART Initialization. Код на С я вам прямо к сообщению пристегнул.
    • в пункте 22.2 Overview говорится, что USART0, USART1, USART2, and USART3 have different I/O registers, то есть имеют различные регистры, о чем говорится в “Register Summary” на странице 399.
    • проследовав на страницу 399, понимаешь что различия между регистрами скорости для разных портов (например Baud Rate Register High Byte UBRR0H, UBRR1H, UBRR2H) - незначительны и пригодны для понимания сразу.
    • Паровоз вам показал как инициализировать нулевой USART. Как инициализировать первый и потом перекинуть данные из нулевого в первый - догадаться не трудно ведь?
     

    Вложения:

    Последнее редактирование: 21 ноя 2019
    parovoZZ нравится это.
  10. asam

    asam Гик

    А чем стандартная библиотека не подходит? На какой скорости передаются данные по UART и в каком количестве? Где тормозит на стандартной библиотеке? Пример кода демонстрирующий тормоза есть?

    Может дело не в бобине?
     
  11. timon

    timon Гик

    Ну вы даете... Паровоз, выше, уже поделился всем, что вам необходимо, абсолютно исчерпывающе.
     
    Daniil нравится это.
  12. parovoZZ

    parovoZZ Гуру

    Раз задан вопрос, то на него должен быть дан ответ.
    Код (C++):
    /* USART0, Rx Complete */
    #define USART0_RX_vect_num        25
    #define USART0_RX_vect            _VECTOR(25)
    #define SIG_USART0_RECV            _VECTOR(25)

    /* USART0 Data register Empty */
    #define USART0_UDRE_vect_num    26
    #define USART0_UDRE_vect        _VECTOR(26)
    #define SIG_USART0_DATA            _VECTOR(26)

    /* USART0, Tx Complete */
    #define USART0_TX_vect_num        27
    #define USART0_TX_vect            _VECTOR(27)
    #define SIG_USART0_TRANS        _VECTOR(27)
    Для остальных UARTов по аналогии.
     
  13. Vovka

    Vovka Гик

    Код (C++):

    #define NOP __asm__ __volatile__ ("nop\n\t")
    #define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 4UL)) / ((uint32_t)(baudRate) * 8UL) - 1)
    void UART0_Init(uint32_t UART_BAUD_RATE )
    {
        UBRR0H = (UART_CALC_BAUDRATE(UART_BAUD_RATE)>>8) & 0xFF;
        UBRR0L = (UART_CALC_BAUDRATE(UART_BAUD_RATE) & 0xFF);
        UCSR0A = (1 << U2X0 ); // удвоение скорости
        UCSR0B = (1 << RXCIE0)|(1 << RXEN0)|(1 << TXEN0);    // разрешение прерывания приема, разрешение приема и передачи
    //    UCSR0C = (1 << UCSZ01)|(1 << UCSZ00);
        UCSR0C = (3 << UCSZ00);
    }
    void UART0_SendByte(uint8_t data)
    {
        while ( !(UCSR0A & (1 << UDRE0)) ) NOP;    // пока не пуст регистр данных
        UCSR0B &= ~(1 << RXEN0);
        UDR0 = data;
        while ( !(UCSR0A & (1 << UDRE0)) ) NOP;    // пока не пуст регистр данных
        UCSR0B |= (1 << RXEN0);
    }
    void UART1_Init(uint32_t UART_BAUD_RATE )
    {
        UBRR1H = (UART_CALC_BAUDRATE(UART_BAUD_RATE)>>8) & 0xFF;
        UBRR1L = (UART_CALC_BAUDRATE(UART_BAUD_RATE) & 0xFF);
        UCSR1A = (1 << U2X1 );
        UCSR1B = (1 << RXCIE1)|(1 << RXEN1)|(1 << TXEN1);
        UCSR1C = (3 << UCSZ10);
    }

    void UART1_SendByte(uint8_t data)
    {
        while ( !(UCSR1A & (1 << UDRE1)) ) NOP;
        UCSR1B &= ~(1 << RXEN1);
        UDR1 = data;
        while ( !(UCSR1A & (1 << UDRE1)) ) NOP;
        UCSR1B |= (1 << RXEN1);
    }

    void setup()
    {
       UART0_Init( 19200 );
       UART1_Init( 19200 );
    }

    ISR(USART0_RX_vect)
    {
      UART1_SendByte( UDR0 );
    }

    ISR(USART1_RX_vect)
    {
         UART0_SendByte( UDR1 );
    }

    void loop()
    {
       NOP;
    }
     
    В итоге:
    - если с терминала посылаю байт с UART0 в UART1, то в UART1 байт приходит без ошибок, но и одновременно в UART0 тоже приходит этот байт, а иногда мусор.
    - если с терминала посылаю байт из UART1 в UART0, то в UART0 ничего не приходит!
    что не так?
     
  14. timon

    timon Гик

    Вы еще порты забыли направить как положено.
    2019-11-22_16-27-12.png
    Смотрите, USART0 на вашем МК это пины РЕ0 и РЕ1 порта Е (РЕ это обозначение PORT E, а номера - ноги МК, они же биты порта Е). По своей сути порт является полновесным байтом (8 бит) и каждую его ногу/бит можно направить обычным битом (0 на вход, 1 на выход). Это аналог ардуиновской функции pinMode(). То есть вам надо в функцию инициализации вставить "направлятор" ног (какая на чтение, какая на запись), что бы TX был на выход (в единичке), а RX соответственно на вход (в нуле):
    команду DDRE b00000010; где DDR это Data Direction Register а E это порт Е а b00000010 - это байт в бинарном представлении для наглядности как ноги будут соориентированы (самое правое значение это РЕ0, самое левое - РЕ7).
    То же самое необходимо будет проделать с USART1, пины на МК которого расположены на порту... ?? )))
    2019-11-22_16-44-52.png
    ... и соответственно команда DDRчотам? и байт b00000000 - как должен выглядеть? Что бы RX на вход, а TX на выход ))

    Вообще я чертовски раз за вас, что вот так без криков памагитя - спокойно начали писать свой модуль инициализации без всяких ардуиновских либ.
     
    Последнее редактирование: 22 ноя 2019
    Daniil нравится это.
  15. parovoZZ

    parovoZZ Гуру

    какие-то лишние действия. Достаточно взвести биты RXENx и TXENx и эти ноги сами переключатся на модуль USARTx. Малое x - номер UARTа в МК.
     
    timon нравится это.
  16. parovoZZ

    parovoZZ Гуру

    если МК больше НИЧЕГО НЕ ДЕЛАЕТ (а только занимается пересылкой данных), то я бы копировал данные из одного интерфейса в другой по готовности флагов приема и передачи.
     
  17. timon

    timon Гик

    Вот как знал, что херню опять сморожу ))) даже писать не хотел, но бесы заставили!
     
  18. Vovka

    Vovka Гик

    а вот в PIC-ах достаточно было включить сам модуль, чтобы ноги сконфигурировались :(
     
  19. Vovka

    Vovka Гик

    если бы, но там еще GSM-модуль и ИК-пульт в довесок :(
     
  20. parovoZZ

    parovoZZ Гуру

    а вот в MSP430 альтернативные функции (а их 3-4) ног переключаются отдельным регистром. И что надо записать в регистр так с ходу и не разберешься, пока дашик не выкуришь.