Портал для радиолюбителей и разработчиков электроники · с 2003 годаРеклама на сайте
Найти компонент, схему или даташит

Даташиты, справочник отечественных приборов, схемы с разбором и живой форум

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

 
Опции темы

Получение данных по USART

Непрочитано 28.11.2014, 16:14  
Fangir
Временная регистрация
 
Регистрация: 31.10.2014
Сообщений: 59
Сказал спасибо: 24
Сказали Спасибо 7 раз(а) в 7 сообщении(ях)
Fangir на пути к лучшему
По умолчанию Получение данных по USART

Я передаю данные по 1 байту, как другому МК распознать команду?
Допустим, в команде "led_off" - 7 байт

Я передал её с помощью функции
Код:
// Передача строки
void usart0_put(char *str) {
	while(*str != '\0') {
		while(!(UCSRA & (1 ‹‹ UDRE))); // Ожидаем, когда очистится буфер
		UDR = *str; // Помещаем данные в буфер
		str++;
	}
}
Хотел записывать все принятые данные в стек, а после обрабатывать их, как-то так
Код:
// Прерывание по окончанию приема данных
unsigned char usart0_stack[100], usart0_counter = 0;
interrupt[USART0_RXC] void usart0_rx_isr(void) {
	// Записываем символ
	if(usart0_counter ‹= 100) {
		usart0_stack[usart0_counter++] = UDR;
	}
}
Но застопорился и не знаю как дальше развить идею

И да, я использую RTOS, так что процесс, который мог бы обработать данные, может очухаться примерно через 5-20ms после начала приема
Он не сможет обработать данные сразу же
Реклама:
Fangir вне форума  
Непрочитано 28.11.2014, 17:13  
_Артём_
Гражданин KAZUS.RUN
 
Регистрация: 16.03.2011
Сообщений: 486
Сказал спасибо: 8
Сказали Спасибо 131 раз(а) в 116 сообщении(ях)
_Артём_ на пути к лучшему
По умолчанию Re: Получение данных по USART

Сообщение от Fangir Посмотреть сообщение
Я передаю данные по 1 байту, как другому МК распознать команду?
Допустим, в команде "led_off" - 7 байт
Зависит от формата команд. Можно в каждой команде передавать её длину. Или заканчивать команду каким-либо зарезервированным символом (переводом строки например) и при приёме этого символа можно начинать разбор команды.


Сообщение от Fangir Посмотреть сообщение
Хотел записывать все принятые данные в стек, а после обрабатывать их, как-то так
Буфер - это правильно.

Сообщение от Fangir Посмотреть сообщение
И да, я использую RTOS, так что процесс, который мог бы обработать данные, может очухаться примерно через 5-20ms после начала приема
Он не сможет обработать данные сразу же
Что-то долго у вас процесс очухивается...На 8 МГц тактовой процесс может за 40-50 мкс среагировать. Что за RTOS у вас?

Сообщение от Fangir Посмотреть сообщение
Он не сможет обработать данные сразу же
Используйте семафоры или события для запуска обработки.
_Артём_ вне форума  
Непрочитано 28.11.2014, 17:30  
NewWriter
Почётный гражданин KAZUS.RUN
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,481
Сказал спасибо: 396
Сказали Спасибо 2,222 раз(а) в 1,317 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: Получение данных по USART

А может для начала команды использовать некий зарезервированный код, который будет содержать данные о начале и длине команды. Например, как м MIDI-сообщениях. Команды разделены по типам и у каждого типа - своя длина в байтах. Тип команды зашифрован в первом байте.
Может, за основу взять протокол MIDI? Тогда и придумывать ничего не придется.

Последний раз редактировалось NewWriter; 28.11.2014 в 17:35.
NewWriter вне форума  
Непрочитано 28.11.2014, 17:46  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,821
Сказал спасибо: 919
Сказали Спасибо 4,289 раз(а) в 2,570 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Получение данных по USART

Элементарно. Каждый входящий байт вызывает прерывание, правильно. Но еще он обнуляет таймер, который переполняется через время, за которое приходит полтора байта. Иными словами, если байт не пришел, вызывается прерывание таймера, в котором вы поднимаете флаг о том, что стек заполнен, пора обрабатывать.
Easyrider83 вне форума  
Непрочитано 28.11.2014, 21:34  
Fangir
Временная регистрация
 
Регистрация: 31.10.2014
Сообщений: 59
Сказал спасибо: 24
Сказали Спасибо 7 раз(а) в 7 сообщении(ях)
Fangir на пути к лучшему
По умолчанию Re: Получение данных по USART

Написал такой код, проверить щас возможности нет, буду рад если кто протестирует хотя бы его работающую часть


Код:
// Передача символа
void usart0_putChar(char с) {
	while(!(UCSRA & (1 ‹‹ UDRE))); // Ожидаем, когда очистится буфер
	UDR = с; // Помещаем данные в буфер
}


// Передача строки
void usart0_putStr(char *str) {
	while(*str != '\0') {
		usart0_putChar(*str); // Отсылаем символ
		str++;
	}
	usart0_putChar('#'); // Символ конца команды
}


//##################################################  #############################################
//##################################################  #############################################



#define usart0_MAX 20     // Максимальная длина команды
#define usart0_STACK 100  // Длина стека


// Прием данных
unsigned char usart0_get(void) {
	unsigned char data[usart0_MAX];

	// Пока счетчик не равен нулю
	while(usart0_counter) {
		// хз как реализовать выборку из стека
		// И попутно уменьшение счетчика
		// Надо делать как-то с конца но я щас слишком сонный
		// Буду благодарен, если кто поможет
		// data[] = usart0_stack[usart0_counter--]
	}
	// return data;
}



// Прерывание по окончанию приема данных
unsigned char usart0_stack[usart0_STACK];   // Стек
unsigned char usart0_counter = 0;  // Счетчик стека
unsigned char usart0_max_len = 0;  // Счетчик длины команды
interrupt[USART0_RXC] void usart0_rx_isr(void) {
	unsigned char data = UDR;

	// Если стек переполнился то просто игнорируем прием данных
	if(usart0_counter ‹= usart0_STACK) {
		usart0_stack[usart0_counter++] = data; // Записываем в стек символ 

		// Конец команды!
		if(data == '#') {
			usart0_max_len = 0; // Сбрасываем счетчик 
		}

		// Счетчик дошел до предела, команда слишком большая
		if(usart0_max_len++ == usart0_MAX) { 
			usart0_max_len = usart0_MAX;      // Сбрасываем
			usart0_counter -= usart0_MAX + 1; // Откатываем назад
		}
	}
}
Fangir вне форума  
Непрочитано 28.11.2014, 22:21  
akegor
Гуру портала
 
Аватар для akegor
 
Регистрация: 06.05.2005
Адрес: Краснодар, возле укротворного моря.
Сообщений: 19,313
Сказал спасибо: 2,633
Сказали Спасибо 12,076 раз(а) в 6,082 сообщении(ях)
akegor на пути к лучшему
По умолчанию Re: Получение данных по USART

Сообщение от Fangir Посмотреть сообщение
UDR = с; // Помещаем данные в буфер
Это буфер в аппаратном, а не в программном смысле. В программном один байт - огромаднейший буфер!
Я путчаром загоняю всю посылку в буфер, а содержимое буфера передается по прерываниям.
При приеме жду ожидаемое количество байтов в буфере и проверяю первый байт (признак начала сообщения) - если байт правильный, провожу разбор посылки, если нет - жду дальше.
Обмен в ASCII, Все, кроме заголовка, шестнадцатиричное. Заголовок - любой знак, кроме 0...F и 0x0A, 0x0D, 0x00 0xFF. Пока не встречалось необходимости в своих интерфейсах применять другой подход. В случае приема чужих посылок ситуация посложнее.
__________________
Не бейте больно, ежели чо, ну не удержался... А вааще,
"Мы за все хорошее, против всей х..., По лугам некошеным чтобы шли ступни,
Чтобы миром правила правда, а не ложь, Мы за все хорошее, нас не на...!
..." (Ленинград)
Я не несу ответственности за свои действия в Вашей голове.
akegor вне форума  
Непрочитано 28.11.2014, 23:22  
_Артём_
Гражданин KAZUS.RUN
 
Регистрация: 16.03.2011
Сообщений: 486
Сказал спасибо: 8
Сказали Спасибо 131 раз(а) в 116 сообщении(ях)
_Артём_ на пути к лучшему
По умолчанию Re: Получение данных по USART

Сообщение от Fangir Посмотреть сообщение
Написал такой код, проверить щас возможности нет, буду рад если кто протестирует хотя бы его работающую часть
А что её тестировать, если она работающая?
Или тут такой принцип - компилируется значит работает?

Сообщение от Fangir Посмотреть сообщение
Код:
#define usart0_MAX 20     // Максимальная длина команды
#define usart0_STACK 100  // Длина стека


// Прием данных
unsigned char usart0_get(void) {
	unsigned char data[usart0_MAX];

	// Пока счетчик не равен нулю
	while(usart0_counter) {
		// хз как реализовать выборку из стека
		// И попутно уменьшение счетчика
		// Буду благодарен, если кто поможет
		// data[] = usart0_stack[usart0_counter--]
	}
	// return data;
}
Сообщение от Fangir Посмотреть сообщение
// хз как реализовать выборку из стека
Неудивительно что ХЗ - неправильно делаете вот и не знаете. Стек - это LIFO (last in — first out, «последним пришёл — первым вышел»). Для вашего случая больше подойдёт FIFO(кольцевой буфер, или циклический буфер): в прерывании приёма делается инкремент индекса последнего принятого символа,
в основной программе - инкремент индекса самого раннего символа (до тех пор пока индексы не станут равны).

P.S. Почему переменные usart0_stack и usart0_counter не volatile?
_Артём_ вне форума  
Непрочитано 28.11.2014, 23:41  
jump
Почётный гражданин KAZUS.RUN
 
Регистрация: 20.06.2006
Адрес: Украина, Запорожье
Сообщений: 8,011
Сказал спасибо: 0
Сказали Спасибо 4,955 раз(а) в 2,379 сообщении(ях)
jump на пути к лучшему
По умолчанию Re: Получение данных по USART

Сообщение от Easyrider83 Посмотреть сообщение
еще он обнуляет таймер, который переполняется через время, за которое приходит полтора байта
вах, адын палавынка МОДБАС!
тогда уж и втарой палавынка вазми дарагой - 3.5 длительности байта.
и назначение согласно стандарта МОДБАС (для таймера) - 1.5 длительности байта (разрыв посылки, уничтожение пакета) и 3.5 длительности байта (окончание пакета, начало обработки), прерывание от USART складывает байты в буфер и обнуляет таймер
jump вне форума  
Непрочитано 28.11.2014, 23:54  
rafik65
Почётный гражданин KAZUS.RUN
 
Аватар для rafik65
 
Регистрация: 19.02.2011
Адрес: Жуковский, МО
Сообщений: 3,250
Сказал спасибо: 3,700
Сказали Спасибо 7,524 раз(а) в 1,581 сообщении(ях)
rafik65 на пути к лучшему
По умолчанию Re: Получение данных по USART

приёмник должен знать сколько байтов принимать, а то по умолчанию может только 2 байта
__________________
ничего нет сложнее простого решения
без ТЗ результат ХЗ.
rafik65 вне форума  
Непрочитано 29.11.2014, 02:06  
kosmos440o
Заблокирован
 
Регистрация: 23.09.2007
Сообщений: 761
Сказал спасибо: 84
Сказали Спасибо 352 раз(а) в 151 сообщении(ях)
kosmos440o на пути к лучшему
По умолчанию Re: Получение данных по USART

Сообщение от Fangir Посмотреть сообщение
while(*str != '\0')
а если "\0" вдруг чего-то не придёт?
Функция void usart0_put(char *str) 7 мсек - не много?


Надо контроль ошибок сделать.
Начало сообщения обозначить может быть.
вообще понадёжнее как-то.
Читайте про Модбас, там вроде минималка для нормального обмена.
Стандартная библиотека USART чем не нравится? Там получше обработка будет.

#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)

// USART0 Receiver buffer
#define RX_BUFFER_SIZE0 16
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0‹256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART0 Receiver buffer overflow
bit rx_buffer_overflow0;
char rx_errors=0;
// USART0 Receiver interrupt service routine
interrupt [USART0_RXC] void usart0_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer0[rx_wr_index0]=data;
if (++rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
if (++rx_counter0 == RX_BUFFER_SIZE0)
{
rx_counter0=0;
rx_buffer_overflow0=1;
};
}else {rx_errors++;};
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART0 Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0];
if (++rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif

// USART1 Transmitter buffer
#define TX_BUFFER_SIZE1 255
unsigned char tx_message [TX_BUFFER_SIZE1];
unsigned char tx_counter1=0;
unsigned char tx_len=0;

// USART1 Transmitter interrupt service routine
//перед этим первый байт отправить вручную и tx_len длину сообщения определить.
interrupt [USART1_TXC] void usart1_tx_isr(void)
{
tx_counter1++;
while ((UCSR1A & DATA_REGISTER_EMPTY)==0){};
if (tx_counter1‹tx_len)
{
UDR1=tx_message [tx_counter1];
}
}

Последний раз редактировалось kosmos440o; 29.11.2014 в 02:49.
kosmos440o вне форума  
 
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
FAQ (ЧаВО) по PROTEUS для начинающих и не только dosikus Proteus 221 07.03.2024 22:45
Получение данных по USART в CVAVR himik131 Микроконтроллеры, АЦП, память и т.д 6 12.03.2011 00:12
Передача данных с ATmega8 на COM порт ПК sergx1300 Микроконтроллеры, АЦП, память и т.д 32 20.04.2010 14:19
Помогите разобраться с USART в CodeVisionAVR vendim Микроконтроллеры, АЦП, память и т.д 20 26.07.2007 16:42
Вопрос по мультипроцессорному обмену USART MEGA8 vikont-s Микроконтроллеры, АЦП, память и т.д 0 10.08.2006 14:55


Часовой пояс GMT +4, время: 01:41.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.