基于W55MH32Q-EVB 实现 HTTP 服务器配置 OLED 滚动显示信息
目录
1 前言
2 项目环境
2.1 硬件准备
2.2 软件环境
3.硬件连接和方案
3.1 硬件连接
3.2 方案图示
4.例程修改
5.运行结果
5.运行结果
6.总结
1 前言
HTTP(超文本传输协议,HyperText Transfer Protocol)是一种用于分布式、协作式、超媒体信息系统的应用层协议, 基于 TCP/IP 通信协议来传递数据,是万维网(WWW)的数据通信的基础。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法,通过 HTTP 或者 HTTPS 协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。 以上是 HTTP 协议的简介,如想深入了解该协议,请参考 mozilla 网站上的介绍:HTTP 概述 - HTTP | MDN
W55MH32Q-EVB 是基于 W55MH32L 芯片开发的一款开发板,主频为 216MHz,1MB 的闪存以及 96KB 的 SRAM,同时还具有一个完整的硬件 TCP/IP 卸载引擎,只需要简单的 socket 编程即可实现以太网应用。 具有以下特点:
- 增强型、真随机数、硬件加密算法单元
- 32 位 Arm® Cortex®-M3 核心的片上
- 1024K 字节闪存的微控制器
- 10/100M 以太网 MAC 和 PHY、集成完整的全硬件 TCP/IP 协议栈引擎
- USB、CAN、17 个定时器
- 3 个 ADC、2 个 DAC、12 个通信接口
产品链接:商品详情
2 项目环境
2.1 硬件准备
- W55MH32Q-EVB 模块
- 杜邦线若干
- 交换机或路由器
- oled 模块
- 一根网线
2.2 软件环境
- 例程链接:https://www.w5500.com/w55mh32.html
- 飞思创串口助手
- Keil5
3.硬件连接和方案
3.1 硬件连接
1.W55MH32Q-EVB_3.3V ---> OLED_VCC
2.W55MH32Q-EVB_GND ---> OLED_GND
3.W55MH32Q-EVB_SCL ---> OLED_SCL
4.W55MH32Q-EVB_SDA ---> OLED_SDA
3.2 方案图示
4.例程修改
本次以 HTTP_Server 为例:
找到 Webpage.h 将文件内容替换成以下内容
#ifndef _WEBPAGE_H_
#define _WEBPAGE_H_/************************************************************************************** HTML Pages (web pages)*************************************************************************************/#define index_page "<html>\n"\
"<head>\n"\
" <title>W55MH32 SMTP Configuration</title>\n"\
" <style>\n"\
" body {\n"\
" font-family: Arial, sans-serif;\n"\
" margin: 20px;\n"\
" padding: 20px;\n"\
" background-color: #f4f4f9;\n"\
" }\n"\
" h1 {\n"\
" text-align: center;\n"\
" color: #333;\n"\
" }\n"\
" form {\n"\
" max-width: 400px;\n"\
" margin: auto;\n"\
" background: #ffffff;\n"\
" padding: 20px;\n"\
" border-radius: 8px;\n"\
" box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\n"\
" }\n"\
" label {\n"\
" display: block;\n"\
" margin-bottom: 8px;\n"\
" font-weight: bold;\n"\
" }\n"\
" input[type=text],\n"\
" input[type=submit] {\n"\
" width: 400px;\n"\
" padding: 8px;\n"\
" margin-bottom: 12px;\n"\
" border: 1px solid #ccc;\n"\
" border-radius: 4px;\n"\
" }\n"\
" input[type=submit] {\n"\
" background-color: #4CAF50;\n"\
" color: white;\n"\
" border: none;\n"\
" cursor: pointer;\n"\
" margin-top: 20px;\n"\
" }\n"\
" input[type=submit]:hover {\n"\
" background-color: #45a049;\n"\
" }\n"\
" textarea {\n"\
" width: 400px;\n"\
" height: 100px;\n"\
" resize: none;\n"\
" margin-bottom: 20px;\n"\
" }\n"\
" </style>\n"\
" <script>\n"\
" </script>\n"\
"</head>\n"\
"<body>\n"\
" <h1>W55MH32 OLED DISPLAY Configuration</h1>\n"\
" <form method=\"post\" action=\"config.cgi\" >\n"\
" <label>text: </label><textarea name=\"text\">%s</textarea><br>\n"\
" <label>\n"\
" <input type=\"checkbox\" id=\"vehicle1\" name=\"is_Rolling\" value=\"Rolling\"> Rolling\n"\
" </label>\n"\
" <input type=\"submit\" value=\"OK\">\n"\
" </form>\n"\
"</body>\n"\
"</html>\n"\#define CONFIG_SUCCESS_PAGE "<html lang=en>\n"\
"<head>\n"\
" <meta charset=UTF-8>\n"\
" <meta name=viewport content=width=device-width, initial-scale=1.0>\n"\
" <title>Configuration Modification Succeeded</title>\n"\
" <style>\n"\
" body {\n"\
" font-family: Arial, sans-serif;\n"\
" text-align: center;\n"\
" padding-top: 100px;\n"\
" background-color: #f0f0f0;\n"\
" }\n"\
" h1 {\n"\
" color: skyblue;\n"\
" animation: fadeInOut 2s infinite;\n"\
" }\n"\
" </style>\n"\
"</head>\n"\
"<body>\n"\
" <h1>The device has received the message!</h1>\n"\
" <h1>OLED will be displayed soon!</h1>\n"\
"<script>\n"\
"</script>\n"\
"</body>\n"\
"</html>\n"\#endif
在 httpUtil.c 中修改 predefined_set_cgi_processor 函数,这个是处理浏览器提交过来的数据的函数,代码如下
uint8_t predefined_set_cgi_processor(uint8_t *uri_name, uint8_t *uri, uint8_t *buf, uint16_t *len)
{if (strcmp((const char *)uri_name, "config.cgi") == 0)
{uint8_t *param;param = get_http_param_value((char *)uri, "text");set_data(param);param = get_http_param_value((char *)uri, "is_Rolling");if (!strcmp(param, "Rolling"))
{set_rolling_flag(1);
}else
{set_rolling_flag(0);
}set_dispaly_flag(1);*len = sprintf((char *)buf, (char *)CONFIG_SUCCESS_PAGE);return 1;
}return 0;
}
添加 oled.c 函数,用于控制 oled。通过向oled相应寄存器赋值,即可实现oled滚动。代码如下
#include "oled.h"
#include "delay.h"
#include "flash.h"
#include "oledfont.h"
#include "stdint.h"
#include "string.h"
#include "w55mh32.h"unsigned char data[64] = "";
unsigned char is_rolling_flag = 0;
unsigned char display_flag = 0;
unsigned char startup_flag = 1;void IIC_Start()
{OLED_SCLK_Set();OLED_SDIN_Set();OLED_SDIN_Clr();OLED_SCLK_Clr();
}/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop()
{OLED_SCLK_Set();// OLED_SCLK_Clr();OLED_SDIN_Clr();OLED_SDIN_Set();
}void IIC_Wait_Ack()
{// GPIOB->CRH &= 0XFFF0FFFF;// GPIOB->CRH |= 0x00080000;// OLED_SDA = 1;// delay_us(1);// OLED_SCL = 1;// delay_us(50000);/* while(1)
{if(!OLED_SDA)
{//GPIOB->CRH &= 0XFFF0FFFF;//GPIOB->CRH |= 0x00030000;return;
}
}*/OLED_SCLK_Set();OLED_SCLK_Clr();
}
/**********************************************
// IIC Write byte
**********************************************/void Write_IIC_Byte(unsigned char IIC_Byte)
{unsigned char i;unsigned char m, da;da = IIC_Byte;OLED_SCLK_Clr();for (i = 0; i < 8; i++)
{m = da;// OLED_SCLK_Clr();m = m & 0x80;if (m == 0x80)
{OLED_SDIN_Set();
}elseOLED_SDIN_Clr();da = da << 1;OLED_SCLK_Set();OLED_SCLK_Clr();
}
}
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{IIC_Start();Write_IIC_Byte(0x78); // Slave address,SA0=0IIC_Wait_Ack();Write_IIC_Byte(0x00); // write commandIIC_Wait_Ack();Write_IIC_Byte(IIC_Command);IIC_Wait_Ack();IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{IIC_Start();Write_IIC_Byte(0x78); // D/C#=0; R/W#=0IIC_Wait_Ack();Write_IIC_Byte(0x40); // write dataIIC_Wait_Ack();Write_IIC_Byte(IIC_Data);IIC_Wait_Ack();IIC_Stop();
}
void OLED_WR_Byte(unsigned dat, unsigned cmd)
{if (cmd)Write_IIC_Data(dat);elseWrite_IIC_Command(dat);
}void OLED_Set_Pos(unsigned char x, unsigned char y)
{OLED_WR_Byte(0xb0 + y, OLED_CMD);OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);OLED_WR_Byte((x & 0x0f), OLED_CMD);
}void OLED_Display_On(void)
{OLED_WR_Byte(0X8D, OLED_CMD);OLED_WR_Byte(0X14, OLED_CMD); // DCDC ONOLED_WR_Byte(0XAF, OLED_CMD); // DISPLAY ON
}void OLED_Display_Off(void)
{OLED_WR_Byte(0X8D, OLED_CMD);OLED_WR_Byte(0X10, OLED_CMD); // DCDC OFFOLED_WR_Byte(0XAE, OLED_CMD); // DISPLAY OFF
}void OLED_Clear(void)
{unsigned char i, n;for (i = 0; i < 8; i++)
{OLED_WR_Byte(0xb0 + i, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0x10, OLED_CMD);for (n = 0; n < 128; n++)OLED_WR_Byte(0, OLED_DATA);
}
}
void OLED_On(void)
{unsigned char i, n;for (i = 0; i < 8; i++)
{OLED_WR_Byte(0xb0 + i, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0x10, OLED_CMD);for (n = 0; n < 128; n++)OLED_WR_Byte(1, OLED_DATA);
}
}void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr, unsigned char Char_Size)
{unsigned char c = 0, i = 0;c = chr - ' ';if (x > Max_Column - 1)
{x = 0;y = y + 2;
}if (Char_Size == 16)
{OLED_Set_Pos(x, y);for (i = 0; i < 8; i++)OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);OLED_Set_Pos(x, y + 1);for (i = 0; i < 8; i++)OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
}else
{OLED_Set_Pos(x, y);for (i = 0; i < 6; i++)OLED_WR_Byte(F6x8[c][i], OLED_DATA);
}
}unsigned int oled_pow(unsigned char m, unsigned char n)
{unsigned int result = 1;while (n--)result *= m;return result;
}void OLED_ShowString(unsigned char x, unsigned char y, char *chr, unsigned char Char_Size)
{unsigned char j = 0;while (chr[j] != '\0')
{OLED_ShowChar(x, y, chr[j], Char_Size);x += 8;if (x > 120)
{x = 0;y += 2;
}j++;
}
}void OLED_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_5 | GPIO_Pin_6);delay_ms(800);OLED_WR_Byte(0xAE, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0x10, OLED_CMD);OLED_WR_Byte(0xB0, OLED_CMD);OLED_WR_Byte(0x40, OLED_CMD);OLED_WR_Byte(0x81, OLED_CMD);OLED_WR_Byte(0xFF, OLED_CMD);OLED_WR_Byte(0xA1, OLED_CMD);OLED_WR_Byte(0xA6, OLED_CMD);OLED_WR_Byte(0xA8, OLED_CMD);OLED_WR_Byte(0x3F, OLED_CMD);OLED_WR_Byte(0xC8, OLED_CMD);OLED_WR_Byte(0xD3, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0xD5, OLED_CMD);OLED_WR_Byte(0x80, OLED_CMD);OLED_WR_Byte(0xD9, OLED_CMD);OLED_WR_Byte(0xF1, OLED_CMD);OLED_WR_Byte(0xDA, OLED_CMD);OLED_WR_Byte(0x12, OLED_CMD);OLED_WR_Byte(0xDB, OLED_CMD);OLED_WR_Byte(0x30, OLED_CMD);OLED_WR_Byte(0x8D, OLED_CMD);OLED_WR_Byte(0x14, OLED_CMD);OLED_WR_Byte(0xAF, OLED_CMD);OLED_Clear();
}void set_data(unsigned char *dat)
{memset(data, 0, sizeof(data));strcpy(data, dat);
}void set_rolling_flag(unsigned char flag)
{is_rolling_flag = flag;
}void set_dispaly_flag(unsigned char flag)
{display_flag = flag;
}unsigned char get_dispaly_flag()
{return display_flag;
}// 添加滚动控制函数
void OLED_StartHorizontalScroll(unsigned char direction, unsigned char start_page,unsigned char end_page, unsigned char interval)
{OLED_WR_Byte(0x2E, OLED_CMD); // 关闭滚动// 设置滚动方向OLED_WR_Byte(direction, OLED_CMD); // 0x26=右滚, 0x27=左滚OLED_WR_Byte(0x00, OLED_CMD); // 虚拟字节OLED_WR_Byte(start_page, OLED_CMD); // 起始页 (0-7)OLED_WR_Byte(interval, OLED_CMD); // 滚动间隔 (0-7, 数值越大越慢)OLED_WR_Byte(end_page, OLED_CMD); // 终止页 (0-7)OLED_WR_Byte(0x00, OLED_CMD); // 虚拟字节OLED_WR_Byte(0xFF, OLED_CMD); // 虚拟字节OLED_WR_Byte(0x2F, OLED_CMD); // 启动滚动
}// 停止滚动
void OLED_StopScroll(void)
{OLED_WR_Byte(0x2E, OLED_CMD);
}void oled_display()
{unsigned char len = strlen(data);unsigned char *point = data;char buff[17] = {0};OLED_StopScroll();OLED_Clear();// clear bufffor (unsigned char i = 0; i < 4; i++)
{memset(buff, 0, 16);if (len > 16)
{strncpy(buff, (char *)point, 16);OLED_ShowString(0, i * 2, buff, 16);point += 16;len -= 16;
}else
{strcpy(buff, (char *)point);OLED_ShowString(0, i * 2, buff, 16);break;
}
}if (startup_flag)
{startup_flag = 0;
}else
{Flash_Write(data, is_rolling_flag);
}// 启动滚动 (从第0页到第7页,向左滚动,速度中等)if (is_rolling_flag)OLED_StartHorizontalScroll(0x27, 0, 7, 7);
}
添加 oled.h 头文件,代码如下,可以修改对应的宏定义为自己的引脚
#ifndef __OLED_H
#define __OLED_H
#include "delay.h"
#include "stdlib.h"#define OLED_MODE 0
#define SIZE 8
#define XLevelL 0x00
#define XLevelH 0x10
#define Max_Column 128
#define Max_Row 64
#define Brightness 0xFF
#define X_WIDTH 128
#define Y_WIDTH 64#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_5) // SCL
#define OLED_SCLK_Set() GPIO_SetBits(GPIOB, GPIO_Pin_5)#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_6) // SDA
#define OLED_SDIN_Set() GPIO_SetBits(GPIOB, GPIO_Pin_6)#define OLED_CMD 0
#define OLED_DATA 1void OLED_WR_Byte(unsigned dat, unsigned cmd);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(unsigned char x, unsigned char y, unsigned char t);
void OLED_Fill(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char dot);
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr, unsigned char Char_Size);
void OLED_ShowNum(unsigned char x, unsigned char y, unsigned int num, unsigned char len, unsigned char size);
void OLED_ShowString(unsigned char x, unsigned char y, char *p, unsigned char Char_Size);
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowCHinese(unsigned char x, unsigned char y, unsigned char no);
void OLED_DrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[]);
void Delay_50ms(unsigned int Del_50ms);
void Delay_1ms(unsigned int Del_1ms);
void fill_picture(unsigned char fill_Data);
void Picture(void);
void IIC_Start(void);
void IIC_Stop(void);
void Write_IIC_Command(unsigned char IIC_Command);
void Write_IIC_Data(unsigned char IIC_Data);
void Write_IIC_Byte(unsigned char IIC_Byte);
void OLED_ShowDecimal(unsigned char x, unsigned char y, float num);void IIC_Wait_Ack(void);
void OLED_ShowNumber(unsigned char x, unsigned char y, short num);void set_data(unsigned char *dat);
void set_rolling_flag(unsigned char flag);
void set_dispaly_flag(unsigned char flag);
unsigned char get_dispaly_flag(void);
void oled_display(void);
#endif
添加 flash.c 文件,用于保存显示内容到 flash,这样即使电源断开后,再次通电也能显示之前保存的显示内容。代码如下
#include "Flash.h"
#include "w55mh32_flash.h"unsigned char Flash_Write(char *data1, unsigned char data2)
{unsigned char status = 0;unsigned int address = startAddress;unsigned int rolling = data2;char str[100] = "";strcpy(str, data1);FLASH_Unlock();status = FLASH_ErasePage(startAddress);if (FLASH_COMPLETE != status)return status;status = FLASH_ProgramWord(address, rolling);address += 4;if (FLASH_COMPLETE != status)return status;unsigned char i;for (i = 0; i < strlen(str) && (status == FLASH_COMPLETE); i++)
{status = FLASH_ProgramWord(address, str[i]);address += 4;
}FLASH_ProgramWord(address, '\0');FLASH_Lock();return 0;
}void Flash_Read(char *str, unsigned char *rolling)
{unsigned int address = startAddress;char temp = ' ';*rolling = (unsigned char)*(__IO uint32_t *)address;address += 4;for (unsigned char i = 0; i < 64; i++)
{temp = (char)*(__IO uint32_t *)address;if (temp == 0)
{str[i] = '\0';return;
}str[i] = temp;address += 4;
}
}
添加 flash.h 头文件,代码如下
#ifndef _FLASH_H
#define _FLASH_H#include "string.h"#define startAddress ((uint32_t)0x08020000)unsigned char Flash_Write(char *data1, unsigned char data2);
void Flash_Read(char *str, unsigned char *rolling);#endif
修改主函数 main.c,代码如下:
#include "bsp_rcc.h"
#include "bsp_tim.h"
#include "bsp_uart.h"
#include "delay.h"
#include "flash.h"
#include "httpServer.h"
#include "oled.h"
#include "webpage.h"
#include "wiz_interface.h"
#include "wizchip_conf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define SOCKET_ID 0
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)/* network information */
wiz_NetInfo default_net_info = {.mac = {0x00, 0x10, 0xdc, 0x12, 0x22, 0x12},.ip = {192, 168, 1, 30},.gw = {192, 168, 1, 1},.sn = {255, 255, 255, 0},.dns = {8, 8, 8, 8},.dhcp = NETINFO_DHCP};static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t http_tx_ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t http_rx_ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t socknumlist[1] = {SOCKET_ID};
int main(void)
{char page[2048];char str[64] = "asdasdasd";unsigned char flag = 0;wiz_NetInfo net_info;/* hardware initialization */rcc_clk_config();delay_init();console_usart_init(115200);tim3_init();OLED_Init();printf("%s HTTP Server example\r\n", _WIZCHIP_ID_);/* wiztoe init */wiz_toe_init();wiz_phy_link_check();network_init(ethernet_buf, &default_net_info);wizchip_getnetinfo(&net_info);printf("Please enter% d.% d.% d.% d in your browser to access the %s HTTP server\r\n", net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3], _WIZCHIP_ID_);// 查询flashFlash_Read(str, &flag);if (str != NULL)
{set_data(str);set_rolling_flag(flag);set_dispaly_flag(1);
}sprintf(page, (char *)index_page, "");reg_httpServer_webContent((uint8_t *)"index.html", (uint8_t *)page); // Build HTTP server web pageshttpServer_init(http_tx_ethernet_buf, http_rx_ethernet_buf, 1, socknumlist); // Initializing the HTTP serverwhile (1)
{httpServer_run(SOCKET_ID);if (get_dispaly_flag())
{oled_display();set_dispaly_flag(0);
}
}
}
5.运行结果
如图为 http 网页,用户可以输入内容,并且可以选择是否滚动显示
如图为提交后的页面
如图为 OLED 显示结果
在 httpUtil.c 中修改 predefined_set_cgi_processor 函数,这个是处理浏览器提交过来的数据的函数,代码如下:
uint8_t predefined_set_cgi_processor(uint8_t *uri_name, uint8_t *uri, uint8_t *buf, uint16_t *len)
{if (strcmp((const char *)uri_name, "config.cgi") == 0)
{uint8_t *param;param = get_http_param_value((char *)uri, "text");set_data(param);param = get_http_param_value((char *)uri, "is_Rolling");if (!strcmp(param, "Rolling"))
{set_rolling_flag(1);
}else
{set_rolling_flag(0);
}set_dispaly_flag(1);*len = sprintf((char *)buf, (char *)CONFIG_SUCCESS_PAGE);return 1;
}return 0;
}
添加 oled.c 函数,用于控制 oled。通过向oled相应寄存器赋值,即可实现oled滚动。代码如下
#include "oled.h"
#include "delay.h"
#include "flash.h"
#include "oledfont.h"
#include "stdint.h"
#include "string.h"
#include "w55mh32.h"unsigned char data[64] = "";
unsigned char is_rolling_flag = 0;
unsigned char display_flag = 0;
unsigned char startup_flag = 1;void IIC_Start()
{OLED_SCLK_Set();OLED_SDIN_Set();OLED_SDIN_Clr();OLED_SCLK_Clr();
}/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop()
{OLED_SCLK_Set();// OLED_SCLK_Clr();OLED_SDIN_Clr();OLED_SDIN_Set();
}void IIC_Wait_Ack()
{// GPIOB->CRH &= 0XFFF0FFFF;// GPIOB->CRH |= 0x00080000;// OLED_SDA = 1;// delay_us(1);// OLED_SCL = 1;// delay_us(50000);/* while(1)
{if(!OLED_SDA)
{//GPIOB->CRH &= 0XFFF0FFFF;//GPIOB->CRH |= 0x00030000;return;
}
}*/OLED_SCLK_Set();OLED_SCLK_Clr();
}
/**********************************************
// IIC Write byte
**********************************************/void Write_IIC_Byte(unsigned char IIC_Byte)
{unsigned char i;unsigned char m, da;da = IIC_Byte;OLED_SCLK_Clr();for (i = 0; i < 8; i++)
{m = da;// OLED_SCLK_Clr();m = m & 0x80;if (m == 0x80)
{OLED_SDIN_Set();
}elseOLED_SDIN_Clr();da = da << 1;OLED_SCLK_Set();OLED_SCLK_Clr();
}
}
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{IIC_Start();Write_IIC_Byte(0x78); // Slave address,SA0=0IIC_Wait_Ack();Write_IIC_Byte(0x00); // write commandIIC_Wait_Ack();Write_IIC_Byte(IIC_Command);IIC_Wait_Ack();IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{IIC_Start();Write_IIC_Byte(0x78); // D/C#=0; R/W#=0IIC_Wait_Ack();Write_IIC_Byte(0x40); // write dataIIC_Wait_Ack();Write_IIC_Byte(IIC_Data);IIC_Wait_Ack();IIC_Stop();
}
void OLED_WR_Byte(unsigned dat, unsigned cmd)
{if (cmd)Write_IIC_Data(dat);elseWrite_IIC_Command(dat);
}void OLED_Set_Pos(unsigned char x, unsigned char y)
{OLED_WR_Byte(0xb0 + y, OLED_CMD);OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);OLED_WR_Byte((x & 0x0f), OLED_CMD);
}void OLED_Display_On(void)
{OLED_WR_Byte(0X8D, OLED_CMD);OLED_WR_Byte(0X14, OLED_CMD); // DCDC ONOLED_WR_Byte(0XAF, OLED_CMD); // DISPLAY ON
}void OLED_Display_Off(void)
{OLED_WR_Byte(0X8D, OLED_CMD);OLED_WR_Byte(0X10, OLED_CMD); // DCDC OFFOLED_WR_Byte(0XAE, OLED_CMD); // DISPLAY OFF
}void OLED_Clear(void)
{unsigned char i, n;for (i = 0; i < 8; i++)
{OLED_WR_Byte(0xb0 + i, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0x10, OLED_CMD);for (n = 0; n < 128; n++)OLED_WR_Byte(0, OLED_DATA);
}
}
void OLED_On(void)
{unsigned char i, n;for (i = 0; i < 8; i++)
{OLED_WR_Byte(0xb0 + i, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0x10, OLED_CMD);for (n = 0; n < 128; n++)OLED_WR_Byte(1, OLED_DATA);
}
}void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr, unsigned char Char_Size)
{unsigned char c = 0, i = 0;c = chr - ' ';if (x > Max_Column - 1)
{x = 0;y = y + 2;
}if (Char_Size == 16)
{OLED_Set_Pos(x, y);for (i = 0; i < 8; i++)OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);OLED_Set_Pos(x, y + 1);for (i = 0; i < 8; i++)OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
}else
{OLED_Set_Pos(x, y);for (i = 0; i < 6; i++)OLED_WR_Byte(F6x8[c][i], OLED_DATA);
}
}unsigned int oled_pow(unsigned char m, unsigned char n)
{unsigned int result = 1;while (n--)result *= m;return result;
}void OLED_ShowString(unsigned char x, unsigned char y, char *chr, unsigned char Char_Size)
{unsigned char j = 0;while (chr[j] != '\0')
{OLED_ShowChar(x, y, chr[j], Char_Size);x += 8;if (x > 120)
{x = 0;y += 2;
}j++;
}
}void OLED_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_5 | GPIO_Pin_6);delay_ms(800);OLED_WR_Byte(0xAE, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0x10, OLED_CMD);OLED_WR_Byte(0xB0, OLED_CMD);OLED_WR_Byte(0x40, OLED_CMD);OLED_WR_Byte(0x81, OLED_CMD);OLED_WR_Byte(0xFF, OLED_CMD);OLED_WR_Byte(0xA1, OLED_CMD);OLED_WR_Byte(0xA6, OLED_CMD);OLED_WR_Byte(0xA8, OLED_CMD);OLED_WR_Byte(0x3F, OLED_CMD);OLED_WR_Byte(0xC8, OLED_CMD);OLED_WR_Byte(0xD3, OLED_CMD);OLED_WR_Byte(0x00, OLED_CMD);OLED_WR_Byte(0xD5, OLED_CMD);OLED_WR_Byte(0x80, OLED_CMD);OLED_WR_Byte(0xD9, OLED_CMD);OLED_WR_Byte(0xF1, OLED_CMD);OLED_WR_Byte(0xDA, OLED_CMD);OLED_WR_Byte(0x12, OLED_CMD);OLED_WR_Byte(0xDB, OLED_CMD);OLED_WR_Byte(0x30, OLED_CMD);OLED_WR_Byte(0x8D, OLED_CMD);OLED_WR_Byte(0x14, OLED_CMD);OLED_WR_Byte(0xAF, OLED_CMD);OLED_Clear();
}void set_data(unsigned char *dat)
{memset(data, 0, sizeof(data));strcpy(data, dat);
}void set_rolling_flag(unsigned char flag)
{is_rolling_flag = flag;
}void set_dispaly_flag(unsigned char flag)
{display_flag = flag;
}unsigned char get_dispaly_flag()
{return display_flag;
}// 添加滚动控制函数
void OLED_StartHorizontalScroll(unsigned char direction, unsigned char start_page,unsigned char end_page, unsigned char interval)
{OLED_WR_Byte(0x2E, OLED_CMD); // 关闭滚动// 设置滚动方向OLED_WR_Byte(direction, OLED_CMD); // 0x26=右滚, 0x27=左滚OLED_WR_Byte(0x00, OLED_CMD); // 虚拟字节OLED_WR_Byte(start_page, OLED_CMD); // 起始页 (0-7)OLED_WR_Byte(interval, OLED_CMD); // 滚动间隔 (0-7, 数值越大越慢)OLED_WR_Byte(end_page, OLED_CMD); // 终止页 (0-7)OLED_WR_Byte(0x00, OLED_CMD); // 虚拟字节OLED_WR_Byte(0xFF, OLED_CMD); // 虚拟字节OLED_WR_Byte(0x2F, OLED_CMD); // 启动滚动
}// 停止滚动
void OLED_StopScroll(void)
{OLED_WR_Byte(0x2E, OLED_CMD);
}void oled_display()
{unsigned char len = strlen(data);unsigned char *point = data;char buff[17] = {0};OLED_StopScroll();OLED_Clear();// clear bufffor (unsigned char i = 0; i < 4; i++)
{memset(buff, 0, 16);if (len > 16)
{strncpy(buff, (char *)point, 16);OLED_ShowString(0, i * 2, buff, 16);point += 16;len -= 16;
}else
{strcpy(buff, (char *)point);OLED_ShowString(0, i * 2, buff, 16);break;
}
}if (startup_flag)
{startup_flag = 0;
}else
{Flash_Write(data, is_rolling_flag);
}// 启动滚动 (从第0页到第7页,向左滚动,速度中等)if (is_rolling_flag)OLED_StartHorizontalScroll(0x27, 0, 7, 7);
}
添加 oled.h 头文件,代码如下,可以修改对应的宏定义为自己的引脚
#ifndef __OLED_H
#define __OLED_H
#include "delay.h"
#include "stdlib.h"#define OLED_MODE 0
#define SIZE 8
#define XLevelL 0x00
#define XLevelH 0x10
#define Max_Column 128
#define Max_Row 64
#define Brightness 0xFF
#define X_WIDTH 128
#define Y_WIDTH 64#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_5) // SCL
#define OLED_SCLK_Set() GPIO_SetBits(GPIOB, GPIO_Pin_5)#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_6) // SDA
#define OLED_SDIN_Set() GPIO_SetBits(GPIOB, GPIO_Pin_6)#define OLED_CMD 0
#define OLED_DATA 1void OLED_WR_Byte(unsigned dat, unsigned cmd);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(unsigned char x, unsigned char y, unsigned char t);
void OLED_Fill(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char dot);
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr, unsigned char Char_Size);
void OLED_ShowNum(unsigned char x, unsigned char y, unsigned int num, unsigned char len, unsigned char size);
void OLED_ShowString(unsigned char x, unsigned char y, char *p, unsigned char Char_Size);
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowCHinese(unsigned char x, unsigned char y, unsigned char no);
void OLED_DrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[]);
void Delay_50ms(unsigned int Del_50ms);
void Delay_1ms(unsigned int Del_1ms);
void fill_picture(unsigned char fill_Data);
void Picture(void);
void IIC_Start(void);
void IIC_Stop(void);
void Write_IIC_Command(unsigned char IIC_Command);
void Write_IIC_Data(unsigned char IIC_Data);
void Write_IIC_Byte(unsigned char IIC_Byte);
void OLED_ShowDecimal(unsigned char x, unsigned char y, float num);void IIC_Wait_Ack(void);
void OLED_ShowNumber(unsigned char x, unsigned char y, short num);void set_data(unsigned char *dat);
void set_rolling_flag(unsigned char flag);
void set_dispaly_flag(unsigned char flag);
unsigned char get_dispaly_flag(void);
void oled_display(void);
#endif
添加 flash.c 文件,用于保存显示内容到 flash,这样即使电源断开后,再次通电也能显示之前保存的显示内容。代码如下
#include "Flash.h"
#include "w55mh32_flash.h"unsigned char Flash_Write(char *data1, unsigned char data2)
{unsigned char status = 0;unsigned int address = startAddress;unsigned int rolling = data2;char str[100] = "";strcpy(str, data1);FLASH_Unlock();status = FLASH_ErasePage(startAddress);if (FLASH_COMPLETE != status)return status;status = FLASH_ProgramWord(address, rolling);address += 4;if (FLASH_COMPLETE != status)return status;unsigned char i;for (i = 0; i < strlen(str) && (status == FLASH_COMPLETE); i++)
{status = FLASH_ProgramWord(address, str[i]);address += 4;
}FLASH_ProgramWord(address, '\0');FLASH_Lock();return 0;
}void Flash_Read(char *str, unsigned char *rolling)
{unsigned int address = startAddress;char temp = ' ';*rolling = (unsigned char)*(__IO uint32_t *)address;address += 4;for (unsigned char i = 0; i < 64; i++)
{temp = (char)*(__IO uint32_t *)address;if (temp == 0)
{str[i] = '\0';return;
}str[i] = temp;address += 4;
}
}
添加 flash.h 头文件,代码如下
#ifndef _FLASH_H
#define _FLASH_H#include "string.h"#define startAddress ((uint32_t)0x08020000)unsigned char Flash_Write(char *data1, unsigned char data2);
void Flash_Read(char *str, unsigned char *rolling);#endif
修改主函数 main.c,代码如下:
#include "bsp_rcc.h"
#include "bsp_tim.h"
#include "bsp_uart.h"
#include "delay.h"
#include "flash.h"
#include "httpServer.h"
#include "oled.h"
#include "webpage.h"
#include "wiz_interface.h"
#include "wizchip_conf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define SOCKET_ID 0
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)/* network information */
wiz_NetInfo default_net_info = {.mac = {0x00, 0x10, 0xdc, 0x12, 0x22, 0x12},.ip = {192, 168, 1, 30},.gw = {192, 168, 1, 1},.sn = {255, 255, 255, 0},.dns = {8, 8, 8, 8},.dhcp = NETINFO_DHCP};static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t http_tx_ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t http_rx_ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0};
static uint8_t socknumlist[1] = {SOCKET_ID};
int main(void)
{char page[2048];char str[64] = "asdasdasd";unsigned char flag = 0;wiz_NetInfo net_info;/* hardware initialization */rcc_clk_config();delay_init();console_usart_init(115200);tim3_init();OLED_Init();printf("%s HTTP Server example\r\n", _WIZCHIP_ID_);/* wiztoe init */wiz_toe_init();wiz_phy_link_check();network_init(ethernet_buf, &default_net_info);wizchip_getnetinfo(&net_info);printf("Please enter% d.% d.% d.% d in your browser to access the %s HTTP server\r\n", net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3], _WIZCHIP_ID_);// 查询flashFlash_Read(str, &flag);if (str != NULL)
{set_data(str);set_rolling_flag(flag);set_dispaly_flag(1);
}sprintf(page, (char *)index_page, "");reg_httpServer_webContent((uint8_t *)"index.html", (uint8_t *)page); // Build HTTP server web pageshttpServer_init(http_tx_ethernet_buf, http_rx_ethernet_buf, 1, socknumlist); // Initializing the HTTP serverwhile (1)
{httpServer_run(SOCKET_ID);if (get_dispaly_flag())
{oled_display();set_dispaly_flag(0);
}
}
}
5.运行结果
如图为 http 网页,用户可以输入内容,并且可以选择是否滚动显示
如图为提交后的页面
如图为 OLED 显示结果

6.总结
本文详细介绍了如何利用 W55MH32Q-EVB 的 HTTP 功能,通过使用 http 服务器来获取 oled 显示内容,然后将内容显示在 oled 上。感谢大家的耐心阅读!如果您在阅读过程中有任何疑问,或者希望进一步了解这款产品及其应用,欢迎随时通过私信或评论区留言。我们会尽快回复您的消息,为您提供更详细的解答和帮助!