最近闲着无聊,买了个树莓派Zero,准备在上面跑.Net Core,来驱动各种传感器

  就是上面这货。之前手上已经有一个树莓派3B+,但是介于3B+已经被我挂在路由器旁边当做服务器用,不是很方便拿来研究接口,于是就挑了一个便宜的Zero玩玩,事实证明,我想太天真了,我以为只要是Linux系统,就能安装.net Core,实际上呢,我整了一个晚上才不得不认识到一个事实:即便是.net Core也是认CPU架构的,Pi Zero用的ARMv6就是不支持,哎早知道在买之前多做做功课了,买一个树莓派4也是个不错的选择啊。

幸好苍天不负有心人,我找到了 另外一个能在Linux上面运行.net的途径,那就是在Linux上面安装一个Mono,然后.net通过Mono当做虚拟机运行,其实在原理上和.net core是差不多的,可是Mono在性能上比原生的.net core差了很多便是,不过我们只是用来跑外部模块,也不是很需要多高性能便是了。

好了,唠嗑正式结束,让我们开始正题吧

首先,我们需要在Linux上面配置Mono的程序,讲人话就是安装Mono,不过在安装之前,我们还需要更改源,毕竟树莓派自带的源别指望在国内有好的下载体验

sudo sed -i 's#://raspbian.raspberrypi.org#s://mirrors.tuna.tsinghua.edu.cn/raspbian#g' /etc/apt/sources.list
sudo sed -i 's#://archive.raspberrypi.org/debian#s://mirrors.tuna.tsinghua.edu.cn/raspberrypi#g' /etc/apt/sources.list.d/raspi.list

运行上述两条指令,把树莓派自带的源替换成清华源,这样安装Mono会快很多

sudo apt-get install mono-devel mono-complete mono-dbg

运行上面指令后,在树莓派Zero上就会自动安装配置完毕Mono环境了。

对了,为了方便调试,我们还需要配置SSH的远程root连接

sudo nano /etc/ssh/sshd_config

运行上述指令后

找到这一条,然后改成上图这样子后(其实也就去掉#,后面的参数改成yes罢了)

完事以后,按Ctrl+X,退出编辑并覆盖保存就行。

sudo service ssh --full-restart

最后我们运行上述指令重启SSH服务以后就能够以root权限登录树莓派了。

以上是树莓派的系统的配置过程。

接下来我们需要配置Visual Studio

首先我们新建一个项目,由于最新的Mono支持.net core,所以我们直接建立.net core 3框架的项目就行,而且甚至不需要拖家带口带上.net core那么多运行库就能直接在Mono虚拟机下跑,简直了...

然后,我们需要有一个扩展能够直接在PC上远程调试树莓派上的程序,因此

搜索Mono的调试插件,有很多个,功能都差不多,挑一个顺手的就行

安装好Mono调试插件以后

需要配置下Mono调试插件的设置

其实主要的无非就是这么几个,新建一个配置,输入IP、端口、用户名和密码,避免麻烦最好直接上root权限,反正自己用

然后每次调试的时候,点击通过SSH生成和调试

就能获得和本地调试一样的体验,不得不说,这个体验实在是太好了。

接下来是项目的

其实也就一点,在Nuget上面找一个第三方的库来调用GPIO接口就行,没别的了

Nuget下搜索Raspberry,下面的库基本上都是关于调用树莓派gpio的,随便挑一个便是

我这边选择了文档最为齐全的Unosquare.Raspberry.IO

下面两个是依赖项,尤其是WiringPi,是直接管理接口的主要库

好,以上是准备工作,下面的是具体实现

上面这张图,对应的就是树莓派Zero上,一共40个针脚的定义,其中,两个5V的接口可以直接当做电源输入或者输出用,GND是接地这个没啥好说的,我们主要看GPIO,这里有很多很多GPIO接口,这些接口才是负责信号输入以及输出使用,我们控制的主要也是这些接口。

然后我们这次的主角也上场了

注意看接线的颜色,其中CLK和DIO代表时钟信号和数据信号,虽说是时钟信号,其实是类似于发送命令的接口,因此都接GPIO,VCC是电源,这个没啥好说的,就是输入电源(注意看传感器的电压,如果电压过高会烧毁传感器,所以树莓派预留了两个3.3V的电压接口),GND是接地,随便找个接地的接口插上去就行。

根据照片所示,我使用了4,14,16,18号接口,其中16口接了时钟信号,18口接了数据信号

好了,线也接好了,环境也配置好了,我们正式开始编程阶段

Pi.Init<BootstrapWiringPi>();//初始化通信接口,分配内存空间等
var clkPin = Pi.Gpio[BcmPin.Gpio23];//引用16接口
var dataPin = Pi.Gpio[BcmPin.Gpio24];//引用18接口
clkPin.PinMode = GpioPinDriveMode.Output;//设置16接口模式为输出
dataPin.PinMode = GpioPinDriveMode.Output;//设置18接口模式为输出

上面代码是初始化阶段,反正刚开头照这个姿势填就行了,值得注意的是接口引用部分

你看,我明明CLK接口插的是树莓派16号物理接口,为啥这里引用的却是GPIO23呢,其实这个是编码方式的不同导致的,主要有以下两种

  • BCM

编号侧重CPU寄存器,根据BCM2835的GPIO寄存器编号。

  • wiringPi

编号侧重实现逻辑,把扩展GPIO端口从0开始编号,这种编号方便编程。

具体使用哪一种,需要看调用库用的哪一套,因为我用的这个库使用的是Bcm(引用的时候已经写明了BcmPin)所以查表得知,16接口对应的GPIO23,18接口对应的GPIO24

接口配置完毕以后我们就可以正式开始驱动四位数码管了

驱动数码管实际上是操控TM1637芯片,我们的操作规程需要满足TM1637芯片的特性,

其中最主要的特性是

//数据输入开始
void startDisp()
{
clkPin.Write(GpioPinValue.High);//CLK拉为高电平
dataPin.Write(GpioPinValue.High);//DIO拉为高电平
dataPin.Write(GpioPinValue.Low);//和上面那句指令一起就是DIO由高变低
clkPin.Write(GpioPinValue.Low);//然后CLK上的时钟信号拉低,DIO接口的数据允许改变,代表开始写入数据
}

上面这四句执行完后,就表示告诉TM1637芯片,我要开始写数据了,后面DIO接口的任何电位变化,都是我要写的数据,下面就是写数据的过程

//开始写入数据
void writeByte(byte input)
{
for (int i = ; i < ; i++)//每次写入一个byte,一共8bit
{
  clkPin.Write(GpioPinValue.Low);//确保无误输入前再拉低一次时钟 ,代表开始写入数据
  if ((input & 0x01) == )//判断每一位的高低电平
  {
    dataPin.Write(GpioPinValue.High);
  }
  else
  {
    dataPin.Write(GpioPinValue.Low);
  }
  input >>= ;//每写入完毕一次,移动一位
  clkPin.Write(GpioPinValue.High);//每次输入完一位,就拉高一次时钟
}
//应答信号ACK,这里本来是用来判断DIO脚是否被自动拉低,代表上面写入的数据TM1637已经接受到了
//但是我这里闲麻烦,直接将CLK信号低高低的拉,让芯片直接执行下一步操作
clkPin.Write(GpioPinValue.Low);//先拉低
clkPin.Write(GpioPinValue.High);//需要判断D是否为低电平此期间C一直拉高
clkPin.Write(GpioPinValue.Low);//应答完毕以后拉低C
}

上面执行完以后,我们就已经向芯片发送了一个字节,也就是8位的数据,写完以后,我们还需要告知芯片,数据传输完毕了

//结束条件是CLK为高时,DIO由低电平变为高电平
void stopDisp()
{
clkPin.Write(GpioPinValue.Low);//先拉低CLK,代表允许DIO改变数据
dataPin.Write(GpioPinValue.Low);//拉低DIO
clkPin.Write(GpioPinValue.High);//CLK拉高,满足结束条件前半部分
dataPin.Write(GpioPinValue.High);//DIO由低变高,代表数据输入结束
}

好了,上面三段代码一起执行完毕,就表示一个完整的,信号从准备输入,开始输入,结束输入的过程,每次要输入1字节,都需要经过以上三个过程,因此我们将上面三个过程分别写成各自的方法,毕竟是需要经常调用的东西,而且基本上都不会变。以上的代码实现,都是基于TM1637规格书,就是上面的接口说明实现的。

下面开始介绍该怎么在数码管上显示出东西来

在开始之前,我们先仔细看看数码管是怎么一个样子的

  //      A
  // ---
  // F | | B
  // -G-
  // E | | C
  // ---
  // D
 XGFEDCBA
  00111111, // 0 //0x3f
  00000110, // 1 //0x06
  01011011, // 2 //0x5b
  01001111, // 3 //0x4f
  01100110, // 4 //0x66
  01101101, // 5 //0x6d
  01111101, // 6 //0x7d
  00000111, // 7 //0x07
  01111111, // 8 //0x7f
  01101111, // 9 //0x6f
  01110111, // A //0x77
  01111100, // b //0x7C
  00111001, // C //0X39
  01011110, // d //0X5E
  01111001, // E //0X79
  01110001 // F //0X71

上图展示了数码管,一个字样的显示方式,跟我们写汉字一样,一共准备了7个笔画,我们想让哪个笔画亮起来,就让那个笔画的电平拉高就行,总的来说还是挺直观的,因为我们只有7个笔画,但是一个比特有8位,所有还有一位空置为低电平,如果有其他用处的话,可以补上()。于是我们把这些二进制,通过计算器换算成16进制的话就变成了0x3F样式的字节码

static byte[] Characters = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0~9,A,b,C,d,E,F            

当然,也可以自己任意根据上面的描述,编写想要的走线图案,不一定非要按照0到9的数字或者字母定式来写。

//设置基本参数
startDisp();//开始写入指令
writeByte(0x40);//指定功能参数
stopDisp();//结束写入指令 //设置显示地址以及显示内容
startDisp();
writeByte(0xC0);//设置首地址,指向第一个字符
var Date = DateTime.Now.ToString("hhmm").ToCharArray();//获得当前日期,并表示为小时分钟
byte[] Characters = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 };//0~9,A,b,C,d,E,F
for (int i = ; i <4; i++)//循环更改四个字符的显示,想更改数码管的显示,只要更改循环体内的操作就行
{
  if (i != ) writeByte(Characters[Date[i] - ]);//从Characters数组根据索引获得字符显示的编码
  else writeByte((byte)(Characters[Date[] - ] + 0x80));//第二个字符带有冒号,因此将第一位空置拉高
}
stopDisp(); //开始写入亮度
startDisp();
writeByte(0x8f);
stopDisp();

以上代码便是驱动数码管显示的完整代码,循环运行上述代码就能不断驱动数码管显示当前的时间,同时更改循环体内的writeByte()方法参数,就能实现不同字符的显示。startDisp();stopDisp(); writeByte();方法体,都在上面有完全的展示。

除去上述三个方法,

writeByte(0x40);//指定功能参数
writeByte(0xC0);//设置首地址,指向第一个字符
writeByte((byte)(Characters[Date[1] - 48] + 0x80));//显示 :符号,这三个参数需要单独讲一下。
writeByte(0x8f);//指定亮度

首先,上述代码的先后顺序不能变,一定是先指定功能参数,后指定显示位置,然后指定显示内容,最后指定显示亮度

而功能参数0x40写入进去有啥用呢

我们查阅TM1637的规格书可知

0x40翻译成二进制便是

0 | 1  | 0 | 0 |  0 | 0 | 0 |  0
B7|B6|B5|B4|B3|B2|B1|B0

根据上述表格我们可以知道01000000(0X40)所代表的的意思就是

1:数据写到显示寄存器,也就是功能是显示

2:地址的增加模式是自+1

3:测试模式为普通模式

在此介绍一下前两种的区别

第一条的意思就是,这个芯片是支持按键响应和屏幕输出的,也就是说,如果B1置1则芯片功能是读取按钮 (虽然数位管上并没有任何按键),B1置0就是显示输出模式

第二条的意思就是,

for (int i = ; i <; i++)//循环更改四个字符的显示,想更改数码管的显示,只要更改循环体内的操作就行
{
  writeByte(Characters[Date[i] - ]);//从Characters数组根据索引获得字符显示的编码
}

如果B2置0,功能为自动地址增加模式,那么循环体内每次循环写入一个字符以后,下一次循环光标位置就会移到下一个字符的位置,就和我们打字类似

那么如果B2置1,功能为固定地址模式的话,顾名思义,就是哪个位置显示什么字符串由我们决定。

那么显示代码就变成了

  startDisp();
  writeByte(0xC0);//第一个字符
  writeByte(Characters[Date[] - ]);
  stopDisp();   startDisp();
  writeByte(0xC1);//第二个字符
  writeByte(Characters[Date[] - ]);
  stopDisp();   startDisp();
  writeByte(0xC2);//第三个字符
  writeByte(Characters[Date[] - ]);
  stopDisp();   startDisp();
  writeByte(0xC3);//第四个字符
  writeByte(Characters[Date[] - ]);
  stopDisp();

那么这个0xC0,0xC1,0xC2,0xC3哪里来的呢,同样查阅规格书可知

就是11000000,11000001,11000010,11000011,上述几个二进制转换成16进制便是C0,C1,C2,C3,当然,该芯片最多可支持显示6个字符

对了,中间这个  : 的符号,并不占用一个字符显示,这个符号归类到0xC1地址内,被当成了一个标点使用

   XGFEDCBA
  , // 0 //0x3f

还记得上面那张图吧,A~G,分别表示7个笔画,但是多了一位闲置的在这里就派上用场了,只要把0xC1,也就是第二个字符的位置最高位置1,变成10111111,那么这个符号变会显示出来

writeByte((byte)(Characters[Date[] - ] + 0x80));

代码上就是在原先的基础上加上0x80就可以了。

上面的步奏全部完成以后,其实只是把需要显示的数据存到芯片里面而已,芯片还没有输出任何数据给数码管,因为我们还什么都看不到

所以我们还需要再输入一次命令

writeByte(0x8f);//指定亮度并显示

那这个 0x8f又是哪里来的呢

这里同样有一张表格,B3表示开关,B0~B2表示脉冲宽带pwm,脉冲宽度越长,代表输出给数码管的时间越长,也就越亮,参照之前的方法,把对应的8位二进制转换成16进制填入进去就行,我想都看到这里了,应该没啥疑问的。

好,上述就是完整的教程,下面贴完整代码

        private static void Main(string[] args)
{
Pi.Init<BootstrapWiringPi>();//初始化通信接口,分配内存空间等
var clkPin = Pi.Gpio[BcmPin.Gpio23];//引用16接口
var dataPin = Pi.Gpio[BcmPin.Gpio24];//引用18接口
clkPin.PinMode = GpioPinDriveMode.Output;//设置16接口模式为输出
dataPin.PinMode = GpioPinDriveMode.Output;//设置18接口模式为输出
clkPin.Write(GpioPinValue.Low);//初始化电平为低,可不加
dataPin.Write(GpioPinValue.Low);//初始化电平为低,可不加 void startDisp()
{
//数据输入开始
clkPin.Write(GpioPinValue.High);//CLK拉为高电平
dataPin.Write(GpioPinValue.High);//DIO拉为高电平
dataPin.Write(GpioPinValue.Low);//和上面那句指令一起就是DIO由高变低
clkPin.Write(GpioPinValue.Low);//然后CLK上的时钟信号拉低,DIO接口的数据允许改变,代表开始写入数据
}
void stopDisp()
{
//结束条件是CLK为高时,DIO由低电平变为高电平
clkPin.Write(GpioPinValue.Low);//先拉低CLK,代表允许DIO改变数据
dataPin.Write(GpioPinValue.Low);//拉低DIO
clkPin.Write(GpioPinValue.High);//CLK拉高,满足结束条件前半部分
dataPin.Write(GpioPinValue.High);//DIO由低变高,代表数据输入结束
}
void writeByte(byte input)
{
//开始写入数据
for (int i = ; i < ; i++)//每次写入一个byte,一共8bit
{
clkPin.Write(GpioPinValue.Low);//确保无误输入前再拉低一次时钟 ,代表开始写入数据
if ((input & 0x01) == )//判断每一位的高低电平
{
dataPin.Write(GpioPinValue.High);
}
else
{
dataPin.Write(GpioPinValue.Low);
}
input >>= ;//每写入完毕一次,移动一位
clkPin.Write(GpioPinValue.High);//每次输入完一位,就拉高一次时钟
}
//应答信号ACK,这里本来是用来判断DIO脚是否被自动拉低,代表上面写入的数据TM1637已经接受到了,
//但是我们这里闲麻烦,直接将CLK信号低高低的拉,让芯片直接执行下一步操作
clkPin.Write(GpioPinValue.Low);//先拉低
clkPin.Write(GpioPinValue.High);//需要判断D是否为低电平此期间C一直拉高
clkPin.Write(GpioPinValue.Low);//应答完毕以后拉低C
}
void Show()
{
//设置基本参数
startDisp();//开始写入指令
writeByte(0x40);//指定功能参数为自动增加
stopDisp();//结束写入指令 //设置显示地址以及显示内容
startDisp();
writeByte(0xC0);//设置首地址,指向第一个字符
var Date = DateTime.Now.ToString("hhmm").ToCharArray();//获得当前日期,并表示为小时分钟
byte[] Characters = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 };//0~9,A,b,C,d,E,F
for (int i = ; i < Date.Length; i++)
{
if (i != ) writeByte(Characters[Date[i] - ]);//从Characters数组根据索引获得字符显示的编码
else writeByte((byte)(Characters[Date[] - ] + 0x80));//第二个字符带有冒号,因此将第一位空置拉高
} //开始写入亮度
startDisp();
writeByte(0x8f);
stopDisp();
}
while (true)
{
Show();
}
}

以上是字符地址自增加的代码

        private static void Main(string[] args)
{
Pi.Init<BootstrapWiringPi>();//初始化通信接口,分配内存空间等
var clkPin = Pi.Gpio[BcmPin.Gpio23];//引用16接口
var dataPin = Pi.Gpio[BcmPin.Gpio24];//引用18接口
clkPin.PinMode = GpioPinDriveMode.Output;//设置16接口模式为输出
dataPin.PinMode = GpioPinDriveMode.Output;//设置18接口模式为输出
clkPin.Write(GpioPinValue.Low);//初始化电平为低,可不加
dataPin.Write(GpioPinValue.Low);//初始化电平为低,可不加 void startDisp()
{
//数据输入开始
clkPin.Write(GpioPinValue.High);//CLK拉为高电平
dataPin.Write(GpioPinValue.High);//DIO拉为高电平
dataPin.Write(GpioPinValue.Low);//和上面那句指令一起就是DIO由高变低
clkPin.Write(GpioPinValue.Low);//然后CLK上的时钟信号拉低,DIO接口的数据允许改变,代表开始写入数据
}
void stopDisp()
{
//结束条件是CLK为高时,DIO由低电平变为高电平
clkPin.Write(GpioPinValue.Low);//先拉低CLK,代表允许DIO改变数据
dataPin.Write(GpioPinValue.Low);//拉低DIO
clkPin.Write(GpioPinValue.High);//CLK拉高,满足结束条件前半部分
dataPin.Write(GpioPinValue.High);//DIO由低变高,代表数据输入结束
}
void writeByte(byte input)
{
//开始写入数据
for (int i = ; i < ; i++)//每次写入一个byte,一共8bit
{
clkPin.Write(GpioPinValue.Low);//确保无误输入前再拉低一次时钟 ,代表开始写入数据
if ((input & 0x01) == )//判断每一位的高低电平
{
dataPin.Write(GpioPinValue.High);
}
else
{
dataPin.Write(GpioPinValue.Low);
}
input >>= ;//每写入完毕一次,移动一位
clkPin.Write(GpioPinValue.High);//每次输入完一位,就拉高一次时钟
}
//应答信号ACK,这里本来是用来判断DIO脚是否被自动拉低,代表上面写入的数据TM1637已经接受到了,
//但是我们这里闲麻烦,直接将CLK信号低高低的拉,让芯片直接执行下一步操作
clkPin.Write(GpioPinValue.Low);//先拉低
clkPin.Write(GpioPinValue.High);//需要判断D是否为低电平此期间C一直拉高
clkPin.Write(GpioPinValue.Low);//应答完毕以后拉低C
}
void Show()
{
//设置基本参数
startDisp();//开始写入指令
writeByte(0x44);//指定功能参数为固定地址显示
stopDisp();//结束写入指令 var Date = DateTime.Now.ToString("hhmm").ToCharArray();//获得当前日期,并表示为小时分钟
byte[] Characters = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 };//0~9,A,b,C,d,E,F
//设置显示地址以及显示内容
startDisp();
writeByte(0xC0);//第一个字符
writeByte(Characters[Date[] - ]);
stopDisp(); startDisp();
writeByte(0xC1);//第二个字符
writeByte((byte)(Characters[Date[] - ] + 0x80));//第二个字符带有冒号,因此将第一位空置拉高
stopDisp(); startDisp();
writeByte(0xC2);//第三个字符
writeByte(Characters[Date[] - ]);
stopDisp(); startDisp();
writeByte(0xC3);//第四个字符
writeByte(Characters[Date[] - ]);
stopDisp(); //开始写入亮度
startDisp();
writeByte(0x8f);
stopDisp();
}
while (true)
{
Show();
}
}

以上是固定字符显示代码

对于.net core的项目来说,如果想使用Mono运行,那么命令是

执行mono xxxx.dll的方式,如果是普通的.net4.0框架的程序才是mono xxxx.exe的方式

在树莓派Zero上使用C#+Mono驱动TM1637四位数码管的更多相关文章

  1. sruts2:单个文件上传,多个文件上传(属性驱动)

    文件上传功能在Struts2中得到了很好的封装,主要使用fileUpload上传组件. 1. 单个文件上传 1.1 创建上传单个文件的JSP页面.显示提交结果的JSP页面 uploadTest1.js ...

  2. Raspberry Pi(树莓派)上从零开始构建Linux系统(简称PiLFS)(一)

    一. 准备工作 1. 装有Linux宿主系统的树莓派主板,可参考 Raspberry Pi(树莓派)上安装Raspbian(无路由器,无显示器) 2. 参考网址:Linux From Scratch ...

  3. 在树莓派2上安装 Windows 10

    微软在2015年4月29日发布了树莓派玩家期待已久的 Windows 10 物联网核心预览版(Windows 10 IoT Core Insider Preview Image for Raspber ...

  4. 在树莓派3B上安装node.js

    本文主讲如何在树莓派3B上安装node.js 环境描述1. 树莓派安装了`2016-11-25-raspbian-jessie-lite`(PS:在此版本的镜像中,默认禁用了ssh,在烧录好镜像之后, ...

  5. 2019 年在 Raspberry Pi 「树莓派」上运行的 10 个操作系统推荐

    原文:2019 年在 Raspberry Pi 「树莓派」上运行的 10 个操作系统推荐 image Raspberry Pi** 是一款基于 ARM 的单板计算机,默认运行一款称为 Raspbian ...

  6. 【Linux开发】【CUDA开发】Ubuntu上安装NVIDIA显卡驱动

    机型为戴尔Vostro3900  显卡型号为GTX 745  对于Nvidia显卡的驱动,如今很多Linux发行版会默认使用名为nouveau的驱动程序.Nouveau是由第三方为Nvidia开发的一 ...

  7. [七月挑选]树莓派Raspberrypi上配置Git

    title: 树莓派Raspberrypi上配置Git 树莓派Raspberrypi上配置Git. 开始 首先你得有一树莓派!!! 过程 查看自己树莓派的版本 pi@raspberrypi:~ $ u ...

  8. 在香蕉派的树莓派系统上配置 Syncthing 自启动

    在香蕉派的树莓派系统上配置 Syncthing 自启动 —— 魏刘宏 2020 年 1 月 19 日 首先做个名词解释,” 香蕉派” 是国内一款山寨树莓派的硬件产品,” 树莓派系统” 指的是”rasp ...

  9. raspberrypi(树莓派)上安装mono和jexus,运行asp.net程序

    参考网址: http://www.linuxdot.net/ http://www.cnblogs.com/mayswind/p/3279380.html http://www.raspberrypi ...

随机推荐

  1. LeetCode75----分类颜色(变相快排)

    给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 0. 1 和 2 分别表示红色.白色和蓝色. ...

  2. 基于Xposed hook 实时监测微信消息

    本文以微信版本6.7.3为例进行分析有hook, 大部分做微信机器人的话,首先要实时抓取微信的消息,在这里展示三种方式对微信的消息进行hook: 1.基于UI层拉取加载进行监听 2.基于微信dao层调 ...

  3. LeetCode 43. 字符串相乘(Multiply Strings) 大数乘法

    题目描述 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式. 示例 1: 输入: num1 = "2" ...

  4. Windows下安装TensorFlow教程

    目录 安装Python3.6 配置环境变量 安装TensorFlow 验证安装 报错或选版本 安装Python3.6 建议直接安装anaconda 下载地址:https://www.anaconda. ...

  5. webpack 第二部分

    默认根目录 当前项目 修改目录 devServer devServer:{ open:true, //自动打开浏览器 port:3000, // 端口 contentBase:"dist&q ...

  6. out 传值(传址)

    传值,只将这个变量的值给拿走,不返还,除非return赋值.将a的值传入函数,无论这个值在函数中如何变化,不会影响main中的a 传址,将这个变量的值拿走运算,完成后还是得返还回来(不用return, ...

  7. android studio中方法和类被调用多次,但是AS显示灰色,解决办法

    Android Studio里面的一些类及方法,明明有被其他的类或者方法调用,但是去看的时候显示灰色,鼠标放上面的时候显示:Class ‘XXX’ is never used或者Method ‘XXX ...

  8. ListView 中如何优化图片?

    图片的优化策略比较多.1.处理图片的方式:如果 ListView 中自定义的 Item 中有涉及到大量图片的,一定要对图片进行细心的处理,因为图片占的内存是ListView 项中最头疼的,处理图片的方 ...

  9. Computer Network Homework2’s hard question

    Computer Network Homework2’s hard question 2. What is the signal which is used to modulate the origi ...

  10. 物料批量盘点,调用其中两个BAPI BAPI_MATPHYSINV_COUNT BAPI_MATPHYSINV_CHANGECOUNT

    涉及两个BAPI:录入数量BAPI_MATPHYSINV_COUNT 修改数量:BAPI_MATPHYSINV_CHANGECOUNT REPORT  ZSC_133 NO STANDARD PAGE ...