项目场景:

项目需求,需要做一个基于边缘端的人脸识别远程监控摄像头并在网页前端展示 ,这里采用国产香橙派作为边缘计算终端,安装ubuntu系统,系统中采用v4l2接口对摄像头进行获取,当客户端通过网页进行请求时,服务器通过http服务的形式将一帧帧图像发送给客户端,只要一秒钟能够传送25帧左右,展示效果就是在网页端播放视频:


问题描述1

怎样从摄像头里面获取帧数据,这里我们将USB摄像头连接在开发板上:

可以看到,确实是有video0这个摄像头,该摄像头就是外接的USB摄像头


解决方案1:

采用V4L2接口通过中断将内核状态读取到的数据映射到用户空间:

以下代码是将内核空间与用户空间进行映射

for(int i = 0; i <4;i++) {mapbuffer.index = i;ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer); //从内核空间中查询一个空间作映射if (ret < 0){perror("查询内核空间失败");}//映射到用户空间mptr[i] = (unsigned char *)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);size[i] = mapbuffer.length; //保存映射长度用于后期释放//查询后通知内核已经放回ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer);if (ret < 0){perror("放回失败");}}

以下代码是通过中断获取内核态的数据,并在用户态对数据进行内存拷贝,即将数据拷贝到数组,方便其他线程进行数据处理和数据展示

struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //每个结构体都需要设置type为这个参赛要记住ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer);int read_len = mapbuffer.length;int send_len = 1024;//printf("%d \n",read_len);if (ret < 0){perror("读取数据失败");}if(1){void *ptr = mptr[readbuffer.index];memcpy(jpg_buff, ptr, readbuffer.length);
}

问题描述2

在网页前端播放视频,首先视频是一帧帧图像组成的,这里我们每间隔一个短时间就发送一帧,同时http 客户端和服务端采用keep-live长连接形式。为了加快速度,这里我采用了两个线程,现成1读取视频,并将图像帧放在一个公共数组中,线程2将公共数组中的数据通过tcp传输发送给客户端。

同时,线程1和线程之间采用的是条件变量进行同步


解决方案2:

多线程共享全局变量加快视频读取速度和图像发送速度:

线程1

 pthread_mutex_lock(&lock);void *ptr = mptr[readbuffer.index];memcpy(jpg_buff, ptr, readbuffer.length);//将读取到的图像拷贝到字符数组       pthread_mutex_unlock(&lock);pthread_cond_signal(&hasNode);

线程2

pthread_cond_wait(&hasNode,&lock);
void *ppptr = jpg_buff;
pthread_mutex_unlock(&lock);

这里的jpg_buff是共享全局数组


问题描述3

网页长连接设置问题:

服务器端在返回报文头时,加上

"Content-Type:multipart/x-mixed-replace;

即表示当前连接是基于长连接


解决方案:

提示:这里填写该问题的具体解决方案:

下面是报文头的内容

/*
HTTP长连接处理客户端请求
"HTTP/1.0 200 OK\r\n"
"Server: wbyq\r\n"
"Content-Type:multipart/x-mixed-replace;boundary=boundarydonotcross\r\n"
"\r\n"
"--boundarydonotcross\r\n"
*/

这是程序运行时的效果图:

需要在与开发板同一个局域网的终端上网址中键入:192.168.0.105:8080

其中192.168.0.105是开发板的ip地址

项目的文件结构是

网页源代码是

<!DOCTYPE html>
<html><head><meta  charset=UTF-8"><title>动态显示当前时间的钟表</title><meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /></head><style>canvas{border: 1px solid black;}</style><script>(function(){//cavas元素对象var canvas=null;//canvas的3d上下文var ctx=null;//cavan的尺寸var cw=0;var ch=0;/*** 页面导入时的事件处理*/window.addEventListener("load",function(){canvas=document.getElementById("sample");ctx=canvas.getContext("2d");cw=parseInt(canvas.width);ch=parseInt(canvas.height);ctx.translate(cw/2, ch/2);//绘制时钟draw_watch();},false);  /*** 绘制时钟*/function draw_watch(){//清空Canvasctx.clearRect(-cw/2,-ch/2,cw,ch);//计算针的最大长度var len=Math.min(cw, ch)/2;//绘制刻度盘var tlen=len*0.85;ctx.font="14px 'Arial'";ctx.fillStyle="black";ctx.textAlign="center";ctx.textBaseLine="middle";for(var i=1; i<=12; i++){var tag1=Math.PI*2*(3-i)/12;var tx=tlen * Math.cos(tag1);var ty=-tlen * Math.sin(tag1);ctx.fillText(i,tx,ty);}//获取当前的时分秒var d=new Date();var h=d.getHours();var m=d.getMinutes();var s=d.getSeconds();if(h >12 ){h=h-12;}//绘制时针var angle1 = Math.PI * 2 *(3 - (h+ m/60))/12;var length1=len * 0.5;var width1=5;var color1="#000000";drawhand(angle1,length1,width1,color1);//绘制分针var angle2 = Math.PI * 2 *(15 - (m+ s/60))/60;var length2=len * 0.7;var width2=3;var color2="#555555";drawhand(angle2,length2,width2,color2);//绘制秒针var angle3 = Math.PI * 2 *(15 - s)/60;var length3=len * 0.8;var width3=1;var color3="#aa0000";drawhand(angle3,length3,width3,color3);//设置timersetTimeout(draw_watch,1000);}/*** 针绘制函数*/function drawhand(angle,len,width,color){//计算针端的坐标var x=len*Math.cos(angle);var y=-len * Math.sin(angle);//绘制针ctx.strokeStyle=color;ctx.lineWidth=width;ctx.lineCap="round";ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(x,y);ctx.stroke();}})();</script><body><canvas id="sample" width="200" height="200"></canvas><center><img src="my.jpg" width="1280px" height="720px" /></center></body>
</html>

最后附上总代码

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <assert.h>
#include <fcntl.h>
#include <jpeglib.h>
#include <linux/fb.h>
#include <linux/videodev2.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <pthread.h>
#include "sd_usb_pic.h"
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/types.h>          /* See NOTES */
#include <unistd.h>
#include <sys/time.h>#define HTTP_PORT 8080   //HTTP服务器端口号
pthread_mutex_t mutex;
pthread_cond_t hasNode = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
char jpg_buff[614400]; //保存从USB摄像头读取的图像矩阵
int send_html_cnt = 0 ;
/*
服务端响应客户端请求"HTTP/1.1 200 OK\r\n"
"Content-type:image/jpeg\r\n"
"Content-Length:1234\r\n"
"\r\n"形参:c_fd  --客户端套接字type  --文件类型file  --要发送的文件
返回值:0成功,其它失败
*/
void *ppp_tr = NULL;
int fd_fb;
static struct fb_var_screeninfo var; /* LCD可变参数 */
static unsigned int *fb_base = NULL; /* Framebuffer映射基地址 */
int lcd_w = 800 ,lcd_h= 480; //定义显示器分辨率/*
形参:c_fd  --客户端套接字type  --文件类型file  --要发送的文件
返回值:0成功,其它失败
*/
int Http_SendData(int c_fd,const char *type,const char *file)
{int fd=open(file,O_RDONLY);//打开文件if(fd<0)return -1;//打开文件失败struct stat statbuf;fstat(fd,&statbuf);if(statbuf.st_size<=0){close(fd);return -2;}char buff[1024]={0};snprintf(buff,sizeof(buff),"HTTP/1.1 200 OK\r\n""Content-type:%s\r\n""Content-Length:%ld\r\n""\r\n",type,statbuf.st_size);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){close(fd);return -3;//发送数据头失败}/*发送文件内容*/int size;while(1){size=read(fd,buff,sizeof(buff));if(write(c_fd,buff,size)!=size)break;//发送失败if(size!=sizeof(buff))break;//发送完成}close(fd);return 0;
}int Http_SendPic(int c_fd,const char *type,const char *file)
{char buff[1024]={0};snprintf(buff,sizeof(buff),"HTTP/1.1 200 OK\r\n""Content-type:%s\r\n""Content-Length:%ld\r\n""\r\n",type,614400);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){return -3;//发送数据头失败}/*发送文件内容*/int size;int cnt = 0 ; pthread_mutex_lock(&mutex);void *ppptr = jpg_buff;while(1){int size= 1024;int wt_len = write(c_fd,ppptr,size);//发送失败cnt += wt_len ; ppptr += wt_len ; if(cnt >= 614400  ) {break;}//发送完成}pthread_mutex_unlock(&mutex);return 0;
}int Http_SendPic1(int c_fd,const char *type,const char *file)
{char buff[1024]={0};snprintf(buff,sizeof(buff),"HTTP/1.1 200 OK\r\n""Server:LiMeng \r\n""Content-type:image/jpeg\r\n""Content-Length:%ld\r\n""\r\n",614400);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){return -3;//发送数据头失败}/*发送文件内容*/int size;int cnt = 0 ; pthread_mutex_lock(&mutex);void *ppptr = jpg_buff;while(1){int size= 1024;int wt_len = write(c_fd,ppptr,size);//发送失败cnt += wt_len ; ppptr += wt_len ; if(cnt >= 614400  ) {break;}//发送完成}pthread_mutex_unlock(&mutex);return 0;
}/*
HTTP长连接处理客户端请求
"HTTP/1.0 200 OK\r\n"
"Server: wbyq\r\n"
"Content-Type:multipart/x-mixed-replace;boundary=boundarydonotcross\r\n"
"\r\n"
"--boundarydonotcross\r\n"
*/int Http_Content(int c_fd)
{char buff[1024]={0};/*建立长连接*/snprintf(buff,sizeof(buff),"HTTP/1.0 200 OK\r\n""Server: wbyq\r\n""Content-Type:multipart/x-mixed-replace;boundary=boundarydonotcross\r\n""\r\n""--boundarydonotcross\r\n");if(write(c_fd,buff,strlen(buff))!=strlen(buff))return -1;//发送报文头失败int jpe_image_size = 614400;//保存jpeg图像大小//int send_html_cnt = 0 ;clock_t t1;t1 = clock();char save_name[10];int save_idx = 0 ;struct timeval start_time, end_time;while(1){//auto beg = clock();t1 = clock();pthread_cond_wait(&hasNode,&lock);//printf("wait time is %d us \n",  (clock() - t1)   ); auto beg = clock();gettimeofday(&start_time, NULL);/*(1)响应报文头"Content-type:image/jpeg\r\n""Content-Length:666\r\n""\r\n"*/snprintf(buff,sizeof(buff), "Content-type:image/jpeg\r\n""Content-Length:%d\r\n""\r\n",jpe_image_size);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){return -2;//响应报文头失败}/*发送jpg图像数据*///pthread_mutex_lock(&mutex);//互斥锁上锁//pthread_cond_wait(&hasNode,&lock);void *ppptr = jpg_buff;//void *ppptr = ppp_tr;//sprintf(save_name,"my_%d.jpg",save_idx++);//FILE *file=fopen(save_name, "w");//fwrite(ppptr , 614400, 1,file);//close(file);int cnt = 0 ; while(1){int size= 1024 * 600;//int size= 1024 ;int wt_len = write(c_fd,ppptr,size);//发送失败cnt += wt_len ; ppptr += wt_len ; if(cnt >= 614400  ) {break;}//发送完成}  //pthread_mutex_unlock(&mutex);//互斥锁上锁//pthread_mutex_unlock(&lock);//sleep(20);/*(3)发送间隔字符串"\r\n""--boundarydonotcross\r\n"*/strcpy(buff,"\r\n--boundarydonotcross\r\n");if(write(c_fd,buff,strlen(buff))!=strlen(buff)){break;//发送间隔符失败}auto end = clock();gettimeofday(&end_time, NULL);double timeuse = (end_time.tv_sec - start_time.tv_sec) + (double)(end_time.tv_usec - start_time.tv_usec) / 1000000.0;//printf("sendtime is %d us \n",  (end - beg)   ); //printf("send cnt is %d us \n",  send_html_cnt   ); send_html_cnt++;//pthread_mutex_unlock(&lock);//usleep(40000);//auto beg = clock();//printf("sendtime is %d ms \n",  (end - beg)   ); printf("sendtime is %d ms \n",  timeuse   ); pthread_mutex_unlock(&lock);usleep(1);}return -4;//发送图像数据失败
}/*线程工作函数*/
void *pth_work(void *arg)
{int c_fd=*(int *)arg;free(arg);char buff[1024]={0};int size;size=read(c_fd,buff,sizeof(buff)-1);if(size<=0){close(c_fd);pthread_exit(NULL);}buff[size]='\0';printf("buff=%s\n",buff);if(strstr(buff,"GET / HTTP/1.1"))//请求网页文件{Http_SendData(c_fd,"text/html","./html/image.html");}else if(strstr(buff,"GET /1.bmp HTTP/1.1")){Http_SendData(c_fd,"application/x-bmp","./html/1.bmp");}else if(strstr(buff,"GET /my.jpg HTTP/1.1")){//Http_SendData(c_fd,"application/x-jpg","./html/my.jpg");//Http_SendPic(c_fd,"application/x-jpg","./html/my.jpg");Http_Content(c_fd);}else if(strstr(buff,"GET /my_32.jpg HTTP/1.1")){Http_SendData(c_fd,"application/x-bmp","./html/my_32.jpg");}else if(strstr(buff,"GET /100.bmp HTTP/1.1")){Http_SendData(c_fd,"application/x-bmp","./html/100.bmp");}else if(strstr(buff,"GET /favicon.ico HTTP/1.1")){Http_SendData(c_fd,"image/x-icon","./html/wmp.ico");}else{Http_SendData(c_fd,"application/x-jpg","./html/limeng.jpg");//Http_SendData(c_fd,"application/x-bmp","./html/my.jpg");}close(c_fd);//printf("22222222222222222222222   \n");pthread_exit(NULL);
}int generate_pic()
{int fd = open("/dev/video0",O_RDWR); //打开摄像头设备if (fd < 0){perror("打开设备失败");return -1;}struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //摄像头采集vfmt.fmt.pix.width = 640; //设置摄像头采集参数,不可以任意设置vfmt.fmt.pix.height = 480;vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; //设置视频采集格式为mjpg格式int ret = ioctl(fd,VIDIOC_S_FMT,&vfmt);if (ret < 0){perror("设置格式失败1");}//申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP;  //映射方式ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffer);if (ret < 0){perror("申请空间失败");}//映射unsigned char *mptr[4];//保存映射后用户空间的首地址unsigned int size[4];struct v4l2_buffer mapbuffer;//初始化type和indexmapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;for(int i = 0; i <4;i++) {mapbuffer.index = i;ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer); //从内核空间中查询一个空间作映射if (ret < 0){perror("查询内核空间失败");}//映射到用户空间mptr[i] = (unsigned char *)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);size[i] = mapbuffer.length; //保存映射长度用于后期释放//查询后通知内核已经放回ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer); if (ret < 0){perror("放回失败");}}//开始采集int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd,VIDIOC_STREAMON,&type); if (ret < 0){ perror("开启失败");}//定义一个空间存储解码后的rgbint sum = 0;//这里是用来控制读取的帧的数量 实际场景下 可以不要这个限制int read_cnt = 0 ;//记录读取图像线程char save_name[10];int save_idx = 0 ;struct timeval start_time, end_time;while(1){struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //每个结构体都需要设置type为这个参赛要记住ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer); int read_len = mapbuffer.length;int send_len = 1024;//printf("%d \n",read_len);if (ret < 0){perror("读取数据失败");}if(1){//void *ptr = mptr[readbuffer.index];//pthread_mutex_lock(&mutex);//gettimeofday(&start_time, NULL);pthread_mutex_lock(&lock);void *ptr = mptr[readbuffer.index];///ppp_tr = mptr[readbuffer.index];//auto beg = clock();//printf("read frame %d \n",beg);//printf("read frame %d  %d  %d \n",read_cnt++,send_html_cnt,beg);//pthread_mutex_lock(&mutex);memcpy(jpg_buff, ptr, readbuffer.length);//将读取到的图像拷贝到字符数组//ppp_tr = ptr ; //auto end  = clock();//gettimeofday(&end_time, NULL);//double timeuse = (end_time.tv_sec - start_time.tv_sec) + (double)(end_time.tv_usec - start_time.tv_usec) / 1000000.0;sprintf(save_name,"my_%d.jpg",save_idx++);//int fd = open(save_name,  O_CREAT |O_WRONLY|O_TRUNC,0666);//char buf[1024*600]={0};//FILE *file=fopen(save_name, "w");//fwrite(mptr[readbuffer.index] , readbuffer.length, 1,file);//fwrite(ptr , readbuffer.length, 1,file);//close(file);//write(fd,buf,1024 * 600);//close(fd);pthread_mutex_unlock(&lock);pthread_cond_signal(&hasNode);//gettimeofday(&end_time, NULL);//pthread_mutex_unlock(&mutex);auto end  = clock();//printf("runtime is %f \n",  (end - beg) / CLOCKS_PER_SEC  ); //printf("runtime is %f \n",  (end - beg)   ); printf("runtime is %d ms \n",  timeuse   ); //sleep(20);usleep(1);}//通知内核使用完毕ret = ioctl(fd, VIDIOC_QBUF, &readbuffer);if(ret < 0){perror("放回队列失败");}}//停止采集ret = ioctl(fd,VIDIOC_STREAMOFF,&type);//释放映射for(int i=0; i<4; i)munmap(mptr[i], size[i]);close(fd); //关闭文件return 0;err1:close(fd_fb);return -1;
}void shuijiao()
{struct timeval start_time, end_time;while(1){gettimeofday(&start_time, NULL);pthread_cond_wait(&hasNode,&lock);usleep(10000);pthread_mutex_unlock(&lock);gettimeofday(&end_time, NULL);double timeuse = (end_time.tv_sec - start_time.tv_sec) + (double)(end_time.tv_usec - start_time.tv_usec) / 1000000.0;//printf("shuijiao   time is %f  ms \n",  timeuse * 1000   );}
}int main()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){printf("创建网络套接字失败\n");return 0;}/*允许绑定已使用的端口号*/int on = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));/*绑定端口号*/struct sockaddr_in s_addr={.sin_family=AF_INET,//IPV4.sin_port=htons(HTTP_PORT),.sin_addr.s_addr=INADDR_ANY};if(bind(sockfd,(const struct sockaddr *)&s_addr,sizeof(s_addr))){printf("绑定端口号失败\n");return 0;}/*设置监听数量*/listen(sockfd,100);/*等待客户端连接*/struct sockaddr_in c_addr;socklen_t len=sizeof(c_addr);int c_fd;pthread_t pthid;int *p=NULL;pthread_t pthid1;pthread_create(&pthid1,NULL,generate_pic,NULL);pthread_detach(pthid1);//设置为分离属性//shuijiao();//while(1){shuijiao();}while(1){c_fd=accept(sockfd,(struct sockaddr *)&c_addr,&len);if(c_fd==-1){printf("客户端连接失败\n");continue;}printf("套接字 : %d  连接成功,%s:%d\n",c_fd,inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));p=malloc(4);*p=c_fd;pthread_create(&pthid,NULL,pth_work,p);pthread_detach(pthid);//设置为分离属性}
}

代码的编译命令是

gcc serv.c -o serv -ljpeg

Linux + 香橙派 + V4L2 + http 实现远程监控摄像头在网页端显示相关推荐

  1. 远程监控摄像头在流媒体服务器显示无视频信号?

    在显示器正常的情况下,远程监控摄像机在流媒体服务器画面显示"无网络视频",通常是由于摄像机的供电异常.网线不通.密码设置.IP地址冲突等四点问题造成的. 有的开发者在使用EasyN ...

  2. 香橙派可以运行linux,如何使用SSH远程命令登录香橙派开发板

    香橙派Orange Pi 系列开发板是开源的单板电脑,新一代的arm开发板,可以运行Android.Ubuntu.Debian等操作系统.CPU使用全志H2.H3.H6.RK3399等芯片,拥有多种内 ...

  3. Mysql orangepi_SSH远程登录香橙派Orange Pi Zero2开发板的操作方法

    香橙派Zero2开发板是新一代开源的单板电脑,采用全志H616 四核 64位处理器,拥有512MB/1GB 内存可选,集成千兆以太网卡.蓝牙5.0+双频WiFi.Micro-HDMI输出.USB2.0 ...

  4. c# .net iot+香橙派orangepi开发板 200多块打造自家远程 浇花助手 系统

    由于出差多,这里的花经常过一段时间才能浇水,有些花都旱晕了,所以想做一个助手帮我远程就可以操作浇花,当然也完全可以发展为一个商用系统,拿浇花来做为一个测试平台吧,现在已经完成了,并已经运行了一个多月 ...

  5. 【踩坑日记 · 嵌入式 Linux】在香橙派 Zero 2 上编译安装 CH340 驱动(OrangePi Zero 2)

    前言 最近想尝试在 Linux 下编写和烧录 51 单片机程序,需要用到 CH340 模块,但是香橙派 Zero 2 没有预装它的驱动,所以需要下载 CH340 驱动的源码手动编译安装.在这里记录一下 ...

  6. 香橙派全志H3烧入U-boot和Linux内核以及配置

    全志H3烧入U-boot和Linux内核以及配置 1.U-boot的烧入和U-boot环境配置 1.1U-boot烧入和启动测试 2.编译完的内核处理和烧入 2.1处理内核 2.2烧入内核 U-boo ...

  7. Linux篇 一、香橙派Zero2设置开机连接wifi

    香橙派Zero2系列文章目录 一.香橙派Zero2设置开机连接wifi 文章目录 香橙派Zero2系列文章目录 前言 一.调试串口的连接说明 二.WIFI 连接测试 1.首先使用 `nmcli dev ...

  8. 瑞芯微RK3399芯片开发板香橙派4的HDMI音频播放功能测试(Linux系统)

    瑞芯微RK3399芯片开发板香橙派OrangePi 4(16G)用拥有4G内存16G存储,集成双频WiFi.蓝牙5.0.HDMI输出.千兆网口.USB接口等丰富的功能接口,支持双摄像头输入和两路视频输 ...

  9. Python控制Linux(OrangePi 香橙派) GPIO (wiringOP + OPi.GPIO)

    1. 安装wiringOP 官方教程如下图: 上面的Linux 终端命令在这里: //下载 wiringOP 的代码 root@orangepi:~# apt update root@orangepi ...

最新文章

  1. pandas使用datetime创建示例dataframe:包含完整的时分秒信息、创建时间索引、使用不同的时间频率、date_range中参数freq的偏移量别名
  2. 心得丨在开始第一个机器学习项目之前就了解的那些事儿
  3. 有关bbr以及锐速的更新搬运
  4. 在CentOS7下安装mysql5.7
  5. linux编译安装git
  6. oracle 10g/11g 命令对照,日志文件夹对照
  7. iOS_9_scrollView分页
  8. SAP Spartacus的一个问题 - CheckoutStepsSetGuard无法import
  9. (17)FPGA面试题永久防止亚稳态发生
  10. Hbase 中文参考指南 3.0 校对活动发车了~
  11. 产品管理有行业特殊性吗
  12. 华师计算机硕士考试科目,华中师范大学(专业学位)计算机技术研究生考试科目和考研参考书目...
  13. Linux课程笔记 Day05 命令总结
  14. 金蝶生成凭证模板_凭证模板
  15. RK3399平台开发系列讲解(外设篇)3.35、GMAC RGMII Delayline Guide 窗口配置
  16. 台式计算机开机不自检不起动,台式机开机不自检怎么办
  17. dble安装zk及配置mysql主从模式,在已有mysql存在数据升级mysql配置
  18. 蒙太奇服务器维修,蒙太奇服务器多台互连导片方法.pdf
  19. RF01 RF环境搭建及简介
  20. 14个适合后台管理系统开发的前端框架,建议收藏!

热门文章

  1. android 系统升级 方法,ROM之家简析:Android手机系统怎么升级
  2. 国产自主研发CAD-浩辰CAD
  3. Ubuntu搭建渗透测试环境
  4. outlook 发送邮件没有“附件”、“主题”提醒
  5. 2017第十七届中国金属冶金展(重庆)会刊(参展商名录)
  6. ubuntu 下查看网卡流量速度
  7. 数据库设计~电影院管理系统
  8. 适用于DELL G3 GTX1650的CUDA驱动
  9. Scratch3.0——助力新进程序员理解程序(十二、画笔)
  10. Matlab实现图片格式转换 pgm转jpg等