diff options
Diffstat (limited to '_PROGRAMs/C++')
| -rw-r--r-- | _PROGRAMs/C++/C UART.md | 165 | ||||
| -rw-r--r-- | _PROGRAMs/C++/MQTT.md | 29 | ||||
| -rw-r--r-- | _PROGRAMs/C++/TIME.md | 26 | ||||
| -rw-r--r-- | _PROGRAMs/C++/WiFi.md | 40 | ||||
| -rw-r--r-- | _PROGRAMs/C++/snprintf.md | 48 | ||||
| -rw-r--r-- | _PROGRAMs/C++/УСРЕДНЕНИЕ.md | 67 |
6 files changed, 375 insertions, 0 deletions
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.h> + +## а) Передача по 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 <HDL51001_ccf.h> +#include <uart.h> + +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 + +Функция `snprintf` объявлена в заголовочном файле `<stdio.h>`. В C++ вы также можете использовать `<cstdio>`. + +`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 <stdio.h> + +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++/УСРЕДНЕНИЕ.md b/_PROGRAMs/C++/УСРЕДНЕНИЕ.md new file mode 100644 index 0000000..3204281 --- /dev/null +++ b/_PROGRAMs/C++/УСРЕДНЕНИЕ.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; +} + +################################################ + + +################################################ +``` + |
