Ice_bag的技术博客,欢迎!

keen on hack and geek :~)


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 站点地图

未来一段时间的小规划

发表于 2020-09-03

Recovery-Eminem

姗姗来迟の更新

拖更的原因说来有点尴尬,忘记把博客仓库文件夹和密钥带回家…多亏COVID-19带来一段史无前例长的家里蹲时光,再次更新博客已是九月浅秋,而我也进入大三。自2020年初,世界开始变得不安分,明天会是更好、还是更烂?when the world was at war we kept dancing 这半年来我的学习步调与以往略有差异,注意到曾经忽视的东西,也对未来的路有了新的思考。

参与的项目

虽然在家里东西没有学校全,但还是有搞出一些名堂的,这里先粗略列出,以后会开贴细说。

  • STM32CubeMX & HAL
  • 数模培训(多目标优化,高斯-赛德尔,龙格库塔法,crank-nicholson)
  • 学校项目设计的android app、上位机代码、微控制器代码
  • Xctf单片机固件逆向的两道题
  • 网络安全作品赛:基于蜜罐的网址安全性检查系统
  • 一辆fpv wifi 遥控车77送我的❤

Todo

没有计划是不行的,随心所欲是我以前的作风,这样做的后果是学习不系统、不深入、学了就忘,而且容易错过许多重要的事。下面是这学期我的学习规划(多出门学习,别老窝在宿舍):

  • 数字信号处理实践matlab,fpga
  • 航模航模
  • SDR (电磁场+高频+数字信号处理)
  • aujlefLJ8c9QDpGRdX+B/xzuDvUUzQO9d+NcX24PA0F2

OSI

发表于 2019-12-09

计算机网络层级

以前在协议组学到的一些东西,互联网的本质就是一系列的网络协议,这个协议就叫OSI协议(一系列协议),按照功能不同,分工不同,人为的分层七层。实际上这个七层是不存在的。没有这七层的概念,只是人为的划分而已。区分出来的目的只是让你明白哪一层是干什么用的。
七层划分为从高到低:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。

物理层

物理层就是唯一看得见摸得着的一层,也是最底层。它指的是计算机与计算机之间的物理连接,可以是光纤,双绞线,电话线,电磁波信号。是计算机网络组成必不可少的一层。

链路层

物理层传输的只是010二进制信号,如果没有编解码,将不会有任何意义。链路层的意义就是对二进制信号进行编码与解码。

局域网

局域网是一种私有网络,一般在一座建筑物内或建筑物附近,比如家庭、办公室或工厂。局域网络被广泛用来连接个人计算机和消费类电子设备,使它们能够共享资源和交换信息。当局域网被用于公司时,它们就称为企业网络,互联网就是由一个个局域网组成。

一个经典例子:ethernet

对物理层的二进制信号分组,每一组称为一个数据包,ethernet协议规定了ethernet数据包的结构。

head data
18byte 46~1500byte

head

1.源地址(6 byte)
2.目标地址(6 byte)
3.数据类型(6 byte)

此处的地址指的就是mac地址,Ethernet规定接入Internet的设备都必须具备网卡,发送端的和接收端的地址便是指网卡的地址,即Mac地址。每块网的Mac地址都应该是唯一的。

ethernet广播

数据在局域网中以Ethernet协议传输时,采用的是广播的方式,所有的数据包都是可以被接收到的,但是一般只接收目标地址与本机Mac地址相符的包,因为正常情况下数据是被加密的,即使接受到了发给别人的数据包,也没有用。所以数据的加密是很重要的。

网络层

那么问题来了,1.广播中怎么知道目标的Mac地址?2.怎么与不在同一个局域网的主机通信?

IP编址

除了Mac地址,还有一个比较常提及的地址IP地址。IP地址用于标识主机所处的局域网。IP地址是由网络地址与主机地址两部分所组成。

网络地址

网络地址可用来识别设备所在的网络,网络地址位于IP地址的前段。当组织或企业申请IP地址时,所获得的并非IP地址,而是取得一个唯一的、能够识别的网络地址。同一网络上的所有设备,都有相同的网络地址。IP路由的功能是根据IP地址中的网络地址,决定要将IP信息包送至所指明的那个网络。

主机地址

主机地址位于IP地址的后段,可用来识别网络上设备。同一网络上的设备都会有相同的网络地址,而各设备之间则是以主机地址来区别。

IP路由

IP主要包含三方面内容:IP编址方案、分组封装格式及分组转发规则

互联网是由许多个局域网连接所形成的大型网络。如果要在互联网中传送IP信息包,除了确保网络上每个设备都有一个唯一的IP地址之外,网络之间还必须有传送的机制,才能将IP信息包通过一个个的网络传送到目的地。此种传送机制称为IP路由。
网关:局域网的出入口,连通不同的局域网。在IP路由的过程中,由网关负责选择路径,IP信息包则是被传送的对象。
IP信息包传送时还有一项很重要的特性,即使用非连接式的传送方式。非连接式的传送方式是指IP信息包传送时,源设备与目的设备双方不必事先连接,即可将IP信息包送达。即源设备完全不用理会目的设备,而只是单纯地将IP信息包逐一送出。至于目的设备是否收到每个信息包、是否收到正确的信息包等,则由上层的协议(例如TCP)来负责检查。
使用非连接式的优点是过程简单化,可提高传输的效率。此外,由于IP信息包必须通过IP路由的机制,在一个个路由器之间传递,非连接式的传送方式较易在此种机制中运行。
不同局域网间的数据传输:通过网络地址区分,计算机运算判断出目标不在同一个局域网内,

ARP

主机A的IP地址为192.168.1.1,MAC地址为0A-11-22-33-44-01;
主机B的IP地址为192.168.1.2,MAC地址为0A-11-22-33-44-02;
当主机A要与主机B通信时,地址解析协议可以将主机B的IP地址(192.168.1.2)解析成主机B的MAC地址,以下为工作流程:
第1步:根据主机A上的路由表内容,IP确定用于访问主机B的转发IP地址是192.168.1.2。然后A主机在自己的本地ARP缓存中检查主机B的匹配MAC地址。
第2步:如果主机A在ARP缓存中没有找到映射,它将询问192.168.1.2的硬件地址,从而将ARP请求帧广播到本地网络上的所有主机。源主机A的IP地址和MAC地址都包括在ARP请求中。本地网络上的每台主机都接收到ARP请求并且检查是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求。
第3步:主机B确定ARP请求中的IP地址与自己的IP地址匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存中。
第4步:主机B将包含其MAC地址的ARP回复消息直接发送回主机A。
第5步:当主机A收到从主机B发来的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存。本机缓存是有生存期的,生存期结束后,将再次重复上面的过程。主机B的MAC地址一旦确定,主机A就能向主机B发送IP通信了。

IP发包

计算机网络模型就像套娃,底层套上层,一层又一层。位于网络层的IP数据包被套在了数据链路层ethernet的数据里。它大概长这样。

ethernet head ip head ip data

如果源主机和目标主机在同一局域网内,包长这样

源Mac 目标Mac 源IP 目标IP data

目标Mac地址可通过ARP查询得到。ARP包长这样

源Mac FF:FF:FF:FF:FF:FF 源IP 目标IP data

返回目标MAC地址。
如果源主机和目标主机不在同一局域网,包长这样

源Mac 网关Mac 源IP 目标IP data

网关mac也通过ARP查询得到。这时候ARP包长这样

源Mac FF:FF:FF:FF:FF:FF 源IP 网关IP data

返回网关MAC地址。

传输层

应用层

我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容。
如果想要使传输的数据有意义,则必须使用到应用层协议。

FPVcar

发表于 2019-12-09

项目概况

使用的是上一个项目Ball Tracer的底盘,硬件方面基本没变。这次主要是想尝试一下用python实现socket通信。

Socket简介

Socket又称”套接字”,应用程序通常通过”套接字”向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。Socket是应用层与传输层间的一个抽象层,是个编程接口。

拓展阅读:计算机网络层级

在协议组学到的一些东西。

架构

网络

电脑和树莓派连接同一个路由器,处于一个局域网内。使用ifconfig/ipconfig查看ip地址,便于后续连接的建立。

socket

使用了两个socket,socket0负责传输图像,socket1负责传输操控指令。socket0从树莓派发往PC,socket1从PC发往树莓派。都是PC做服务器,树莓派做客户端。使用的是udp传输协议,延迟更低,丢包对视频传输的影响也不大。

操控

使用键盘操控,w前进,s后退,a左转,d右转。

代码

PC端

camera.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import cv2
import numpy
import socket
import struct
HOST='192.168.1.101'
PORT=9999
buffSize=65535

server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind((HOST,PORT))

print('now waiting for frames')
while True:
data,address=server.recvfrom(buffSize)
if len(data)==1 and data[0]==1:
server.close()
cv2.destroyAllWindows()
exit()
try:
data=bytearray(data)
print('have recevied one frame',address)
data=numpy.array(data)
imgdecode=cv2.imdecode(data,1)
cv2.imshow('frames',imgdecode)
keycode=cv2.waitKey(10)&0xff
if keycode==ord('q'):
break
except:
continue
server.close()
cv2.destroyAllWindows()

control.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import cv2
import socket
HOST='192.168.1.101'
PORT=8888
buffSize=65535

server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind((HOST,PORT))

print('now waiting for connection')

background=cv2.imread('background.jpg')

while True:
data,address=server.recvfrom(buffSize)
if len(data)==1 and data[0]==1:
server.close()
exit()
if data==b'hello':
print('start',address)

while True:
cv2.imshow('background',background)
c=cv2.waitKey(100)&0xff
if c==ord('q'):
server.close()
exit()
c=chr(c)
server.sendto(c.encode('utf-8'),address)
try:

print('have recevied one msg:',data,address)

except:
continue
server.close()
exit()

树莓派

camera.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
buffSize=65535
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

cap = cv2.VideoCapture(0)
while True:
ret, frame= cap.read()
frame=cv2.flip(frame,-1,dst=None)
if ret is False:
print 'f'
continue
cv2.imshow('the frame',frame)
keycode=cv2.waitKey(10)&0xff
if keycode==ord('q'):
break

ret,imgencode=cv2.imencode('.jpg',frame,[cv2.IMWRITE_JPEG_QUALITY,50])
server.sendto(imgencode,(HOST,PORT))

control.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import socket
import time
import RPi.GPIO as GPIO
import gpiotest as gp

GPIO.setmode(GPIO.BOARD)
INT1=11
INT2=12
INT3=13
INT4=15

GPIO.setup(INT1,GPIO.OUT)
GPIO.setup(INT2,GPIO.OUT)
GPIO.setup(INT3,GPIO.OUT)
GPIO.setup(INT4,GPIO.OUT)

HOST='192.168.1.101'
PORT=8888
buffSize=65535
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

server.sendto('hello',(HOST,PORT))
while True:
c,addr=server.recvfrom(buffSize)
c=c.decode('utf-8')
c=c.encode('ascii','ignore')
print(c,type(c))


if c=='w':
gp.f(0.05)
print('w'*100)
elif c==u's':
gp.b(0.05)
elif c==u'a':
gp.t_l(0.05)
elif c==u'd':
gp.t_r(0.05)
elif c==u'q':
server.close()
exit()

gpiotest.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import cv2
import RPi.GPIO as GPIO
import time
import random

GPIO.setmode(GPIO.BOARD)

INT1=11
INT2=12
INT3=13
INT4=15

GPIO.setup(INT1,GPIO.OUT)
GPIO.setup(INT2,GPIO.OUT)
GPIO.setup(INT3,GPIO.OUT)
GPIO.setup(INT4,GPIO.OUT)

def b(time_):
GPIO.output(INT2,GPIO.HIGH)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT3,GPIO.HIGH)
GPIO.output(INT4,GPIO.LOW)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)

def f(time_):
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT1,GPIO.HIGH)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.HIGH)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)

def t_l(time_):
GPIO.output(INT2,GPIO.HIGH)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.HIGH)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)

def t_r(time_):
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT1,GPIO.HIGH)
GPIO.output(INT3,GPIO.HIGH)
GPIO.output(INT4,GPIO.LOW)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)

pywifi

发表于 2019-12-04

用python操作wifi的代码,实现了扫描,连接的基本功能。具体怎么用,你懂的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import pywifi,time
from pywifi import const
def wifi_connect_status():
wifi=pywifi.PyWiFi()
iface=wifi.interfaces()[0]
if iface.status() in [const.IFACE_CONNECTED,const.IFACE_INACTIVE]:
print('wifi已连接')
else:
print('wifi未连接')
return 0
def scan_wifi():
wifi=pywifi.PyWiFi()
iface=wifi.interfaces()[0]
iface.scan()
time.sleep(1)
basewifi=iface.scan_results()
for i in basewifi:
print('wifi ssid:{}'.format(i.ssid))
print('wifi mac:{}'.format(i.bssid))
return basewifi
def connect_wifi(ssid,pw):
wifi=pywifi.PyWiFi()
ifaces=wifi.interfaces()[0]
print(ifaces.name())
ifaces.disconnect()
time.sleep(3)

profile=pywifi.Profile()
profile.ssid=ssid
profile.auth=const.AUTH_ALG_OPEN
profile.akm.append(const.AKM_TYPE_WPA2PSK)
profile.cipher=const.CIPHER_TYPE_CCMP
profile.key=pw

ifaces.remove_all_network_profiles()
tmp_profile=ifaces.add_network_profile(profile)

ifaces.connect(tmp_profile)
time.sleep(10)
isok=True
if ifaces.status()==const.IFACE_CONNECTED:
print('connected')
else:
print('faild')
time.sleep(1)
return isok

if __name__=='__main__':
wifi_connect_status()
time.sleep(5)
scan_wifi()

Project:BallTracer

发表于 2019-12-04

项目概述

2019年星火杯人工智能赛道作品,机器学习、机器视觉实践。主要实现了网球的识别、追踪。

环境

板子:RaspberryPi 4B,系统:raspbian-buster 2019-09-26。python版本:2.7。opencv版本:2.4.13。电机驱动:L298N

连接

开启远程图形化桌面,同一局域网下可通过VNC-Viewer连接,简化操作。也可以接屏幕,不过还要连接键鼠。如果熟悉linux命令行,SSH也可。

训练部分

主要在电脑上完成,采用opencv库中的adaboost进行训练。训练得到cascade集成分类器文件。

训练集准备

正样本
负样本

识别部分

说白了就是画框框,在树莓派上调用摄像头拍照,再用opencv识别。

跟踪部分

根据窗口的偏移,树莓派gpio控制电机转动。

吐槽

做这个项目的那几天,正好碰上监管周,梯子挂了一大片,然后树莓派的镜像源都好久不更新了,装个opencv装到自闭。
python,python2,python3,pip,pip2,pip3???linux下python版本也是整了半天。
opencv2,opencv3???这个版本兼容也是。。。
树莓派系统老是莫名奇妙坏掉,我明明什么都没干,在stackoverflow上翻了半天,才知道是boot损坏,期间刷写了好几次固件,后来靠dd才修复的。

testbench

发表于 2019-12-01

What is testbench

编写testbench的主要目的是为了对使用硬件描述语言(HDL)设计的电路进行仿真验证,测试设计电路的功能、部分性能是否与预期的目标相符。

testbench构造

一些基本约定

简单的testbench的结构通常需要建立一个顶层文件,顶层文件没有输入和输出端口。在顶层文件里,把被测模块和激励产生模块实例化进来,并且把被测模块的端口与激励模块的端口进行对应连接,使得激励可以输入到被测模块。
一般用initial块给信号赋初值,initial块执行一次,always或者forever表示由事件激发反复执行。input对应的端口应当申明为reg,output对应的端口申明为wire。

时间精度与延迟

字符#,该符号的意思是指延迟timescale中设定的单位时间的个数。一般在testbench的开头定义时间单位和仿真精度,比如

1
`timescale 1ns/1ps

前面一个是代表时间单位,后面一个代表仿真时间精度。以上面的例子而言,一个时钟周期是 20 个单位,也就是 20ns。

时钟的发生

always加#延时固定时间间隔生成时钟信号,注意给时钟初始化。

1
2
3
4
5
6
7
8
9
10
always #10 begin
clk<=~clk;
end

initial begin
#0 begin
clk<=1'b0;
end
...
end

载入存储镜像

仿真时,有时需要向存储器预先载入准备好的数据。可以使用$readmemh系统任务从文件中读入数据并设置存储器。格式:$readsmemh(“文件名”,读入对象”)。存储镜像文件使用十六进制文本文件记录,每一行记录一个地址的数据。

A simple example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

timescale 1ns/1ps

module exam();
reg rst_n;
reg clk;
reg data;

initial
begin
clk = 1'b0;
rst = 1'b1;
#10
rst = 1'b0;
#500
rst = 1'b1;
end

always
begin
#10 clk = ~clk;
end

endmodule

PS.7isthecoolestgirlintheworld

Python学习札记

发表于 2019-11-24

基本概念

axis

数组(矩阵)的数轴,几维数组就有几个axis,用于矩阵元素的引索。

操作对象Ndarray

Numpy中定义的最重要的对象是称为ndarray的N维数组类型,它描述相同类型的元素集合。ndarray对象由计算机内存中的一维连续区域组成,ndarray中的每个元素在内存中使用相同大小的块。基本的ndarray是使用NumPy中的数组函数创建的。

数据类型对象dtype

数据类型对象dtype描述了对应于数组固定内存块的解释,包括以下几个方面:

1.数据类型(整数、浮点或者Python对象)。
2.数据大小。
3.字节序(小端或大端)。
4.在结构化类型的情况下,字段的名称,每个字段的数据类型,和每个字段占用的内存块部分。
5.如果数据类型是子序列,它的形状和数据类型。

1
numpy.dtype(object, align, copy)

1.object:被转换为数据类型的对象。
2.align:如果为true,则向字段添加间隔,使其类似C的结构体。
3.copy:生成dtype对象的新副本,如果为false,结果是内建数据类型对象的引用。

1
2
3
4
5
# int8,int16,int32,int64可替换为等价的字符串'i1','i2','i4','i8'
import numpy as np
dt = np.dtype('i8')
print(dt)
# int64

数组属性

ndarray.shape:这一数组属性返回一个包含数组维度的元组,它也可以用于调整数组大小。

1
2
3
4
5
6
7
a = numpy.array([[1, 2, 3], [4, 5, 6]])
a.shape = (3, 2)
#等价a=a.reshape(3,2)
print(a)
# [[1 2]
# [3 4]
# [5 6]]

创建数组

numpy.empty

创建指定形状和dtype的未初始化数组

1
numpy.empty(shape, dtype = float, order = 'C')

numpy.zeros

返回特定大小,以0填充的新数组。

1
numpy.zeros(shape, dtype = float, order = 'C')

numpy.ones

返回特定大小,以1填充的新数组。

1
numpy.ones(shape, dtype = None, order = 'C')

numpy.arange

返回ndarray对象,包含给定范围内的等间隔值。

1
numpy.arange(start, stop, step, dtype)

数组的索引和切片

(未完待续。。。

the way of hardware design study

发表于 2019-10-05

A Small Introduction Of Hardware

1.器件

主要分类

1.MCU
2.DSP
3.FPGA
4.Embedded
5.System on Chip

MCU

MCU俗称单片机,通常无操作系统,用于简单的控制,如电梯,空调等。

DSP

DSP叫做数字信号处理器,它的结构与MCU不同,加快了运算速度,用于复杂的计算,像离散余弦变换、快速傅里叶变换,常用于图像处理,在数码相机、MP3等设备中使用。

FPGA

现场可编程门阵列,以硬件描述语言(Verilog 或 VHDL)所完成的电路设计,可以经过简单的综合与布局,快速的烧录至 FPGA 上进行测试,是现代集成电路设计验证的技术主流。

Embedded

嵌入式操作系统,相比较PC机这种通用系统来说,嵌入式系统是个专用系统,结构精简,在硬件和软件上都只保留需要的部分,而将不需要的部分裁去。所以嵌入式系统一般都具有便携、低功耗、性能单一等特性。常用于路由器,无人机。

SoC

片上系统,系统级芯片,不仅集成了ROM、RAM,等外部设备,还拥有强大的代码能力,可以运行操作系统。智能手机就属于这一类。


常见器件

MCU DSP FPGA Embedded SoC
8051系列 MSP430 XILINX Openwrt 树莓派
stm32(CM3) TMS320 ALTERA uCLinux 高通骁龙

2.基本协议

1.uart
2.spi
3.iic

3.MISC

冯·诺依曼体系结构与哈佛体系结构、CISC与RISC、流水线技术、信息存储的字节顺序。
组合逻辑电路基础、时序逻辑电路、总线电路及信号驱动、电平转换电路、可编程逻辑器件基础。
进位计数制与转换、计算机中数的表示、非数值数据编码、差错控制编码。
嵌入式操作系统(嵌入式Linux)经验、内核裁剪经验、驱动程序开发经验。

一起玩蛇(I)

发表于 2019-09-13

沙雕人写沙雕文章

众所周知,python是一门很牛逼的语言,基本能满足全栈的业务需求,语法简单。因此,越来越多的企业、工程师、程序员,开始使用它。
那咋办嘛?学一点python总没有错的,大家一起来玩蛇吧!

环境搭建

基础的python环境很简单,最简单的,只需要一个解释器,毕竟,python是一门脚本语言,你只需要给python解释器输入一个语法正确的脚本他就可以工作,不存在编译过程。你要做的就是写脚本,最简单的用windows自带的notepad.exe都可以。
python_exe
hello
save

又不是不能用

大概就这样啦
run

温饱思淫欲

用记事本写的话就很累,没有代码预测补全,记事本的背景太单调。库、依赖包管理管理也不方便,这才是最重要的,这些功能强大的库正是python强大的根源。所以,我们最好使用一些小工具来辅助我们开发,我使用的是anaconda+vscode。

anaconda安装

你不会google吗?

vscode安装

你不会baidu吗?

开始了

先从图像处理开始熟悉一下python的使用吧!

计算机系统中的图片

图片,对计算机来说就是一个矩阵,每一个像素对应一个矩阵元素。你应该听说过三原色(rgb),所有颜色都可以用这三种颜色混合而成,像素元素在计算机矩阵中对应四个值(32bit深度),red,green,blue,alpha,前面三个是三原色,alpha是透明度。每个8bit也就是一个字节,在0~255之间变化,幻变出你屏幕上的七彩斑斓。
你眼中的老婆
tifa
计算机眼中你的老婆
ttifa

蟒蛇·枕头

pillow是一个专门处理图像的库。
pillow

上代码

cscode
MSvisualstudio风格的编译环境,看久了眼睛也不累,还有代码补全,还很轻量级(50m),还开源,微软这一次还是很够意思的。这个程序实现的功能主要是:将一张黑白图片中的黑色部位像素点转换为’1’白色像素点转为’0’,打开一个txt文本,写入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from PIL import Image
im=Image.open(r'C:\Users\94900\Pictures\Camera Roll\long.png')
width=im.size[0]
height=im.size[1]
fh=open('long.txt','w')
for i in range(height):
for j in range(width):
color=im.getpixel((j,i))
colorsum=color[0]+color[1]+color[2]
if(colorsum==0):
fh.write('1')
else:
fh.write('0')
fh.write('\n')
fh.close()

效果

long
llong
恶龙@世龙学长

to be continue…

python能做到的远不止这些,图像处理是个大坑,我尽量填吧。

谈谈51

发表于 2019-09-01

引子

51单片机作为学习单片机的过程中必须要经过的一个过程来讲是非常重要的,原因在于51单片机从内部的硬件到软件有一套完整的按位操作系统。学习单片机是入门计算机科学的一个好方法。

何为单片机

你可以把单片机想象成一台电脑,一台压缩成卡片大小的电脑,CPU、RAM、ROM、I/O口和中断、系统定时器/计数器。拆开你的笔记本或台式电脑,你会发现它们的基本构造几乎是一样的。(这么多年过去了,上层的架构更新了一代又一代,冯诺依曼体系却从未动摇)

51单片机

“上古单片机”

51单片机是对所有兼容Intel 8031指令系统的单片机的统称。是上个世纪80年代的产品了,在功耗、主频、带宽、稳定性等方面都无法与现代单片机相提并论。不过,得益于功能简单、成本低廉,51单片机成了很好的教学单片机。

51单片机的组成

最小系统电路
如上图,不含外部设备,能让51单片机实现图灵完备的最基本电路,它包括:供电电源、时钟晶振、复位开关。尽管市面上有很多现成的开发板,还是建议自己焊一个,顺便提高焊接技术,今后的工作生活中用到烙铁的地方还多着。
众所周知,对计算机来说软件和硬件一样重要,制作好最小系统后,我们需要给我们的单片机注入灵魂。计算机被发明出来就是为了解决问题的,通过程序指令,操纵单片机为我们服务。我们自然不可以在单片机上编程编译环境在windows上。

编程方法

51单片机支持C和汇编编程,C语言简化了编程的过程,reg51.h库函数让一个有 C语言基础的新手快速入门5单片机开发。而汇编语言更接近计算机的本质,编译器也只是把C代码转换为汇编代码的工具,这涉及到编译原理的知识吗,对计算机感兴趣的朋友可以逛逛我的博客,51入门以C为主,在这里就不详细探讨汇编了。

helloworld?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<reg51.h>
#define uint unsigned int

void main(){
uint n=5000;
while(1){
P1=0xfe;
while(n--);
n=5000;
P1=0xff;
while(n--);
n=5000;
}
}

程序分析

一个非常简单的例程,单片机没有显示器,没办法printf在终端打印helloworld,我们只好用灯的亮灭来验证程序执行的结果。和X86下的C语言一样,main函数为程序开始执行的地方,P1变量定义于reg51.h中,对应的是串口寄存器P1的地址,P1=0xfe;这条语句将P1的值设为0xfe,在二进制下这就是11111110,最低位为0。P1=0xff;这条语句将P1的值设为0xff,在二进制下为11111111,最低位为1。
有一点你需要知道的是,单片机P1串口寄存器为一个Byte,也就是8个bit,在电气封装上表现为8个针脚,每一个bit和每一个针脚的高低电平正好对应。刚才的两条语句完成了P1最低位的0,1切换,控制P1.0的电位变换,在P1.0上连接一个发光二极管,就可以控制暗灭了!
注意,我们一般都要将单片机主循环写死,这是与windows下的C不同的,单片机没有操纵系统接管,我们得让程序一直跑下去。在本例程里,程序控制led灯亮暗交替,永不停息,直到没电。。。
单片机的速度很快时钟频率12Mhz,亮暗变化在 1 us间,但是在上面这个程序里我们加了while(n–);语句,相当于程序在这段时间里什么都没做,我们的眼睛就能观察到亮暗的变化了。

烧写程序

可以使用keil编译51单片机的C程序,输出十六进制文件,连接单片机与电脑,通过stc-isp烧写十六进制文件到单片机中。
这就是51单片机编程的全部过程,我在B站有更详细的视频教程,如果还有不明白的地方,在星火交流群里都可以讨论。

进阶与展望

前提是你已经有了比较熟练的C语言基础:循环、判断、选择、指针、结构体、函数调用都能运用自如,会配置IO、定时器、中断、IIC等功能。如果学完这些你还对单片机/嵌入式开发感兴趣的话,可以试试更复杂的系统,MSP430、STM32、Raspberry Pi,开始完整的项目制作,做些小车、飞机、机器人之类的玩玩。
单片机/嵌入式系统是物联网场景的最优解,完美满足物联网低功耗、低成本、轻量化的需求,特别是现在有些单片机支持无线网络接入,大大提升了物联网的发展速度。nodemcu是一个支持高级语言Lua脚本的平台,配合node.js搭建服务器,使用起来非常简便。
本人水平有限,文章如有错误,还请师傅们指出。

12…4

Ice_bag(WXJ)

35 日志
10 分类
25 标签
© 2020 Ice_bag(WXJ)
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4