Страница 1 из 1

Программный UART в микроконтроллерах ATmega

Добавлено: Вт янв 27, 2009 00:13:15
trans
Никто не пытался сделать программный UART? а то одного не хватает.
Есть Учебно-отладочный стенд на базе ATmega16, к нему даделали модуль с передатчиком Xbee. С самим модулем мне работать пока не надо, однако стоит задача связи передатчика с ПК через стенд (стенд - обязательное звено). Проблема в том, что в МК UART один.
Его решено завязать на Xbee, а вот несчет компа - то ему остается фигура из трех пальцев, до тех пор, пока не написан программный UART. Полопатил инет, не нашел. может кто подкинет хотя бы идею...
заранее благодарен

Добавлено: Вт янв 27, 2009 10:12:08
asteroid7
Нужна идея как сделать, или где готовое взять?
Если первое, то я использовал таймерные временные метки в режиме совпадения. Два прерывания: совпадение, переполнение. Заранее составляется массив значений, зависит от скорости. В совпадении считывается/записывается бит, и заносится новое значение OCR. По переполнению байт передан или принят.

Код: Выделить всё

    //ФОРМАТ 1-го байта
    // ____      _____________________
    //     \ St / 0 \/ 1 \/ 2 \/ 3 \/ 4 \/ 5 \/ 6 \/ 7  / Stop Stop \ St  /
    //      \__/\___/\___/\___/\___/\___/\___/\___/\___/             \___/
    // Rx   *     |    |    |    |    |    |    |    |
    // Tx   *   |    |    |    |    |    |    |    |    |           |owf
Скорости, которые работали у меня. Полудуплекс. AVR на 100% занят только этим процессом.

Код: Выделить всё

 *     "ПОДДЕРЖИВАЕМЫЕ СКОРОСТИ ОБМЕНА от тактируемой частоты устройства"
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 * |           | 1200 | 2400 | 4800 | 9600 | 19200 | 38400 | 57600 | 115200 |
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 * |   1 Mhz   |  +   |  +   |   +  |  +   |   +   |   *   |   -   |   -    |
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 * |   2 Mhz   |  +   |  +   |   +  |  +   |   +   |   +   |   *   |   -    |
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 * |   4 Mhz   |  +   |  +   |   +  |  +   |   +   |   +   |   +   |   *    |
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 * |   8 Mhz   |  +   |  +   |   +  |  +   |   +   |   +   |   +   |   +    |
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 * |  12 Mhz   |  +   |  +   |   +  |  +   |   +   |   +   |   +   |   +    |
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 * |  16 Mhz   |  +   |  +   |  +   |  +   |   +   |   +   |   +   |   +    |
 * +-----------+------+------+------+------+-------+-------+-------+--------+
 *     "+" - поддерживается
 *     "-" - не поддерживается
 *     "*" - нестабильно (использовать не желательно)

// таблица тактов таймера затраченных на один бит
        // +-----------+------+------+------+------+-------+-------+--------+
        // |           | 1200 | 2400 | 4800 | 9600 | 19200 | 57600 | 115200 |
        // +-----------+------+------+------+------+-------+-------+--------+
        // |   1 Mhz   | 833  | 417  | 209  | 104  |  52   |  17   |  8-9   |
        // +-----------+------+------+------+------+-------+-------+--------+
        // |   2 Mhz   | 1667 | 833  | 417  | 209  |  105  |  35   |  17    |
        // +-----------+------+------+------+------+-------+-------+--------+
        // |   4 Mhz   | 3333 | 1667 |  833 | 417  |  209  |  70   |  35    |
        // +-----------+------+------+------+------+-------+-------+--------+
        // |   8 Mhz   | 6667 | 3333 | 1667 | 833  |  417  |  139  |  70    |
        // +-----------+------+------+------+------+-------+-------+--------+
        // |  12 Mhz   |10000 | 5000 | 2500 | 1250 |  625  |  208  |  104   |
        // +-----------+------+------+------+------+-------+-------+--------+
        // |  16 Mhz   |13333 | 6667 | 3333 | 1667 |  833  |  278  |  139   |
        // +-----------+------+------+------+------+-------+-------+--------+
Приём/передача бита/байта/строки и прерывания лучше на ASMе писать.

Добавлено: Вт янв 27, 2009 21:58:44
trans
Есть следующий код. По идее, он должен передавать значение 0xC2 раз в секунду на скорости 9600 бод с двумя стоп-битами. Однако в терминале ловлю сплошные нули, и то только при включении/сбросе или смене параметров соединения со стороны компа. подскажите, где я налажал? (код написан в WinAVR):

Код: Выделить всё

#include avr/io.h>//определяет имена регистров
#include util/delay.h>	// дает функцию _delay_ms();
#include avr/interrupt.h>// определяет названия прерываний

unsigned char a[11]={0,2,2,0,0,0,0,2,0,2,2}; 
                                       //в разряде tx "0  11000010  11"
unsigned char i=0;		//счетчик бит

int main(void)
{
	DDRB=255;		//порт B на выход
	
	TCCR0=10;	//CTC mode, 8x prescaler
       TIMSK=1<<OCIE0;	//разрешить прерывание т./сч.0 по сравнению
       OCR0=52;//выставить модуль счета (416 тактов/8x prescaler=52)
	sei();			//  разрешить прерывания глобально
	
	
	return 0;
}

ISR(TIMER0_COMP_vect)
                            //обработчик прерывания "Т./Сч.0 -> сравнение"
{
	PORTB=a[i];	// вывести в порт i-й символ массива
	if(i<10)		// Если не закончилась последовательность
		reti();	// то завершить обработку прерывания и быть 
                                    //готовым обрабатывать следующий бит
					//иначе
	cli();				//запретить прерывания
	_delay_ms(1000);	//подождать секунду
	i=0;				//обнулить счетчик бит
	sei();				// разрешить прерывания взад
	reti();				// выйти из обработчика
}

Добавлено: Вт янв 27, 2009 22:58:07
smac
trans писал(а):.... подскажите, где я налажал? (код написан в WinAVR):

Код: Выделить всё

...

ISR(TIMER0_COMP_vect)
                            //обработчик прерывания "Т./Сч.0 -> сравнение"
{
	PORTB=a[i];	// вывести в порт i-й символ массива
	if(i<10)		// Если не закончилась последовательность
		reti();	// то завершить обработку прерывания и быть 
                                    //готовым обрабатывать следующий бит
					//иначе
	cli();				//запретить прерывания
	_delay_ms(1000);	//подождать секунду
	i=0;				//обнулить счетчик бит
	sei();				// разрешить прерывания взад
	reti();				// выйти из обработчика
}
задержка на секунду в прерываниях - это не есть гуд, за это время таймер успевает "нащелкать" множество тактов, а вы пропустите прерывания, во вторых - где увеличивается i ?
Вообще видимо неоптимальный код, но я не могу дать рекоммендаций к написанию "хорошего" кода на С. На асм элементарно решается

Добавлено: Вт янв 27, 2009 23:31:04
trans
А..... Шайтан-арба!!!!! (спасибо проглядел)

Код: Выделить всё

PORTB=a[i++];
Правда не помогло. Взглянул на схему - max232 вроде бы с инвертором... В общем, инвертировал поток - стал получать посылки ежесекундно, хотя не то, что посылал:
1) Сначала сразу два байта 0xFE, 0xFF
2) затем один 0xFF
3) наконец, 0x00
и сначала. Может кто подскажет в чем косяк?

Добавлено: Вт янв 27, 2009 23:34:02
Секретный кот
Тем временем баском без проблем поддерживает программные УАРТы, которые причём можно повесить практически на любые ноги МК.

Добавлено: Ср янв 28, 2009 00:37:37
trans
Однако нужно родить код или на Си, или на Асме. С Асмом у меня пока туговато.

Добавлено: Вт фев 03, 2009 02:02:03
EternalEngine
Присоединяюсь к теме! тоже нужен доп. УАПП для получения MIDI сигнала. Есть ли пример в CodeVision?