• Система автоматизации с открытым исходным кодом на базе 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.
 
Сверху Снизу