реклама на сайте
подробности

 
 
> Программный UART для Tiny13
Skaf
сообщение Oct 2 2009, 20:18
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 228
Регистрация: 4-06-09
Пользователь №: 49 940



Есть замечательные, маленькие и дешевые микроконтроллеры ATtiny13. У них толкьо один минус- нет UART.

Я подумал что смогу написать его сам. Временные интервалы отсчитывает таймер. Однако не удается никак заставить его передавать данные с нужной скоростью.


Вот код программы

Код
/*************************************
Software UART
**************************************/

   #include <avr/io.h>
   #include <avr/iotn13.h>
   #include <avr/interrupt.h>


unsigned char _GetBit (unsigned char byte, unsigned char bit){
    byte &= 1<<(bit);

    if(byte){
        return 1;
    } else {
        return 0;
    }
}

// --------- SOFT UART -------------------

volatile unsigned char SU_DataByte, SU_BitCounter, SU_Mode, SU_SpeecConst;

void SU_On(void){
    TCCR0B = (1<<CS00);
    //TCNT0 = SU_SpeecConst;
}

void SU_Off(void){
    TCCR0B = (0<<CS00);
    SU_Mode = 5;
}

ISR(TIM0_OVF_vect){
    TCNT0 = SU_SpeecConst - TCNT0;

    switch(SU_Mode){
        case 4 : SU_Off(); break;
        case 3 : PORTB |= 1<<1; SU_Mode = 4; break; // Stop bit
        case 2 :
            if (_GetBit(SU_DataByte, SU_BitCounter)){
                PORTB |= 1<<1; // 1
            } else {
                PORTB &= ~1<<1; // 0
            }
            SU_BitCounter++;
            if (SU_BitCounter == 8){
                SU_Mode = 3;
                TCNT0 = SU_SpeecConst;
            }
            break;
        case 1 : PORTB &= ~1<<1; SU_Mode = 2; break; // Start bit
        case 0 : SU_Mode = 1; break; // Empty cycle
    }
}


void SU_Init(void){
    TIMSK0 = (1<<TOIE0); // Ðàçðåøåíèå ïðåðûâàíèé ïî ïåðåïîëíèþ
    SU_Mode = 5; // Off
    SU_SpeecConst = 127;
    PORTB |= 1<<1; // 1
}

void SU_Send(unsigned char Data){
    if (SU_Mode == 5){ // If Soft Uart can be use
        SU_DataByte = Data;
        SU_BitCounter = 0;
        SU_Mode = 0; // Empty cycle
        SU_On();
    }
}

int main(void) {    // íà÷àëî îñíîâíîé ïðîãðàììû
    DDRB = 0b00000010;  // Âûõîäû
    SREG |= 1<<7; // Ãëîáàëüíî ðàçðåøàåì ïðåðûâàíèÿ
    SU_Init();

    unsigned char buttons;

    buttons = PINB;

    while(1){
        if (PINB != buttons){ // Èçìåíèëîñü ñîñòîÿíèå êëàâèø
            if (!_GetBit(PINB, 2)){ // +1
                SU_SpeecConst++;
                SU_Send(0x55);
            }
            if (!_GetBit(PINB, 3)) { // -1
                SU_SpeecConst--;
                SU_Send(0x55);
            }
            buttons = PINB;
        }
    }
}



Подогнать скорость я решил опытным путем. Нажимая кнопки +1 и -1 я меняю на единицу константу, которой инициализируется счетчик. таким образом точно управляю временем до его переполнения. Расчеты показывают, что можно добиться точности по крайней мере в процент. Приделал к выходу PB1 терминал, настроил скорость и стал слушать что на него приходит. Ожидал своего числа 55h в момент, когда константа скорости примет нужное значение. Однако этого так и не произошло за перебор всех возможных значений... Не знаете в чем дело? )

Это просто протеус сглючил. Удалось передавать данные на определенной скорости. В моем случае 9600. Однако в железном исполнении на компьютер приходит A5 или B5 вместо 55. Завтра буду разбиратсья.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Artem_Petrik
сообщение Oct 3 2009, 06:41
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006



Промежуток между посылками длинее времени передачи байта (10 бит) нужен. Иначе УАРТ не может понять какой из кучи нулевых байт - стартовый.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 20:04
Рейтинг@Mail.ru


Страница сгенерированна за 0.01413 секунд с 7
ELECTRONIX ©2004-2016