OK-MX93开发板-实现Web页面无线点灯

news2024/10/7 8:28:32

上篇文章:i.MX9352——介绍一款多核异构开发板,介绍了OK-MX9352开发板的基础硬件功能。

本篇来使用OK-MX9352开发板,通过Web界面进行点灯测试,最终的效果如下:

在进行代码编写之前,先在Ubuntu虚拟机上把这个板子的交叉编译环境配置好。

1 交叉编译环境配置

1.1 OKMX93 SDK源码拷贝与解压

将压缩包(OKMX93-linux-sdk.tar.bz2.00和OKMX93-linux-sdk.tar.bz2.01)拷贝到自己的Ubuntu虚拟机中。

sdk_md5sum.txt是对应的md5信息,也拷贝一下。使用md5sum指令确认压缩包的md5信息是否正确,以验证压缩包是否完整。

xxpcb@ubuntuTest:~/myTest/ok-mx93/sourcecode$ md5sum OKMX93-linux-sdk.tar.bz2.0*
8ce38d0ab6cc754b2c0d9c232e1d0a4e  OKMX93-linux-sdk.tar.bz2.00
7733d956ae8121699fb25b94e61dde3f  OKMX93-linux-sdk.tar.bz2.01

然后使用如下指令解压:

sudo cat OKMX93-linux-sdk.tar.bz2.0* | sudo tar xj

解压需要一些时间,解压后如下:

1.2 交叉编译工具链的安装

再新建一个文件夹,将解压后SDK源码中tools中的fsl-imx-xwayland-glibc-x86_64-meta-toolchain-qt6-armv8a-imx93-11x11-lpddr4x-evk-toolchain-5.15-kirkstone.sh拷贝到自己的文件夹中,然后执行该脚本进行交叉编译工具链的安装。

安装过程如下:

安装信息的第一行要选择SDK的安装目录,回车默认即可,接着再输入Y确认,然后是输入自己虚拟机的用户密码,就开始安装了。

看到打印SDK has been successfully set up and is ready to be used表示安装成功。

最后的信息是说明如何设置编译环境:每次打开一个新的shell进行交叉编译时,需要使用如下指令进行环境变量的设置:

. /opt/fsl-imx-xwayland/5.15-kirkstone/environment-setup-armv8a-poky-linux 

设置好之后,可以使用**$CC -v**显示gcc版本确认环境变量是否设置成功,如下:

1.3 helloword程序测试

hello.c

#include <stdio.h>

int main()
{
	printf("hello ok-mx93\n");
	return 0;
}

Makefile

TARGET=hello

OBJS=hello.o

CFLAGS+=-c -Wall -g

$(TARGET):$(OBJS)
	$(CC) $^ -o $@ 

%.o:%.c
	$(CC) $^ $(CFLAGS) -o $@

clean:
	$(RM) *.o $(TARGET) -r

执行make编译

也可以执行使用指令进行编译:

$CC hello.c -o hello

然后将编译的可执行文件复制到板子中,可以使用ssh命令:

scp hello root@192.168.5.115:/home/mytest

复制成功之后可在板子上运行,查看打印结果

2 Web页面点灯代码

嵌入式开发板,Web页面点灯的基本原理是:在开发板上配置Web服务器,然后在指定的文件位置,放置如html等类型的网页文件,然后板子连网,用电脑的浏览器输入板子的IP地址,连接到开发板的Web服务,实现开发板中网页内容的展示。

对于网页中内容或操作按钮等功能,要与开发板进行数据交互,通常使用CGI(Common Gateway Interface,公共网关接口)的方式进行编程。

2.1 lighttpd配置修改

OK-MX9352开发板中已经配置了lighttpd这个Web服务器,为了便于自己测试,可以修改其配置文件

/etc/lighttpd/lighttpd.conf

比如我这里把存放Web页面的默认位置更改为了/www/pages

另外,对应cgi的配置,还需要增加227行这句,否则cgi执行可能不能正常运行

2.2 Web页面设计

这里使用html语言设计一个LED的控制界面。

OK-MX9352开发板上有两个可以控制的LED,一个位于核心板上,另一个位于底板上,在设置html时,可以使用select功能实现一个下拉选项,选择要控制的LED。

另外,LED也有多种控制模式,如基础的开关模式(设置开,或关),心跳灯模式,定时器模式(设置亮的时间和灭的时间),也使用下拉选项的方式。

选择不同的控制模式后,为了能动态展示不同模式下的操作功能,比如开关模式下需要显示开和关的按钮,心跳灯模式则不需要额外的配置,定时器模式则需要两个输入框来设置亮的时间和灭的时间。这里使用script功能,来实现此功能,通过读取网页中当前LED模式的值,来进行对应控件的显示或隐藏。

完整的html代码如下,led.html:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
    <title>led control</title>
    </head>
 
    <body background="background.png"       
        style="background-repeat:no-repeat;       
        background-size:100% 100%;                     
        background-attachment: fixed;">  
    
    <center><br><br><br><br>
    <h1 align="center">基于飞凌OK-MX9352的web控制LED灯</h1>
    <!--新建一个表单,动作链接到开发板的/cgi-bin/led.cgi,采用的方法为GET--> 
    <form action="led.cgi" method="get">  
        <p align="center">LED选择:
        <select name="led_id">
            <option value="LED0" selected>核心板LED</option>
            <option value="LED1">底板LED</option>
        </select></p>
        <p align="center">模式选择:
        <select name="led_mode" onclick="select_event(this.options[this.selectedIndex].value);">
            <option value="ONOFF" selected>开关模式</option>
            <option value="HEARTBEAT">心跳灯模式</option>
            <option value="TIMER">定时器灯模式</option>
        </select></p>
        <p align="center" id = "id_led_time_on" >亮时间:<input type="text" value=500 name="led_time_on"/></p>
        <p align="center" id = "id_led_time_off" >灭时间:<input type="text" value=500 name="led_time_off"/></p>
        <p align="center" id = "id_led_onoff">LED开关:
            <input type="radio" name="led_val" value="ON" checked><input type="radio" name="led_val" value="OFF"></p><br><br>
        <p align="center">
            <input type="submit" value="确认"/>        
            <input type="reset" value="返回"/>
        </p>
    </form>
    </center>

    <script>
        document.getElementById("id_led_time_on").style.display = "none";
        document.getElementById("id_led_time_off").style.display = "none";
    </script>
    <script>
        function select_event(value) 
        {
            document.getElementById("id_led_onoff").style.display = "none";
            document.getElementById("id_led_time_on").style.display = "none";
            document.getElementById("id_led_time_off").style.display = "none";
            if (value === "ONOFF") 
            {
                document.getElementById("id_led_onoff").style.display = "";
            } 
            else if (value === "TIMER") 
            {
                document.getElementById("id_led_time_on").style.display = "";
                document.getElementById("id_led_time_off").style.display = "";
            }
        }
    </script>
    
    </body>
</html>

可以先使用浏览器直接打开这个html文件查看效果,实际效果如下:

2.3 CGI程序设计

CGI是Web服务器主机提供信息服务的标准接口。

通过CGI接口,Web服务器可以获取网页客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。

CGI程序可以使用多种语言来实现,对于嵌入式开发,那就用熟悉的C语言来编写吧。

编写CGI程序,需要用到CGI的库,下载地址:https://github.com/boutell/cgic,只需要用到cgic.c和cgic.h这两个文件。

本次测试的LED点灯功能,CGI程序需要实现的,就是获取网页上的用户操作信息,然后控制板子上的LED进行对应模式的亮灭,完整的代码实现如下,led.c:

#include "cgic.h"
#include <stdlib.h>
#include <string.h>

// cgic程序以cgiMain作为入口点, cgic的函数库会自动把cgiMain连接到相应的main()上去
int cgiMain() 
{ 
    char led_id[10];
    char led_mode[10]; 
    char led_val[10];
    int led_time_on;
    int led_time_off; 
    cgiFormString("led_id",  led_id, 10);
    cgiFormString("led_mode",  led_mode, 10); 
    cgiFormString("led_val",  led_val, 10);     
    cgiFormInteger("led_time_on",  &led_time_on, -1);
    cgiFormInteger("led_time_off",  &led_time_off, -1);
    
    // 设定输出的内容格式 这里我们要输出HTML
    cgiHeaderContentType("text/html;charset=\"UTF-8\"");         
    fprintf(cgiOut,"<title>LED Web Control</title>");   
    fprintf(cgiOut,"<center>");
    fprintf(cgiOut,"<br>");
    fprintf(cgiOut,"<br>");
    fprintf(cgiOut,"<br>");
    fprintf(cgiOut,"<p>OK-MX93开发板从Web页面收到数据:</p>");
    fprintf(cgiOut,"led_id: %s", led_id);
    fprintf(cgiOut,"<br>"); 
    fprintf(cgiOut,"led_mode: %s", led_mode);
    fprintf(cgiOut,"<br>"); 
    fprintf(cgiOut,"<br>"); 
    fprintf(cgiOut,"led_val: %s", led_val);
    fprintf(cgiOut,"<br>");     
    fprintf(cgiOut,"led_time_on: %d", led_time_on);
    fprintf(cgiOut,"<br>"); 
    fprintf(cgiOut,"led_time_off: %d", led_time_off);
    fprintf(cgiOut,"<br>"); 

    int ret = 0;
    
    if (0==strncmp("ONOFF",led_mode,10))
    {
        if (0==strncmp("ON",led_val,10))
        {
            if (0==strncmp("LED0",led_id,10))
            {
                ret |= system("echo none > /sys/class/leds/heartbeat/trigger");
                ret |= system("echo 1 > /sys/class/leds/heartbeat/brightness");
            }
            else if (0==strncmp("LED1",led_id,10))
            {
                ret |= system("echo none > /sys/class/leds/led1/trigger");
                ret |= system("echo 1 > /sys/class/leds/led1/brightness");
            }
        }
        else if (0==strncmp("OFF",led_val,10))
        {
            if (0==strncmp("LED0",led_id,10))
            {
                ret |= system("echo none > /sys/class/leds/heartbeat/trigger");
                ret |= system("echo 0 > /sys/class/leds/heartbeat/brightness");
            }
            else if (0==strncmp("LED1",led_id,10))
            {
                ret |= system("echo none > /sys/class/leds/led1/trigger");
                ret |= system("echo 0 > /sys/class/leds/led1/brightness");
            }
        }   
    }
    else if (0==strncmp("HEARTBEAT",led_mode,10))
    {
        if (0==strncmp("LED0",led_id,10))
        {
            ret |= system("echo heartbeat > /sys/class/leds/heartbeat/trigger");
        }
        else if (0==strncmp("LED1",led_id,10))
        {
            ret |= system("echo heartbeat > /sys/class/leds/led1/trigger");
        }   
    }
    else if (0==strncmp("TIMER",led_mode,10))
    {
        char tmp1[256];
        char tmp2[256];
        if (0==strncmp("LED0",led_id,10))
        {
            ret |= system("echo timer > /sys/class/leds/heartbeat/trigger");
            sprintf(tmp1, "echo %d > /sys/class/leds/heartbeat/delay_on", led_time_on);
            sprintf(tmp2, "echo %d > /sys/class/leds/heartbeat/delay_off", led_time_off);
            ret |= system(tmp1);
            ret |= system(tmp2);
        }
        else if (0==strncmp("LED1",led_id,10))
        {
            ret |= system("echo timer > /sys/class/leds/led1/trigger");
            sprintf(tmp1, "echo %d > /sys/class/leds/led1/delay_on", led_time_on);
            sprintf(tmp2, "echo %d > /sys/class/leds/led1/delay_off", led_time_off);
            ret |= system(tmp1);
            ret |= system(tmp2);
        }         
    }
    
    fprintf(cgiOut,"<br>"); 
    fprintf(cgiOut,"执行结果: %s", ret == 0 ? "成功" : "失败");
    fprintf(cgiOut,"<br>"); 
    fprintf(cgiOut,"<br>"); 
    fprintf(cgiOut,"<a href=\"led.html\"><button type=\"button\">返回</button></a>");
    fprintf(cgiOut,"</center>");

    return 0;
}

此cgi程序的执行效果实测如下:

3 编译与测试

在Ubuntu中对cgi程序进行交叉编译。

每次打开一个bash窗口进行交叉编译时,都要先执行一次交叉编译环境的生效:

. /opt/fsl-imx-xwayland/5.15-kirkstone/environment-setup-armv8a-poky-linux 

然后使用gcc指令编译即可,编译的后缀为.cgi

$CC led.c cgic.c -o led.cgi

然后将led.cgi和led.html以及html用到的背景图片拷贝到开发板中,可以新建一个led目录单独存放,如下:

root@ok-mx93:/etc/lighttpd# cd /www/pages/led/
root@ok-mx93:/www/pages/led#
root@ok-mx93:/www/pages/led# ls
background.png  led.cgi  led.html
root@ok-mx93:/www/pages/led#

OK-MX9352开发板开机自动启动Web服务,复制完之后,在电脑的浏览器中,输入板子ip以及对应目录的html文件目录即可,如我的是:

192.168.5.115/led/led.html

4 总结

本篇介绍了在OK-MX9352开发板上,通过Web服务,实现网页上LED控制界面来控制板子上LED进行不同模式的亮灭。

文章首先介绍了在Ubuntu虚拟机中,进行OK-MX9352的C/C++交叉编译环境配置,然后介绍了Web点灯功能的代码实现,通过html设置页面,通过CGI程序实现网页指令的接收和板子上LED的控制,最后进行代码编译和实际测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

对比损失Contrastive Loss(CVPR 2006)原理解析

paper&#xff1a;http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf 本文提出的对比损失contrastive loss被广泛应用于自监督模型中&#xff0c;但最初对比损失是作为一个特征降维方法而提出的。 摘要 降维是学习一种映射关系&#xff0c;通过这种映射关…

day10 线程池及gdb调试多线程

目录 线程池的概念 概念&#xff1a; 必要性&#xff1a; 线程池的基本结构&#xff1a; 线程池的实现 完整代码 线程的GDB调试 线程池的概念 概念&#xff1a; 通俗的讲就是一个线程的池子&#xff0c;可以循环的完成任务的一组线程集合&#xff1b; 必要性&#xff…

【软件工程】为什么要选择软件工程专业?

个人主页&#xff1a;【&#x1f60a;个人主页】 文章目录前言软件工程&#x1f4bb;&#x1f4bb;&#x1f4bb;就业岗位&#x1f468;‍&#x1f4bb;&#x1f468;‍&#x1f4bb;&#x1f468;‍&#x1f4bb;就业前景&#x1f6e9;️&#x1f6e9;️&#x1f6e9;️工作环…

趣谈之什么是 API 货币化?

本文介绍了 API 货币化和 APISIX 实现 API 货币化方法。 作者刘维&#xff0c;API7.ai 技术工程师&#xff0c;Apache APISIX Contributor 原文链接 什么是 API 货币化 想象你开发并部署了一个服务&#xff0c;能够搜集你所在城市所有超市的打折和优惠信息&#xff0c;其他的…

C生万物 | 校招热门考点 —— 结构体内存对齐

文章目录一、前言结构体偏移量计算&#xff1a;offsetof二、规则介绍例题的分解与细说三、习题演练1、练习①2、练习②四、为什么存在内存对齐?1、平台原因(移植原因)2、性能原因五、如何修改默认对齐数六、实战演练✍一道百度笔试题&#xff1a; offsetof 宏的实现&#x1f4…

深度学习基础篇之深度神经网络(DNN)

神经网络不应该看做是一个算法&#xff0c;应该看做是一个特征挖掘方法。在实际的业界发展过程中&#xff0c;数据的作用往往大于模型&#xff0c;当我们把数据的隐藏特征提取出来之后&#xff0c;用很简单的模型也能预测的很好。 神经网络模型由生物神经中得到启发。在生物神…

【Linux】Makefile的简述

目录 前言&#xff1a; 一、Makefile的规则 二、Makefile的函数语法 &#xff08;1&#xff09;通配符pattern ​&#xff08;2&#xff09; 删除clean ​&#xff08;3&#xff09; 立即变量、延时变量 &#xff08;4&#xff09; Makefile常用函数 3-1.Makefile要达到…

第11章_常用类和基础API

第11章_常用类和基础API 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 字符串相关类之不可变字符序列&#xff1a;String 1.1 String的特性 java.lang.String 类代表字符串…

vue之--使用TypeScript

搭配 TypeScript 使用 Vue​ 像 TypeScript 这样的类型系统可以在编译时通过静态分析检测出很多常见错误。这减少了生产环境中的运行时错误&#xff0c;也让我们在重构大型项目的时候更有信心。通过 IDE 中基于类型的自动补全&#xff0c;TypeScript 还改善了开发体验和效率。…

2023年美赛春季赛 Y题详细思路

由于今年各种各样的原因&#xff0c;导致美赛头一次&#xff0c;据说也将是最后一次&#xff0c;临时调整&#xff0c;加设春季赛。这对于急需建模奖项的大家来说是一个很好的机会。无论怎样的原因&#xff0c;今年美赛我们可能有所遗憾。但&#xff0c;春季赛也许就是弥补遗憾…

HTML4.1表单标签

input&#xff08;登录、注册、搜索功能&#xff09; type属性值类型称号展示类型text文本框placeholder占位符password密码框placeholder占位符radio单选框name checked&#xff08;默认选中&#xff09;同类型单选checkbox复选框 checked file 文件选择multiple多文件选择s…

分类预测 | MATLAB实现CNN-GRU-Attention多输入分类预测

分类预测 | MATLAB实现CNN-GRU-Attention多输入分类预测 目录分类预测 | MATLAB实现CNN-GRU-Attention多输入分类预测分类效果模型描述程序设计参考资料分类效果 模型描述 Matlab实现CNN-GRU-Attention多变量分类预测 1.data为数据集&#xff0c;格式为excel&#xff0c;12个输…

集合-LinkedList

LinkedList LinkedList的概述 LinkedList的底层使用双向链表实现。 链表是一种线性数据结构&#xff0c;其中每个元素都是一个单独的对象&#xff0c;包含一个指向列表中下一个节点的引用。 它可以用于实现各种抽象数据类型&#xff0c;例如列表、堆栈、队列等。 LinkedLis…

安装Nginx——docker安装

使用docker安装Nginx 1.开启docker systemctl start docker docker search nginx[rootlocalhost ~]# systemctl start docker //开启docker [rootlocalhost ~]# docker search nginx //搜素镜像 2. docker pull nginxdocker imagesdocker run -…

如何将录音转成文字?

在现代社会中&#xff0c;随着语音技术的不断发展和普及&#xff0c;将录音转换为文字变得越来越容易。无论是为了记录会议、面试、讲座、采访&#xff0c;还是为了记录个人的思考和想法&#xff0c;将录音转换为文字是一种方便快捷的方式。本文将介绍几种将录音转换为文字的方…

计算机系统结构教程-第七章-储存系统笔记(1)

7.1储存系统的层次结构 概述 理想的储存器&#xff1a;容量大、速度快、价格低。 但以上三种要求在实际应用中是相互矛盾&#xff1a; &#xff08;1&#xff09;速度快&#xff0c;价格高。 &#xff08;2&#xff09;容量大&#xff0c;价格低。 &#xff08;3&#xf…

ESLint检测VUE和JSON文件

ESLint 默认只支持检测JS文件中的文件&#xff0c;无法识别其它类型的文件&#xff0c;如果需要检测其它类型的文件就需要安装并指定对应的处理器&#xff0c;有点类似webpack的loader 处理vue文件 使用ESLint默认的处理器处理Vue文件大多数情况下会收到一个这样的错误。 Pa…

贪心算法

章节目录&#xff1a;一、算法介绍二、应用场景-集合覆盖问题2.1 问题引出2.2 思路分析2.3 代码示例三、结束语一、算法介绍 贪心算法&#xff08;greedy algorithm &#xff0c;又称贪婪算法&#xff09;是指&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来是最好的…

Vue04_事件绑定_methods

v-on:事件名"表达式" methods: 定义回调函数 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><div id"app"><!--eve…

12、Qt生成dll方式-libs方式使用

Qt创建dll&#xff0c;使用LIBS -L$PWD -lxxx的方式调用dll 一、创建项目 1、打开Qt->新建文件->其他项目->Empty qmake Project->Choose... 2、输入项目名->选择位置->下一步 3、MinGW->下一步 4、默认&#xff0c;完成 5、在.pro中添加TEMPLATE sub…