Ещё один программный UART на ATtiny13



    Привет всем хаброюзерам. Совсем недавно, товарищ Himura опубликовал свою статью UART в ATtiny13 или Как вывести данные из МК за 52р, и тут я вспомнил, что имею кроме предыдущих наработок по этой теме, а именно Трёхканальный UART АЦП на ATtiny13, есть ещё кое-что, часть которой я вырезал из довольно таки любопытного проекта Happy Christmas and Happy New Year wishes from Attiny13, там есть и программный UART, как чтение так и отправка, и ещё кое что по SPI, вообщем рекомендую заглянуть всем кто заинтересовался, правда ресурс англоязычный.
    Вот видео работы:



    Урезав всё, что для меня лишнее из кода товарища Vinod.S, получилось:

    Исходники
    #define F_CPU 9600000
    
    #include <avr/io.h>
    #include <util/delay.h>
    
    #define SOFT_TX_PIN (1<<PB1) // PB1 будет работать как TXD 
    #define SOFT_TX_PORT PORTB
    #define SOFT_TX_DDR DDRB
    
    int helloHabr = 0; 
    
    int main (void) {
      uart_tx_init (); // инициализация прог. UARTа
    
      while (1) {
        helloHabr++; 
        uart_print("Hello Habr, I'm ATtiny13 "); // превед 
        num_to_str(helloHabr, 4); // 0..9999 т.к. только 4 числа можно вывести
        uart_print(" counds"); 
        uart_print("\r\n");	// переход на новую строчку
        _delay_ms(1000); 
      }
      return 0; 
    }
    
    void uart_tx_init ()
    {
      TCCR0A = 1 << WGM01;		// compare mode
      TCCR0B = 1 << CS00;		// prescaler 1
      SOFT_TX_PORT |= SOFT_TX_PIN;
      SOFT_TX_DDR |= SOFT_TX_PIN;
      OCR0A = 75;			//115200 baudrate at prescaler 1
    }
    
    // Функция вывода содержимого переменной
    void num_to_str(unsigned int value, unsigned char nDigit)
    {
      switch (nDigit)
      {
      case 4:
        uart_send_byte((value / 1000) + '0');
      case 3:
        uart_send_byte(((value / 100) % 10) + '0');
      case 2:
        uart_send_byte(((value / 10) % 10) + '0');
      case 1:
        uart_send_byte((value % 10) + '0');
      }
    }
    
    void uart_print(char *str)
    {
      byte i = 0;
      while (str[i]) {
        uart_send_byte(str[i++]);
      }
    }
    
    //bitbanged UART transmit byte
    void uart_send_byte (unsigned char data)
    {
      unsigned char i;
      TCCR0B = 0;
      TCNT0 = 0;
      TIFR0 |= 1 << OCF0A;
      TCCR0B |= (1 << CS00);
      TIFR0 |= 1 << OCF0A;
      SOFT_TX_PORT &= ~SOFT_TX_PIN;
      while (!(TIFR0 & (1 << OCF0A)));
      TIFR0 |= 1 << OCF0A;
      for (i = 0; i < 8; i++)
      {
        if (data & 1)
          SOFT_TX_PORT |= SOFT_TX_PIN;
        else
          SOFT_TX_PORT &= ~SOFT_TX_PIN;
        data >>= 1;
        while (!(TIFR0 & (1 << OCF0A)));
        TIFR0 |= 1 << OCF0A;
      }
      SOFT_TX_PORT |= SOFT_TX_PIN;
      while (!(TIFR0 & (1 << OCF0A)));
      TIFR0 |= 1 << OCF0A;
    }
    


    Arduino IDE без проблем проглотила его:



    Всё это занимает 470 байт, то есть меньше половины памяти ATtiny13, можно ещё немало напрограммировать, если умело использовать ресурсы микроконтроллера.

    Как видите набор символов Hello Hаbr, I'm ATtiny 13 выводиться при помощи функции uart_print("..."); а значение переменных, к примеру, пускай переменная будет называться value, тогда вывод в строчку содержимого будет осуществляться при помощи функции num_to_str(value, 4); где 4 — количество цифр, в данном случае можно вывести значение от 0 до 9999. Строчки uart_print("\r\n"); заканчивают строчку при выводе в UART и осуществляется переход на новую, по аналогии кнопка Enter на клавиатуре. Порт который будет работать как TXD задаётся в строчках #define SOFT_TX_PIN (1<<PB1). На карте портов это выглядит вот так:



    Ну и напоследок — ATtiny13 тактируется от внутренней RC цепочки, настроенной на частоту в 9.6 МГц, делитель на 8 отключён, это задаётся фьюз-битом lf 0x7A.

    Скорость UART'а 115200 бод(англ. baud).

    И напоследок фотосессия:
    image

    image

    Чтобы фотки не пропадали.

    Ссылки:

    UART в ATtiny13 или Как вывести данные из МК за 52р;

    Трёхканальный UART АЦП на ATtiny13;

    Happy Christmas and Happy New Year wishes from Attiny13;

    Прошивка и программирование ATtiny13 при помощи Arduino(обновлено);

    Все мои публикации.

    P.S. Если нагреть микроконтроллер до ~60 градусов, то начнёт приходить мусор, проверил лично, но это простимо учитывая цену ATtiny13.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 47

      0
      Прикольно надо попробывать
        +1
        while (!(TIFR0 & (1 << OCF0A)));
        

        А что там, прерываний нет? Так всю жизнь прождать можно.
          0
          А как нужно? Автор кода как Вы заметили по большому счёту не я, особенно той части что касается вывода.
            +4
            Взвел таймер, поготовил значение. Как таймер стрельнул — вывел значение на ногу, выставил таймер, подготовил следующее значение
            А в главном цикле там программа шарашит свое
              +3
              Если я ещё умел бы это так запрограммировать как Вы сказали…
                0
                Программный UART в прерывании это то же самое что delay…
                  0
                  ..., потому что… ???
            0
            Ээээ… а как на счёт тактовой частоты контроллера, неужели она стабильна? Ведь там используется жутко нестабильный RC-генератор частота которого зависит от напряжения питания и температуры, и довольно серьёзно. А для UART нужна тактовая частота с точностью не хуже +-2%. Неужели контроллер без калибровки поехал, или ваш USB-UART переходник автоматически подстраивается под скорость передачи?
              0
              Нет конечно, скорость UART 115200 выставлена. Стоит только нагреть микроконтроллер до градусов с 50-ти и всё… начинает приходить мусор…
                0
                Значит все-таки конвертор подстраивается под скорость. 50 градусов нагрева это будет уже под 20% отклонение в тактовой частоте.
                Я делал на тиньке девайс, +-10% коррекция предусмотрена программная и её уже на обычных сквозняках не хватает.
                  0
                  Попробуйте снизить до 9600, у меня была подобная проблема на меге8 без кварца, когда от теплового дрифта частоты переставал работать уарт, спаслось уменьшением скорости передачи данных. Вам же не потоковое аудио слать, а мелкие строки, скорее всего — пару байт в секунду, так что 9600 за глаза.
                    0
                    Я бы с удовольствием снизил скорость до 9600, но как? Когда речь заходит про регистры микроконтроллера то я тут особо ничего не понимаю…
                      +2
                      У вас есть шанс и время разобраться =)
                        +2
                        Насколько я понимаю, здесь:

                          TCCR0A = 1 << WGM01; // compare mode
                          TCCR0B = 1 << CS00; // prescaler 1
                          OCR0A = 75; //115200 baudrate at prescaler 1
                        

                        говорится следующее:
                        Таймер настроен на совпадение со значением в регистре OCR0A, на частоте 9.6 МГц.
                        Тогда если выбрать предделитель на 8:
                        TCCR0B = 1 << CS01; // prescaler 8
                        

                        Получим частоту 14400.
                        Теперь чтобы добиться меньшей частоты, необходимо увеличить задержку, через увеличение регистра сравнения:
                        OCR0A = 75, тогда 14400/75=192, 14400-9600=4800, 4800/192=25.
                        Получается такой код:
                          TCCR0A = 1 << WGM01 ;// compare mode
                          TCCR0B = 1 << CS01; // prescaler 8
                          OCR0A = 100; //9600 baudrate at prescaler 8
                        

                          +2
                          Вы объяснили работу таймеров лучше чем первые 5 мануалов в гугле, в которых только сказано «что бы включить делай так».
                            0
                            Рад, что смог объяснить доходчиво, только гуглу не говорите, а то заберет меня в рабство — отвечать на запросы пользователей :)

                            А если серьезно, то это далеко не все возможности таймеров и их режимов. Я еще сам не все использовал в своих приложениях. Попробуйте разобраться с ШИМ, причем как аппаратным, так и программным — это не сложно, а таймеры Вам станут ближе! А прошивку лучше испытывать в программе Proteus, там есть счетчик частоты, логический анализатор, осциллограф и другие полезные штуки для тестов.
                              0
                              Так я и так сначала в симуляторе тренируюсь, а потом уже в железо переношу. Правда сейчас по работе перешел на ARM STM32. Мне они показались более гибкими чем avr'ки, хотя у них ресурсов поболее будет. Еще 9 тинек осталось и несколько посылок с китая в пути. Как время будет заряжу что ни будь на них.
                                0
                                STM32 замечательны когда нужны такие вычислительные мощности, для более простых задач это оверхед.
                            0
                            Увы, но не заработало.
                              0
                              Приходит мусор.
                                0
                                Осциллограф есть? Определить бы скорость в результате модификации…
                                  0
                                  Увы но нет.
                                    0
                                    тогда пробуйте подбирать близкие скорости с шагом в 0.5%
                                      0
                                      Не получится :(
                                      Насколько я понял ТС юзает такую: байду, и судя по описанию, она на PL-2303

                                      А вот ДШ на PL-2303, в котором сказано, что частота в ней программируемая. То есть сама она не подстраивается, а задается.
                                        0
                                        Сетка скоростей получается делением опорной частоты на какой-то делитель. Так что скорость подбирать получится еще как, особенно на малых скоростях шаг будет точнее чем ближе к максимальным.
                                      +1
                                      9600 прекрасно берется входом аудиокарты… посчитать период с записанного с аналогового входа этот сигнал в программе вроде CoolEdit на 96К не представляется проблемой.
                              0
                              Проблема не уйдет, поскольку скорость даже на 9600 точно так же привязана к тактовой частоте, относительное изменение скорости будет точно таким же.
                                +1
                                Вы не учли такой показатель как шаг градуирования, который этим действием увеличен в 10 раз, что дает увеличение точности, благодаря увеличенному диапазону дрейфа частоты.
                                Ваше: «Проблема не уйдет...», применимо в данной задаче в любых условиях (так как идеальных не существует в природе).
                                Но очевидно, что проявления указанных недостатков, благодаря снижению частоты, будут отложены так как 1% намного менее 10% (кстати как и 2% < 20%)
                                  0
                                  тактовая частота уходит одинаково. для формирования интервалов мы опираемся только на неё, и если она уплывёт на 10% то скорость 115200 будет так же отличаться на 10% и 9600 уйдут на те же 10%. Ну да, изначальную скорость можно будет выставить точнее, но речь идет о уходе частоты после калибровки.
                                    0
                                    Это справедливо (с натяжкой) при условии одинаковой задержки.
                                    Повторюсь: при использовании внутреннего задающего генератора частоты, у Вас нет альтернатив. Вы не сможете его откалибровать через вычисление задержек, потому как в критических условиях, погрешности спонтанны. Они — шум на графике, и если вы откалибруете «константу» в момент времени T0, то для T1 она будет отличаться. А усреднение показателей при длинных итерациях, даже если и будет достижимо разрядностью, то даст поправку только для временного интервала Т'. И пока вы будете гонять циклы итераций для усреднения, наступит время интервала T'', в котором Ваши, усредненные показатели уже не действительны.
                                      0
                                      Что за моменты времени T0 и T1? И причем тут время?
                                      У нас есть только два параметра — тактовая частота и скорость передачи. Они жестко связаны. В этом вопросе не касаемся проблемы джиттера — она не устранима при таком способе формирования.
                                      Уходит тактовая частота — и в след за ней уходит скорость передачи. Как только она уходит дальше чем может обеспечить приемник устойчивый прием — начинается мусор.
                                        0
                                        Я чего-то не до-понимаю, Вы пришли с решением проблемы, или — за ним?
                                        Или мы друг друга сознательно убеждаем в нерешимости проблемы?! :)
                                          0
                                          определиться надо какую проблему решаем?
                                          В лоб пробелма неразрешима, нужна какая-то опорная частота, в МК с RC-генератором ей взяться неоткуда — от напряжения питания и температуры эта частота плавает. Причем как правило не мгновенно, если периодически калибровать по какому-то внешнему источнику то можно удержаться в пределах. У меня калибровка основана именно на внешнем источнике образцовой частоты(через измерение длительности специально сформированного стартового импульса перед передачей пакета данных).

                                          А к вашему посту, для понимания сказанного очень не хватает иллюстрации.

                                          Проблемы кстати нет если использовать контроллер ATTINY85 или ATTINY45 у которого RC-генератор встроенный с термокомпенсацией — один раз откалибровал и без проблем.
                                          0
                                          Просто решение очень банальное и копеечное:
                                          вот одно, а вот второе
                                            0
                                            Тинька 20Мгц не потянет, к тому же один вывод будет использован, а их бывает хватает только впритык.
                                            К тому же, если вы бы заглянули бы в даташит ATTINY13 не работает с кварцевым резонатором принципиально — у неё нет встроенного кварцевого генератора для работы с резонаторами, только режим работы от внешней тактовой частоты.
                                              0
                                              К тому же, если вы бы заглянули бы,

                                              Вот и загляните, с генератором работает.
                                              На первой странице:
                                              Advanced RISC Architecture
                                              – 120 Powerful Instructions – Most Single Clock Cycle Execution
                                              – 32 x 8 General Purpose Working Registers
                                              – Fully Static Operation
                                              – Up to 20 MIPS Througput at 20 MHz

                                              На 24-ой:
                                              CKSEL[1:0] Device Clocking Option
                                              00 External Clock (see page 24)
                                              01,10 Calibrated Internal 4.8/9.6 MHz Oscillator (see page 25)
                                              11 Internal 128 kHz Oscillator (see page 26)
                                                0
                                                Ага. Именно то что я и сказал. Три режима работы с внутренним RC-генератором, и режим входа внешнего источника частоты. Режима работы с кварцевым резонатором НЕТ.
                                                External Clock — это и есть вход тактовой частоты, у него нет выхода генератора для кварцевого резонатора.
                                                  0
                                                  А где я говорил про кварцевый резонатор? А то я что-то утомлен.
                                                    0
                                                    По ссылкам, они ведут на кварцевые резонаторы а не генераторы.
                                                      0
                                                      Пример генератора но ценник не гуманный.
                                                        0
                                                        Учите мат-часть, у генератора 4 контакта или больше, у резонатора два.
                                                          0
                                                          Боюсь разочаровать, но это лишь необходимое но не достаточное условие. Кварцы бывают и в 4-х контактном корпусе где используются только два из них, иногда туда же помещают и конденсаторы выводя их на третий вывод.
                                                            0
                                                            А, ну точно! Еще в корпус XMega помещают ATTiny, a в корпусе i7 можно на Pentium-II нарваться :)
                                                            Видимо по этой банальной причине ATTiny не запускается от внешнего генератора на 20 МГц!
                                                              0
                                                              Только не валите все на китайцев, они парни отличные, и умные.
                                                              Со многими из них знаком лично, с ними можно дела вести, для них это дело чести!
                                                              0
                                                              Типичный 4-х контактный кварц.
                                                              image
                                                                0
                                                                Тогда вынужден извиниться, не встречал. Видимо потому что стараюсь использовать подножное.
                                                                такие и такие, тоже не подходят?
                                                                И если подходят, проблема решена?
                                                                  0
                                                                  Подходят. Но… жаба давит, это уже не 7 копеек. И для использования с UART-ом лучше найти генератор на кратную частоту.

                                Only users with full accounts can post comments. Log in, please.