河北省住房和城乡建设厅网站首页,网站被301,汕头网站seo外包,微信网站搭建公司stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器#xff0c;集成2个Cortex-A7核和1个Cortex-M4 核#xff0c;A7核上可以跑Linux操作系统#xff0c;M4核上可以跑FreeRT…stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器集成2个Cortex-A7核和1个Cortex-M4 核A7核上可以跑Linux操作系统M4核上可以跑FreeRTOS、RT-Thread等实时操作系统。开发板搭配仿真器、显示屏、摄像头、资源扩展板等丰富的扩展模块可拓展物联网、人工智能等相关技术学习还可以拓展丰富的项目实战非常贴合企业当下开发需求是一款嵌入式Linux入门进阶必备开发板 可学习技术嵌入式Linux应用/系统/驱动开发、ARM裸机开发、Qt界面编程、STM32单片机、FreeRTOS、人工智能机器视觉等。其中ARM Cortex-A7裸机开发课程是华清远见独有特色课程可关注https://www.bilibili.com/video/BV1Xe4y1i7vm/持续更新中。可实战项目14个LinuxQt综合项目案例6个MP1A物联网拓展项目关注公众号“华清远见在线实验室”回复“mp157项目”即可领取。LinuxQt综合项目案例华清远见stm32mp157开发板优势特色部分包括音乐播放器、智慧家庭、智能工业电表、智能出行助手、智能猫眼、环境监测、智能安防、智能语音识别等10余个项目案例涉及家居、医疗、农业多种应用方向在案例中使用了多种物联网和嵌入式技术包括OT开发、linux应用开发、linux驱动开发、物联网云端接入、MQTT协议、json字符串等知识点。基于LinuxQt的智慧医疗项目项目简介使用心率/脉搏传感器采集数据通过算法计算得到心率和血氧。心率并不像环境光及接近传感器那样数据比较简单并不能通过读取一个文件获得当前的心率或血氧而是通过一系列的数据计算出来的这样 sys 文件系统的接口就不能完全适用了所以需要结合系统调用以字符设备的方式获取对应数据计算出心率和血氧。关键文件说明/sys/bus/iio/devices/iio:device2/scan_elements/(in_intensity_ir_en/in_intensity_red_en): 通道使能通过写 1 或 0 使能或关闭通道。/sys/bus/iio/devices/iio:device2/scan_elements/(in_intensity_ir_type/in_intensity_red_type): 通道数据类型。读取格式为be:u18/328be 表示数据为大端存储(bigendian)、u 表示 数据为无符号数18/328 表示 32 位数据左移 8 位后有效数据为 18 位。/sys/bus/iio/devices/iio:device2/scan_elements/(in_intensity_ir_index/in_intensity_red_index): 读取数据为当前通道的序号red 为 0 通道ir 为 1 通道/sys/bus/iio/devices/iio:device2/buffer/length 写入数据用来设置缓存区样本数量。/sys/bus/iio/devices/iio:device2/buffer/enable 写入 1 或 0 用来使能设备采样或停止设备采样。开发平台华清远见stm32mp157开发板豪华套餐开发板仿真器五寸屏摄像头资源扩展板tf卡读卡器源码分析数据采集线程threadgetheart.h该文件主要对数据采集用到的函数进行声明。#ifndef THREADGETHEART_H#define THREADGETHEART_H#include QThread#define true1#define false0#define FS100#define BUFFER_SIZE(FS*5)//#define BUFFER_SIZE (FS* 2)#define HR_FIFO_SIZE7#define MA4_SIZE4// DO NOT CHANGE#define HAMMING_SIZE5// DO NOT CHANGE#define min(x,y)((x)(y)?(x):(y))QT_BEGIN_NAMESPACEconst unsigned short auw_hamm[31]{41,276,512,276,41};const unsigned char uch_spo2_table[184]{95,95,95,96,96,96,97,97,97,97,97,98,98,98,98,98,99,99,99,99,99,99,99,99,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,99,99,99,99,99,99,99,99,98,98,98,98,98,98,97,97,97,97,96,96,96,96,95,95,95,94,94,94,93,93,93,92,92,92,91,91,90,90,89,89,89,88,88,87,87,86,86,85,85,84,84,83,82,82,81,81,80,80,79,78,78,77,76,76,75,74,74,73,72,72,71,70,69,69,68,67,66,66,65,64,63,62,62,61,60,59,58,57,56,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,31,30,29,28,27,26,25,23,22,21,20,19,17,16,15,14,12,11,10,9,7,6,5,3,2,1};static int an_dx[BUFFER_SIZE-MA4_SIZE];static int an_x[BUFFER_SIZE];//irstatic int an_y[BUFFER_SIZE];//redclassThreadgetheart:public QThread{Q_OBJECTpublic:Threadgetheart();virtual voidrun();private:int write_sys_int(char *filename, int data);int enable_disable_all_channels(int enable);int enable_disable_buffer(int enable);int set_buffer_len(int len);voidmaxim_heart_rate_and_oxygen_saturation(unsigned int *pun_ir_buffer,int n_ir_buffer_length, unsigned int *pun_red_buffer, int *pn_spo2, int*pch_spo2_valid,int *pn_heart_rate, int *pch_hr_valid);voidmaxim_find_peaks( int *pn_locs, int *pn_npks, int *pn_x, int n_size, intn_min_height, int n_min_distance, int n_max_num );voidmaxim_peaks_above_min_height( int *pn_locs, int *pn_npks, int *pn_x,int n_size, int n_min_height );voidmaxim_remove_close_peaks( int *pn_locs, int *pn_npks, int *pn_x, intn_min_distance );voidmaxim_sort_ascend( int *pn_x, int n_size );voidmaxim_sort_indices_descend( int *pn_x, int *pn_indx, int n_size);voidget_heart_rate();signals:voidinforsignal(int SpO2,int heart_rate);};#endif // THREADGETHEART_Hthreadgethreat.cpp这里只把线程的 run 函数展示出来run 函数里调用的一些其他成员函数因为代码量太大就不展示了可以参考源码。这些成员函数都是对采集的数据进行处理转换成心率和血氧void Threadgetheart::run(){get_heart_rate();}void Threadgetheart::get_heart_rate(){int ret 0;int data[2];char device_path[128]{0};int fd 0;int i, j;int read_size;int SpO2;int heart_rate;int hr_valid;int spo2_valid;int tmp_val 0;sprintf(device_name,%s,iio:device2);enable_disable_all_channels(1);set_buffer_len(4);enable_disable_buffer(1);sprintf(device_path,/dev/%s, device_name);fd open(device_path,O_RDONLY|O_NONBLOCK);if(fd 0){/* TODO: If it isnt there make the node */goto error;}for(j 0; j DATA_BUF_SIZE; j){struct pollfd pfd {.fd fd,.events POLLIN,};ret poll(pfd,1,-1);if(ret 0){ret -errno;goto error;}elseif(ret 0){printf(continue\n);continue;}read_size read(fd, data,8);if(read_size 0){if(errno EAGAIN){qDebug()nothing available\n;continue;}else{break;}}tmp_val be32toh(data[0]);aun_red_buf[j](tmp_val DATA_SHIFT)DATA_MASK;tmp_val be32toh(data[1]);aun_ir_buf[j](tmp_val DATA_SHIFT)DATA_MASK;}maxim_heart_rate_and_oxygen_saturation(aun_ir_buf,DATA_BUF_SIZE,aun_red_buf,SpO2,spo2_valid,heart_rate,hr_valid);while(1){for(i 100; i DATA_BUF_SIZE; i){aun_red_buf[i -100] aun_red_buf[i];aun_ir_buf[i -100] aun_ir_buf[i];}int count 0;for(j DATA_BUF_SIZE-100; j DATA_BUF_SIZE; j){struct pollfd pfd {.fd fd,.events POLLIN,};ret poll(pfd,1,-1);if(ret 0){ret -errno;goto error;}elseif(ret 0){qDebug(continue\n);continue;}read_size read(fd, data,8);if(read_size 0){if(errno EAGAIN){qDebug(nothing available\n);continue;}else{break;}}tmp_val be32toh(data[0]);aun_red_buf[j](tmp_val DATA_SHIFT)DATA_MASK;tmp_val be32toh(data[1]);aun_ir_buf[j](tmp_val DATA_SHIFT)DATA_MASK;count;}maxim_heart_rate_and_oxygen_saturation(aun_ir_buf,DATA_BUF_SIZE,aun_red_buf,SpO2,spo2_valid,heart_rate,hr_valid);if(spo2_validhr_valid){qDebug(SpO2: %d\t, SpO2);qDebug(heart rate: %d\n, heart_rate);emit inforsignal(SpO2,heart_rate);}}error:qDebug()error;}主线程mainwindow.ui这是 ui 界面的设计可以自行改动用到的图片资源可以参考源码mainwindow.h#include QMainWindow#include threadgetheart.hnamespace Ui {classMainWindow;}QT_END_NAMESPACEclassMainWindow:public QMainWindow{Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow();private:Ui::MainWindow *ui;Threadgetheart *thread1;voidbeepring();voidbeepunring();private slots:voidpushbuttonSlot();voidsetLable(int SpO2,int heart_rate);voidpushbutton_stopSlot();voidpushbutton_restartSlot();voidringSlot();signals:voidring();};#endif // MAINWINDOW_Hmainwindow.cpp子线程实时并计算心率和血氧通过信号发送给主线程主线程将心率和血氧显示到 UI 界面上并设置超过指定心率蜂鸣器报警。#include mainwindow.h#include ui_mainwindow.h#include stdint.h#include string.h#include fcntl.h#include stdio.h#include stdlib.h#include linux/input.h#include unistd.hMainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(newUi::MainWindow){ui-setupUi(this);thread1 newThreadgetheart;connect(ui-pushButton,SIGNAL(clicked()),this,SLOT(pushbuttonSlot()));connect(ui-pushButton_stop,SIGNAL(clicked()),this,SLOT(pushbutton_stopSlot()));connect(thread1,SIGNAL(inforsignal(int,int)),this,SLOT(setLable(int,int)));connect(ui-pushButton_restart,SIGNAL(clicked()),this,SLOT(pushbutton_restartSlot()));connect(this,SIGNAL(ring()),this,SLOT(ringSlot()));}MainWindow::~MainWindow(){delete ui;}void MainWindow::pushbuttonSlot(){thread1-start();ui-pushButton-setEnabled(false);}void MainWindow::pushbutton_restartSlot(){system(echo 1 /sys/bus/iio/devices/iio:device2/buffer/enable);}void MainWindow::pushbutton_stopSlot(){system(echo 0 /sys/bus/iio/devices/iio:device2/buffer/enable);ui-label_heart-setText(QString::number(0));ui-label_SpO2-setText(QString::number(0));}void MainWindow::setLable(int SpO2,int heart_rate){ui-label_heart-setText(QString::number(heart_rate));ui-label_SpO2-setText(QString::number(SpO2));if(heart_rate 100){ui-label_heart_scope_Normal-setText(异常);// beepring();emit ring();if(heart_rate 200)ui-label_heart_scope_info-setText(请检查手离传感器的距离重新测量);}else{ui-label_heart_scope_Normal-setText(正常);ui-label_heart_scope_info-clear();beepunring();}}void MainWindow::beepring(){int fd;struct input_event event;struct timeval time;fd open(/dev/input/by-path/platform-beeper-event,O_RDWR);event.type EV_SND;event.code SND_TONE;event.value 1000;time.tv_sec 1;time.tv_usec 0;event.time time;write(fd,event,sizeof(struct input_event));}void MainWindow::beepunring(){int fd;struct input_event event;struct timeval time;fd open(/dev/input/by-path/platform-beeper-event,O_RDWR);event.type EV_SND;event.code SND_TONE;event.value 0;time.tv_sec 0;time.tv_usec 0;event.time time;write(fd,event,sizeof(struct input_event));}void MainWindow::ringSlot(){beepring();usleep(500);beepunring();}实验源码源码路径【5_智慧医疗\实验源码\5_znyl】注意事项1.在开发板运行时需要导入中文字库否则会因为识别不了中文。将【5_智慧医疗\工具软件\wqy-zenhei-0.9.47-nightlybuild.tar.gz 或 wqyzenhei-0.8.38-1.tar.gz】复制到 ubuntu 下。并使用 scp 命令将文件拷贝到开发板的 usr/share/fonts 目录下使用 tar 命令解压后即可。linuxubuntu:~$ scp wqy-zenhei-0.8.38-1.tar.gzroot192.168.10.128:/usr/share/fonts/2.如果使用 mipi 五寸屏运行此项目需要进行屏幕旋转以适应屏幕具体步骤如下在/etc/profile.d/qt-eglfs.sh 添加环境变量如下下面变量的 event0 设备需要填实际的触摸屏设备这里即填 event0exportQT_QPA_EGLFS_ROTATION90exportQT_QPA_EGLFS_NO_LIBINPUT1exportQT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS/dev/input/event0:rotate90