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

Работа с uart в esp8266

pvvx

Активный участник сообщества
Подождите, подождите. А разве "свалка" от pvvx не избавлена от SDK Espressif в части работы с TCP стеком? А то я тут уже на этой свалке себе сервер пилить начал.
"Свалка" в части web не использует глючные функции espconn, а базируется на LwIP и при полном избавлении от SDK LwIP останется. Может версия его будет 1.4.1...
 

hd44780

New member
Снова привет :)
Кидаю в уарт с компа через FT232 97 байт (команда + аргументы). Но таск приёма не ловит ничего, такое ощущение, что модуль вообще впадает в ступор, потому что он и на другие команды перестаёт реагировать. Из ступора вывожу передёргиванием питания.
В таске приёма сделал эхо принимаемых байтов. От 97 байт эха вообще никакого.
Другие команды это - сброс, получение статуса, MAC/IP адресов. Все они однобайтные (только код команды).

Поэтому вопрос - какими порциями можно слать данные в уарт? И какого размера у него FIFO?
Для отправки данных использую Eltima Serial Port Monitor 5.0 (это монитор COM-порта) и FT232.

Ещё попробую отсылать не все 97 байт, а кусками.
 

pvvx

Активный участник сообщества
Поэтому вопрос - какими порциями можно слать данные в уарт? И какого размера у него FIFO?
fifo rx и tx по 128 байт.
Смотрите процедуру прерывания приема UART. У вас вроде была от AT, но там не очень всё хорошо.
Вариантов обработки приема с UART много - зависит от требуемых алгоритмов (что куда и когда) и указать что-то конкретное невозможно.
При нормальной скорости UART (от 115200) гарантии что "таск" успеет отработать до переполнения fifo в кодах AT нет и RTS там не задействован.
Ещё там куча проблем с включением/выключением прерываний от UART.
Чтение fifo rx в буфер:
Код:
   uint8 *ptr = &buf;
   int cnt = 0;
    while((sizebuf--) && (READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))) {
        *ptr++ = READ_PERI_REG(UART_FIFO(UART0));
        cnt++;
    }
 
Последнее редактирование:

hd44780

New member
фу-ух ..
Вставил Ваш код в обработчик прерывания уарта, добавил туда эхо для контроля. Таски свои вырубил вообще.
Кидаю 10 байт и меньше - нормально всё, эхо проходит. 11 и больше - глухой висяк..
Даже вот такое:

Код:
    while ( READ_PERI_REG ( UART_STATUS ( UART0 ) ) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S) )
    {
        temp = READ_PERI_REG ( UART_FIFO ( UART0 ) );
        // Эхо
        uart0_sendByte ( temp );
/*
        // сохраняем байт в буфере
        cmdBuffer [ cmdBufferWriteIdx ++ ] = temp;

        // Закольцовываем
        if ( cmdBufferWriteIdx == CMD_BUFFER_SIZE )
            cmdBufferWriteIdx = 0;
*/
    } // while
глохнет.

Видимо придётся ещё какое-то подобие своего терминала писать ... Чтобы руками эти куски не клеить.
 
Последнее редактирование:

hd44780

New member
Да, сброс прерывания я прогавил, каюсь :) . Поправил.
Заметил в обработчике прерывания ветку:
if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
{
// os_printf("fifo full\r\n");
uart0_sendStr ( "FIFO full\r\n" );
ETS_UART_INTR_DISABLE();/////////
// system_os_post(taskReceivePrio, 0, 0);
} // if

Послал 16 байт, получил в ответ это сообщение :) . Т.е. входной буфер == 16 байт. Если, конечно, я это правильно понимаю.
 

pvvx

Активный участник сообщества
Послал 16 байт, получил в ответ это сообщение :) . Т.е. входной буфер == 16 байт. Если, конечно, я это правильно понимаю.
Нет. Fifo 128 байт, а у вас в конфигах UART назначено RXFIFO_FULL_INT по 16-ти байтам.
 

pvvx

Активный участник сообщества
WRITE_PERI_REG(UART_CONF1(UART0),
((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) // для срабатывания int_fifo_full при приеме одного символа и заряжающий таймер на набор fifo перед передачей.
| ((0x10 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) // для срабатывания сигнала int, когда в передающем fifo (tx) остается ещё 16 символов и успела отработать процедура int до новой догрузки fifo, чтобы дырок в передаче не было.
| ((0x70 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) // для срабатывания сигнала RTS, когда в fifo останется ещё место для 16 символов и передающий успел сообразить, что забил буфер.
| ((0x01 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S) //
);
+ ещё много других установок в регистрах Uart и разных процедур обработки...
А вы пока не выбрали даже метод работы - по прерываниям или путем опроса, с таймерами или без и т.д...
(пример из моей свалки TCP2UART Web_base\app\web\uart.c и tcp_terminal.c)
Описание регистров UART, Таймера, SPI, I/O портов
 
Последнее редактирование:

hd44780

New member
Вроде разобрался, заработало. RTS я убрал, не использую его. Даже не знаю на какой он ноге у меня :( . Модуль - ESP-03.
pvvx, спасибо Вам огромное.
 

diygoodies

New member
Добрый день. Тоже мучаюсь с настройкой УАРТ и прерываниями. У меня приходят пакеты по 20 байт, выходит что получает 3 пакета и зависает и уходит в перезагрузку.
Код:
//Stupid bit of code that does the bare minimum to make os_printf work.

/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/

#include <esp8266.h>
#include <uart_hw.h>
#include "serial_transfer.h"



typedef struct {
    uint32     RcvBuffSize;
    uint8     *pRcvMsgBuff;
    uint8     *pWritePos;
    uint8     *pReadPos;
    uint8      TrigLvl; //JLU: may need to pad
    RcvMsgBuffState  BuffState;
} RcvMsgBuff;

static RcvMsgBuff rcv_buff;


LOCAL void
uart0_rx_intr_handler(void *para)
{
  uint8 RcvChar;
  uint8 uart_no = UART0;//UartDev.buff_uart_no;

  if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST))
  {
    os_printf("FRM_ERR\r\n");
    WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
  }

  if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
  {
    os_printf("fifo full\r\n");
    ETS_UART_INTR_DISABLE();
    WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
    while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))
    {
     RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
     //os_printf("%02X", RcvChar);
     get_package_char(RcvChar);
    }
  }

  else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))
  {
    ETS_UART_INTR_DISABLE();
    WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR);
    while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))
    {
     RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
     //os_printf("%02X", RcvChar);
     get_package_char(RcvChar);
    }
  }
  else if(UART_RXFIFO_TOUT_INT_ST != 0)
  {
    ETS_UART_INTR_DISABLE();
    os_printf("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no));
    WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xFFFF);
  }
  //ETS_UART_INTR_ENABLE();
}

static void ICACHE_FLASH_ATTR stdoutUartTxd(char c) {
    //Wait until there is room in the FIFO
    while (((READ_PERI_REG(UART_STATUS(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
    //Send the character
    WRITE_PERI_REG(UART_FIFO(0), c);
}

static void ICACHE_FLASH_ATTR stdoutPutchar(char c) {
    //convert \n -> \r\n
    if (c=='\n') stdoutUartTxd('\r');
    stdoutUartTxd(c);
}


void ICACHE_FLASH_ATTR stdoutInit() {


    ETS_UART_INTR_ATTACH(uart0_rx_intr_handler,  &(rcv_buff));
    //Enable TxD pin
    PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
  
    //Set baud rate and other serial parameters to 115200,n,8,1
    uart_div_modify(0, UART_CLK_FREQ/BIT_RATE_115200);
    WRITE_PERI_REG(UART_CONF0(0), (STICK_PARITY_DIS)|(ONE_STOP_BIT << UART_STOP_BIT_NUM_S)| \
                (EIGHT_BITS << UART_BIT_NUM_S));

    //Reset tx & rx fifo
    SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
    CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
    //Clear pending interrupts


    //set rx fifo trigger
    WRITE_PERI_REG(UART_CONF1(0),
                   ((0x10 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
                   ((0x10 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |UART_RX_FLOW_EN |
                   (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S |  UART_RX_TOUT_EN);
    SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA);


    WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);

    SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA);

    //Install our own putchar handler
    os_install_putc1((void *)stdoutPutchar);
    ETS_UART_INTR_ENABLE();
}
И функция разбора пакета

Код:
void ICACHE_FLASH_ATTR get_package_char(char DataUART)
{        
  
    //Some packet function

    WRITE_PERI_REG(0X60000914, 0x73);
    if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST))
    {
    WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
    }
    else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_TOUT_INT_ST))
    {
    WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
    }
    ETS_UART_INTR_ENABLE();
}
Скорее всего переполняется буфер хотелось бы знать как правильно его очистить
 
Чёт не понял что значит SDK? С ним я смогу переписать прошивку самого SIM900??? Я просто по этой ссылке не вижу никаких сдк,, пдфок много, еще какой-то сервер, поммогите пожалуйста понять как загрузить это сдк, и перепрошивать
SIM900, извините что не в тему пишу.
 

diygoodies

New member
Короче такой обработчик рабочий
Код:
static void ICACHE_FLASH_ATTR recvTask(os_event_t *events)
{
    uint8_t i;    
    while (READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))
    {
        WRITE_PERI_REG(0X60000914, 0x73); //WTD
        uint16 length = 0;
        while ((READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) && (length<MAX_UARTBUFFER))
            uartbuffer[length++] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
        for (i = 0; i < MAX_CONN; ++i)
            if (connData[i].conn)
                espbuffsent(&connData[i], uartbuffer, length);       
    }

    if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST))
    {
        WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
    }
    else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_TOUT_INT_ST))
    {
        WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
    }
    ETS_UART_INTR_ENABLE();
}
взял здесь https://github.com/beckdac/ESP8266-transparent-bridge/blob/master/user/user_main.c
 

Tomahawk

New member
Во многих проектах их авторы используют в тексте os_printf для вывода отладочной информации, но на деле через uart в terminal 1.9 ничего не выводится. Судя по описанию, достаточно подключить osapi.h, но нет... В чём секрет? Единственный рабочий способ, который я знаю, находился в UDK (функция console_print).
 

pvvx

Активный участник сообщества
Во многих проектах их авторы используют в тексте os_printf для вывода отладочной информации, но на деле через uart в terminal 1.9 ничего не выводится. Судя по описанию, достаточно подключить osapi.h, но нет... В чём секрет? Единственный рабочий способ, который я знаю, находился в UDK (функция console_print).
os_printf() - это в SDK os_printf_plus():
Имеет отключение вывода с помощью system_set_os_print(flag), flag = 0 отключает вывод.
Так-же os_printf() может выводить строки из области flash и IRAM.
Для вывода она использует назначенную функцию по os_install_putc1(func), назначенная func может быть любой. Т.е. может выводить побайтно хоть в память, а не в UART0 или UART1. По умолчанию в SDK назначена функция вывода в UART0 с иcпользованием FIFO (fifo у uart 128 байт, если сообщение лезет в него, то ожидания не происходит и оно аппаратно выводится и после выполнения os_printf() не тормозя основную программу).
Выход TX UART0 может быть переключен на другой вывод чипа ESP8266, а так-же полностью отключен.
В UDK console_print - это переназначенная ets_uart_printf(), которая находится в ROM-BIOS и имеет ошибки (к примеру с "%p:"), да работает с функцией _putc1() по адресу ROM:40001DCC которая использует номер UART из структуры UartDev.buff_uart_no и не использует FIFO. Т.е. при выводе через неё ожидается вывод каждого символа.
 

Tomahawk

New member
Использую ESP-01, хочу вывести через os_print на RxD и TxD (console_print на них же работает, а os_print нет). Ставить system_set_os_print(1); пробовал, но не помогло. Получается выводить возможно только на GPIO2? Зачем такие сложности, интересно...)
 
Сверху Снизу