Funpack3-4任务二基于FRDM-MCXN947开发板的嵌入式web服务器
一 、硬件介绍
FRDM-MCXN947是一款紧凑且可扩展的开发板,可让您快速基于MCX N94x MCU开展原型设计。板卡上集成行业标准的接口,可轻松使用MCU的I/O、集成的开放标准串行接口、外部闪存和板载MCU-Link调试器,具体结构如图1所示
图1.FRDM-MCXN947结构框图
二、开发环境搭建
这里使用的开发环境是MCUXpresso IDE 的开发环境,SDK的版本为2.14.0,使用的引脚功能配置工具为MCUXpresso Config Tools v15.1,开发过程中直接使用MCUXpresso IDE的引脚配置工具会找不芯片的,将为MCUXpresso Config Tools v15.1中的芯片数据导出,导入MCUXpresso IDE的引脚配置工具。
三、任务说明
这里主要有3个任务如下
任务1:
• 实现USB多协议HUB。板卡上集成了HS-USB接口,要求使用CAN口和UART口向MCU发送信息,通过USB显示出数据;从USB端可以指定向CAN和UART发送数据,并从对应端口发送出去。
任务2:
• 使用板卡上的以太网接口连接到电脑上并通过以太网和电脑通信,实现数据传输。要求电脑可以获取到板卡上的温度,触摸和按键信息,并可以通过电脑控制板卡上的RGB LED灯(有搭配扩展模块,传感器类的在电脑上显示数据,执行器类的能用电脑控制其工作)。
任务3:
• 使用eIQ NPU 实现机器学习加速。可以自己搭配摄像头模组,若无模组可以使用调试器的串口向MCU直接发送图像或者相应的音频数据,进行测试。要求使用eIQ 实现图像分类或者音频分类,自行搭建可用的NN结构,实现鞋子or帽子检测或者音频的鼓声or钢琴检测。
这里完成的主要是任务二硬件部分使用了nRF7002-DK的网络芯片模块;软件部分通过MCUXpresso IDE进行开发。
四、功能概述
4.1. 传感器数据监控:
- 温度传感器: 显示当前的温度数据,并附带单位(°C)。
- 触摸传感器: 显示触摸传感器的当前状态或值。
- 按键状态: 显示按键的当前状态(如按下或松开)。
- 浊度传感器: 显示当前的水浊度值。
自动数据刷新
通过JavaScript中的setTimeout()
函数,网页会每隔一秒自动向服务器请求传感器数据,从而实现数据的实时更新。
4.2.GPIO控制
- RGB LED灯开关控制
- 蜂鸣器 开关控制。
具体web的索引界面的界面如图2所示,GPIO控制界面如图3所示,传感器监控界面如图4。
图2.web的索引界面
图3.GPIO控制
图4.传感器监控界面
五、 软件设计流程
5.1.前端设计
- HTML: 使用HTML构建了基本的网页结构,包括标题、表格、和描述文字。表格用于显示传感器的数据。
- CSS: 通过引入CSS样式表,定义了表格的样式,使得网页的外观简洁美观。
- JavaScript: 编写了用于与服务器交互的JavaScript代码,负责发送请求、接收并解析数据,并动态更新网页内容。
5.2. 嵌入式服务器设计
- CGI脚本: 每个传感器的数据通过独立的CGI脚本来获取。例如
temperature.cgi
获取温度数据,touch.cgi
获取触摸传感器数据,button.cgi
获取按键状态数据,turbidity.cgi
获取浊度数据。 - 数据传输与解析: 前端通过JavaScript的
make_request
函数向服务器发送GET请求,服务器返回相应的传感器数据,JavaScript接收到数据后通过parse_vars
函数解析并更新HTML元素的内容。 - 嵌入式服务器: 使用lwip的网络协议栈,和板载的ETH芯片实现了一个微型嵌入式服务器,处理CGI传过来的数据。
5.3. 数据处理与展示
- 数据接收与解析: 使用
alertContents
函数接收服务器的响应数据,根据请求的URL确定数据的类型,并将数据传递给相应的parse_vars
函数。 - 动态更新页面: 通过获取到的数据,使用
document.getElementById().innerHTML
来更新页面上的传感器值,实现动态数据展示。
5.4. 整体流程
- 网页加载:
- 网页加载时,JavaScript的
window.onload
事件会触发loop()
函数,开始定时获取传感器数据。
- 网页加载时,JavaScript的
- 数据请求与接收:
- 每隔一秒,JavaScript会向服务器发送一次GET请求,请求不同的CGI脚本获取各个传感器的数据。
- 当服务器响应时,
alertContents()
函数会被调用,解析返回的数据并根据不同的传感器类型将数据更新到对应的HTML元素中。
- 数据显示:
- 网页表格中的传感器值会随着数据的更新自动刷新,用户可以实时查看到最新的传感器状态。
5.5. 扩展性
- 可以很方便地扩展更多的传感器。只需要在HTML中增加新的行,在JavaScript中添加对应的CGI请求和解析逻辑,即可实现对更多传感器的监控。
5.6.程序介绍
软件设计的整体框图如图5所示。
图5.软件设计的整体框图
软件的实现流程如图6所示,主要分为六块内容,包括外设初始化,传感器和GPIO控制的CGI程序编写,前端界面的编写(使用makefsdata工具转化成16进制的数组)、操作系统(freertos)、LWIP(网络协议栈)。
图6.软件流程图
程序首先是时钟的初始化、GPIO的初始化、温度接口的初始化、网络接口的初始化、LED灯的初始化、按键的初始化、adc读取触摸板和浊度传感器的初始化、最后使用FreeRTOS的任务创建API创建了main_task任务。
主函数的程序如下:
int main(void)
{
CLOCK_EnableClock(kCLOCK_InputMux);
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
init_eth();
p351755_init();
LED_RED_INIT(LOGIC_LED_OFF);
LED_GREEN_INIT(LOGIC_LED_OFF);
LED_BLUE_INIT(LOGIC_LED_OFF);
BUZZER_INIT(LOGIC_BUZZER_OFF);
button_init();
adc0_clock_and_vref();
adc0_with_irq_drv_init();
/* create server task in RTOS */
if (xTaskCreate(main_task, "main", HTTPD_STACKSIZE, NULL, HTTPD_PRIORITY, NULL) != pdPASS)
{
PRINTF("main(): Task creation failed.", 0);
__BKPT(0);
}
// /* run RTOS */
vTaskStartScheduler();
/* should not reach this statement */
while(1)
{
}
}
main_task函数主要做了两件事 :1、LWIP协议栈的初始化、2、http服务器的初始化。
具体程序如下:
static void main_task(void *arg)
{
LWIP_UNUSED_ARG(arg);
stack_init();
http_server_socket_init();
vTaskDelete(NULL);
}
http服务器的初始化中核心部分是cgi_lnk_tbl数组,其中储存的是一些回调函数(用于处理js请求的cgi)。
http服务器的初始化具体代码如下:
void http_server_socket_init(void)
{
HTTPSRV_PARAM_STRUCT params;
uint32_t httpsrv_handle;
/* Init Fs*/
HTTPSRV_FS_init(httpsrv_fs_data);
/* Init HTTPSRV parameters.*/
memset(¶ms, 0, sizeof(params));
params.root_dir = "";
params.index_page = "/index.html";
params.cgi_lnk_tbl = cgi_lnk_tbl;
/* Init HTTP Server.*/
httpsrv_handle = HTTPSRV_init(¶ms);
if (httpsrv_handle == 0)
{
PRINTF(("HTTPSRV_init() is Failed"));
}
}
cgi_lnk_tbl中分别为温度、触摸板、浊度传感器的回调函数以及控制GPIO和按键的回调函数,函数的具体实现请参考附件中httpsrv_freertos.c的代码。
cgi_lnk_tbl具体内容如下:
const HTTPSRV_CGI_LINK_STRUCT cgi_lnk_tbl[] = {
{"temperature",cgi_temperature},
{"touch",cgi_touch},
{"turbidity",cgi_turbidity},
{"gpio_control",cgi_gpio_control},
{"button",cgi_button},
{0, 0} // DO NOT REMOVE - last item - end of table
};
以上是服务器后端处理的部分,前端的页面使用html搭配css和js来进行编写,具体实现了三个html页面:index.html、sensor_cgi.html(显示传感器数值)、gpio_cgi.html(控制gpio口),使用httpsrv.css进行样式控制,使用request.js处理cgi的请求,以上这些实现通过makefsdata工具转化成数组,写入板子的flash。由于程序代码太长,这里仅展示index.html的具体代码,其余代码不再展示,详细代码请参考附件内容。
index.html具体实现了一个目录索引的功能,可以点击GPIO控制和传感器数值读取的按键跳转至gpio_cgi.html和sensor_cgi.html的子页面。
index.html具体代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>Funpack第三季第四期</title>
<link rel="stylesheet" href="httpsrv.css">
</head>
<body>
<h2>Funpack第三季第四期项目展示</h2>
<img src="Funpack.png" alt="Funpack Logo" style="max-width: 100%; height: auto;">
<div class="form-container">
<button type="button" onclick="location.href='gpio_cgi.html'">GPIO控制</button>
<button type="button" onclick="location.href='sensor_cgi.html'">传感器数值读取</button>
</div>
</body>
</html>
六.结果与总结
6.1结果
板子连接上电脑后,打开软件,把程序下载到FRDM-MCXN947中,打开浏览器,输入192.168.102连接上嵌入式web服务器,点击相应的按钮,可以控制LED和蜂鸣器,以及读取传感器数据,详细演示在视频里。
6.2总结
使用FRDM-MCXN947学习到了NXP芯片的开发流程以及gpio、lwip、eth、CGI技术、以及web服务器的搭建,感谢电子森林和得捷提供这么好的平台。