Listing 1. Fragment programu odpowiedzialny za współpracę z modułem Wi-Fi ESP8266 [...] /* USER CODE BEGIN Includes */ #include „stdlib.h” #include „string.h” /* USER CODE END Includes */ /* USER CODE BEGIN PV */ UART_HandleTypeDef * esp_uart = &huart1; volatile uint8_t esp_recv_char; volatile uint8_t esp_char_counter = 0; char esp_pattern[] = „+IPD,”; volatile uint8_t esp_recv_flag = 0; volatile char esp_recv_mux; volatile char esp_recv_buffer[1024]; volatile uint16_t esp_recv_len; char webpage[483], error[139]; /* USER CODE END PV */ [...] /* USER CODE BEGIN 0 */ // Funkcja obliczająca korekcję gamma i ustawiająca jasność diody void set_led_brightness(TIM_HandleTypeDef * timer, uint32_t channel, uint8_t brightness) { int32_t value = powf((double) brightness / 255.0, 2.2) * 49999; __HAL_TIM_SET_COMPARE(timer, channel, value); } // Funkcja ustawiająca kolor świecenia diody RGB void set_color(uint8_t red, uint8_t green, uint8_t blue) { set_led_brightness(&htim1, TIM_CHANNEL_2, red); set_led_brightness(&htim1, TIM_CHANNEL_3, green); set_led_brightness(&htim1, TIM_CHANNEL_1, blue); } // Funkcja wysyłająca podany ciąg znaków przez interfejs UART void uart_write_line(UART_HandleTypeDef * handler, char * text) { HAL_UART_Transmit(handler, text, strlen(text), 1000); HAL_UART_Transmit(handler, „\r\n”, 2, 100); } // Funkcja odbierająca linię tekstu przez interfejs UART void uart_read_line(UART_HandleTypeDef * handler, char * buffer, uint16_t buffer_size) { HAL_StatusTypeDef status; char current_char; uint16_t char_counter = 0; while (char_counter < buffer_size - 1) { status = HAL_UART_Receive(handler, ¤t_char, 1, 1); if (status == HAL_OK) { if (current_char == ‚\r’ || current_char == ‚\n’) if (char_counter == 0) continue; else break; (buffer + char_counter++) = current_char; } } *(buffer + char_counter) = ‚\0’; } // Funkcja odczytująca pojedynczy znak odebrany przez UART char uart_read_char(UART_HandleTypeDef * handler) { char buffer = ‚\0’; HAL_UART_Receive(handler, &buffer, 1, 1000); return buffer; } // Funkcja wysyłająca polecenie do modułu ESP8266 // i oczekująca na jego potwierdzenie uint8_t esp_send_cmd(UART_HandleTypeDef * uart, char * command) { char response[30]; response[0] = ‚\0’; uart_write_line(uart, command); __HAL_UART_FLUSH_DRREGISTER(&huart1); while (strcmp(response, „OK”) != 0 && strcmp(response, „no change”) != 0 && strcmp(response, „ERROR”) != 0) uart_read_line(uart, response, 30); if (strcmp(response, „ERROR”) == 0) return 0; else return 1; } // Funkcja wysyłająca dane przez nawiązane połączenie TCP // i zamykająca to połączenie void esp_send_data_and_close(UART_HandleTypeDef * uart, char mux_id, char * content) { char cmd[17]; sprintf(cmd, „AT+CIPSEND=%c,%d”, mux_id, strlen(content)); uart_write_line(uart, cmd); HAL_Delay(20); HAL_UART_Transmit(uart, content, strlen(content), 5000); HAL_Delay(100); sprintf(cmd, „AT+CIPCLOSE=%c”, esp_recv_mux); uart_write_line(esp_uart, cmd); } // Funkcja uruchamiająca obsługę przerwań void esp_start_int_recv(UART_HandleTypeDef * uart) { __HAL_UART_FLUSH_DRREGISTER(uart); HAL_UART_Receive_IT(uart, &esp_recv_char, 1); } // Funkcja obsługująca przerwanie, wywoływana w momencie odebrania // przez interfejs UART pojedynczego bajtu danych void HAL_UART_RxCpltCallback(UART_HandleTypeDef * uart) { if (esp_recv_char == esp_pattern[esp_char_counter]) { esp_char_counter++; if (esp_char_counter == 5) { // Jeśli odbierzemy ciąg znaków „+IPD,”: // Odczytujemy numer połączenia do zmiennej esp_recv_mux esp_recv_mux = uart_read_char(uart); uart_read_char(uart); // Odczytujemy długość odebranych dancyh do esp_recv_len char length_str[5]; char current_char = 0; uint8_t char_counter = 0; do { current_char = uart_read_char(uart); length_str[char_counter++] = current_char; } while (current_char != ‚:’); length_str[char_counter] = ‚\0’; uint16_t esp_recv_len = atoi(&length_str); // Odbieramy dane do bufora esp_recv_buffer HAL_UART_Receive(uart, esp_recv_buffer, esp_recv_len, 1000); esp_recv_flag = 1; return; } } else esp_char_counter = 0; // Ponowne uruchomienie przerwania HAL_UART_Receive_IT(uart, &esp_recv_char, 1); } // Funkcja przesyłająca do modułu ESP8266 polecenia konfigurujące uint8_t esp_setup() { HAL_Delay(500); // Oczekujemy na uruchomienie modułu if (!esp_send_cmd(esp_uart, „AT+CWMODE=1”)) return 0; if (!esp_send_cmd(esp_uart, „AT+CWJAP=\”NAZWA_SIECI\”,\”KLUCZ_SIECIOWY\””)) return 0; if (!esp_send_cmd(esp_uart, „AT+CIPMUX=1”)) return 0; if (!esp_send_cmd(esp_uart, „AT+CIPSERVER=1,80”)) return 0; return 1; } // Funkcja wywoływana w momencie otrzymania danych przez połączenie TCP void handle_request() { // Odczytujemy pierwsze 6 znaków odebranego żądania HTTP char request_begining[7]; for (uint8_t i = 0; i < 6; i++) request_begining[i] = esp_recv_buffer[i]; request_begining[6] = ‚\0’; // Jeśli przesłane zostały parametry - początek żądania: // „GET /?red=XXX&green=XXX&blue=XXX HTTP/1.1” if (strcmp(request_begining, „GET /?”) == 0) { // Odczytujemy pierwsze 3 liczby, jakie pojawią się w adresie // - są to wartości poszczególnych kolorów składowych (RGB) int nums[3] = { 0, 0, 0 }; int num_counter = 0; uint8_t last_char_was_digit = 0; for (int i = 6; i < 41; i++) if (esp_recv_buffer[i] >= ‚0’ && esp_recv_buffer[i] <= ‚9’) { last_char_was_digit = 1; nums[num_counter] *= 10; nums[num_counter] += esp_recv_buffer[i] - ‚0’; } else if (last_char_was_digit == 1) { last_char_was_digit = 0; num_counter++; if (num_counter == 4) break; } // Ustawiamy kolor na diodzie RGB set_color(nums[0], nums[1], nums[2]); // Zwracamy stronę WWW z formularzem wyboru kolorów esp_send_data_and_close(esp_uart, esp_recv_mux, webpage); // Jeśli żądanie dotyczy strony głównej - «GET / HTTP/1.1» } else if (strcmp(request_begining, „GET / „) == 0) esp_send_data_and_close(esp_uart, esp_recv_mux, webpage); // W innym przypadku - zwracamy komunikat o błędzie (404 Not Found) else esp_send_data_and_close(esp_uart, esp_recv_mux, error); // Resetujemy flagę obsługi danych i wznawiamy odbiór w przerwaniach esp_recv_flag = 0; HAL_UART_Receive_IT(esp_uart, &esp_recv_char, 1); } /* USER CODE END 0 */ int main(void) { [...] /* USER CODE BEGIN 2 */ HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3); strcpy(webpage, „HTTP/1.1 200 OK\r\n”); strcat(webpage, „Content-Type: text/html\r\n”); strcat(webpage, „Content-Lenght: 398\r\n”); strcat(webpage, „Connection: close\r\n\r\n”); strcat(webpage, „\r\n\r\n\r\n”); strcat(webpage, „Dioda RGB\r\n\r\n”); strcat(webpage, „\r\n
\r\n”); strcat(webpage, „

Czerwony (0-255):

\r\n”); strcat(webpage, „

Zielony (0-255):

\r\n”); strcat(webpage, „

Niebieski (0-255):

\r\n”); strcat(webpage, „\r\n”); strcat(webpage, „
\r\n\r\n”); strcpy(error, „HTTP/1.1 404 Not Found\r\n”); strcat(error, „Content-Type: text/html\r\n”); strcat(error, „Content-Lenght: 48\r\n”); strcat(error, „Connection: close\r\n\r\n”); strcat(error, „

404 Not Found

”); if (esp_setup()) { set_color(0, 60, 0); esp_start_int_recv(esp_uart); } else set_color(60, 0, 0); /* USER CODE END 2 */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ // Obsługujemy dane przychodzące przez połączenie TCP, // jeśli w przerwaniu ustawiono flagę esp_recv_flag if (esp_recv_flag == 1) handle_request(); } /* USER CODE END 3 */ }