之前还在纠结是不是要写这篇文章,因为自己看来其实好像也并没有什么意义,但是既然提起了,加上派流水账也不是那么麻烦的一件事情,还是来写一写吧。大致都是一些无聊的日常?因为确实算不上是个年终总结,所以也没有必要在标题中冒充是篇总结。
2018年1月
其实刚刚打下2018年1月这行字的时候还在怀疑自己是不是打错了。“2018年才是新的一年吧,我是不是想打2017年”然而很遗憾,今年已经是2019了,2018确确实实已经是过去了。
之前还在纠结是不是要写这篇文章,因为自己看来其实好像也并没有什么意义,但是既然提起了,加上派流水账也不是那么麻烦的一件事情,还是来写一写吧。大致都是一些无聊的日常?因为确实算不上是个年终总结,所以也没有必要在标题中冒充是篇总结。
其实刚刚打下2018年1月这行字的时候还在怀疑自己是不是打错了。“2018年才是新的一年吧,我是不是想打2017年”然而很遗憾,今年已经是2019了,2018确确实实已经是过去了。
#安装编译依赖
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
#新版本 Ubuntu 的源中没有 libjasper-dev 手动添加源
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt update
sudo apt install libjasper1 libjasper-dev
#创建编译目录:
mkdir opencv-build
#下载 OpenCV 源代码:
git clone https://github.com/Itseez/opencv.git
mkdir build
cd build
#创建 cmake 编译信息:
cmake -DENABLE_VFPV3=ON -DENABLE_VFPV4=ON -DENABLE_NEON=ON -DCMAKE_TOOLCHAIN_FILE=../opencv/platforms/linux/arm-gnueabi.toolchain.cmake ../opencv
#编译:
make -j4
make install
东西都在 ./install
目录下了。
编译自己的应用时注意 opencv2 头文件都是在 opencv4 文件夹下的。 编译参数:
OPENCV_INCLUDE=$(LIBPREFIX)/include/opencv4 -I$(OPENCV_INCLUDE) -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_flann
只是做一下记录。由于uboot的兼容性问题,仍然选用gcc5。以下主要记录命令,基本可以直接复制使用。因目标平台为Cortex-A7,选择gnueabihf工具链。全文基本复读https://ntzyz.io/post/arm-v7-a-cross-compile-notes,zyz真是太强啦!
环境:Ubuntu 16.04 LTS + bash 执行用户需要具有root权限
这个屏幕是给VerilogBoy实体机使用的屏幕,MIPI DSI接口,因为以前从来没有点过MIPI的屏幕,这里记录下过程方便以后参考。
Delay_ms(120);
GP_COMMAD_PA(2);
SPI_WriteData(0x36); // Memory data access control
SPI_WriteData(0x48); // Reverse X, BGR
GP_COMMAD_PA(2);
SPI_WriteData(0x3A); // Interface pixel format
SPI_WriteData(0x77); // 16.7M Color (not defined in DS???)
GP_COMMAD_PA(2);
SPI_WriteData(0xF0); // Command Set Control
SPI_WriteData(0xC3); // Enable Command 2 Part I
GP_COMMAD_PA(2);
SPI_WriteData(0xF0); // Command Set Control
SPI_WriteData(0x96); // Enable Command 2 Part II
GP_COMMAD_PA(3);
SPI_WriteData(0xB1); // Frame Rate Control
SPI_WriteData(0xA0); // FRS = 10 DIVA = 0 RTNA = 32
SPI_WriteData(0x10); // FR = 10^7 / ((168+RTNA+32x(15-FRS))(320+VFP+VBP))
GP_COMMAD_PA(2);
SPI_WriteData(0xB4); // Display Inversion Control
SPI_WriteData(0x00); // 00: Column INV, 01: 1-Dot INV, 10: 2-Dot INV
GP_COMMAD_PA(5);
SPI_WriteData(0xB5); // Blacking Porch Control
SPI_WriteData(0x40); // VFP = 64
SPI_WriteData(0x40); // VBP = 64
SPI_WriteData(0x00); // Reserved
SPI_WriteData(0x04); // HBP = 4
GP_COMMAD_PA(4);
SPI_WriteData(0xB6); // Display Function Control
SPI_WriteData(0x8A); // Bypass RAM, DE mode
SPI_WriteData(0x07); // Non inverting
SPI_WriteData(0x27); // 8*(0x27+1) = 320 lines
GP_COMMAD_PA(2);
SPI_WriteData(0xB9); // There is no B9 in datasheet
SPI_WriteData(0x02);
GP_COMMAD_PA(2);
SPI_WriteData(0xC5); // VCOM Control
SPI_WriteData(0x2E); // 1.450V
GP_COMMAD_PA(9);
SPI_WriteData(0xE8); // Display Output
SPI_WriteData(0x40);
SPI_WriteData(0x8A);
SPI_WriteData(0x00);
SPI_WriteData(0x00);
SPI_WriteData(0x29);
SPI_WriteData(0x19);
SPI_WriteData(0xA5);
SPI_WriteData(0x93);
GP_COMMAD_PA(15);
SPI_WriteData(0xe0); // Positive Gamma Control
SPI_WriteData(0xf0);
SPI_WriteData(0x07);
SPI_WriteData(0x0e);
SPI_WriteData(0x0a);
SPI_WriteData(0x08);
SPI_WriteData(0x25);
SPI_WriteData(0x38);
SPI_WriteData(0x43);
SPI_WriteData(0x51);
SPI_WriteData(0x38);
SPI_WriteData(0x14);
SPI_WriteData(0x12);
SPI_WriteData(0x32);
SPI_WriteData(0x3f);
GP_COMMAD_PA(15);
SPI_WriteData(0xe1); // Negative Gamma Control
SPI_WriteData(0xf0);
SPI_WriteData(0x08);
SPI_WriteData(0x0d);
SPI_WriteData(0x09);
SPI_WriteData(0x09);
SPI_WriteData(0x26);
SPI_WriteData(0x39);
SPI_WriteData(0x45);
SPI_WriteData(0x52);
SPI_WriteData(0x07);
SPI_WriteData(0x13);
SPI_WriteData(0x16);
SPI_WriteData(0x32);
SPI_WriteData(0x3f);
GP_COMMAD_PA(2);
SPI_WriteData(0xF0); // Command Set Control
SPI_WriteData(0x3C); // Disable Command 2 Part I
GP_COMMAD_PA(2);
SPI_WriteData(0xF0); // Command Set Control
SPI_WriteData(0x69); // Disable Command 2 Part II
GP_COMMAD_PA(1),
SPI_WriteData(0x11); // Sleep Out
Delay_ms(120);
GP_COMMAD_PA(1),
SPI_WriteData(0x29); // Display ON
Delay_ms(50);
GP_COMMAD_PA(1);
SPI_WriteData(0x21); // Display Inversion ON
GP_COMMAD_PA(5);
SPI_WriteData(0x2A); // Column Address Set
SPI_WriteData(0x00);
SPI_WriteData(0x00);
SPI_WriteData(0x01);
SPI_WriteData(0x3F);
GP_COMMAD_PA(5);
SPI_WriteData(0x2B); // Row Address Set
SPI_WriteData(0x00);
SPI_WriteData(0x00);
SPI_WriteData(0x01);
SPI_WriteData(0x3F);
在进行了两期的背景介绍后,本期也是终于是进入正题了。如果你之前有了解过数字电路,大概就听说过数字电路大致可以分为组合逻辑电路和时序逻辑电路,而大部分的电路都是这两者的结合。本期所要介绍的也就是这其中的前者:组合逻辑。顺便,上期之后,大概部分玩家购买的74芯片或者FPGA开发板也已经到货了吧?本期也会附带关于如何用74或者FPGA实现这些实验的说明。 第一个例子还是从第一期举过的例子开始好了。想要设计一个电路,里面有两个开关和一个灯泡,希望实现两个开关任意一个打开的时候灯泡点亮。当然,一个显而易见的解决方案就是把两个开关并联,如下图所示:
但是如果我们用像一般考虑单片机电路一样的思路去考虑,那么就可以把两个开关看作是两个输入口,而灯泡是一个输出口,那么这个电路就会变成这样:
而这个盒子里面所包括的就是需要实现的电路。这个电路可以是一块74,也可以是一块单片机,或者只是像图1一样简单的连接起来而已。这里就来考虑下,如果要用单片机来实现要怎么做吧。很简单,一句if语句的事情,直接翻译要求,if ((a == 1)||(b == 1)) c = 1; else c = 0; 可以看见逻辑运算已经出现了,输入1为高或者输入2为高时,输出1为高,否则输出1为低,这样就是这个简单例子的逻辑。另外等于1 可以省略,就变成了if (a || b) c = 1; else c = 0;,再考虑到因为逻辑运算的结果本身就是1或者0,这里甚至不需要if,只需要 c = (a || b) 即可。 只有一个简单的“或”运算(||, OR)的关系,如果要用图示描述出来的话: