0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

米尔电子MYD-YA15XC-T开发板试用测评---dql2016

jf_36690210 ? 2022-01-04 15:01 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

近期,米尔电子重磅发布新品“MYD-YA15XC-T”开发板,并在电子工程世界、电子发烧友、电路城等各大论坛发布试用通知,受到了众多工程师、广大电子爱好者围观,米尔选取了电子发烧友平台一篇优秀试用报告,在此同步给各位小伙伴们。

01

【米尔MYD-YA15XC-T评测】+开箱上电测

7e428d98-6b1f-11ec-ad3b-dac502259ad0.gif

STM32MP1 是意法半导体推出的首款 MPU,其内部集成了 1-2 颗主频 650MHz 的 Arm Cortex-A7 应用处理器内核和 1 颗运行频率 209MHz 的高性能 Arm Cortex-M4 微 控制器内核。两种内核之间分工明确、配合默契,Cortex-A7 内核专用于开源操作系统, Cortex-M4 内核则专用于实时及低功耗任务处理。这一灵活的异构计算架构在单一芯片 上执行快速数据处理和实时任务,可以实现最高的能效。MYC-YA15XC-T 核心板基于 STM32MP1 系列处理器研制,完美继承了该处理器高 性能、低功耗的优点,且拥有良好的软件开发环境,Cortex-A7 内核支持开源操作系统 Linux,Cortex-M4 内核完美沿用现有的 STM32 MCU 生态系统,有助于开发者轻松实 现各类开发应用。

这次的板卡包装比米尔以往的板卡包装大得多。

7e4e1adc-6b1f-11ec-ad3b-dac502259ad0.jpg

7e6965b2-6b1f-11ec-ad3b-dac502259ad0.jpg

包装很用心:含有指导手册

7e8da940-6b1f-11ec-ad3b-dac502259ad0.jpg

电源适配器赠送了不同国家的插口适配器:

7e97a404-6b1f-11ec-ad3b-dac502259ad0.jpg

一如既往的黑色沉金

7ea417e8-6b1f-11ec-ad3b-dac502259ad0.jpg

板卡背面

7eb169c0-6b1f-11ec-ad3b-dac502259ad0.jpg

赠送了塑料螺柱

7ebe9212-6b1f-11ec-ad3b-dac502259ad0.jpg

上电效果

7ec9f436-6b1f-11ec-ad3b-dac502259ad0.jpg

接下来就需要下载资料进行交叉编译器和SDK环境的安装了。

02

【米尔MYD-YA15XC-T评测】+ USB UVC摄像头测试

7e428d98-6b1f-11ec-ad3b-dac502259ad0.gif

UVC全称为USB Video Class,即:USB视频类,是一种为USB视频捕获设备定义的协议标准。是Microsoft与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标准,已成为USB org标准之一。米尔MYD-YA15XC-T开发板内核已经开启了UVC驱动,因此插入USB UVC摄像头后可以看到识别信息:7ee22970-6b1f-11ec-ad3b-dac502259ad0.png

V4L2是Video for linux2的简称,为linux中关于视频设备的内核驱动。在Linux中,视频设备是设备文件,可以像访问普通文件一样对其进行读写,摄像头在/dev/video*下,如果只有一个视频设备,通常为/dev/video0。v4l2-ctl是用户空间一组用于测试,配置和使用整个相机子系统的工具,包括外部相机传感器和相机接口。v4l2-ctl 是最有用的实用工具。

v4l2-ctl基本常用的命令如下:

  • 使用--list-devices选项列出所有可用的视频设备


  • v4l2-ctl --list-devices

7ef0f41e-6b1f-11ec-ad3b-dac502259ad0.png

  • 获得有关特定设备的信息,加上-D 选项:


  • v4l2-ctl -d /dev/video1 -D

7eff3790-6b1f-11ec-ad3b-dac502259ad0.png

7f0ad7b2-6b1f-11ec-ad3b-dac502259ad0.png

  • 获取受支持的参数设置接口列表


  • v4l2-ctl -L -d /dev/video1

7f1d6116-6b1f-11ec-ad3b-dac502259ad0.png

其中可以通过 --set-ctrl 选项更改控制值,如:


  • v4l2-ctl --set-ctrl test_pattern=1

控制值可以动态更改。

  • 设置像素格式,分辨率和帧率,使用 --list-formats-ext 选项可获取受支持的像素格式、分辨率和帧速率:


  • v4l2-ctl --list-formats-ext -d /dev/video1

7f294ec2-6b1f-11ec-ad3b-dac502259ad0.png

  • 查看当前摄像头支持的视频压缩格式


  • v4l2-ctl -d /dev/video1 --list-formats

7f3a0e06-6b1f-11ec-ad3b-dac502259ad0.png

  • 查看摄像头所有参数


  • v4l2-ctl -d /dev/video1 --all

7f49c7e2-6b1f-11ec-ad3b-dac502259ad0.png

7f5a33c0-6b1f-11ec-ad3b-dac502259ad0.png

  • 查看摄像头所支持的分辨率


  • v4l2-ctl --list-framesizes=MJPG -d /dev/video1

7f6bc0fe-6b1f-11ec-ad3b-dac502259ad0.png

GStreamer是用于创建流媒体应用程序的框架,开发板集成了gstreamer系列命令。

  • 单次拍照


  • gst-launch-1.0 v4l2src device=/dev/video1 num-buffers=1 ! image/jpeg,width=1920,height=1080 ! filesink location=/tmp/capture.jpg

7f7f2c5c-6b1f-11ec-ad3b-dac502259ad0.png

使用 gst-typefind 命令检查图片分辨率


  • gst-typefind-1.0 /tmp/capture.jpg

7f8b07d4-6b1f-11ec-ad3b-dac502259ad0.png

初步完成了usb摄像头图像的采集,后续将研究简单的图像处理,视频采集,体验米尔MYD-YA15XC-T开发板的多媒体处理性能。

03

【米尔MYD-YA15XC-T评测】+使用mjpg-streamer搭建网络摄像头

7e428d98-6b1f-11ec-ad3b-dac502259ad0.gif

0、mjpg-streamer介绍

mjpg-streamer是一款免费基于IP地址的视频流服务器,它的输入插件从摄像头读取视频数据,这个输入插件产生视频数据并将视频数据复制到内存中,它有多个输出插件将这些视频数据经过处理,其中最重要的输出插件是网站服务器插件,它将视频数据传送到用户浏览器中,mjpg-streamer的工作就是将其中的一个输入插件和多个输出插件绑定在一起,所有的工作都是通过它的各个插件完成的。mjpg-streamer各个文件如下:

(1)input_testpicture.so。这是一个图像测试插件,它将预设好的图像编译成一个头文件,可以在没有摄像头的情况下传输图像,从而方便调试程序。

(2)input_uvc.so。此文件调用USB摄像头驱动程序V4L2,从摄像头读取视频数据。

(3)input_control.so。这个文件实现对摄像头转动的控制接口。

(4)output_http.so。这是一个功能齐全的网站服务器,它不仅可以从单一文件夹中处理文件,还可以执行一定的命令,它可以从输入插件中处理一幅图像,也可以将输入插件的视频文件根据现有M-JPEG标准以HTTP视频数据服务流形式输出。

(5)output_file.so。这个插件的功能是将输入插件的JPEG图像存储到特定的文件夹下,它可以用来抓取图像。

mjpg-streamer优点是对RAMCPU的消耗比较少,可以快速的传输jpeg流。

一、米尔SDK安装

7fda7f26-6b1f-11ec-ad3b-dac502259ad0.png

在终端执行命令:


  • . /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

将设置好交叉编译工具链,常用的环境变量如CC。

二、libjpeg交叉编译

有些UVC摄像头只支持输出YUV原始图像,此时mjpg-streamer会将其转码为mjpeg,然后进行传输,此时会对CPU的消耗以及实时流的流畅度有影响,特别是分辨率比较大的时候。

因此mjpg-streamer 依赖 libjpeg, libjpeg下载地址:
http://www.ijg.org/

7fe620ce-6b1f-11ec-ad3b-dac502259ad0.png

目前最新版本是v9d。libjpeg交叉编译命令:


  • make clean

  • . /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

  • ./configure --host=arm-ostl-linux-musl --prefix=$HOME/stm32mp1/build_jpegsrc.v9d

  • make -j6

  • make install

写成编译脚本:

7ff3e4d4-6b1f-11ec-ad3b-dac502259ad0.png

编译成功后得到动态库:

80044e3c-6b1f-11ec-ad3b-dac502259ad0.png

米尔MYD-YA15XC-T内核已经配置好了UVC和USB 驱动,因此无需重新配置编译内核。

三、mjpg-streamer交叉编译

mjpeg-streamer下载

https://sourceforge.net/p/mjpg-streamer/code/HEAD/tree/

80113cc8-6b1f-11ec-ad3b-dac502259ad0.png

目前最新版本为r182,本次测试使用版本r63。

在ubuntu可通过2种命令下载代码:


  • svn checkout svn://svn.code.sf.net/p/mjpg-streamer/code/ mjpg-streamer-code

或者


  • svn checkout https://svn.code.sf.net/p/mjpg-streamer/code/ mjpg-streamer-code

在编译前需要对源码的Makefile做以下修改:
将源码的所有Makefile(包含其子目录)中的编译工具链修改为米尔开发板的编译工具链,由于在终端执行命令. /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi会设置好交叉编译相关的环境变量,因此去掉Makefile文件中的CC 即可。

本次测试只需要 input_uvc.so 和 output_http.so,在主目录中的Makefile里面只选择这两个,其它的去掉。

插件input_uvc依赖jpeg,因此修改plugins/input_uvc/Makefile文件,指定jpeg库头文件路径:


  • CFLAGS += -I$HOME/stm32mp1/build_jpegsrc.v9d/include

指定链接jpeg动态库路径:


  • -ljpeg -L$HOME/stm32mp1/build_jpegsrc.v9d/lib

804a9e1e-6b1f-11ec-ad3b-dac502259ad0.png

编译成功之后,在lib目录会生成如下输入、输出动态库文件:

8078c992-6b1f-11ec-ad3b-dac502259ad0.png

在mjpg-streamer-r63目录生成mjpg-streamer可执行文件:

80862042-6b1f-11ec-ad3b-dac502259ad0.png

查看一下mjpg-streamer文件信息,ARM 32位可执行程序:

80902150-6b1f-11ec-ad3b-dac502259ad0.png

将上面生成的动态库文件都复制到lib目录:

80a06010-6b1f-11ec-ad3b-dac502259ad0.png

然后将lib目录里面的文件和mjpg-streamer可执行文件一起打包为app_and_lib.tar.xz,使用SCP命令将它复制到开发板home目录:

80bc53c4-6b1f-11ec-ad3b-dac502259ad0.png

解压:

80c677b4-6b1f-11ec-ad3b-dac502259ad0.png

得到如下文件,使用chmod +x mjpg-streamer命令为mjpg-streamer添加可执行权限:

80d75278-6b1f-11ec-ad3b-dac502259ad0.png

四、测试

插入USB UVC摄像头,正确识别到了视频设备:

80e73062-6b1f-11ec-ad3b-dac502259ad0.png

手动指定一下库路径:


  • export LD_LIBRARY_PATH=./

执行下列命令启动mjpg-streamer:


  • ./mjpg_streamer -i "input_uvc.so -r 1920x1080" -o "output_http.so -w ./www"

80f48fe6-6b1f-11ec-ad3b-dac502259ad0.png


如果是输出YUV格式的UVC摄像头,则执行命令:


  • ./mjpg_streamer -i "input_uvc.so -y -r 1920x1080" -o "output_http.so -w ./www

查看图片,在浏览器输入:
http://192.168.1.136:8080/?action=snapshot
查看视频,在浏览器输入:
http://192.168.1.136:8080/?action=stream
其中192.168.1.136为开发板IP地址。

附录:

MJPG简介:MJPEG全名为 "Motion Joint Photographic Experts Group",是一种视频编码格式,Motion JPEG技术常用闭合电路的电视摄像机的模拟视频信号“翻译”成视频流,并存储在硬盘上。典型的应用如数字视频记录器等。MJPEG不像MPEG,不使用帧间编码,因此用一个非线性编辑器就很容易编辑。MJPEG的压缩算法与MPEG一脉相承,功能很强大,能发送高质图片,生成完全动画视频等;从另一个角度说,在某些条件下,MJPEG也许是效率最低的编码/解码器之一。MJPEG与MJPG的区别:mjpeg视频,就是由系列jpg图片组成的视频。

还有一款MJPG视频流服务开源软件uStreamer:

?Streamer is a lightweight and very quick server to streamMJPGvideo from any V4L2 device to the net.

https://github.com/pikvm/ustreamer

8126277c-6b1f-11ec-ad3b-dac502259ad0.png

04

【米尔MYD-YA15XC-T评测】+ 使用ffmpeg音视频处理软件处理多媒体文件(上)

7e428d98-6b1f-11ec-ad3b-dac502259ad0.gif

在多媒体音视频处理应用中一个常见的需求就是给视频或者图像叠加水印文字、图片logo等。以下是ffmpeg的介绍:

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。
FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac OS X等。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer项目,而且当前FFmpeg也是放在MPlayer项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"。[1] FFmpeg编码库可以使用GPU加速。

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它包括了领先的音/视频编码库libavcodec等。
libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构
和读取音视频帧等功能;
libavcodec:用于各种类型声音/图像编解码;
libavutil:包含一些公共的工具函数;
libswscale:用于视频场景比例缩放、色彩映射转换;
libpostproc:用于后期效果处理;
ffmpeg:该项目提供的一个工具,可用于格式转换、解码或电视卡即时编码等;
ffsever:一个 HTTP 多媒体即时广播串流服务器;
ffplay:是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示;

本次就打算使用ffmpeg进行中英文特殊字符水印、图片水印的叠加测试,首先在电脑端实现功能,然后交叉编译移植到米尔MYD-YA15XC-T平台,顺便定性对比下电脑和米尔MYD-YA15XC-T的多媒体处理性能。

在编译ffmpeg前需要先编译字体处理软件freetype,这里使用了freetype-2.10.2版本。

编译命令如下:


  • make clean

  • ./configure --prefix=/opt/nrjd/nrjd-olms-0201/apps/aaa/comm/pc/freetype --with-zlib=no --with-png=no --enable-static=no

  • make -j12

  • make install

  • make clean

81453806-6b1f-11ec-ad3b-dac502259ad0.png

然后编译ffmpeg,指定freetype库和头文件路径:


  • make clean

  • ./configure --enable-shared --disable-static --target-os=linux --enable-libx264 --enable-gpl --enable-libfreetype --enable-filter=drawtext --extra-cflags="-I/home/qldeng/ffmpeg_watermark_test/ffmpeg_test_pc/comm/pc/freetype/include/freetype2" --extra-ldflags="-L/home/qldeng/ffmpeg_watermark_test/ffmpeg_test_pc/comm/pc/freetype/lib" --prefix=/home/qldeng/ffmpeg_watermark_test/ffmpeg_test_pc/comm/pc/ffmpeg

  • make -j12

  • make install

  • make clean

8173b744-6b1f-11ec-ad3b-dac502259ad0.png

项目文件夹内容如下:


  • qldeng@ubuntu:~/ffmpeg_watermark_test/ffmpeg_test_pc$ tree -L 2

  • .

  • ├── build

  • ├── CMakeLists.txt

  • ├── comm

  • │ ├── ffmpeg-4.4

  • │ ├── freetype-2.10.2

  • │ └── pc

  • ├── in.jpg

  • ├── logo.png

  • ├── main.cpp

  • ├── out.jpg

  • ├── readme.txt

  • ├── SourceHanSansCN-Bold.ttf

  • ├── toolchain.cmake

  • └── 捕获.PNG

  • 5 directories, 9 files

8180139a-6b1f-11ec-ad3b-dac502259ad0.png

测试项目使用CMake构建,CMakeLists.txt内容如下:


  • cmake_minimum_required(VERSION 3.17)

  • #输出可执行文件的文件名

  • set(ARTIFACT_NAME myapp)

  • project(${ARTIFACT_NAME})

  • set(CMAKE_CXX_STANDARD 11)

  • set(CMAKE_C_STANDARD 99)

  • set(MYLIBS_PATH /opt/nrjd/nrjd-olms-0201/apps/ffmpeg_test_pc/comm/pc)

  • set(INC_DIR

  • ${PROJECT_SOURCE_DIR}

  • ${MYLIBS_PATH}/freetype/include/freetype2

  • ${MYLIBS_PATH}/ffmpeg/include

  • )

  • set(LINK_DIR

  • ${MYLIBS_PATH}/freetype/lib

  • ${MYLIBS_PATH}/ffmpeg/lib

  • )

  • include_directories(${INC_DIR})

  • link_directories(${LINK_DIR})

  • aux_source_directory(${PROJECT_SOURCE_DIR} SOURCE_FILES)

  • set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})

  • link_libraries(

  • freetype

  • avcodec

  • avdevice

  • avfilter

  • avformat

  • avutil

  • postproc

  • swresample

  • swscale

  • )

  • add_executable(${ARTIFACT_NAME} ${SOURCE_FILES})

  • target_link_libraries(${ARTIFACT_NAME}

  • freetype

  • avcodec

  • avdevice

  • avfilter

  • avformat

  • avutil

  • postproc

  • swresample

  • swscale

  • pthread)

main.cpp是测试代码,直接使用system函数调用ffmpeg即可,需要注意的是特殊符号需要转义:


  • cmd = "ffmpeg -loglevel quiet -i " + string(dest_path) + " -vf drawtext="fontcolor=white:fontfile=SourceHanSansCN-Bold.ttf:fontsize=40:x=w-tw-th/2:y=h-th-th::alpha=0.65:box=1:boxcolor=0x000000:text='" + string(s5) + "" -y " + string(dest_path);

  • system(cmd.c_str());


  • float battery_voltage = 12.345;

  • float battery_current = 0.678;

  • float device_temperature = 37.2;

  • s1 = "日期\\:" + string(str) + """;

  • memset(str, 0, sizeof(str));

  • sprintf(str, "处理器\\:%0.1f\℃ 电源\\:%0.1fV %0.2fA CSQ\\:%d%%", device_temperature, battery_voltage,battery_current,64);

  • s2 = string(str);

toolchain.cmake内容:


  • set(CMAKE_CXX_COMPILER g++)

  • set(CMAKE_C_COMPILER gcc)

进入build目录,打开终端执行以下命令进行编译:


  • cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake ..

  • make

可以看到图片上叠加了预期的水印内容,处理时间183毫秒:
818d88ea-6b1f-11ec-ad3b-dac502259ad0.png

下一步就是眼睛就如何正确交叉编译ffmpeg到米尔MYD-YA15XC-T平台了,周六晚上折腾了半天,虽然编译出了命令行工具个库,但是放到米尔MYD-YA15XC-T里面无法运行,总是提示命令找不到,还得仔细研究下。

05

【米尔MYD-YA15XC-T评测】+ 使用STM32CubeProgrammer软件更新系统固件

7e428d98-6b1f-11ec-ad3b-dac502259ad0.gif

米尔提供的资料01_Documents\User_Manual\Chinese\软件手册\MYD-YA15XC-T_Linux软件开发指南V1.0.0.pdf第四节描述了如何更新系统固件。

MYC-YA15XC-T 开发板采用的是 ST 公司的 STM32MP1 系列微处理器,原生支持使用ST推出的STM32CubeProgrammer软件更新系统固件,只需要连接一根USB线通信即可完成烧录固件,快速方便。按照米尔提供的资料,实际使用中遇到些小问题

首先选择启动模式,将拨码开关拨到 Download 模式(B2/B1/B0 : 0/0/0)。将开发板的 J5 USB接口与电脑连接,插入电源适配器。如下图所示:

81e609e8-6b1f-11ec-ad3b-dac502259ad0.jpg

这时候可以在电脑发现USB DFU设备了:

81f1d80e-6b1f-11ec-ad3b-dac502259ad0.png

打开 STM32CubeProgrammer 软件,选择 USB烧录方式:

8226d6bc-6b1f-11ec-ad3b-dac502259ad0.png

点击 connect按钮连接,连接正常就会显示处理器的信息,如下图:

82362040-6b1f-11ec-ad3b-dac502259ad0.png

根据本开发板的处理器选择的烧录包位于目录myir-image-core\256N256D。然后点击Open File,选择nand的 TSV 文件myir-image-core\256N256D\myir-image-core\flashlayout_myir-image-core\trusted\FlashLayout_nand-2-256_stm32mp15xc-ya151c-256d-t-trusted.tsv,如下图所示:

824366d8-6b1f-11ec-ad3b-dac502259ad0.png

但是按照这个步骤烧录出错了:

8286e4bc-6b1f-11ec-ad3b-dac502259ad0.png

根据错误原因提示,将目录myir-image-core\256N256D\myir-image-core下的arm-trusted-firmware、bootloader、myir-image-core-openstlinux-eglfs-myir-ya151c-t_nand_2_256_multivolume.ubi复制到目录myir-image-core\256N256D\myir-image-core\flashlayout_myir-image-core\trusted下即可:

82c505c6-6b1f-11ec-ad3b-dac502259ad0.png

82d3746c-6b1f-11ec-ad3b-dac502259ad0.png

然后就可以烧录成功了:

82fc58dc-6b1f-11ec-ad3b-dac502259ad0.png

831072b8-6b1f-11ec-ad3b-dac502259ad0.png

06

【米尔MYD-YA15XC-T评测】+ epoll串口通信

7e428d98-6b1f-11ec-ad3b-dac502259ad0.gif

串口是嵌入式系统中最常用的接口之一,系统终端通常都是串口。除了终端功能之外,实际应用中,Linux系统也经常通过串口与其它设备进行通信和数据传递,如232、485等接口传感器通常底层都是串口。在Linux下的串口编程不像微控制器上那么简单。本帖以米尔MYD-YA15XC-T为例,实现串口基本操作、串口属性设置、如串口数据读写。米尔MYD-YA15XC-T开发板扩展排针接口引出了串口3供我们使用。位置如下图所示:

834e9ee4-6b1f-11ec-ad3b-dac502259ad0.png

终端使用ls /dev/tty*命令查看设备文件:

835e28fa-6b1f-11ec-ad3b-dac502259ad0.png

Linux的串口表现为设备文件,Linux的串口设备文件命名一般为/dev/tty*,米尔MYD-YA15XC-T开发板串口设备命名为/dev/ttySTM*

可以看到串口3对应的设备文件是/dev/ttySTM3,使用一个TTL串口调试助手连接到串口3:
836aa60c-6b1f-11ec-ad3b-dac502259ad0.jpg

首先使用echo命令测试发送数据,可以看到串口3收到了数据:
8377cbe8-6b1f-11ec-ad3b-dac502259ad0.png

接下来通过编写代码的方式实现串口的数据收发。

首先配置网络,因为后面拷贝文件到开发板需要用到。
8387cf84-6b1f-11ec-ad3b-dac502259ad0.png

在编写Linux串口的C程序代码时,需要包含termios.h头文件。主要流程为:

打开串口:用open()函数打开它所对应的设备文件。

关闭串口:用close()函数关闭串口。

发送数据:使用write()函数可以发送数据。

读取数据:使用read()函数可以读取接收到的数据。

此外,如果对串口属性进行设置需要包含头文件,该文件包含了POSIX终端属性描述结构struct termios。

完整的代码如下所示:


  • #include

  • using namespace std;

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • class MySerial

  • {

  • private:

  • int fd = -1;

  • string serial_dev;

  • int serial_baudrate;

  • string serial_parity;

  • int serial_databits;

  • int serial_stopbits;

  • void* (*rx_cb_fun)(void*);

  • int epfd;

  • struct epoll_event event;// 告诉内核要监听什么事件

  • struct epoll_event wait_event;

  • public:

  • MySerial(string serial_dev, int serial_baudrate, string serial_parity, int serial_databits, int serial_stopbits,void* (*rx_cb_fun)(void*))

  • {

  • this-> serial_dev= serial_dev;

  • this-> serial_baudrate= serial_baudrate;

  • this-> serial_parity= serial_parity;

  • this-> serial_databits= serial_databits;

  • this-> serial_stopbits= serial_stopbits;

  • this->rx_cb_fun = rx_cb_fun;

  • epfd = epoll_create(10); // 创建一个 epoll 的句柄,参数要大于 0, 没有太大意义

  • if( -1 == epfd )

  • {

  • perror ("epoll_create");

  • }

  • };

  • int OpenSerial()

  • {

  • struct termios tios;

  • int speed;

  • fd = open(serial_dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);

  • if (fd < 0)

  • {

  • perror("open");

  • }

  • memset(&tios, 0, sizeof(struct termios));

  • switch (serial_baudrate)

  • {

  • case 50:

  • speed = B50;

  • break;

  • case 75:

  • speed = B75;

  • break;

  • case 110:

  • speed = B110;

  • break;

  • case 134:

  • speed = B134;

  • break;

  • case 150:

  • speed = B150;

  • break;

  • case 200:

  • speed = B200;

  • break;

  • case 300:

  • speed = B300;

  • break;

  • case 600:

  • speed = B600;

  • break;

  • case 1200:

  • speed = B1200;

  • break;

  • case 1800:

  • speed = B1800;

  • break;

  • case 2400:

  • speed = B2400;

  • break;

  • case 4800:

  • speed = B4800;

  • break;

  • case 9600:

  • speed = B9600;

  • break;

  • case 19200:

  • speed = B19200;

  • break;

  • case 38400:

  • speed = B38400;

  • break;

  • case 57600:

  • speed = B57600;

  • break;

  • case 115200:

  • speed = B115200;

  • break;

  • case 230400:

  • speed = B230400;

  • break;

  • case 460800:

  • speed = B460800;

  • break;

  • case 500000:

  • speed = B500000;

  • break;

  • case 576000:

  • speed = B576000;

  • break;

  • case 921600:

  • speed = B921600;

  • break;

  • case 1000000:

  • speed = B1000000;

  • break;

  • case 1152000:

  • speed = B1152000;

  • break;

  • case 1500000:

  • speed = B1500000;

  • break;

  • case 2000000:

  • speed = B2000000;

  • break;

  • case 2500000:

  • speed = B2500000;

  • break;

  • case 3000000:

  • speed = B3000000;

  • break;

  • case 3500000:

  • speed = B3500000;

  • break;

  • case 4000000:

  • speed = B4000000;

  • break;

  • default:

  • speed = B9600;

  • break;

  • }

  • if ((cfsetispeed(&tios, speed) < 0) || (cfsetospeed(&tios, speed) < 0))

  • {

  • close(fd);

  • fd = -1;

  • perror("cfsetispeed or cfsetospeed");

  • }

  • tios.c_cflag |= (CREAD | CLOCAL);

  • tios.c_cflag &= ~CSIZE;

  • switch (serial_databits)

  • {

  • case 5:

  • tios.c_cflag |= CS5;

  • break;

  • case 6:

  • tios.c_cflag |= CS6;

  • break;

  • case 7:

  • tios.c_cflag |= CS7;

  • break;

  • case 8:

  • default:

  • tios.c_cflag |= CS8;

  • break;

  • }

  • if (serial_stopbits == 1)

  • {

  • tios.c_cflag &= ~CSTOPB;

  • }

  • else

  • {

  • tios.c_cflag |= CSTOPB;

  • }

  • if (serial_parity == "none")

  • {

  • tios.c_cflag &= ~PARENB;

  • }

  • else if (serial_parity == "even")

  • {

  • tios.c_cflag |= PARENB;

  • tios.c_cflag &= ~PARODD;

  • }

  • else if (serial_parity == "odd")

  • {

  • tios.c_cflag |= PARENB;

  • tios.c_cflag |= PARODD;

  • }

  • tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

  • if (serial_parity == "none")

  • {

  • tios.c_iflag &= ~INPCK;

  • }

  • else

  • {

  • tios.c_iflag |= INPCK;

  • }

  • tios.c_iflag &= ~(IXON | IXOFF | IXANY);

  • tios.c_oflag &= ~OPOST;

  • tios.c_cc[VMIN] = 0;

  • tios.c_cc[VTIME] = 0;

  • if (tcsetattr(fd, TCSANOW, &tios) < 0)

  • {

  • close(fd);

  • fd = -1;

  • perror("tcsetattr");

  • }

  • event.data.fd = fd; // 串口描述符

  • event.events = EPOLLIN; // 表示对应的文件描述符可以读

  • // 事件注册函数,将描述符fd加入监听事件

  • int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);

  • if(-1 == ret)

  • {

  • perror("epoll_ctl");

  • }

  • return fd;

  • }

  • void loop()

  • {

  • int ret;

  • // 监视并等待多文件(串口)描述符的属性变化(是否可读)

  • // 没有属性变化,这个函数会阻塞,直到有变化才往下执行,这里没有设置超时

  • ret = epoll_wait(epfd, &wait_event, 2, -1);

  • if(ret == -1) // 出错

  • {

  • close(epfd);

  • perror("epoll");

  • }

  • else if(ret > 0) // 准备就绪的文件描述符

  • {

  • //char buf[100] = {0};

  • if((fd == wait_event.data.fd) && (EPOLLIN == wait_event.events & EPOLLIN))

  • {

  • rx_cb_fun(&fd);

  • }

  • }

  • else if(0 == ret)

  • {

  • printf("time out\n");

  • }

  • }

  • ~MySerial()

  • {

  • close(fd);

  • close(epfd);

  • }

  • };

  • void *SerialRxCB(void* arg)

  • {

  • int fd = *(int*)arg;

  • char buf;

  • read(fd, &buf, 1);

  • printf("%c\n", buf);

  • return NULL;

  • }

  • void thread_task(void* arg)

  • {

  • int fd = *(int*)arg;

  • while(1)

  • {

  • char tx_buf[]="hello eeworld & mier";

  • this_thread::seconds(1));

  • write (fd, tx_buf, sizeof(tx_buf));

  • }

  • }

  • int main(int argc,char* argv[])

  • {

  • MySerial *ps = new MySerial("/dev/ttySTM3",9600,"none",8,1,SerialRxCB);

  • int ret = ps->OpenSerial();

  • if(ret < 0)

  • {

  • perror("open serial");

  • return -1;

  • }

  • thread t(thread_task,&ret);

  • t.detach();

  • while(1)

  • {

  • ps->loop();

  • }

  • return 0;

  • }

程序中使用到了epoll,类似单片机里面的中断,可以实现异步数据的接收,程序中还使用到了c++11的线程库,米尔提供的交叉编译器版本很新,完全支持c++11的各种特性。首先在虚拟机终端执行命令,这样交叉编译环境变量就在该终端生效了:


  • . /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

可以看到CXX环境变量:

8395d188-6b1f-11ec-ad3b-dac502259ad0.png

然后执行命令进行程序的编译:


  • $CXX stm32mp1_uart_test.cpp -o uart_test -lpthread

c++11的线程库底层使用了pthread实现,因此需要加链接参数-lpthread

83a41c02-6b1f-11ec-ad3b-dac502259ad0.png

交叉编译完成后,使用scp命令将程序拷贝到开发板上执行:


  • scp qldeng@192.168.1.131:/home/qldeng/stm32mp1_uart_test/uart_test ./

复制到板子上的效果:
83add71a-6b1f-11ec-ad3b-dac502259ad0.png

最后看看实际效果吧:

83d14ce0-6b1f-11ec-ad3b-dac502259ad0.gif

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 开发板
    +关注

    关注

    25

    文章

    5877

    浏览量

    108015
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    【作品合集】米尔RK3576开发板测评

    米尔RK3576开发板测评作品合集 产品介绍: RK3576 是瑞芯微一款面向AI市场推出的高性能处理器,它配备了四核Cortex-A72和四 核Cortex-A53 的 CPU,集成了6TOPS
    发表于 09-11 10:19

    有奖丨米尔 瑞芯微RK3506开发板免费试用来啦!

    米尔与瑞芯微合作发布的新品基于瑞芯微RK3506应用处理器的MYD-YR3506开发板免费试用名额增加啦
    的头像 发表于 07-10 08:03 ?414次阅读
    有奖丨<b class='flag-5'>米尔</b> 瑞芯微RK3506<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>来啦!

    有奖丨米尔 瑞芯微RK3506开发板免费试用

    米尔与瑞芯微合作发布的新品基于瑞芯微RK3506应用处理器的MYD-YR3506开发板免费试用名额来啦~~米尔提供了3块价值299元的
    的头像 发表于 06-19 08:04 ?619次阅读
    有奖丨<b class='flag-5'>米尔</b> 瑞芯微RK3506<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>

    基于米尔全志T536开发板的多协议物联网关的方案测试

    本文将介绍基于米尔电子MYD-LT536开发板米尔基于全志T536
    的头像 发表于 06-19 08:03 ?1172次阅读
    基于<b class='flag-5'>米尔</b>全志<b class='flag-5'>T</b>536<b class='flag-5'>开发板</b>的多协议物联网关的方案测试

    有奖丨米尔 瑞芯微RK3562开发板免费试用新增名额!

    米尔与瑞芯微合作发布的新品基于瑞芯微RK3562应用处理器的MYD-YR3562开发板免费试用名额增加
    的头像 发表于 06-13 08:04 ?582次阅读
    有奖丨<b class='flag-5'>米尔</b> 瑞芯微RK3562<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>新增名额!

    有奖丨米尔 NXP i.MX91开发板免费试用来啦

    米尔与NXP合作发布的新品基于NXPi.MX91应用处理器的MYD-LMX91开发板免费试用名额来啦~~米尔提供了3套价值588元的
    的头像 发表于 06-05 08:02 ?852次阅读
    有奖丨<b class='flag-5'>米尔</b> NXP i.MX91<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>来啦

    免费丨米尔 STM32MP257开发板有奖试用

    米尔与ST合作发布的新品基于STM32MP257应用处理器的MYD-LD25X开发板免费试用活动来啦~~米尔提供了2块价值488元的
    的头像 发表于 03-20 08:05 ?707次阅读
    免费丨<b class='flag-5'>米尔</b> STM32MP257<b class='flag-5'>开发板</b>有奖<b class='flag-5'>试用</b>

    有奖丨米尔 瑞芯微YR3562开发板免费试用

    米尔与瑞芯微合作发布的新品基于瑞芯微RK3562应用处理器的MYD-YR3562开发板免费试用活动来啦~~米尔提供了3块价值599元的
    的头像 发表于 03-20 08:05 ?625次阅读
    有奖丨<b class='flag-5'>米尔</b> 瑞芯微YR3562<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>

    有奖丨米尔 全志T536开发板免费试用

    米尔与全志合作发布的新品基于全志T536应用处理器的MYD-LT536-GK开发板免费试用活动来啦~~
    的头像 发表于 12-26 08:05 ?1073次阅读
    有奖丨<b class='flag-5'>米尔</b> 全志<b class='flag-5'>T</b>536<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>

    如何用OpenCV进行手势识别--基于米尔全志T527开发板

    本文将介绍基于米尔电子MYD-LT527开发板米尔基于全志T527
    的头像 发表于 12-13 08:04 ?1493次阅读
    如何用OpenCV进行手势识别--基于<b class='flag-5'>米尔</b>全志<b class='flag-5'>T</b>527<b class='flag-5'>开发板</b>

    米尔-Xilinx XC7A100T FPGA开发板试用】测试一

    感谢米尔电子电子发烧友提供的米尔-Xilinx XC7A100T FPGA开发板
    发表于 12-08 08:48

    FacenetPytorch人脸识别方案--基于米尔全志T527开发板

    本篇测评电子工程世界的优秀测评者“小火苗”提供。本文将介绍基于米尔电子MYD-LT527
    的头像 发表于 11-28 15:12 ?1082次阅读
    FacenetPytorch人脸识别方案--基于<b class='flag-5'>米尔</b>全志<b class='flag-5'>T</b>527<b class='flag-5'>开发板</b>

    追加名额丨米尔瑞芯微RK3576开发板有奖试用

    米尔与瑞芯微合作发布的新品基于瑞芯微RK3576应用处理器的MYD-LR3576开发板免费试用活动加码啦~~米尔追加了2块价值849元的
    的头像 发表于 11-22 01:00 ?822次阅读
    追加名额丨<b class='flag-5'>米尔</b>瑞芯微RK3576<b class='flag-5'>开发板</b>有奖<b class='flag-5'>试用</b>

    米尔-Xilinx XC7A100T FPGA开发板试用】+01.开箱(zmj)

    米尔-Xilinx XC7A100T FPGA开发板试用】+01.开箱(zmj) 1.感谢 感谢米尔
    发表于 11-12 15:45

    有奖丨米尔 瑞芯微RK3576开发板免费试用

    米尔与瑞芯微合作发布的新品基于瑞芯微RK3576应用处理器的MYD-LR3576开发板免费试用活动来啦~~米尔提供了7块价值849元的
    的头像 发表于 11-12 01:00 ?996次阅读
    有奖丨<b class='flag-5'>米尔</b> 瑞芯微RK3576<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>