• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь Приём данных от ESP в Atmega

Konstantin

New member
Как реализовать сортировку ответа от ESP. Т.е. запустив сервер на ESP, клиент отсылает какие то данные, ESP ловит их в виде результата (+IPD,0,5:hello). как на атмеги отсортировать ответ, чтобы переменная была в виде строки (hello), а не в виде (+IPD,0,5:hello)???
Код инициализации UART-a:
[inline]
[HASHTAG]#define[/HASHTAG] BAUDRATE 9600
[HASHTAG]#define[/HASHTAG] F_CPU 8000000UL
[HASHTAG]#include[/HASHTAG] <avr/io.h>
[HASHTAG]#include[/HASHTAG] <util/delay.h>
[HASHTAG]#include[/HASHTAG] <stdlib.h>
[HASHTAG]#include[/HASHTAG] <avr/interrupt.h>

unsigned char byte_receive = 0;
unsigned char NUM = 0;

void send_Uart(char c)
{
while(!(UCSRA&(1<<UDRE)));
UDR = c;
}

void send_Uart_str(char *s)
{
while (*s != '\0')
{
send_Uart(*s);
s++;
}
}

int getch_Uart(void)
{
while(!(UCSRA&(1<<RXC)));
return UDR;
}

void init_UART(void)
{
UBRRH=0;
UBRRL=51;
UCSRB |= (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}

ISR(USART_RXC_vect)
{
NUM = UDR;
byte_receive = 1;
send_Uart(NUM);
}

int main(void)
{
DDRC |= (1<<5);
DDRC |= (1<<4);
DDRC |= (1<<3);

init_UART();

_delay_ms(5000);


send_Uart(13);send_Uart(10);

send_Uart_str("AT+CIPMUX=1");
send_Uart(13);send_Uart(10);
_delay_ms(5000);

send_Uart_str("AT+CIPSERVER=1,8888");
send_Uart(13);send_Uart(10);
_delay_ms(5000);

PORTC |= (1<<5);

while(1)
{
//sei();
if (NUM == 1)
PORTC |= (1<<3);
if (NUM == 2)
PORTC &=~ (1<<3);
//cli()
}
}
[/inline]
 

Andy Korg

Moderator
Команда форума
Предлагаю вот в этом месте организовать проверку на последовательность символов +IPD
Код:
ISR(USART_RXC_vect)
{
NUM = UDR;
byte_receive = 1;
send_Uart(NUM);
}
Код:
const u08 PROGMEM ipdCmd[] = "+IPD,";                            //Команда приема данных от наружного хоста

ISP(){
u08 rxbyte = ESP_UART_DATA;
    static u08 RxCount = 0, HostAnswerCount = 0, HostAnsweLen = 0, Tmp = 0;
   
    //Обработка команды приема данных +IPD
    if (HostAnsweLen == 0){                                //Ответа от хоста еще не было
        if (pgm_read_byte(&ipdCmd[HostAnswerCount]) == ','){//Конец приема команды получения данных от хоста
            if (rxbyte == ESP_RCV_CMD_END){                //Конец команды IPD, дальше пойдут данные
                HostAnsweLen = Tmp;
                Tmp = 0;
                espHostAnswrCnt = 0;                    //Дальше пойдут уже сами данные
                HostAnswerCount = 0;
            }
            else{                                        //Длина данных. В режиме мультиконекта может быть номер соединения
                if ((rxbyte>='0') && (rxbyte <= '9'))    //В режиме приема длины данных принимаются только цифры
                    Tmp = (Tmp*10) + (rxbyte & 0xf);
            }
            return;
        }
        if (rxbyte == pgm_read_byte(&ipdCmd[HostAnswerCount])){//Это символ из команды получения данных
            HostAnswerCount++;
            if ((espSndAnswrCnt == 0) || (rxbyte != espSndAnswrBuf[RxCount])) //Так же символ может совпадать с ответом, в этом случае его надо проверить в ветке всех других команд
                return;                                    //Нет необходимости обрабатывать дальше
        }
        else
            HostAnswerCount = 0;                        //Не символ команды получения данных
    }
    else{                                                //Есть ответ от хоста, прнимаем его
        espHostAnswrBuf[espHostAnswrCnt] = rxbyte;
        if (HostAnsweLen == espHostAnswrCnt){            //Принят последний байт, сбрасываем режим приема данных и ставим в очередь команду готовности принятых данных
            HostAnsweLen = 0;
            SetTask(HostAnswer);
        }
        else
            espHostAnswrCnt++;
        return;
    }
}
 

Victor

Administrator
Команда форума
Konstantin,
тэг [inline][/inline] применяется для вставки небольшого фрагмента кода прямо в текст, вот так [inline][HASHTAG]#define[/HASHTAG][/inline],
а для больших фрагментов кода используйте [code=язык программирования][/code]
BB-коды
 

Konstantin

New member
Предлагаю вот в этом месте организовать проверку на последовательность символов +IPD

Код:
const u08 PROGMEM ipdCmd[] = "+IPD,";                            //Команда приема данных от наружного хоста

ISP(){
u08 rxbyte = ESP_UART_DATA;
    static u08 RxCount = 0, HostAnswerCount = 0, HostAnsweLen = 0, Tmp = 0;
  
    //Обработка команды приема данных +IPD
    if (HostAnsweLen == 0){                                //Ответа от хоста еще не было
        if (pgm_read_byte(&ipdCmd[HostAnswerCount]) == ','){//Конец приема команды получения данных от хоста
            if (rxbyte == ESP_RCV_CMD_END){                //Конец команды IPD, дальше пойдут данные
                HostAnsweLen = Tmp;
                Tmp = 0;
                espHostAnswrCnt = 0;                    //Дальше пойдут уже сами данные
                HostAnswerCount = 0;
            }
            else{                                        //Длина данных. В режиме мультиконекта может быть номер соединения
                if ((rxbyte>='0') && (rxbyte <= '9'))    //В режиме приема длины данных принимаются только цифры
                    Tmp = (Tmp*10) + (rxbyte & 0xf);
            }
            return;
        }
        if (rxbyte == pgm_read_byte(&ipdCmd[HostAnswerCount])){//Это символ из команды получения данных
            HostAnswerCount++;
            if ((espSndAnswrCnt == 0) || (rxbyte != espSndAnswrBuf[RxCount])) //Так же символ может совпадать с ответом, в этом случае его надо проверить в ветке всех других команд
                return;                                    //Нет необходимости обрабатывать дальше
        }
        else
            HostAnswerCount = 0;                        //Не символ команды получения данных
    }
    else{                                                //Есть ответ от хоста, прнимаем его
        espHostAnswrBuf[espHostAnswrCnt] = rxbyte;
        if (HostAnsweLen == espHostAnswrCnt){            //Принят последний байт, сбрасываем режим приема данных и ставим в очередь команду готовности принятых данных
            HostAnsweLen = 0;
            SetTask(HostAnswer);
        }
        else
            espHostAnswrCnt++;
        return;
    }
}
Побывал без результативно, может более подробнее подскажите? Я побывал загнать в массив полученные данные и работать с ним.
 

Andy Korg

Moderator
Команда форума
Побывал без результативно, может более подробнее подскажите?
Могу приложить файлы на Си целиком, но в них множество ссылок на другие файлы, и на мой взгляд будет неудобно вам в них копаться. Давайте сделаем наоборот - что у вас конкретно не заработало? Как выполняли отладку? Например у меня для отладки вышеприведенного кода был Atmega644, т.к. у него есть два порта uart, один завел на esp8266, а через второй выводил логи.
 

Konstantin

New member
Могу приложить файлы на Си целиком, но в них множество ссылок на другие файлы, и на мой взгляд будет неудобно вам в них копаться. Давайте сделаем наоборот - что у вас конкретно не заработало? Как выполняли отладку? Например у меня для отладки вышеприведенного кода был Atmega644, т.к. у него есть два порта uart, один завел на esp8266, а через второй выводил логи.
У меня Atmega 8, UART - 1. собственно к нему я и подключил ESP. В указанном выше коде, атмега работает на отлично. использовал на прямую с ПК, через UART переходник. т.е. я в терминале вводил 1 или 2 и у меня выполнялось действие вкл\выкл светодиода. атмега считывает символ и сверяет его [inline]if (NUM == '1')[/inline] но мне нужно считать всю строку! а в дальнейшем и работать с ней, т.е. возможность отсортировать ответ от ESP (+IPD)
 

Konstantin

New member
У меня Atmega 8, UART - 1. собственно к нему я и подключил ESP. В указанном выше коде, атмега работает на отлично. использовал на прямую с ПК, через UART переходник. т.е. я в терминале вводил 1 или 2 и у меня выполнялось действие вкл\выкл светодиода. атмега считывает символ и сверяет его [inline]if (NUM == '1')[/inline] но мне нужно считать всю строку! а в дальнейшем и работать с ней, т.е. возможность отсортировать ответ от ESP (+IPD)
что то вроде этого [inline]if (NUM == "qwerty")[/inline]
 

alexhi

Member
что то вроде этого [inline]if (NUM == "qwerty")[/inline]
Побывал без результативно, может более подробнее подскажите? Я побывал загнать в массив полученные данные и работать с ним.
По разному конечно можно,я например делаю так. Перед отправкой очищаю буфер приема rxd,отсылаю команду ESP ,а далее по прерыванию жду приема символа /r (им заканчиваются AT команды) После в другой процедуре разбираю что пришло примерно так:
Код:
//парсер команд от ESP  
    //включить светодиод на ATMEGA168
    if(!memcmp_P(rxbuf, PSTR("!SetR1_"),7) )
    { LEDON;}
     else
     ;
 

Konstantin

New member
По разному конечно можно,я например делаю так. Перед отправкой очищаю буфер приема rxd,отсылаю команду ESP ,а далее по прерыванию жду приема символа /r (им заканчиваются AT команды) После в другой процедуре разбираю что пришло примерно так:
Код:
//парсер команд от ESP 
    //включить светодиод на ATMEGA168
    if(!memcmp_P(rxbuf, PSTR("!SetR1_"),7) )
    { LEDON;}
     else
     ;
Сейчас реализую кольцевой буфер, http://chipenable.ru/index.php/prog...lzovaniem-koltsevogo-bufera.html#comment-2101
 

Andy Korg

Moderator
Команда форума
Сейчас реализую кольцевой буфер
Тут могу предложить вот такую реализацию буфера
Код:
/*
* FIFO.h
*
* Created: 11.09.2013 17:23:13
*  Author: http://mainloop.ru/c-language/simple-fifo.html
*/


#ifndef FIFO__H
#define FIFO__H

//размер должен быть степенью двойки: 4,8,16,32...128
#define FIFO( size )\
struct {\
    unsigned char buf[size];\
    unsigned char tail;\
    unsigned char head;\
}

//количество элементов в очереди
#define FIFO_COUNT(fifo)     (fifo.head-fifo.tail)
//размер fifo
#define FIFO_SIZE(fifo)      ( sizeof(fifo.buf)/sizeof(fifo.buf[0]) )
//fifo заполнено?
#define FIFO_IS_FULL(fifo)   (FIFO_COUNT(fifo)==FIFO_SIZE(fifo))
//fifo пусто?
#define FIFO_IS_EMPTY(fifo)  (fifo.tail==fifo.head)
//количество свободного места в fifo
#define FIFO_SPACE(fifo)     (FIFO_SIZE(fifo)-FIFO_COUNT(fifo))
//поместить элемент в fifo
#define FIFO_PUSH(fifo, byte) \
{\
    fifo.buf[fifo.head & (FIFO_SIZE(fifo)-1)]=byte;\
    fifo.head++;\
}
//взять первый элемент из fifo
#define FIFO_FRONT(fifo) (fifo.buf[fifo.tail & (FIFO_SIZE(fifo)-1)])
//уменьшить количество элементов в очереди
#define FIFO_POP(fifo)   \
{\
    fifo.tail++; \
}
//очистить fifo
#define FIFO_FLUSH(fifo)   \
{\
    fifo.tail=0;\
    fifo.head=0;\
}
#endif //FIFO__H

/* FIFO_H_ */
 

pvvx

Активный участник сообщества
//размер должен быть степенью двойки: 4,8,16,32...128
У UART-ов на ESP8266 и так аппаратные fifo в 128 байт на TX и RX и софтовый fifo на такое-же кол-во не эффективен. Тогда уж надо брать в 4 и более раз больше - от пару килобайт :)
Большие аппаратные fifo у UART и SPI на ESP8266 по причине отсутствия DMA.
 
Сверху Снизу