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

PC -> COM -> ATmega8515

Добавлено: Вс сен 27, 2009 20:49:49
J.Joker
Товарищи Коты, помогите разобраться, облазил весь интернет и жутко запутался. Мне нужно через COM порт в МК mega8515 передавать данные, я понял что для этого необходимо использовать UART или USART (кстати так и не пойму в чем разница). Я скачал примеры с сайта atmel, но все равно не понял. Не могли бы вы подробно объяснить, что к чему во вложенных файлах, и какие особенности UART и USART. Заранее спасибо.

PS: Долго ползал в поисковике по форуму, но нужного мне ничего не нашел, если чего проглядел не ругайтесь :)) .

Re: PC -> COM -> ATmega8515

Добавлено: Вс сен 27, 2009 21:21:59
Секретный кот
J.Joker писал(а):UART или USART (кстати так и не пойму в чем разница).
UART vs USART. Всё же не ленитесь пользоваться поиском...

Re: PC -> COM -> ATmega8515

Добавлено: Пн сен 28, 2009 08:20:44
J.Joker
Секретный кот писал(а): UART vs USART. Всё же не ленитесь пользоваться поиском...
Тут с Вами согласен, про поиск в инете как-то забыл, спасибо за информацию. Но основной вопрос все таки висит, как правильно с ними работать?

Добавлено: Пн сен 28, 2009 19:59:38
J.Joker
Если затрудняетесь, то хотя бы дайте простейший пример чтения из COM порта и выдачу прочитанного на ножки... На С, а то у меня уже мозг кипит.

Добавлено: Пн сен 28, 2009 20:23:18
Meteor
Я на Вашем месте занялся не реализацией кода, а разработкой протокола обмена. Ибо только когда будут обозначены такие характеристики как:
1) Что надо передать в ПК от МК?
2) Что надо принять МК от ПК?
3) Как эти посылки будут взаимодействовать?
4) Как часто будет производиться обмен?
5) Что будет инициализировать обмен, ПК или МК?
Можно будет перейти к мыслям о том какбудут представлены данные в обоих направлениях и уже после определить на какой скорости, какой контроль, сколько стоповых бит. Ну и тогда милости просим код.

Добавлено: Пн сен 28, 2009 20:23:34
clawham
Пример чтения из ком порта -
char buf = 0;
buf = getchar();

Пример записи аналогичен консольному вводу выводу на сях

если кодите на КодВижн АВР то просто мастером создайте себе буфферизированный ввод и вывод по прерываниям и получите полный рабочий пример работы

УАРТ - это стандарт
УСАРТ - это модуль в МКшке который можно настроить поразному

Очень рекомендую хотя бы чтение делать буфферизированно....

в принципе вам не нужно вдаваться в подробности достаточно просто взять типовую кинфигурацию этого модуля в МК и соответствующим образом настроить компьютер....самое главное что нужно помнить на выводах компьютера сзади логические уровни не те что надо МК (+-15 вольт) поэтому нужна буфферная микрушка преобразования уровней - МАХ 232 её клонов у каждого производителя предостаточно, главное не запутаться в том что ТХ у мк должен идти на РХ компа :) ибо иначе получите два канала слушающих друг друга и два канала ломающих друг дргуа на свой уровень

Добавлено: Пн сен 28, 2009 21:42:13
J.Joker
Ммм... Ладно, наверно будет проще если изложу задачу.

Задача МК: принять посланную через COM порт цифру и в соответствие с ней мигнуть светодиодом, а затем перейти в ожидание новой передачи.

Пример: послали 7, МК принял эту цифру, 7 раз мигнул светодиодом и стал опрашивать COM порт.

Вот у меня и возникла проблема, с написанием кода для получения по COM порту цифры. Так что если можно напишите пожалуйста как это правильно делать, от инициализации до чтения.
Все что я понял на данный момент прочитав тонну информации, что в итоге присланная цифра должна быть в UDR записана в соответствии с ASCII.

Да, а визард выдает только следующее
UCSRA=0x00;
UCSRB=0x10;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x2F; а чего совсем этим добром делать дальше не понятно.

Добавлено: Пн сен 28, 2009 22:26:42
clawham
я конкретно по вашему МК не знаю..я только работал с АТМегой 8-16-32

но это судя по всему конфиругационные регистры чтоб настроить модуль!!!
Вы же загляните в даташит на микроконтроллер в раздел УСАРТ модуля - там каждый бит (из 8-ми) в каждом из этих регистров многое значит!

Понимаете ли...ком порт это не просто так....тут много есть параметров связи ... есть синхронный режим(который используется очень редко) есть асинхронный, в асинхронном режиме МК отслеживает изменения уровней по определённым временным интервалам и записывает это последовательно в входной буффер.....чтоб всё работало нужно знать с какой скоростью передаёт компьютер данные, сколько стоп битов, есть ли бит четности и сколько вообще бит в посылке - всё это необходимо чтоб модуль МК понял ту какофонию импульсов что выстрелит ему компьютер....если Вы пишите на КодВижнАВР то поставьте галочкинапротив прерывания на приём и выставьте буффер в 8 байт - а дальше в постоянном цикле проверяйте переменную Receive - в ней записано количество неотработанных но принятых в буффер данных(байт) и если она не 0 то в буффере чтото есть - есть же и альтернативная функция getchar()которая будет вычитывать следующий байт из буффера или ждать нового пока не прийдёт

Добавлено: Пн сен 28, 2009 22:38:51
Секретный кот
clawham писал(а):УСАРТ - это модуль в МКшке который можно настроить поразному
Разве у AVR есть аппаратный USART?

Добавлено: Пн сен 28, 2009 22:40:20
clawham
И да простят меня модераторы.....

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

/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 28.09.2009
Author  : 
Company : 
Comments: 


Chip type           : ATmega8515
Program type        : Application
Clock frequency     : 16,000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 128
*****************************************************/

#include <mega8515>
#include <delay>

#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];

#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer[rx_wr_index]=data;
   if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
   if (++rx_counter == RX_BUFFER_SIZE)
      {
      rx_counter=0;
      rx_buffer_overflow=1;
      };
   };
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif

// Standard Input/Output functions
#include <stdio>

// Declare your global variables here

void main(void)
{
// Declare your local variables here

char buf;
char tmp;

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x00;

// Port E initialization
// Func2=In Func1=In Func0=In 
// State2=T State1=T State0=T 
PORTE=0x00;
DDRE=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
EMCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: Off
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x90;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x67;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

// Global enable interrupts
#asm("sei")



while (1)
      {
      // Place your code here
      buf = getchar();
      if(buf>48)
      {
        if(buf<58)
        {
            buf-=48;
            for(tmp=0;tmp<buf;tmp++)
            {
                delay_ms(500);
                PORTB.1=1;
                delay_ms(500);
                PORTB.1=0;
                }
        }
      }                          
      
      };
}
Вот вам пример моргания светодиодом определенное число раз ( смотря что кинули в ком порт) причём буфферизированный и т.д.
[/code]

Добавлено: Пн сен 28, 2009 22:46:34
J.Joker
clawham писал(а): Вот вам пример моргания светодиодом определенное число раз ( смотря что кинули в ком порт) причём буфферизированный и т.д.
Спасибо Вам большое, буду разбираться...

Добавлено: Пн сен 28, 2009 22:57:13
Meteor
J.Joker писал(а):Задача МК: принять посланную через COM порт цифру и в соответствие с ней мигнуть светодиодом, а затем перейти в ожидание новой передачи.
Все что я понял на данный момент прочитав тонну информации, что в итоге присланная цифра должна быть в UDR записана в соответствии с ASCII.
Аски коды цифр принимают значения от 0х30 до 0х39 (десятичные)
Если правильно понял, то Вы ожидаете прием одного байта, со значением от 0х30 до 0х39. В данном случае можно рекомендовать такой вариант:
1) Настраиваем на прием. Сбрасываем флаг "принят байт". Ждем байт, с настроенным адресом ОЗУ (тело программы).Пока флаг пуст - гоняем вечный цикл.
2) Приняв байт записываем его по адресу ОЗУ (обработка прерывания), ставим флаг "принят байт". Выходим из прерывания.
3) Возвращаемся в основное тело, и по флагу переходим к функции "моргания", со сбросом флага.

Добавлено: Пн сен 28, 2009 23:40:11
clawham
Секретный кот писал(а):
clawham писал(а):УСАРТ - это модуль в МКшке который можно настроить поразному
Разве у AVR есть аппаратный USART?
никогда не слышал чтоб у АВР были какие-либо проблемы с периферией.....с объемом оперативки да....с частотой да....но не с периферией.....я именно изза их богатой периферии с ними и работаю....ну что ни возьми что ни придумай всё есть и в таким избытке что никаким извратом не придумать задачу чтоб нельзя было б её решить не программно а запрограммировав правильно периферию :) естественно реч идёт об АТ Мегах потому они и меги :)))
Аски коды цифр принимают значения от 0х30 до 0х39 (десятичные)
Если правильно понял, то Вы ожидаете прием одного байта, со значением от 0х30 до 0х39. В данном случае можно рекомендовать такой вариант:
1) Настраиваем на прием. Сбрасываем флаг "принят байт". Ждем байт, с настроенным адресом ОЗУ (тело программы).Пока флаг пуст - гоняем вечный цикл.
2) Приняв байт записываем его по адресу ОЗУ (обработка прерывания), ставим флаг "принят байт". Выходим из прерывания.
3) Возвращаемся в основное тело, и по флагу переходим к функции "моргания", со сбросом флага.
собственно говоря прочитав мой пример вы обнаружите что там это именно так и организовано только всё вынесено красиво в отдельные блоки и организован обработчик прерывания по факту завершения приёма - так более правильно.

Добавлено: Пн сен 28, 2009 23:43:15
clawham
J.Joker писал(а):
clawham писал(а): Вот вам пример моргания светодиодом определенное число раз ( смотря что кинули в ком порт) причём буфферизированный и т.д.
Спасибо Вам большое, буду разбираться...
кстати....из всего вышеприведенного лично я писал руками только маааханький кусочек :)

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

buf = getchar(); 
      if(buf>48) 
      { 
        if(buf<58) 
        { 
            buf-=48; 
            for(tmp=0;tmp<buf;tmp++) 
            { 
                delay_ms(500); 
                PORTB.1=1; 
                delay_ms(500); 
                PORTB.1=0; 
                } 
        } 
      }
всё остальное - результат работы визарда :)

Добавлено: Вт сен 29, 2009 18:45:43
J.Joker
clawham писал(а): всё остальное - результат работы визарда :)
Да, я это уже понял, когда поставил крякнутую версию, потому что у меня Evolution такое не делал :) . Правда вот столкнулся с тем, что при эмуляции в AVR Studio4 все зависает на строчке

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

char getchar(void)
{
while(rx_counter==0);
...
И не как не реагирует. Хотел в железе прошить сегодня, но не получилось, так что пытаюсь разобраться с VMLAB.

Добавлено: Ср сен 30, 2009 11:39:49
clawham
дак оно и должно было там зависнуть
почему? rx_counter - переменная количества принятых но неотработанных байт
если вы только что запустили микроконтроллер или отработали все байты - оно будет там висеть вечно...пока прерывание на окончание приёма не прийдёт. Обработчик перывания запишет в буффер принятый символ, увеличит счетчик принятых байт на 1 и вернет управление этому вечному ожиданию...а оно-то как-раз уже и не оправдается - там уже 1 будет и пойдёт программа дальше

Добавлено: Ср сен 30, 2009 22:58:25
J.Joker
А вот из любопытства, в ДШ к mega8515 есть такой вот пример чтения

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

unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) )
;
/* Get and return received data from buffer */
return UDR;
}
Я не пойму это рабочий вариант, или туда надо еще чего-то дописать?

Добавлено: Ср сен 30, 2009 23:10:26
Meteor
Это только функция обработки прерывания по приему данных (чтения).

Добавлено: Чт окт 01, 2009 09:08:01
clawham
где вы видели в этой функции прерывание? прерывание висящее в вечном цикле?
это аналог моей функции гетчар только небуфферизированно!

А вообще на мк можно одну и ту же функцию реализовать сотней тысач милионов рабочих способов...только в каждом будут свои плюсы и минусы универсального нету!

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

interrupt [USART_RXC] void usart_rx_isr(void) 
{ 
char status,data; 
status=UCSRA; 
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) 
   { 
   rx_buffer[rx_wr_index]=data; 
   if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; 
   if (++rx_counter == RX_BUFFER_SIZE) 
      { 
      rx_counter=0; 
      rx_buffer_overflow=1; 
      }; 
   }; 
}
в моём примере делается то же самое!!!
посмотрите -

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

data=UDR; 
это мы вов ременную переменную кидаем результат(то что пришло)
потом заносим результат в массив-буффер

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

rx_buffer[rx_wr_index]=data; 
естественно только в том случае если нету ошибок нету сдвигов и всё правильно - это проверяется этим

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

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) 
ну что тут может быт непонятного? я вам дал готовый пример рабочий полностью отлаженный и очень и очень универсальный

Добавлено: Вс окт 04, 2009 17:10:42
J.Joker
А вот еще вопрос, скажите пожалуйста какую скорость на прием\передачу лучше сделать при кварце в 7.372800 MHz, стояла у меня 9600, сейчас переделал на 115200, так как прочел что компам тяжеловато на малых скоростях передачи работать.