From e5abc1fe99340b979b18864d978179f71fe8f5c5 Mon Sep 17 00:00:00 2001 From: vlapa Date: Sat, 13 Jun 2026 20:33:26 +0300 Subject: First --- _PROGRAMs/C++/C UART.md | 165 +++++++++++++++++++++ _PROGRAMs/C++/MQTT.md | 29 ++++ _PROGRAMs/C++/TIME.md | 26 ++++ _PROGRAMs/C++/WiFi.md | 40 +++++ _PROGRAMs/C++/snprintf.md | 48 ++++++ ...224\320\235\320\225\320\235\320\230\320\225.md" | 67 +++++++++ _PROGRAMs/ESP8266-ESP32/EEPROM.md | 33 +++++ ...277\320\260\320\274\321\217\321\202\321\214.md" | 15 ++ 8 files changed, 423 insertions(+) create mode 100644 _PROGRAMs/C++/C UART.md create mode 100644 _PROGRAMs/C++/MQTT.md create mode 100644 _PROGRAMs/C++/TIME.md create mode 100644 _PROGRAMs/C++/WiFi.md create mode 100644 _PROGRAMs/C++/snprintf.md create mode 100644 "_PROGRAMs/C++/\320\243\320\241\320\240\320\225\320\224\320\235\320\225\320\235\320\230\320\225.md" create mode 100644 _PROGRAMs/ESP8266-ESP32/EEPROM.md create mode 100644 "_PROGRAMs/ESP8266-ESP32/RTC \320\277\320\260\320\274\321\217\321\202\321\214.md" (limited to '_PROGRAMs') diff --git a/_PROGRAMs/C++/C UART.md b/_PROGRAMs/C++/C UART.md new file mode 100644 index 0000000..f58dd7c --- /dev/null +++ b/_PROGRAMs/C++/C UART.md @@ -0,0 +1,165 @@ +# Работа с UART (Си) + +Рассмотрим передачу и приём сообщения по UART подробнее (на Си). + +Сконфигурировать UART на передачу и приём сообщения на Си также просто как и на ассемблере мультиклеточного процессора. +Кроме того на Си для работы с UART доступны полезные функции и макросы, такие как вывод значения типа int, вывод строки, +вывод заданного массива памяти данных. + +В приведённых ниже примерах кода используется библиотека для работы с UART, которую необходимо подключить: + +#include + +## а) Передача по UART + +### 1. Настраиваем UART на передачу + +Первым шагом задаём структуру (все элементы структуры можно посмотреть в файле uart.h). + +UART_InitTypeDef UART_InitStructure; + +Затем инициализируем нужные параметры (незаданные параметры по умолчанию инициализируются нулём). + + UART_InitStructure.BaudRate = 38400; //скорость обмена данными + UART_InitStructure.TypeParity = 0x00000000; //тип контроля четности + UART_InitStructure.Parity = 0x00000000; //разрешение контроля четности + UART_InitStructure.FlowControl = 0x00000000; //разрешение аппаратного контроля + UART_InitStructure.Mode = 0x00000002; //разрешение передачи + + +Инициализация для UART0: + +uart_init(UART0, &UART_InitStructure); + + +Для UART3: + +uart_init(UART3, &UART_InitStructure); + +### 2. Разрешаем альтернативные функции порта + +Для UART0: + +GPIOB->BPS = 0x00000F00; + +Для UART3: + +GPIOD->BPS = 0x00000F00; + +### 3. Проверка буфера передатчика на полноту + +Для UART0: + +while(UART_FIFO_TX_FULL(UART0) == 1); + +Для UART3: + +while(UART_FIFO_TX_FULL(UART3) == 1); + +### 4.Передача байта по UART + +Для UART0: + +UART_SEND_BYTE(0xAB, UART0); + +Для UART3: + +UART_SEND_BYTE(0xAB, UART3); + +В результате можно получить простой пример по отправке байта по UART со скоростью 38400 Кбит/с: + +Для UART0: + +#include +#include + +void main() +{ + UART_InitTypeDef UART_InitStructure; + + UART_InitStructure.BaudRate = 38400; //скорость обмена данными + UART_InitStructure.TypeParity = 0x00000000; //тип контроля четности + UART_InitStructure.Parity = 0x00000000; //разрешение контроля четности + UART_InitStructure.FlowControl = 0x00000000; //разрешение аппаратного контроля + UART_InitStructure.Mode = 0x00000002; //разрешение передачи + + uart_init(UART0, &UART_InitStructure); + + GPIOB->BPS = 0x00000F00; + + while(UART_FIFO_TX_FULL(UART0) == 1); + UART_SEND_BYTE(0xAB, UART0); +} + +Для UART3 пример можно составить аналогично, только лишь заменив порт B на D и UART0 на UART3. + +Переданный байт данных можно получить с помощью программы - монитора COM-порта настроенного на данные с 1 стоп-битом, +скоростью передачи 38400 кбит/с, размером данных - 8 бит и отключённым контролем чётности. + +## б) Приём по UART + +Для приёма по UART необходимо: + +### 1. Выполнить пункты 1,2 под а) + +### 2. Проверить буфер приемника на наличие новых данных + +Для UART0: + +while(UART_NEW_DATA(UART0) == 0); + +Для UART3: + +while(UART_NEW_DATA(UART3) == 0); + +### 3. Прочитать данные + +Для UART0: + +rbyte = UART_GET_BYTE(UART0); + +Для UART3: + +rbyte = UART_GET_BYTE(UART3); + +Пример приёма байта данных составить довольно просто по аналогии с передачей байта. Следует заметить, что помимо анализа буфера приемника на +наличие новых данных, необходимо проверять буфер приёма на полноту. + +## API функции UART: + +Кроме полезных макросов имеются функции для вывода данных по UART. +Разберём подробнее каждую функцию, которая объявлена в uart.h + +`void uart_init(UART_TypeDef *UART, UART_InitTypeDef* UART_InitStruct) + +Функция _uart_init()_ выполняет инициализацию заданного номера UART. +UART - может принимать значения: UART0, UART1, UART2, UART3 +UART_InitStruct - структура, содержащая элементы конфигурации UART + +`void DM2UART(UART_TypeDef *UART, int start_address, int size_block) + +Функция _DM2UART ()_ выводит область памяти данных по UART младшим байтом вперёд. +UART - может принимать значения: UART0, UART1, UART2, UART3 +start_address - начальный адрес памяти данных +size_block - размер области данных + +`void uart_send_str(char *str, UART_TypeDef *UART) + +Функция _uart_send_str()_ выводит строку по UART. +UART - может принимать значения: UART0, UART1, UART2, UART3 +str - строка символов + +`void uart_send_int(int str, UART_TypeDef *UART) + +Функция _uart_send_int()_ выводит переменную типа int по UART. +UART - может принимать значения: UART0, UART1, UART2, UART3 +str - переменная типа int + +### Замечание: + +В версиях библиотеки до 01.04.13 необходимо перед вызовом функций DM2UART (), uart_send_int() +применять конструкцию: + +`while(UART_FIFO_TX_EMPTY(UART0) == 0); + +В версиях библиотеки после 01.04.13 функции могут использоваться самостоятельно. \ No newline at end of file diff --git a/_PROGRAMs/C++/MQTT.md b/_PROGRAMs/C++/MQTT.md new file mode 100644 index 0000000..c24332e --- /dev/null +++ b/_PROGRAMs/C++/MQTT.md @@ -0,0 +1,29 @@ + +```C++ +bool reconnect() { + Serial.print("MQTT connect : "); + Serial.println(mqtt_server); + uint8_t countMQTT = 20; // кол-во попыток соединения + uint16_t countPause = 500; // пауза между попытками + while (!(client.connect(mqtt_client, mqtt_user, mqtt_pass)) && countMQTT--) { + Serial.print(countMQTT); + Serial.print('>'); + delay(countPause); + } + if (client.connected()) { + Serial.println("MQTT connected - OK !"); + String topic = "/"; + topic += mqtt_client2; + topic += inTopicTempRoom; + mqtt_subscribe(client, topic); + topic = "/"; + topic += mqtt_client2; + topic += inTopicReboot; + mqtt_subscribe(client, topic); + return true; + } else { + return false; + } +} +``` + diff --git a/_PROGRAMs/C++/TIME.md b/_PROGRAMs/C++/TIME.md new file mode 100644 index 0000000..9643b06 --- /dev/null +++ b/_PROGRAMs/C++/TIME.md @@ -0,0 +1,26 @@ + +```C++ +String timeCalc(uint32_t t) { + uint32_t timer = t / 1000; + uint32_t timeSec = (timer % 3600) % 60; + uint32_t timeMin = (timer % 3600) / 60; + uint32_t timeHour = timer / 3600 % 24; + uint32_t timeDay = timer / 60 / 60 / 24; + String s = ""; + s += timeDay; + s += ":"; + if (timeHour < 10) + s += "0"; + s += timeHour; + s += ":"; + if (timeMin < 10) + s += "0"; + s += timeMin; + s += ":"; + if (timeSec < 10) + s += "0"; + s += timeSec; + return s; +} +``` + diff --git a/_PROGRAMs/C++/WiFi.md b/_PROGRAMs/C++/WiFi.md new file mode 100644 index 0000000..fc47f88 --- /dev/null +++ b/_PROGRAMs/C++/WiFi.md @@ -0,0 +1,40 @@ + +```C++ +const char *ssid = "ssid"; +const char *pass = "passwd"; + +bool setupWiFi(const char *wifi_ssid, const char *wifi_pass) { + digitalWrite(LED_BUILTIN, LOW); // включаем светодиод + Serial.print("\n\nSetup WiFi: "); + Serial.println(ssid); + WiFi.mode(WIFI_STA); + uint8_t countWiFi = 20; // кол-во попыток соединения + uint16_t countPause = 500; // пауза между попытками + WiFi.begin(wifi_ssid, wifi_pass); + while ((WiFi.status() != WL_CONNECTED) && countWiFi--) { + Serial.print(countWiFi); + Serial.print('>'); + delay(countPause); + } + digitalWrite(LED_BUILTIN, HIGH); // выключаем светодиод + if (WiFi.status() == WL_CONNECTED) { + // индикация IP + Serial.print("\nWiFi connected - OK !\n"); + Serial.println(WiFi.localIP()); + // индикация силы сигнала + int16_t dBm = WiFi.RSSI(); + Serial.print("RSSI dBm = "); + Serial.println(dBm); + quality_RSSI = 2 * (dBm + 100); + if (quality_RSSI >= 100) + quality_RSSI = 100; + Serial.print("RSSI % = "); + Serial.println(quality_RSSI); + Serial.println(); + return true; + } else { + return false; + } +} +``` + diff --git a/_PROGRAMs/C++/snprintf.md b/_PROGRAMs/C++/snprintf.md new file mode 100644 index 0000000..376e26b --- /dev/null +++ b/_PROGRAMs/C++/snprintf.md @@ -0,0 +1,48 @@ +# snprintf в C/C++: разбираемся с примерами + +👋 Привет! В этой статье мы поговорим о функции `snprintf`. В отличие от функции [`sprintf`](https://codelessons.dev/ru/sprintf-in-c-cplusplus/), она принимает дополнительный аргумент: максимальная длинна C-строки, которая будет записана по адресу. Сначала мы посмотрим на сигнатуру этой функции, а потом напишем простую программу, чтобы продемонстрировать работу этой функции. В [конце статьи](https://codelessons.dev/ru/snprintf-in-c-cplusplus/#%D1%83%D0%BF%D1%80%D0%B0%D0%B6%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F) вы найдете упражнения для закрепления материала. + +![Иллюстрация snprintf](https://codelessons.dev/static/e86a1cafb44e5cd0493300384183ff37/5a190/snprintf-illustration.png) + +## Как отформатировать строку используя snprintf + +Функция `snprintf` объявлена в заголовочном файле ``. В C++ вы также можете использовать ``. + +`snprintf` форматирует строку как [`printf`](https://codelessons.dev/ru/printf-in-c-cplusplus/), но записывает результат работы по адресу, вместо того, чтобы вывести строку в стандартный вывод. Также эта функция принимает максимальное количество байтов, которые нужно записать по адресу. Это делает ее более безопасной альтернативой функции `sprintf`. + +Прототип этой функции выглядит следующим образом: + +```cpp +int snprintf(char* s, size_t n, const char* format, ...); +``` + +- Первым аргументом функция принимает ссылку на начало строки, куда будет записан результат ее работы. В конец строки будет обязательно записан символ ее окончания - `\0`. +- Вторым аргументом мы передаем максимальное количество байтов, которые будут записаны по адресу (первый аргумент). В максимальное количество байтов включается `\0`. +- Третьим аргументом передается строка форматирования. +- Далее передаются дополнительные аргументы. Их количество зависит от используемых [спецификаторов формата](https://codelessons.dev/ru/printf-in-c-cplusplus/#%D1%81%D0%BF%D0%B5%D1%86%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80%D1%8B-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B0) в строке форматирования (третий аргумент). +- Возвращает функция длину отформатированной строки (как и `printf`). На это число не влияет максимальное число записанных байтов `n` (второй аргумент). + +Теперь давайте посмотрим на простой пример использования этой функции: + +```c +#include + +int main() { + int a = 1, b = 2; + char s[6]; + + int n = snprintf(s, 6, "%d + %d = %d", a, b, a + b); + + printf("s = %s, n = %d", s, n); + + return 0; +} +``` + +Вывод программы: + +```console +s = 1 + 2, n = 9 +``` + +Как вы можете видеть, функция обрезала строку. Только первые пять символов попали в `s` (только пять, потому что последний символ занимает `\0`). \ No newline at end of file diff --git "a/_PROGRAMs/C++/\320\243\320\241\320\240\320\225\320\224\320\235\320\225\320\235\320\230\320\225.md" "b/_PROGRAMs/C++/\320\243\320\241\320\240\320\225\320\224\320\235\320\225\320\235\320\230\320\225.md" new file mode 100644 index 0000000..3204281 --- /dev/null +++ "b/_PROGRAMs/C++/\320\243\320\241\320\240\320\225\320\224\320\235\320\225\320\235\320\230\320\225.md" @@ -0,0 +1,67 @@ + +```C++ +################################################ +// бегущее среднее +float k = 0.1; // коэффициент фильтрации, 0.0-1.0 +float expRunningAverage(float newVal) { + static float filVal = 0; + filVal += (newVal - filVal) * k; + return filVal; +} + +################################################ +// медиана на 3 значения со своим буфером +float medianRoom(float newValRoom) { + static float bufRoom[3] = {0, 0, 0}; + if (!(bufRoom[0] + bufRoom[1] + bufRoom[2])) + bufRoom[0] = bufRoom[1] = bufRoom[2] = newValRoom; + static byte countRoom = 0; + bufRoom[countRoom] = newValRoom; + if (++countRoom >= 3) + countRoom = 0; + float dataRoom = (max(bufRoom[0], bufRoom[1]) == max(bufRoom[1], bufRoom[2])) + ? max(bufRoom[0], bufRoom[2]) + : max(bufRoom[1], min(bufRoom[0], bufRoom[2])); + // return expRunningAverage(data); + return dataRoom; +} + +################################################ + +# это не совсем средние это апериодичное звено или простейший фильтр НЧ , и он имеет зону не чувствительности, скользящие средние делается через массив, код для ПЫКов , ну думаю разберетесь. + +unsigned int ReadADC_AN0(void) +{ static unsigned char s_ucCount; +  static unsigned int  m_TempResalt[32]; +  static unsigned int  s_uiSymm; +  +  s_ucCount++; +  s_ucCount&=0b00011111; +  s_uiSymm -= m_TempResalt[s_ucCount]; +  __delay_us(20);  +  ADCON0bits.GO_DONE=1; +  while(ADCON0bits.GO_DONE) continue; +  __delay_us(5); +  m_TempResalt[s_ucCount] = ADRESH; +  m_TempResalt[s_ucCount]<<=8; +  m_TempResalt[s_ucCount]+= ADRESL; +  s_uiSymm += m_TempResalt[s_ucCount]; +  return s_uiSymm/32;    +} + +################################################ +// AVR: Усредняем показания: +// revOld = старое значение +uint16_t filtr(uint16_t rev) +{ + static uint8_t a = pow(2, KOEFF) - 1; + (revOld > rev / KOEFF) ? revOld = (a * revOld + rev) >> KOEFF : revOld = rev; + return revOld; +} + +################################################ + + +################################################ +``` + diff --git a/_PROGRAMs/ESP8266-ESP32/EEPROM.md b/_PROGRAMs/ESP8266-ESP32/EEPROM.md new file mode 100644 index 0000000..a32093c --- /dev/null +++ b/_PROGRAMs/ESP8266-ESP32/EEPROM.md @@ -0,0 +1,33 @@ +## Список всех функций библиотеки EEPROM для ESP32, ESP8266 с подробными описаниями: + +**1. EEPROM.begin(size):** + +Инициализирует эмулированную EEPROM с указанным размером `size` (в байтах). Обычно вызывается в функции `setup()`. + +**2. EEPROM.end():** + +Завершает работу с эмулированной EEPROM и освобождает зарезервированные ресурсы. Необходимо вызывать, когда вы закончили работу с EEPROM. + +**3. EEPROM.write(address, value):** + +Записывает значение `value` (байт) в указанный адрес `address` в эмулированной EEPROM. + +**4. EEPROM.read(address):** + +Считывает байт данных из указанного адреса `address` в эмулированной EEPROM и возвращает это значение. + +**5. EEPROM.update(address, value):** + +Обновляет значение в указанном адресе `address` в эмулированной EEPROM. Если новое значение отличается от текущего, то происходит запись нового значения. + +**6. EEPROM.get(address, data):** + +Считывает данные из указанного адреса `address` в эмулированной EEPROM и сохраняет их в переменную `data`. Может использоваться для считывания структур или пользовательских типов данных. + +**7. EEPROM.put(address, data):** + +Записывает данные из переменной `data` в указанный адрес `address` в эмулированной EEPROM. Может использоваться для записи структур или пользовательских типов данных. + +**8. EEPROM.commit():** + +Сохраняет все изменения, внесенные в эмулированную EEPROM, во флэш-памяти. Это необходимо вызвать после операций записи, чтобы изменения вступили в силу. \ No newline at end of file diff --git "a/_PROGRAMs/ESP8266-ESP32/RTC \320\277\320\260\320\274\321\217\321\202\321\214.md" "b/_PROGRAMs/ESP8266-ESP32/RTC \320\277\320\260\320\274\321\217\321\202\321\214.md" new file mode 100644 index 0000000..1ea035e --- /dev/null +++ "b/_PROGRAMs/ESP8266-ESP32/RTC \320\277\320\260\320\274\321\217\321\202\321\214.md" @@ -0,0 +1,15 @@ +### Сохраняем данные в RTC-память + +При работе с платой ESP32 данные можно сохранять в RTC память (точнее, в ее RTC-модуль), она оснащена 8 Кб памяти SRAM, которую называют **«быстрой RTC-памятью»**. +Хранящиеся в ней данные не стираются во время глубокого сна, но стираются при нажатии на кнопку сброса под названием **«EN»**. + +Чтобы сохранить данные в RTC-память, перед объявлением переменной нужно добавить конструкцию: +```C++ +RTC_DATA_ATTR + +# В результате код сохранит переменную **«bootCount»** в RTC-память: + +RTC_DATA_ATTR int bootCount = 0; +``` + + -- cgit v1.2.3