打印
[STM32F4]

【STM32F413H Discovery Kit 试用】HTTP 服务器

[复制链接]
30|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

【STM32F413H Discovery Kit 试用】HTTP 服务器

介绍了使用 STM32F413H Discovery Kit 开发板 WiFi 模组实现 HTTP 网页服务器的搭建。

简介

超文本传输协议(Hyper Text Transfer Protocol,HTTP)是标准的应用层协议,用作服务器和客户端之间的请求响应协议,通常运行在 TCP 之上。广泛应用于物联网(IoT)与嵌入式开发,可以实现设备端的远程网络控制、传感器数据采集等。

日常使用浏览器打开的网页使用的就是HTTP 协议。这里基于开发板和 WiFi 模组建立 HTTP 网络服务器,并通过浏览器访问该服务器。

工程测试

使用 STM32CubeIDE 软件打开测试工程 STM32F413\STM32Cube_FW_F4_V1.28.0\Projects\STM32F413H-Discovery\Applications\WIFI\WiFi_HTTP_Server

该工程可利用板载 WiFi 模组实现 HTTP 网页服务器的构建。

打开 Application - User - main.c 文件,输入关键信息后构建工程并运行。

代码

输入可检索到的 WiFi 信息,包括 SSID 和 PASSWORD;

#include "main.h"

#define SSID     "xxx"
#define PASSWORD "xxxxxx"

#define LCD_USE

#define PORT           80

typedef enum
{
  WS_IDLE = 0,
  WS_CONNECTED,
  WS_DISCONNECTED,
  WS_ERROR,
} WebServerState_t;

static   uint8_t http[1024];
static   uint8_t resp[1024];
uint16_t respLen;
uint8_t  IP_Addr[4]; 
uint8_t  MAC_Addr[6]; 
int32_t Socket = -1;
static   WebServerState_t  State = WS_ERROR;
static ADC_HandleTypeDef    AdcHandle;

/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void Error_Handler(void);
static WIFI_Status_t SendWebPage(uint8_t ledIsOn, uint8_t temperature);
static void WebServerProcess(void);
static uint32_t TEMP_SENSOR_Init(void);
static uint32_t TEMP_SENSOR_GetValue(void);

int main(void)
{
#if defined (LCD_USE)
  uint8_t modulestr[20] = {0};
#endif /* LCD_USE */ 

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  
  /* Configure the system clock */
  SystemClock_Config();
  
  /* Configure LED3 and LED4 */
  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);
  
  /*Initialize Temperature sensor */
  TEMP_SENSOR_Init();
  
  /* WIFI Web Server demonstration */
#if defined (LCD_USE)
  BSP_LCD_InitEx(LCD_ORIENTATION_LANDSCAPE_ROT180);
  BSP_LCD_DisplayOn();
  BSP_LCD_Clear(LCD_COLOR_WHITE);
  
  BSP_LCD_Clear(LCD_COLOR_WHITE);
  BSP_LCD_SetBackColor(LCD_COLOR_BLUE);

  BSP_LCD_SetTextColor(LCD_COLOR_BLUE); 
  BSP_LCD_FillRect(0, 0, BSP_LCD_GetXSize(), (BSP_LCD_GetYSize() -200));

  BSP_LCD_SetFont(&Font16);
  BSP_LCD_SetTextColor(LCD_COLOR_WHITE); 
  BSP_LCD_DisplayStringAt(10, 10, (uint8_t *)"WIFI Web", CENTER_MODE );
  BSP_LCD_DisplayStringAt(10, 23, (uint8_t *)"Server demonstration", CENTER_MODE );   
#endif /* LCD_USE */

  /*Initialize and use WIFI module */
  if(WIFI_Init() ==  WIFI_STATUS_OK)
  {
#if defined (LCD_USE)
    BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
    BSP_LCD_SetTextColor(LCD_COLOR_BLUE); 
    BSP_LCD_DisplayStringAtLine(4, (uint8_t *)"ES-WIFI Initialized.");
#endif /* LCD_USE */     
    
      if(WIFI_GetMAC_Address(MAC_Addr) == WIFI_STATUS_OK)
      {       
#if defined (LCD_USE)    
      BSP_LCD_SetTextColor(LCD_COLOR_BLACK); 
      BSP_LCD_DisplayStringAtLine(6, (uint8_t *)"es-wifi MAC Address:");
      sprintf((char*)modulestr,"%X:%X:%X:%X:%X:%X.", MAC_Addr[0],
              MAC_Addr[1],
              MAC_Addr[2],
              MAC_Addr[3],
              MAC_Addr[4],
              MAC_Addr[5]);
      
      BSP_LCD_DisplayStringAtLine(7, (uint8_t *) modulestr);
#endif /* LCD_USE */
      }
      else
      {
#if defined (LCD_USE)  
        BSP_LCD_SetTextColor(LCD_COLOR_RED); 
        BSP_LCD_DisplayStringAtLine(6, (uint8_t *)"CANNOT get MAC address");
#endif /* LCD_USE */  
        BSP_LED_On(LED4);
      }
    
   if( WIFI_Connect(SSID, PASSWORD, WIFI_ECN_WPA2_PSK) == WIFI_STATUS_OK)
    {
#if defined (LCD_USE)  
      BSP_LCD_SetTextColor(LCD_COLOR_BLUE); 
      BSP_LCD_DisplayStringAtLine(9, (uint8_t *)"es-wifi connected");
#endif /* LCD_USE */ 
      
      if(WIFI_GetIP_Address(IP_Addr) == WIFI_STATUS_OK)
      {
#if defined (LCD_USE)
        BSP_LCD_SetTextColor(LCD_COLOR_BLACK);         
        BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"es-wifi IP Address :");
        sprintf((char*)modulestr,"%d.%d.%d.%d",  IP_Addr[0],
                IP_Addr[1],
                IP_Addr[2],
                IP_Addr[3]); 
        
        BSP_LCD_DisplayStringAtLine(11, (uint8_t *) modulestr);
        BSP_LCD_SetTextColor(LCD_COLOR_BLUE); 
        BSP_LCD_DisplayStringAtLine(13, (uint8_t *)"Start HTTP Server... ");
        BSP_LCD_DisplayStringAtLine(14, (uint8_t *)"Wait for connection...  ");
#endif /* LCD_USE */
        State = WS_IDLE;
        
      }
      else
      {    
#if defined (LCD_USE)  
        BSP_LCD_SetTextColor(LCD_COLOR_RED); 
        BSP_LCD_DisplayStringAtLine(12, (uint8_t *)"es-wifi CANNOT get IP address");
#endif /* LCD_USE */
        BSP_LED_On(LED4);
      }
    }
    else
    {
      
#if defined (LCD_USE)  
      BSP_LCD_SetTextColor(LCD_COLOR_RED); 
      BSP_LCD_DisplayStringAtLine(11, (uint8_t *)"es-wifi NOT connected\n");
#endif /* LCD_USE */ 
      BSP_LED_On(LED4);
    }
  }
  else
  {   
#if defined (LCD_USE)  
    BSP_LCD_SetTextColor(LCD_COLOR_RED); 
    BSP_LCD_DisplayStringAtLine(4, (uint8_t *)"WIFI cannot be initialized.\n");
#endif /* LCD_USE */
    BSP_LED_On(LED4);
  }
    
  while(1)
  {
      WebServerProcess ();
  }
}

static void WebServerProcess(void)
{
  uint8_t LedState = 0, temp;
  
  switch(State)
  {
  case WS_IDLE:
    Socket = 0;
    WIFI_StartServer(Socket, WIFI_TCP_PROTOCOL, "", PORT);
    
    if(Socket != -1)
    {
#if defined (LCD_USE) 
      BSP_LCD_ClearStringLine(14);
      BSP_LCD_DisplayStringAtLine(13, (uint8_t *)"HTTP Server Started");
#endif /* LCD_USE */
      State = WS_CONNECTED;
    }
    else
    {
#if defined (LCD_USE)  
      BSP_LCD_SetTextColor(LCD_COLOR_RED); 
      BSP_LCD_DisplayStringAtLine(13, (uint8_t *)"ERROR : Connection cannot be established");
#endif /* LCD_USE */
      State = WS_ERROR;
    }    
    break;
    
  case WS_CONNECTED:
    
    WIFI_ReceiveData(Socket, resp, 1200, &respLen);
    
    if( respLen > 0)
    {
      if(strstr((char *)resp, "GET")) /* GET: put web page */
      {
        temp = TEMP_SENSOR_GetValue();
        if(SendWebPage(LedState, temp) != WIFI_STATUS_OK)
        {
#if defined (LCD_USE)  
      BSP_LCD_SetTextColor(LCD_COLOR_RED); 
      BSP_LCD_DisplayStringAtLine(14, (uint8_t *)"ERROR : Cannot send web page");
#endif /* LCD_USE */
          State = WS_ERROR;
        }
      }
      else if(strstr((char *)resp, "POST"))/* POST: received info */
      {
          if(strstr((char *)resp, "radio"))
          {          
            if(strstr((char *)resp, "radio=0"))
            {
              LedState = 0;
              BSP_LED_Off(LED3);
            }
            else if(strstr((char *)resp, "radio=1"))
            {
              LedState = 1;
              BSP_LED_On(LED3);
            } 
            
            temp = TEMP_SENSOR_GetValue();
            if(SendWebPage(LedState, temp) != WIFI_STATUS_OK)
            {
#if defined (LCD_USE)  
      BSP_LCD_SetTextColor(LCD_COLOR_RED); 
      BSP_LCD_DisplayStringAtLine(14, (uint8_t *)"ERROR : Cannot send web page");
#endif /* LCD_USE */
              State = WS_ERROR;
          }
        }
      }
    }
    if(WIFI_StopServer(Socket) == WIFI_STATUS_OK)
    {
      WIFI_StartServer(Socket, WIFI_TCP_PROTOCOL, "", PORT);
    }
    else
    {
      State = WS_ERROR;  
    }
    break;
  case WS_ERROR:   
  default:
    break;
  }
}

static WIFI_Status_t SendWebPage(uint8_t ledIsOn, uint8_t temperature)
{
  uint8_t  temp[50];
  uint16_t SentDataLength;
  WIFI_Status_t ret;
  
  /* construct web page content */
  strcpy((char *)http, (char *)"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n");
  strcat((char *)http, (char *)"<html>\r\n<body>\r\n");
  strcat((char *)http, (char *)"<title>STM32 Web Server</title>\r\n");
  strcat((char *)http, (char *)"<h2>InventekSys : Web Server using Es-Wifi with STM32</h2>\r\n");
  strcat((char *)http, (char *)"<br /><hr>\r\n");
  strcat((char *)http, (char *)"<p><form method=\"POST\"><strong>Temp: <input type=\"text\" size=2 value=\"");
  sprintf((char *)temp, "%d", temperature);
  strcat((char *)http, (char *)temp);
  strcat((char *)http, (char *)"\"> <sup>O</sup>C");
  
  if (ledIsOn) 
  {
    strcat((char *)http, (char *)"<p><input type=\"radio\" name=\"radio\" value=\"0\" >LED off");
    strcat((char *)http, (char *)"<br><input type=\"radio\" name=\"radio\" value=\"1\" checked>LED on");
  } 
  else 
  {
    strcat((char *)http, (char *)"<p><input type=\"radio\" name=\"radio\" value=\"0\" checked>LED off");
    strcat((char *)http, (char *)"<br><input type=\"radio\" name=\"radio\" value=\"1\" >LED on");
  }

  strcat((char *)http, (char *)"</strong><p><input type=\"submit\"></form></span>");
  strcat((char *)http, (char *)"</body>\r\n</html>\r\n");
  
  ret = WIFI_SendData(0, (uint8_t *)http, strlen((char *)http), &SentDataLength); 
  
  if((ret == WIFI_STATUS_OK) && (SentDataLength != strlen((char *)http)))
  {
    ret = WIFI_STATUS_ERROR;
  }
    
  return ret;
}

static uint32_t TEMP_SENSOR_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;
  
   /* ADC1 Periph clock enable */
  __HAL_RCC_ADC1_CLK_ENABLE();
  
  /* Configure the ADC peripheral */
  AdcHandle.Instance          = ADC1;
  
  AdcHandle.Init.ClockPrescaler        = ADC_CLOCKPRESCALER_PCLK_DIV4;
  AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;
  AdcHandle.Init.ScanConvMode          = DISABLE;                       /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
  AdcHandle.Init.ContinuousConvMode    = ENABLE;                        /* Continuous mode enabled to have continuous conversion */
  AdcHandle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */
  AdcHandle.Init.NbrOfDiscConversion   = 0;
  AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;        /* Conversion start not triggered by an external event */
  AdcHandle.Init.ExternalTrigConv      = ADC_EXTERNALTRIGCONV_T1_CC1;
  AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
  AdcHandle.Init.NbrOfConversion       = 1;
  AdcHandle.Init.DMAContinuousRequests = DISABLE;
  AdcHandle.Init.EOCSelection          = DISABLE;
  
  if (HAL_ADC_Init(&AdcHandle)== HAL_OK)
  {
    /* Configure ADC Temperature Sensor Channel */
    sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
    sConfig.Offset = 0;
    
    if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) == HAL_OK)
    {
      return 0;
    }
  }
  return 1;
}

static uint32_t TEMP_SENSOR_GetValue(void)
{   

  if(HAL_ADC_Start(&AdcHandle) == HAL_OK)
  {
    if(HAL_ADC_PollForConversion(&AdcHandle, 1000)== HAL_OK)
    {
      return ((((HAL_ADC_GetValue(&AdcHandle) * VREF)/MAX_CONVERTED_VALUE) - VSENS_AT_AMBIENT_TEMP) * 10 / AVG_SLOPE) + AMBIENT_TEMP;
    } 
  }
  return  0xFFFFFFFF;
}

static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
  HAL_StatusTypeDef ret = HAL_OK;

  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();

  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 200;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  RCC_OscInitStruct.PLL.PLLR = 2;
  ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);

  if(ret != HAL_OK)
  {
   Error_Handler();
  }

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
  if(ret != HAL_OK)
  {
   Error_Handler();
  }
}

static void Error_Handler(void)
{
  /* User may add here some code to deal with this error */
  while(1)
  {
  }
}

效果

LCD 显示

连接 WiFi 无线网络,给出开发板设备 IP 地址,并提示等待连接

HTTP_waiting_connect.jpg

检测到地址被访问,LCD 提示 HTTP 服务开始

HTTP_start.jpg

在同一网络下输入 LCD 显示的设备 IP 地址,如 192.168.1.122

WiFi_module_HTTP.jpg

网页显示

  • 设备名称 InventekSys : Web Server using Es-Wifi with STM32
  • 温度传感器转换值
  • 板载 LED 控制选项

可实现网页端获取温度信息,以及 LED 控制。

总结

本文介绍了 STM32F413H Discovery kit 开发板实现 HTTP 服务器的搭建以及相关测试,分析了关键工程代码,并对测试方法和测试结果进行了必要的说明。

使用特权

评论回复
沙发
SophiaOP| | 2025-1-22 20:21 | 只看该作者
单片机也能做服务器啊?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

36

帖子

0

粉丝