单片机和Windows程序设计

This commit is contained in:
yinkanglong_lab
2021-03-08 22:53:37 +08:00
parent 429f9d4fcb
commit f70604e6f3
23 changed files with 2564 additions and 0 deletions

View File

@@ -299,3 +299,13 @@ data a,b;
```
a.sold =1;
```
## 7 常用限定符说明
### 存储类别
* auto 默认存储类别自动变量int i = 3;
* static 静态存储类别的变量静态变量static int m = 5;
* register 寄存器变量register n = 6;
* extern 声明外部链接属性
### 类型限定
* const限定制度变量、常变量 const int i = 6;必须直接初始化,避免对重要手进行错误修改。
* volatile限定隐式存取变量。

View File

@@ -0,0 +1,108 @@
# 冯诺依曼计算机
## 组成部分
1. 运算器算术逻辑单元ALU。算术运算和逻辑运算。加法器、寄存器、控制线路。
2. 控制器程序计数器PC、指令寄存器IR、指令译码器ID、时序控制电路。运算器和控制器组成了CPU。
3. 存储器:计算机用来存储数据的记忆装置。内存储器和外存储器。
4. 输入设备:接受用户输入的程序和数据信息,将他们转换成计算机可以处理的二进制形式的数据存储到内存当中。
5. 输出设备:将存放在内存中的计算机处理结果以人们能够识别的形势表现出来。
> 分类:高性能计算机、微信计算机、工作站、服务器、嵌入式计算机。
> 程序和数据均以二进制表示,以相同的方式存放在存储器中,按地址寻访。
## 指令与程序
* 指令:计算机执行某种操作的及其命令,他可以被计算机硬件直接识别和执行。组成:操作码+操作数。操作码指明操作的类型。操作数指明操作对象的数据或所在的内存单元地址。
* 指令系统:一台计算机所有指令的集合称为指令系统。指令分类:数据传送指令、数据处理指令、程序控制指令、输入输出指令、硬件管理指令。
* 执行指令的步骤:取指令、分析指令、处理指令。指令流水线技术。
* 程序:完成一定功能的指令的有序集合。包含算法和数据两部分。
* 算法:控制流是对数据所进行操作的描述,即指定的操作步骤和方法。
* 软件:值程序、程序运行所需要的数据以及开发、使用和维护这些程序所需要的文档的集合。
## 信息的存储与标识
##### 计算机的数字系统
* r称为该数制的基数数制中每个位置对应的单位称为位权。
* 常用的有二进制八进制十进制是,就禁止。
##### 进位计数制的转换
* 进制转换十进制转换r进制除r取余法和乘r取整法。r进制转换十进制基数乘位权相加。二进制、八进制、十六进制的相互转换。直接使用位数对应。
##### 数值数据的表示
* 整数的原码:
* 整数的反码:
* 整数的补码:
* 浮点数的表示32位s-一位符号位。e-八位指数位。f-二十三位小数位。
##### 非数值数据的表示
* ASCII码7位二进制编码。
* 汉字字符及其他双字节编码的字符集。
* 多媒体信息。
## 程序设计语言
* 机器语言二进制0和1按照一定规则组成的能被计算机直接理解和执行的指令集合。难写难记难阅读不同硬件机器指令不同通用性差。机器语言程序占用存储空间少运行速度快。
* 汇编语言
* 高级语言-编译:编译器程序把高级语言编写的源程序翻译成机器指令的目标代码。目标代码和源程序在功能上完全邓建。通过连接器程序将目标程序和相关的库连接成一个完成的可执行的程序。
* 高级语言-解释:解释器程序将高级语言编写的源程序主句进行分析,解释一句执行一句。移植到不同平台是不用修改代码,只要有合适的解释器就能运行。
## 程序设计概述
##### 基本特点
* 确定数学模型和数据结构
* 算法分析和描述
* 编写程序
* 程序测试
##### 算法的定义与特性
* 有穷性
* 确定性
* 有效性
* 算法可以有零个、一个或多个输入
* 算法可以有一个或多个输出。
##### 算法的表示
* 自然语言
* 流程图,顺序结构、选择结构和循环结构。
* N-S图表示
* 伪代码
* UML
##### 结构化程序设计
* 以模块功能和处理过程设计为主的详细设计的基本原则。
##### 面向对象的程序设计
* 类和对象
* 封装与信息隐藏。
* 抽象
* 继承与重用
* 多态性
* 消息传送与处理
## C++的基本词法
* 字符集:字母、数字、符号、空白符
* 三元符
* 关键字
* 标识符
*

View File

@@ -0,0 +1,118 @@
## 进位计数
### 数制
* ##### 2进制
* ##### 8进制
* ##### 10进制
* ##### 16进制
### 数制转化
* ##### r进制数转化成十进制
$$
I = a_{n-1}\times r^{n-1} + \cdots + a_0 \times r^0
$$
* ##### 十进制整数转化r进制数——除r取余法
$$
\frac Ir=\frac{a_{n-1}\times r^{n-1}+ \cdots + a_0 \times r^0}{r} + \frac {a_0 \times r^0}{r}
$$
* ##### 十进制小数转化r进制数——乘r取整法
$$
f = a_{-1} \times r^{-1} + a_{-(m-1)} \times r^{-(m-1)} + a_{-m} \times r^{-(m-1)}
$$
> 为什么十进制相对其他进制来说特殊,因为我们在计算的时候,加减乘除,全部都使用十进制的法则,所以十进制计算表达起来更简单。
## 数值编码
### 原码
$$
(X)_y=
\left\{
\begin{array}{lr}
X & 0 \leq X < 2^{n-1}\\
2^{n-1} + |X| & -2^{n-1} < X \leq 0
\end{array}
\right.
$$
### 反码
$$
(X)_f=
\left\{
\begin{array}{lr}
X & 0 \leq X < 2^{n-1}\\
2^{n}-1 - |X| & -2^{n-1} < X \leq 0
\end{array}
\right.
$$
**关系说明:** 对于正数,反码等于补码;对于负数,反码数值位等于原码数值位按位取反。
### 补码
$$
(X)_b=
\left\{
\begin{array}{lr}
X & 0 \leq X < 2^{n-1}\\
2^{n} - |X| & -2^{n-1} < X \leq 0
\end{array}
\right.
$$
**关系说明:** 为了满足数值计算,使得正数负数能够在同一的编码下进行加减计算。正数的机器数,原码,反码,补码,都是在固定字长下讨论的
### 浮点数
规格化数:
$$
eq = (-1)^s \times 2^E \times 1.f
$$
s-1位符号位E-8位指数位f-23位小数位。提供了24位的小数二进制小数的精度-126~127的指数次二进制范围。
## 字符编码
### 西文字符
ASCII 使用7位而金子编码0~127等128个字符
### 汉字字符
包括输入码、字形码、国标码、机内码
> 汉字机内码 = 汉字国标码 + 8080H = 区位码 + A0A0H
## 程序语言
### 机器语言(指令)
### 汇编语言
### 高级语言
##### 编译
用编译器把高级语言编写的源程序翻译成机器指令表示的目标代码。通过连接器程序将目标程序于相关库连接成一个完整的可执行程序。有点:速度快,脱离源程序运行。
##### 解释
用解释器程序将高级语言编写的源程序进行分析翻译,解释一句,执行一句。优点:跨平台,移植性高。
## 程序设计概述
### 步骤
1. ##### 确定数学模型和数据结构
2. ##### 算法分析和描述
3. ##### 编写程序
4. ##### 程序测试
### 算法
##### 定义
算法是为了求解问题而采取的,按照一定次序进行的操作步骤。
##### 特性
又穷性、确定性、有效性、另个或多个输入、一个或多个输出。
##### 表示方法
* 自然语言
* 流程图
* N-S图
* 伪代码
* UML图

432
Git/git.md Normal file
View File

@@ -0,0 +1,432 @@
Git的本地操作
> 参考文献
> * [git使用教程](https://github.com/geeeeeeeeek/git-recipes/wiki)
一个非常详细的中文版git使用详解
本地操作主要是指在同一个仓库中实现版本控制,包括版本的提交、回退等基本擦偶作。
**git安装**
- Linux上通过命令行能够很轻松的部署好git
- Windows上需要安装GitBash模拟linux命令行
- 安装完成后需要配置全局信息的命令
\$ git config --global user.name "Your Name"
\$ git config --global user.email "email@example.com"
创建版本库
- git init
生成.git文件将这个目录初始化为一个版本的仓库。
- git add readme.txt
将文件添加到缓冲区,可以连续多次向缓冲区中添加东西
- git commit -m "wrote a message"
将缓冲区的文件提交到历史记录当中当中,可以一次提交对缓冲区的多次修改。
**时光穿梭机**
- it status
用来查看当前仓库的状态。主要有changes not staged for
commit状态工作区有变化没有提交chages to be
committed状态缓存区有变化等待提价
- git diff readme.txt
用来对比工作区和历史记录内容的差别。
**版本回退**
- git log
用来查看版本的历史记录
- git log --pretty=oneline
在一行显示历史记录
- git reset --hard HEAD\^
回退到上一次的历史记录
- git reset --hard id
回退到指定id的版本
- git reflog
用来查看所有操作的历史记录可以使用reset命令去定位到任何版本
**工作区和暂存区概念理解**
- 工作区Wording Directory在电脑中能够看到的目录是工作区
- 版本库Repository工作区有一个隐藏的目录.git是版本库
- 版本库中有Stage暂存区和master等分支以及一个纸箱master的指针HEAD
**管理修改**
- git跟踪管理的是对文件的修改而并非文件本身
**撤销修改**
- git checkout --readme.txt
把readme.txt在工作区的修改全部撤销掉。如果缓存区有readme.txt的中间状态则从缓存区恢复如果缓存区没有readme.txt的中间状态则从版本库中恢复。
- git reset HEAD readme.txt
把readmen.txt在缓存区的修改全部撤销掉。但是依然会保留工作区的修改。
**删除文件**
- git rm test.txt
把某个文件从缓存区删掉然后commit之后会从版本库删掉。如果删错了可以通过checkout从缓存区恢复这个文件。
Git的远程操作
远程操作主要是指在不同的仓库之间进行提交和代码更改。是一个明显的对等的分布式系统。其中本地个仓库与远程仓库不同的远程仓库之间都可以建立这种关系。这种关系之间的操作主要有pull和push。
**远程仓库**
- 创建SSH key远程仓库和本地仓库一般是通过ssh通信的需要ssh通信的加密钥匙。
id_rsa是私钥id_rsa.pub是公钥可以告诉别人。
ssh-keygen -t rsa -C 'yinkanglong@163.com'
- 登录github添加公钥内容。建立本地与远程仓库的通信协议
**添加远程仓库**
- github的界面操作可以很轻松的创建一个远程仓库。但如果想要直接上传自己本地的完整git库必须创建一个没有lisence和readme的空库。
- git remote add origin git@github.com:michaelliao/learngit.git
将本地仓库和远程仓库进行关联。一般都叫远程关联仓库为origin本地的主干分支一般名为master
- git push -u origin master
将本地的主干分支master推送到远程的origin分支上。-u参数实现了两个分支的关联将远程的git仓库的master和本地的master进行了分支管理当再次执行时只需要使用git
push origin master命令。
**从远程仓库克隆**
- git clone git@github.com:michaelliao/gitskills.git
分支管理
这里主要体现的git的功能的分离这才是真正的git吧。每一个分支都是一个单独的可以分离的工作单位。每个用户可以建立不同的分支进行工作最终提交到同一个开发分支上。一个用户可以建立不同的分支实现不同的功能最终提交到同一个用户分支上。分支的灵活性可以让我们很容易的实现不同分工的分割。
**创建分支**
- git checkout -b dev
创建分支并且将工作目录切换到dev的工作目录上。
- git branch dev
使用当前版本分支创建新的分支(即添加一个分支指针)。
- git checkout dev
将工作区切换到某一个分支指针所指的版本上。
- git branch
会列出所有的分支目录。
**分支合并**
- git merge dev
将dev分支合并到当前工作目录下的分支上不一定是产生他的父分支
- git branch -d dev
用来删除一个已经无效的分支指正,但是在这个分支指针上左右的操作都会保留。
**解决冲突**
- 当合并过程中出现冲突,会进入长途解决工作区,手动解决后提交,就会退出。
- 关于一点,提交后的分支有必要继续工作吗,都行。完全可以提交后删掉重新创建一个分支,获取主干分支上集成的最新内容,然后继续工作。也可以直接在分支上合并一次主干分支,然后得到最新的内容,继续在原来的分支上进行工作。
- git log --graph
可以查看分支合并图。
**分支合并方式**
- git merge --no-ff -m "merge messge" dev
\--no-ff
不适用fastfoward方式进行合并会产生一个新的版本节点。加上-m参数是因为这种方式合并过程中会自己提交合并后的版本。
**分支管理**
- 团队合作的分支管理组图就是你们要的方式
![clipboard.png](media/202749bd52950c0c839d73190cd2fd9d.png)
**BUG分支**
- 因为总会在自己工作的过程中出现紧急的需要更改的bug但是现在工作区中的内容还不能提交所以必须生成现在工作区的一个快照等处理完紧急的bug之后再来回复工作区的内容。
- git stash
将当前的工作现场储存起来等到修复完成bug之后可以再次进行更改。工作现场包括工作区和stage缓存区。然后可以清空工作区和缓存区的内容新建bug分支进行工作。
- git stash list
用来查看保存中的工作区。
- git stash apply stash@{0}
恢复stash内容但并不清楚stash列表中的内容。
- get stash drop
用来删除stash列表中的内容。因为已经恢复或者没有必要恢复
- git stash pop
可以用来弹出stash列表中的内容。
**Feature分支**
- 当添加一个新的功能的时候,因为是一些实验性的代码,所以要创建一个单独的分支进行处理。
- git checkout -b feature-vulcan
创建一个新的功能分支
git status
git add vulcan.py
git commit -m "add feature vulcan"
git checkout dev
git merge vulcan.py
git branch -D feature-vulcan 不合并,强制删除
多人协作
通过远程库的push和pull操作实现夺人合作
**推送分支或分支内容**
- 当从远程库进行克隆的时候实际上已经将本地master分支和远程的master分支进行乐关联。
- git remote [-v]
可以显示与远程库关联的信息
- git push origin master
推送分支,吧分支上的所有本地内容提交到远程库中的相同分支当中。
- 哪些分支需要推送
mater分支是主分支需要实时推送
dev是开发分支所有成员都要在上面工作。也需要与远程同步。
bug分支只需要在本地修复bug没有必要推送到远程。
feature分支可以不用推送到远程。单人开发不用夺人开发要推送到远程。
**抓取分支或者分支的内容**
- git checkout -b dev origin/dev
可以用来抓取远程分支dev这样会建立一个本地的本地的dev分支与远程的dev分支进行关联可以直接实现dev分支的控制push
- git pull \<remote\> \<branch\>
如果Git push失败说明当前的版本不是最新的版本。git pull
可以将远程库中的最新版本拉去到本地。
- git branch --set-upstream dev origin/\<branch\>
这样会制定git的本地分支与远程的分支之间的链接。
- 如果git pull有冲突与分支合并中解决冲突的方法一直。
**多人协作的协作模式通常是这样:**
> 1\. 首先可以试图⽤git push origin branch-name推送自己的修改
> 2\. 如果推送失败则因为远程分支比你的本地更新需要先用git pull试图合并
> 3\. 如果合并有冲突,则解决冲突,并在本地提交;
> 4\. 没有冲突或者解决掉冲突后再用git push origin branch-name推送就能成功
> 5\. 如果git pull提“no tracking
> information”则说明本地分支和远程分支的链接关系没有创建用命令git branch
> \--set-upstream branch-name origin/branch-name。
标签管理
**创建标签**
- git tag v1.0
对当前版本打标签为v1.0
- git tag
查看所有已经创建的标签
- git tag v0.9 6.225
对指定id的版本打标签
- git show v0.9
查看标签信息
- git tag -a v0.1 -m "version 0.1 released" 3628164
创建带有标签说明的标签
**操作标签**
- git tag -d v0.1
删除制定版本的标签
- git push origin v1.0
推送某个标签到远程
- git push origin --tags
一次性推送所有标签。
- git tag -d v0.9
git push origin :refs/tags/v0.9
从远程删除标签,先在本地删除标签,然后将操作推送到远程。
使用github
https://www.bilibili.com/video/av10475153/index_2.html\#page=5
这是一个比较啰嗦的讲解github页面的东西学号英文真的十分重要。
**git的简介**
Create Repository
创建仓库
Star
收藏
Fork
复制一份远程仓库
Pull Request
拉我呀,快点,我改好了。
Open & Merge Request
拉你了,别墨迹。
Watch
看着你呢,关注一个项目。
Github主页
仓库主页——仓库相关的信息和相关操作
个人主页
这是一些补充的内容
保持同步
**git remote**
- git remote
列出你和远程仓库之间的远程连接
- git remote -v
列出每个连接的名字和url
- git remote add \<name\> \<url\>
创建一个新的远程连接并添加名字
- git remote rm \<name\>
移除远程仓库的链接
git fetch
- git fetch \<remote\>
拉取仓库中的所有分支(包括相关的文件和所有的提交)
- git fetch \<remote\> \<branch\>
拉取制定仓库中的所有分支(包括相关的文件和所欲的提交)
\>
注意,这个步骤知识拉取远程的分支,在本地并没有合并也没有生成本地分支,知识一个可读的远程分支。使用
git branch -r 命令可以查看所有只读的远程分支。使用git
checkout命令可以创建本地分支并与远程分支关联。使用git merge
命令可以将远程分支与本地分支合并。
git pull
- git pull remote
拉取当前分支对应的远程副本并将远程副本的更改写入本地副本。相当于git
fetch之后git merge。
- git pull -rebase \<remote\>
使用git rebase命令合并远程分支与本地分支不使用git merge
git push
- git push \<remote\> \<branch\>
将制定分支推送到远程分支。包括所有的文件和提交。
- git push \<remote\> --force
强制推送
- git push \<remote\> --all
本地所有的分支推送到远程仓库当中
- git push \<remote\> --tags
将本地所有标签推送到远程仓库中

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -0,0 +1,56 @@
果然就语言中的语法来说最基础的两部分超级难的两部分也就是字符串操作和输入输出流的操作。到现在都不知道java各个流的嵌套顺序以及每个流的封装实现的具体方法。Python字符串操作能够支持运算符和强大的通配符匹配感觉相对简单java也还好但是这个C真的烦各种函数……得花点时间来重新学一下C语言的流操作和字符串操作了。
1字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串
strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度字符串 strlen(p)
取字符串长度 strcmp(p, p1) 比较字符串 strcasecmp忽略大小写比较字符串 strncmp(p,
p1, n) 比较指定长度字符串 strchr(p, c) 在字符串中查找指定字符 strrchr(p, c)
在字符串中反向查找 strstr(p, p1) 查找字符串 strpbrk(p, p1)
以目标字符串的所有字符作为集合,在当前字符串查找该集合的任一元素 strspn(p, p1)
以目标字符串的所有字符作为集合,在当前字符串查找不属于该集合的任一元素的偏移
strcspn(p, p1)
以目标字符串的所有字符作为集合,在当前字符串查找属于该集合的任一元素的偏移\*
具有指定长度的字符串处理函数在已处理的字符串之后填补零结尾符
2字符串到数值类型的转换 strtod(p, ppend) 从字符串 p 中转换 double
类型数值,并将后续的字符串指针存储到 ppend 指向的 char\* 类型存储。 strtol(p,
ppend, base) 从字符串 p 中转换 long 类型整型数值base
显式设置转换的整型进制,设置为 0 以根据特定格式判断所用进制0x, 0X
前缀以解释为十六进制格式整型0 前缀以解释为八进制格式整型 atoi(p) 字符串转换到
int 整型 atof(p) 字符串转换到 double 符点数 atol(p) 字符串转换到 long 整型
3字符检查 isalpha() 检查是否为字母字符 isupper() 检查是否为大写字母字符
islower() 检查是否为小写字母字符 isdigit() 检查是否为数字 isxdigit()
检查是否为十六进制数字表示的有效字符 isspace() 检查是否为空格类型字符 iscntrl()
检查是否为控制字符 ispunct() 检查是否为标点符号 isalnum() 检查是否为字母和数字
isprint() 检查是否是可打印字符 isgraph() 检查是否是图形字符,等效于 isalnum() \|
ispunct()
char \*strset(char \*string, int c); 将string串的所有字符设置为字符c,
遇到NULL结束符停止. 函数返回内容调整后的string指针. char \*strnset(char
\*string, int c, size_t count); 将string串开始count个字符设置为字符c,
如果count值大于string串的长度, 将用string的长度替换count值.
函数返回内容调整后的string指针. size_t strspn(const char \*string, const char
\*strCharSet); 查找任何一个不包含在strCharSet串中的字符 (字符串结束符NULL除外)
在string串中首次出现的位置序号. 返回一个整数值,
指定在string中全部由characters中的字符组成的子串的长度.
如果string以一个不包含在strCharSet中的字符开头, 函数将返回0值. size_t
strcspn(const char \*string, const char \*strCharSet);
查找strCharSet串中任何一个字符在string串中首次出现的位置序号,
包含字符串结束符NULL. 返回一个整数值,
指定在string中全部由非characters中的字符组成的子串的长度.
如果string以一个包含在strCharSet中的字符开头, 函数将返回0值.char \*strspnp(const
char \*string, const char \*strCharSet);
查找任何一个不包含在strCharSet串中的字符 (字符串结束符NULL除外)
在string串中首次出现的位置指针. 返回一个指针,
指向非strCharSet中的字符在string中首次出现的位置.char \*strpbrk(const char
\*string, const char \*strCharSet);
查找strCharSet串中任何一个字符在string串中首次出现的位置,
不包含字符串结束符NULL. 返回一个指针,
指向strCharSet中任一字符在string中首次出现的位置.
如果两个字符串参数不含相同字符, 则返回NULL值.
函数名: strcmpi
功 能: 将一个串与另一个比较, 不管大小写
用 法: int strcmpi(char \*str1, char \*str2);

View File

@@ -0,0 +1,36 @@
**基础转化方式**
atoi(p) 字符串转换到 int 整型 atof(p) 字符串转换到 double 符点数 atol(p)
字符串转换到 long 整型
itoa()将整型值转换为字符串
ftoa()将浮点型转化为字符串
ultoa()将无符号长整型值转换为字符串
**字符串操作方式**
strtod(p, ppend) 从字符串 p 中转换 double 类型数值,并将后续的字符串指针存储到
ppend 指向的 char\* 类型存储。 strtol(p, ppend, base) 从字符串 p 中转换 long
类型整型数值base 显式设置转换的整型进制,设置为 0
以根据特定格式判断所用进制0x, 0X 前缀以解释为十六进制格式整型0
前缀以解释为八进制格式整型
char \*ecvt(double value,int ndigIT,int \*dec,int \*sign)
ecvt() 将双精度浮点型值转换为字符串,转换结果中不包含十进制小数点
char \*fcvt(double value,int ndigIT,int \*dec,int \*sign)
fcvt() 以指定位数为转换精度余同ecvt()
char \* gcvt(double value,int ndec,char \*buf)
gcvt() 将双精度浮点型值转换为字符串,转换结果中包含十进制小数点
**流转化方式**
sprintf(ctime, "%d:%d:%d", H, M, S); // 将整数转换成字符串ctime
sscanf( str, "%f", &fp ); // 将字符串转换成浮点数 fp = 15.455000

View File

@@ -0,0 +1,23 @@
MFC 是一个框架。
它封装了主要的win32 接口。win32 接口以函数为主。
MFC Microsoft Foundation Class
Libraray是一个面向对象的以类为主的框架。将库中各种类结合起来构成了一个应用程序框架。是一种对windows
SDK的封装。MFC框架定义了应用程序的轮廓。他是C++的类库。
MFC中的封装
用一个C++ 对象封装Windows 对象。class CWnd是一个C++ window object它把Windows
window(HWND)和Windows window有关的API函数封装在C++ window
object的成员函数内后者的成员变量m_hWnd就是前者的窗口句柄。
用C++的方式,重新定义相关的类。
MFC中继承
MFC抽象出众多类的共同特性设计出一些基类作为实现其他类的基础。这些类中最重要的类是CObject和CCmdTarget。CObject是MFC的根类绝大多数MFC类是其派生的
包括CCmdTarget。CObject
实现了一些重要的特性包括动态类信息、动态创建、对象序列化、对程序调试的支持等等。所有从CObject派生的类都将具备或者可以具备CObject所拥有的特性。CCmdTarget通过封装一些属性和方法提供了消息处理的架构。MFC中任何可以处理消息的类都从CCmdTarget派生。
针对每种不同的对象MFC都设计了一组类对这些对象进行封装每一组类都有一个基类从基类派生出众多更具体的类。这些对象包括以下种类窗口对象基类是CWnd应用程序对象基类是CwinThread文档对象基类是Cdocument等等。

View File

@@ -0,0 +1,592 @@
第二节第一个窗口程序
**创建窗口程序**
主函数为WinMain函数
int APIENTRY WinMain(HINSTANCE hInstance, // 本模块的实例句柄
> HINSTANCE hPrevInstance, // Win16 留下的废物,现在已经不用了
> LPSTR lpCmdLine, // 命令行参数
> int nCmdShow) // 主窗口初始化时的显示方式
> { // 下面这行代码是我添加的,用于弹出一个小对话框
> ::MessageBox(NULL, "Hello, Win32 Application", "04Win32AppDemo", MB_OK);
> return 0;
> }
弹出窗口MessageBox函数
int MessageBox(
> HWND hWnd, // 一个窗口句柄,它指定了哪一个窗口将拥有要创建的消息框
> LPCTSTR lpText, // 将要显示的消息
> LPCTSTR lpCaption, // 对话框的标题
> UINT uType // 指定对话框的内容和行为
> );
uType的取值
1为了指定希望在消息框中显示的按钮要指定下组中的一个值
| MB\_OK | 消息框包含一个按钮:确定。这是默认按钮。 |
|---------------------|------------------------------------------|
| MB_OKCANCEL | 消息框包含两个按钮:确定和取消 |
| MB_ABORTRETRYIGNORE | 消息框包含 3 个按钮:终止、重试和忽略 |
| MB_YESNOCANCEL | 消息框包含 3 个按钮:是、否和取消 |
| MB_YESNO | 消息框包含两个按钮:是和否 |
| MB_RETRYCANCEL | 消息框包含两个按钮:重试和取消 |
2为了在对话框中显示一个图标要指定下组中的一个值
MB_ICONHAND 一个停止标志图标:
MB_ICONQUESTION 一个询问标志图标:
MB_ICONEXCLAMATION 一个感叹号图标:
3为了指示默认的选中按钮要指定下组中的一个值
MB_DEFBUTTON1 第一个按钮是选中按钮
MB_DEFBUTTON2 第二个按钮是选中按钮
MB_DEFBUTTON3 第三个按钮是选中按钮
MB_DEFBUTTON4 第四个按钮是选中按钮
**窗口应用程序实例**
// 窗口函数的函数原形
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
> HINSTANCE hPrevInstance,
> LPSTR lpCmdLine,
> int nCmdShow)
{ char szClassName[] = "MainWClass";
> WNDCLASSEX wndclass;
> // 用描述主窗口的参数填充 WNDCLASSEX 结构
> wndclass.cbSize = sizeof(wndclass); // 结构的大小
> wndclass.style = CS_HREDRAW\|CS_VREDRAW; // 指定如果大小改变就重画
> wndclass.lpfnWndProc = MainWndProc; // 窗口函数指针
> wndclass.cbClsExtra = 0; // 没有额外的类内存
> wndclass.cbWndExtra = 0; // 没有额外的窗口内存
> wndclass.hInstance = hInstance; // 实例句柄
> wndclass.hIcon = ::LoadIcon(NULL, IDI_APPLICATION); // 使用预定义图标
> wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW); // 使用预定义的光标
> wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); //
> 使用白色背景画刷
> wndclass.lpszMenuName = NULL; // 不指定菜单
> wndclass.lpszClassName = szClassName ; // 窗口类的名称
> wndclass.hIconSm = NULL; // 没有类的小图标
> // 注册这个窗口类
> ::RegisterClassEx(&wndclass);
> // 创建主窗口
> HWND hwnd = ::CreateWindowEx(
> 0, // dwExStyle扩展样式
> szClassName, // lpClassName类名
> "My first Window!", // lpWindowName标题
> WS_OVERLAPPEDWINDOW, // dwStyle窗口风格
> CW_USEDEFAULT, // X初始 X 坐标
> CW_USEDEFAULT, // Y初始 Y 坐标
> CW_USEDEFAULT, // nWidth宽度
> CW_USEDEFAULT, // nHeight高度
> NULL, // hWndParent父窗口句柄
> NULL, // hMenu菜单句柄
> hInstance, // hlnstance程序实例句柄
> NULL) ; // lpParam用户数据
> if(hwnd == NULL)
> { ::MessageBox(NULL, "创建窗口出错! ", "error", MB_OK);
> return -1;
}
> // 显示窗口,刷新窗口客户区
> ::ShowWindow(hwnd, nCmdShow);
> ::UpdateWindow(hwnd);
> // 从消息队列中取出消息,交给窗口函数处理,直到 GetMessage 返回
> FALSE结束消息循环
> MSG msg;
> while(::GetMessage(&msg, NULL, 0, 0))
> { // 转化键盘消息
> ::TranslateMessage(&msg);
> // 将消息发送到相应的窗口函数
> ::DispatchMessage(&msg);
> }
> // 当 GetMessage 返回 FALSE 时程序结束
> return msg.wParam;
}
LRESULT CALLBACK MainWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{ char szText[] = "最简单的窗口程序! ";
> switch (message)
> {
> case WM_PAINT: // 窗口客户区需要重画
> { HDC hdc;
> PAINTSTRUCT ps;
> // 使无效的客户区变的有效,并取得设备环境句柄
> hdc = ::BeginPaint (hwnd, &ps) ;
> // 显示文字
> ::TextOut(hdc, 10, 10, szText, strlen(szText));
> ::EndPaint(hwnd, &ps);
> return 0;
> }
> case WM_DESTROY: // 正在销毁窗口
> // 向消息队列投递一个 WM_QUIT 消息,促使 GetMessage 函数返回 0结束消息循环
> ::PostQuitMessage(0) ;
> return 0 ;
}
// 将我们不处理的消息交给系统做默认处理
return ::DefWindowProc(hwnd, message, wParam, lParam);
}
**创建窗体的步骤说明:**
注册窗口类 RegisterClassEx
创建窗口 CreateWindowEx
在桌面显示窗口 ShowWindow
更新窗口客户区 UpdateWindow发送了WM_PAINDT 消息更新他的客户区
进入无线的消息获取消息转化键盘消息将消息转发给消息处理函数GetMessage
\-\>TranslateMessage-\> DispatchMessage
**注册窗口结构体说明**
typedef struct \_WNDCLASSEX {
> UINT cbSize; // WNDCLASSEX 结构的大小
> UINT style; // 从这个窗口类派生的窗口具有的风格,有多种风格
> WNDPROC lpfnWndProc; // 即 window procedure, 窗口消息处理函数指针
> int cbClsExtra; // 指定紧跟在窗口类结构后的附加字节数
> int cbWndExtra; // 指定紧跟在窗口事例后的附加字节数
> HANDLE hInstance; // 本模块的实例句柄
> HICON hIcon; // 窗口左上角图标的句柄
> HCURSOR hCursor; // 光标的句柄
> HBRUSH hbrBackground; // 背景画刷的句柄
> LPCTSTR lpszMenuName; // 菜单名
> LPCTSTR lpszClassName; // 该窗口类的名称
> HICON hIconSm; // 小图标句柄
} WNDCLASSEX;
**消息结构体说明**
typedef struct tagMSG {
> HWND hwnd; // 消息要发向的窗口句柄
> UINT message; // 消息标识符,以 WM\_ 开头的预定义值(意为 Window Message
> WPARAM wParam; // 消息的参数之一
> LPARAM lParam; // 消息的参数之二
> DWORD time; // 消息放入消息队列的时间
> POINT pt; // 这是一个 POINT 数据结构,表示消息放入消息队列时的鼠标位置
} MSG, \*PMSG ;
第二节一个简陋的打字程序
**使用资源**
.rc
资源文件的源文件的脚本。由资源编译器RC.exe编译成res为扩展名的二进制文件。在链接的时候由Link.exe链入到可执行文件中。
resource.h
资源文件的生命文件。给资源一个ID好通过资源的ID进行访问。一般通过资源管理器添加资源直接生成相应的资源文件的脚本文件和声明文件。
**菜单和图标**
可以直接插入菜单资源。
动态设置菜单的方式:
HMENU hMenu = ::LoadMenu(::GetModuleHandle(NULL),(LPCTSTR)IDR_TYPER);
::SetMenu(hwnd,hMenu)
通过这种方式能够动态改变主窗体的菜单栏。
点击菜单之后会接收到**WM_COMMAND消息**使用LOWORD宏从wparam参数中能够取出某个菜单的对应ID。单击后会通过SendMessage函数向窗口发送消息。
> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
> lParam)
> {
> int wmId, wmEvent;
> PAINTSTRUCT ps;
> HDC hdc;
> char szText[] = "最简单的窗口应用程序哈哈哈";
> switch (message)
> {
> case WM_COMMAND:
> wmId = LOWORD(wParam);
> wmEvent = HIWORD(wParam);
> // 分析菜单选择:
> switch (wmId)
> {
> case IDM_ABOUT:
> DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
> break;
> case IDM_EXIT:
> DestroyWindow(hWnd);
> break;
> default:
> return DefWindowProc(hWnd, message, wParam, lParam);
> }
> break;
> case WM_PAINT:
> //DefWindowProc会进行默认处理
> hdc = BeginPaint(hWnd, &ps);
> // TODO: 在此添加任意绘图代码...
> ::TextOut(hdc, 10, 10,szText,strlen(szText));
> EndPaint(hWnd, &ps);
> break;
> case WM_DESTROY:
> PostQuitMessage(0);
> break;
> default:
> return DefWindowProc(hWnd, message, wParam, lParam);
> }
> return 0;
> }
发送消息的方式:
SendMessage函数发送消息并阻塞源程序
PostMessage函数发送消息后立即返回
设置图标
wndclass.hIcon = ::LoadIcon(hInstance, (LPSTR)IDI_TYPER); // 使用自定义图标
**接受键盘的输入**
当一个 WM_KEYDOWN 消息被 TranslateMessage 函数转化以后会有一个 WM_CHAR 消
息产生,此消息的 wParam 参数包含了按键的 ANSI 码。例如,用户敲击一次“A”键,窗口
会顺序地收到以下 3 个消息。
| WM\_KEYDOWN | lParam 的含义为虚拟键码“A” (0x41) |
|-------------|-----------------------------------|
| WM_CHAR | lParam 的含义为 ANSI 码“a” (0x61) |
| WM_KEYUP | lParam 的含义为虚拟键码“A” (0x41) |
**接受鼠标输入**
> 应用程序以接收发送或者投递到它的窗口的消息的形式接收鼠标输入。当用户移动鼠标,
> 或按下、释放鼠标的一个键时,鼠标会产生输入事件。系统将鼠标输入事件转化成消息,投递
> 它们到相应线程的消息队列。和处理键盘输入一样, Windows
> 将捕捉鼠标动作,并把它们发
> 送到相关窗口。
> 当用户移动光标到窗口的客户区时,系统投递 WM_MOUSEMOVE 消息到这个窗口。当
> 用户在客户区按下或者释放鼠标的键时,它投递下面的消息:
> 按下 弹起 双击
> 左键 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK
> 中键 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK
> 右键 WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK
> 发送这些消息时, lParam 参数包含了鼠标的位置坐标,可以这样读出坐标信息。
> xPos = LOWORD (lParam);
> yPos = HIWORD (lParam)
实现坐标转化的函数
> 这些坐标都以客户区的左上角为原点,向右是 x 轴正方向,向下是 y 轴正方向。
> ClientToScreen 函数可以把坐标转化为以屏幕的左上角为原点的坐标。
> BOOL ClientToScreen(HWND hWnd, LPPOINT lpPoint) ;
> BOOL ScreenToClient(HWND hWnd, LPPOINT lpPoint );
wParam 参数包含鼠标按钮的状态,这些状态都以 MK\_意为 mouse key为前缀取值
如下:
| MK_LBUTTON | 左键按下 |
|-------------|-----------------|
| MK_MBUTTON | 中间的键按下 |
| MK_RBUTTON | 右键按下 |
| MK_SHIFT | \<Shift\>键按下 |
| MK_CONTROL | \<Ctrl\>键按下 |
**设置文本和背景**
> 设置背景色为:
> wcex.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
设置文本色
::SetTextColor(hdc, RGB(255, 0, 0));
::SetBkColor(hdc, ::GetSysColor(COLOR_3DFACE));
第四节GDI基本图形
**设备环境**
理解一下几个含义:
应用实例HINSTANCE表示整个应用实例
主窗体hwnd表示应用实例的主窗体是一个窗体不是应用实例
窗口客户区:主窗体客户区指的是窗体中菜单下边的内容,客户区,主要县市区
窗口客户区设备环境句柄HDC绘图的句柄可以是主窗体的设备环境也可以是主窗体客户区的设备环境的句柄。
**文本区域绘制**
case WM_LBUTTONDOWN:
> hdc = ::GetDC(hWnd);
> // 设置 DC 结构中的文本颜色为红色(下一小节我们再介绍 Windows 下的颜色)
> ::SetTextColor(hdc, RGB(255, 0, 0));
> // 设置 DC 结构中的文本背景颜色为蓝色
> ::SetBkColor(hdc, RGB(0, 0, 255));
> ::TextOut(hdc, 10, 10, sz, strlen(sz));
> ::ReleaseDC(hWnd, hdc);
> break;
在注册窗口类时,向 WNDCLASSEX结构的 style 成员添加一个 CS_OWNDC
标志,可以保存每次修改的内容。如果不设置的话,每次刷新窗口又会变为默认的设置,而不是左键点击后的设置。
wcex.style = CS_HREDRAW \| CS_VREDRAW \| CS_OWNDC;
**颜色和像素点**
**RGB**颜色RGB255255255
像素点颜色设置
> COLORREF SetPixel(
> HDC hdc, // 设备环境句柄
> int X, // 象素的 X 坐标
> int Y, // 象素的 Y 坐标
> COLORREF crColor // 要设置的 COLORREF 值
> );
> 像素点颜色获取
> COLORREF GetPixel( HDC hdc, int nXPos, int nYPos);
**绘制线条**
LineTo函数绘制直线。MoveToEx可以设置当前点。
::MoveToEx(hDC, 0, 0, NULL);
::LineTo(hDC, 0, 500);
BOOL MoveToEx(
> HDC hdc, // 设备环境句柄
> int X, // 新位置的 X 坐标
> int Y, // 新位置的 Y 坐标
> LPPOINT lpPoint //
> 用来返回原来的当前点位置,如果不需要的话,这个参数可以被设为 NULL)
使用GetClientRect函数获取窗口客户区的大小。
使用Polyline函数绘制相连的多条线段。
> BOOL Polyline(HDC hdc, CONST POINT \*lpPoint, int cPoints);
> BOOL PolylineTo(HDC hdc, CONST POINT \*lpPoint, DWORD cPoints );
> lpPoint是指向POINT的数组的指针。
**绘制区域**
Rectangle(hdc, x1, y1, x2, y2); // 画以x1, y1x2,
y2为对角坐标的填充矩形
> Ellipse(hdc, x1, y1, x2, y2); // 以x1, y1x2,
> y2为对角坐标定义一个矩形然后画矩形相切的椭
> // 圆并填充
> Polygon(hdc, lpPoint, 5) // lpPoint 指向存放x0, y0x4,
> y4的内存函数从x1, y1x2, y2...
> // 到x4, y4再回到x1, y1一共画 5 条直线并填充
**坐标系统**
**实例:小时钟**
几个缩写的含义说明
WND window
WS window style
CS class style
WM window message

View File

@@ -0,0 +1,21 @@
**两种访问模式**
Windows使用了内核模式和用户模式两种访问权限来控制对内存的访问。每种资源都会标记相应的访问模式只有对应模式才能访问对应的资源。
系统地址空间页只能通过内核模式。所有的用户地址空间都可以从用户模式访问。
当应用程序调用一个系统函数时,用户的应用程序会从用户模式切换到内核模式去执行。
**内核对象**
内核对象是系统提供的用户模式下代码与内核模式下代码进行交互的基本接口。内核对象是一块内核分配的内存,只能在内核模式下的被访问。其资源为系统资源。内核对象的数据结构是隐蔽的,必须通过一个对象服务才能从对象中得到数据或向其中输入数据。
作用:为系统资源提供名字;在进程之间共享资源和数据;保护资源不会被未经认可的代码访问;跟踪对象的引用情况。
**对象句柄**
调用函数创建内核对象时,函数返回标识这个对象的句柄。来定位内核对象。
**使用计数**
内核对象是进程内的资源使用计数属性记录对特定内核对象的引用次数当系统发现引用次数是0时自动关闭资源。

View File

@@ -0,0 +1,188 @@
**线程创建**
DWORD WINAPI ThreadProc(LPVOID lpParam); // 线程函数名称 ThreadProc 可以是任意的
WINAPI
是一个宏明用来说明调用参数的进栈方式和出栈方式。Windows规定由内核函数负责调用的用户函数必须定义为这个类型。
线程创建函数
HANDLE CreateThread (
> LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性
> DWORD dwStackSize, // 指定线程堆栈的大小
> LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数的起始地址
> LPVOID lpParameter, // 传递给线程函数的参数
> DWORD dwCreationFlags, // 指定创线程建后是否立即启动
> DWORD\* lpThreadId // 用于取得内核给新生成的线程分配的线程 ID 号
> );
创建线程的具体示例
\#include \<stdio.h\>
> \#include \<windows.h\>
> // 线程函数
> DWORD WINAPI ThreadProc(LPVOID lpParam)
> { int i = 0;
> while(i \< 20)
> { printf(" I am from a thread, count = %d \\n", i++); }
> return 0;
> }
> int main(int argc, char\* argv[])
> { HANDLE hThread;
> DWORD dwThreadId;
> // 创建一个线程
> hThread = ::CreateThread (
> NULL, // 默认安全属性
> NULL, // 默认堆栈大小
> ThreadProc, // 线程入口地址(执行线程的函数)
> NULL, // 传给函数的参数
> 0, // 指定线程立即运行
> &dwThreadId); // 返回线程的 ID 号
> printf(" Now another thread has been created. ID = %d \\n", dwThreadId);
> // 等待新线程运行结束
> ::WaitForSingleObject (hThread, INFINITE);
> ::CloseHandle (hThread);
> return 0;
> }
WaitForSingleObject
函数用来等待制定对象变为受信状态。默认情况下为INFINITE但在指定对象变为受信状态时会自动结束
**线程内核对象**
与进程内核对象相似,都是存储对象的基本信息,用来管理线程、进程的对象。
![clipboard.png](media/71827cbcb84634eda0a5e339f5c8e351.png)
SuspendCount制定了当前线程的状态。0 表示处于可调度状态1表示处于挂起状态。
获取线程的句柄函数
> HANDLE OpenThread(
> DWORD dwDesiredAccess, // 想要的访问权限,可以为 THREAD_ALL_ACCESS 等
> BOOL bInheritHandle, // 指定此函数返回的句柄是否可以被子进程继承
> DWORD dwThreadId // 目标线程 ID 号
> );
> 唤醒一个挂起的线程
> DWORD ResumeThread (HANDLE hThread); // 唤醒一个挂起的线程
> 挂起一个可调度的线程
> DWORD SuspendThread (HANDLE hThread); // 挂起一个线程
ExitCode退出代码
DWORD dwExitCode;
> if(::GetExitCodeThread(hThread, &dwExitCode))
> { if(dwExitCode == STILL_ACTIVE)
> { // 目标线程还在运行 }
> else
> { // 目标线程已经中止,退出代码为 dwExitCode }
> }
Signaled是否受信。线程运行期间Signaled的值为False线程结束后Signaled的值为True
**线程终止**
- 线程执行结束自然终止
- 使用ExitTread函数来终止自身。
void ExitThread( DWORD dwExitCode); // 线程的退出代码
- 使用TerminateThread函数强行终止另一个线程
BOOL TerminateThread(
> HANDLE hThread, // 目标线程句柄
> DWORD dwExitCode // 目标线程的退出代码
> );
- 使用ExitProcess函数结束进程相关县城就会结束。
**线程的优先级**
**Windows**的6个优先级类idle、below normal、normal、above normal、
high、real-time。
CPU支持0-31优先级号数字越大优先级越高。
优先级设置函数
BOOL SetThreadPriority(HANDLE hThread,int nPriority );
线程同步
……
设计自己的线程局部存储
……
设计线程类
……
多线程文件搜索器
……
OHIUHI
**回调函数的定义**
> 回调函数就是一个通过函数指针调用的函数。如果你把函数的[指针](https://baike.baidu.com/item/%E6%8C%87%E9%92%88)(地址)作为[参数传递](https://baike.baidu.com/item/%E5%8F%82%E6%95%B0%E4%BC%A0%E9%80%92)给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
**::含义**
类作用域,类名::成员变量。用来表示类和他的成员变量
命名空间作用域,命名空间::变量或函数。命名空间中的成员
全局作用域,::变量。全局的变量或函数,好像可以省略。

View File

@@ -0,0 +1,382 @@
这一部分的学习还是要通过大量的代码阅读吧。在这里可以截取有用的代码并添加注释。
**进程定义**
正在运行的程序,拥有自己的虚拟地址空间拥有自己的代码、数据和其他资源。
组成:进程内核对象,操作系统使用内核对象来管理该进程。私有的虚拟地址空间。
**应用程序启动过程**
操作系统通过CreateProcess
函数来创建新的进程分配虚拟地址空间加载代码和数据然后创建一个主线程调用main函数。
CreateProcess(
> LPCSTR lpApplicationName, // 可执行文件的名称
> LPSTR lpCommandLine, // 指定了要传递给执行模块的参数。
> LPSECURITY_ATTRIBUTES lpProcessAttributes,// 进程安全性,值为 NULL
> 的话表示使用默认的安全属性
> LPSECURITY_ATTRIBUTES lpThreadAttributes,// 线程安全性,值为 NULL
> 的话表示使用默认的安全属性
> BOOL bInheritHandles, // 指定了当前进程中的可继承句柄是否可被新进程继承。
> DWORD dwCreationFlags, // 指定了新进程的优先级以及其他创建标志
> LPVOID lpEnvironment, // 指定新进程使用的环境变量
> LPCSTR lpCurrentDirectory, // 新进程使用的当前目录
> LPSTARTUPINFO lpStartupInfo, // 指定新进程中主窗口的位置、大小和标准句柄等
> LPPROCESS_INFORMATION lpProcessInformation
> //【out】返回新建进程的标志信息如 ID 号、句柄等
);
对创建进程中用到的结构体进行简单说明。通过STARTUPINFO类型的变量指定新的进程的相关信息。通过GetStartupInfo函数来获取父进程创建自己时使用的变量
typedef struct {
> DWORD cb; // 本结构的长度,总是应该被设为 sizeof(STARTUPINFO)
> LPSTR lpReserved; // 保留Reserve字段即程序不使用这个参数
> LPSTR lpDesktop; // 指定桌面名称
> LPSTR lpTitle; // 控制台应用程序使用,指定控制台窗口标题
> DWORD dwX; // 指定新创建窗口的位置坐标dwX,dwY和大小信息
> DWORD dwY;
> DWORD dwXSize;
> DWORD dwYSize;
> DWORD dwXCountChars; // 控制台程序使用,指定控制台窗口的行数
> DWORD dwYCountChars;
> DWORD dwFillAttribute; // 控制台程序使用,指定控制台窗口的背景色
> DWORD dwFlags; // 标志。它的值决定了 STARTUPINFO
> 结构中哪些成员的值是有效的。
> WORD wShowWindow; // 窗口的显示方式
> WORD cbReserved2;
> LPBYTE lpReserved2;
> HANDLE hStdInput; // 控制台程序使用, 几个标准句柄
> HANDLE hStdOutput;
> HANDLE hStdError;
} STARTUPINFO, \*LPSTARTUPINFO;
通过pROCESS_INFORMATION结构体来获取进程创建后的信息
typedef struct{
> HANDLE hProcess; // 新建进程的内核句柄
> HANDLE hThread; // 新建进程中主线程的内核句柄
> DWORD dwProcessId; // 新建进程的 ID
> DWORD dwThreadId; // 新建进程的主线程 ID
} PROCESS_INFORMATION, \*LPPROCESS_INFORMATION;
**解决了字符集的问题**
发现内核对象的方法中W表示的宽字符一般对应的是utf8工程如果是用unicode进行编码的时候就会使用W结尾的内核方法。非Unicode编码的时候链接A结尾的方法。所以在工程中可以配置为多字符编码这样可以调用程序设计中的大部分代码不存在编码问题。
**进程控制**
**获取进程快照的方法**
> \#include \<windows.h\>
> \#include \<tlhelp32.h\> // 声明快照函数的头文件
> int main(int argc, char\* argv[])
> {
> //这是一个进程的记录变量
> PROCESSENTRY32 pe32;
> // 在使用这个结构之前,先设置它的大小
> pe32.dwSize = sizeof(pe32);
> //
> 给系统内的所有进程拍一个快照,这个对象是一个列表,需要用专门的函数进行遍历
> HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
> if(hProcessSnap == INVALID_HANDLE_VALUE)
> {
> printf(" CreateToolhelp32Snapshot 调用失败! \\n");
> return -1;
> }
> // 遍历进程快照,轮流显示每个进程的信息
> BOOL bMore = ::Process32First(hProcessSnap, \&pe32);
> while(bMore)
> {
> printf(" 进程名称: %s \\n", pe32.szExeFile);
> printf(" 进程 ID 号: %u \\n\\n", pe32.th32ProcessID);
> bMore = ::Process32Next(hProcessSnap, \&pe32);
> }
> // 不要忘记清除掉 snapshot 对象
> ::CloseHandle(hProcessSnap);
> return 0;
> }
CreateToolhelp32Snapshot()也可以获取其他类型的快照。TH32CS_SNAPPROCESS、TH32CS_SNAPHEAPLIST、TH32CS_SNAPMOUDULE、TH32CS_SNAPMOUDULE。
储存进程信息的结构体PROCESSENTRY32
typedef struct
> { DWORD dwSize; // 结构的长度,必须预先设置
> DWORD cntUsage; // 进程的引用记数
> DWORD th32ProcessID; // 进程 ID
> DWORD th32DefaultHeapID; // 进程默认堆的 ID
> DWORD th32ModuleID; // 进程模块的 ID
> DWORD cntThreads; // 进程创建的线程数
> DWORD th32ParentProcessID; // 进程的父线程 ID
> LONG pcPriClassBase; // 进程创建的线程的基本优先级
> DWORD dwFlags; // 内部使用
> CHAR szExeFile[MAX_PATH]; // 进程对应的可执行文件名
> } PROCESSENTRY32;
**终止当前进程**
主线程的入口函数返回。
进程中一个线程调用了ExitProcess函数。
此进程中的所有线程都结束了。
其他进程中的一个线程调用了TerminateProcess函数
说明:
退出当前进程
void ExitProcess(UINT uExitCode); // 参数 uExitCode
为此程序的退出代码,当期那进程力科技术。
终止其他进程
BOOL TerminateProcess(
> HANDLE hProcess, // 要结束的进程(目标进程)的句柄
> UINT uExitCode // 指定目标进程的退出代码,你可以使用 GetExitCodeProcess
> 取得一个进程的退出代码
> );//用来结束其他进程。
获取某个进程的句柄,方便对一个进程进行操作
HANDLE OpenProcess(
> DWORD dwDesiredAccess, // 想得到的访问权限,可以是
> PROCESS_ALL_ACCESS所有可以进行的权限PROCESS_QUERY_INFORMATION
> 查看该进程信息的权限……
> BOOL bInheritHandle, // 指定返回的句柄是否可以被继承
> DWORD dwProcessId // 指定要打开的进程的 ID 号
> );
> 终止其他进程的代码示例
> BOOL TerminateProcessFromId(DWORD dwId)
> { BOOL bRet = FALSE;
> // 打开目标进程,取得进程句柄
> HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
> if(hProcess != NULL)
> { // 终止进程
> bRet = ::TerminateProcess(hProcess, 0);
> }
> CloseHandle(hProcess);//注意句柄类型需要使用这个函数进行关闭
> return bRet;
> }
> 进程终止后会发生的事情
> 1\. 相关对象句柄都被关闭
> 2\. 进程内的线程终止执行
> 3\. 集成内核对象变为受信状态,所有等待在此对象上的线程开始运行。
> 4\. 系统将进程对象中退出代码的值由STILL_ACTIVE改为退出码。
**保护进程**
> 以下函数用来实现进程内存的读写。
> BOOL ReadProcessMemory(
> HANDLE hProcess, // 待读进程的句柄
> LPCVOID lpBaseAddress, // 目标进程中待读内存的起始地址
> LPVOID lpBuffer, // 用来接受读取数据的缓冲区
> DWORD nSize, // 要读取的字节数
> LPDWORD lpNumberOfBytesRead // 用来供函数返回实际读取的字节数
> );
> WriteProcessMemory( hProcess, lpBaseAddress, lpBuffer, nSize,
> lpNumberOfBytesRead); // 参数含义同上
> 以下函数用来获取当前系统的版本信息
> BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
> 系统会将操作系统的版本信息返回到参数 lpVersionInfo 指向的 OSVERSIONINFO
> 结构中。
> typedef struct OSVERSIONINFO {
> DWORD dwOSVersionInfoSize; // 本结构的大小,必须在调用之前设置
> DWORD dwMajorVersion; // 操作系统的主版本号
> DWORD dwMinorVersion; // 操作系统的次版本号
> DWORD dwBuildNumber; // 操作系统的编译版本号
> DWORD dwPlatformId; // 操作系统平台。可以是 VER_PLATFORM_WIN32_NT2000
> 系列)等
> TCHAR szCSDVersion[128]; // 指定安装在系统上的最新服务包例如“Service Pack
> 3”等
> } OSVERSIONINFO;
**Windows程序设计中常见的类型。**
| BOOL/BOOLEAN | 8bit,TRUE/FALSE | 布尔型 | |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|-----------------------------------------------------------------------------------|---|
| BYTE | unsigned 8 bit | | |
| BSTR CComBSTR \_bstr_t | 32 bit | BSTR是指向字符串的32位指针 是对BSTR的封装 是对BSTR的封装 | |
| CHAR | 8 bit | (ANSI字符类型 | |
| COLORREF | 32 bit | RGB颜色值 整型 | |
| DWORD | unsigned 32 bit | 整型 | |
| FLOAT | float型 | float型 | |
| HANDLE | | Object句柄 | |
| HBITMAP | | bitmap句柄 | |
| HBRUSH | | brush句柄 | |
| HCURSOR | | cursor句柄 | |
| HDC | | 设备上下文句柄 | |
| HFILE | | OpenFile打开的File句柄 | |
| HFONT | | font句柄 | |
| HHOOK | | hook句柄 | |
| HKEY | | 注册表键句柄 | |
| HPEN | | pen句柄 | |
| HWND | | window句柄 | |
| INT | 不同系统长度不同 | 一般为32位 | |
| LONG | 不同系统长度不同 | 一般为32位 | |
| LONGLONG | | 64位带符号整型 | |
| LPARAM | 32 bit | 消息参数 | |
| LPBOOL | | BOOL型指针 | |
| LPBYTE | | BYTE型指针 | |
| LPCOLOREF | | COLORREF型指针 | |
| LPCSTR/LPSTR/PCSTR | | 指向8位ANSI字符串类型指针 | |
| LPCWSTR/LPWSTR/PCWSTR | | 指向16位Unicode字符串类型 | |
| LPCTSTR/LPTSTR/PCTSTR | | 指向一8位或16位字符串类型指针 | |
| LPVOID | | 指向一个未指定类型的32位指针 | |
| LPDWORD | | 指向一个DWORD型指针 | |
| 其他相似类型: LPHANDLE、LPINT、LPLONG、LPWORD、LPRESULT PBOOL、PBOOLEAN、PBYTE、PCHAR、PDWORD、PFLOAT、PHANDLE、PINT、PLONG、PSHORT…… 说明:(1)在16位系统中 LP为16bit,P为8bit,在32位系统中都是32bit(此时等价) (2)LPCSTR等 中的C指Const,T表示TCHAR模式即可以工作在ANSI下也可UNICODE | | | |
| SHORT | usigned | 整型 | |
| 其他UCHAR、UINT、ULONG、ULONGLONG、USHORT为无符号相应类型 | | | |
| TBYTE | | WCHAR型或者CHAR型 | |
| TCHAR | | ANSI与unicode均可 | |
| VARIANT \_variant_t COleVariant | | 一个结构体参考OAIDL.H \_variant_t是VARIANT的封装类 COleVariant也是VARIANT的封装类 | |
| | | | |
| | | | |
| WNDPROC | | 指向一个窗口过程的32位指针 | |
| WCHAR | | 16位Unicode字符型 | |
| WORD | | 16位无符号整型 | |
| WPARAM | | 消息参数 | |
| MFC 独有 数据 类型 | 下面两个数据类型是微软基础类库中独有的数据类型 | | |
| | POSITION | 标记集合中一个元素的位置的值 被MFC中的集合类所使用 | |
| | LPCRECT | 指向一个RECT结构体常量不能修改 的32位指针 | |
| | CString | 其实是MFC中的一个类 | |
| | | | |
**Windows数据类型命名规律**
- 基本数据类型包括BYTE、CHAR、WORD、SHORT、INT等。
- 指针类型的命令方式一般是在其指向的数据类型前加“LP”或“P”比如指向DWORD的指针类型为“LPDWORD”和“PDWORD”
- 各种句柄类型的命名方式一般都是在对象名前加“H”比如位图BITMAP对应的句柄类型为“HBITMAP”。
- 无符号类型一般是以“U”开头比如“INT”是符号类型“UINT”是无符号类型
- DWORD实质上就是 unsigned long 数据类型32位无符号整型。
- 而经常要用到的HANDLE类型实质上是无类型指针void,HANDLE定义为
typedof PVOID HANDLE;
HANDLE实际上就是一个PVOID那PVOID又是什么呢
Typeof void \*PVOID;
PVOID就是指向void的指针。

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,34 @@
C++
是一种语言像java、Python语言他们都通过强大库来提供定向的功能。他们都包含自己基本的库用来实现基础的功能也有自己的基本语法。对于语言的学习起始就是对基本语法的了解和最基础的函数库自带函数库的学习
真正的开发过程是不可能仅仅限于对语言的学真正开发过程往往涉及大量的第三方库C开发也是如此。
C、C++开发windows应用程序的第三方库就是微软光放提供的SDK开发工具包。
C语言不具有跨平台的特性因为如果他要开发windows应用程序必须要使用windows版本的开发工具包进行开发到了其他系统就不能使用了。
C语言的SDK开发工具包实现了程序调用系统资源的方式VisualC++是常用的开发工具可以集成SDK开发工具包使用集成环境进行开发。
一般而言SDK即开发 [Windows](https://baike.baidu.com/item/Windows)
平台下的应用程序所使用的
SDK。它可以简单的为某个程序设计语言提供[应用程序接口](https://baike.baidu.com/item/%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E6%8E%A5%E5%8F%A3)
[**API**](https://baike.baidu.com/item/API)的一些文件但也可能包括能与某种嵌入式系统通讯的复杂的硬件。一般的工具包括用于调试和其他用途的实用工具。SDK
还经常包括示例代码、支持性的技术注解或者其他的为基本参考资料澄清疑点的支持文档。
SDK开发工具包括了基础的API主要包括以下几个模块和基础类库
GDI
GDI+
OpenGL
MonitorConfiguration
WindowsColor System
WPF bitmap Effects
Win32 Application,即SDK程序。
MFC是基于WIN32即SDK的一个框架

View File

@@ -0,0 +1,21 @@
# 仿真开发
## &gt; 仿真开发系统
-----
* **仿真开发系统**
1. 能够诊断用户系统的硬件电路
2. 能够对程序进行加载和修改
3. 能够对程勋进行运行和调试和状态显示
4. 将程序固化(烧录)到程序存储器中
* **仿真器**
1. 单片机替代型仿真器和接口型
2. 像飞思卡尔的LQ-USBDM
* **开发过程**
1. 硬件设计和电路设计pcb布线电路板设计
2. 软件编程PC机
3. 动态在线调试(单步调试
4. 固化程序
5. 脱机运行

View File

@@ -0,0 +1,70 @@
#单片机的指令系统概述
## &gt;指令系统概述
-----
* **基本知识**
1. 包括功能、时间、空间三种属性,每条指令指明具体功能,一条指令执行所用的时间,指令占用的字节数
2. 机器语言指令、汇编语言指令。机器语言的复杂指令集111条。
3. 每条指令由操作码和操作数组成。
* **汇编**
1. [标号:] 操作码助记符 [目的操作数][,源操作数][;注释]
2. 标号要求:非关键字,字符开头,字符数字组成,不超过八个字符,行号位于行首
## &gt;寻址方式
-----
> 地址给出的方式
> 操作数的定义:表示参加操作的**数的本身**或者**操作数所在的地址**。这里的操作数更像是备操作的数据,如果是一个地址时,就像指针指向的数据。暂且理解为动作和动作操纵的对象吧!
* **立即寻址**
操作数直接出现在指令当中,作为操作码的一部分。#号操作数
MOV A,#80H;
* **直接寻址**
直接使用数所在单元的地址找到该操作数direct。
MOV A,00H;
* **寄存器寻址**
寄存器中存有操作数Rn表示工作中的寄存器组DPTRAB。direct。
MOV A,RO;
* **寄存器间接寻址**
寄存器中存有操作数的地址,寄存器起到地址指针的作用。
MOV A,@R0;R0作为地址将其指向的数据传送到RAM中
MOVX A,@DPTR;DPTR作为地址将其指向的数据传到RAM中
* **变址寻址**
基址寄存器和变址寄存器的和基址寄存器只能是指令计数器pc和数据指针DPTR@+。
目的是用来访问程序存储器中的常数表。
MOVE A,@A+DPTR;数据指针可以任意更改
MOVE A,@A+PC;PC示取指令的pc+1不能任意更改
* **相对寻址**
当前的PC值加上一个相对值形成的地址+
指令的第二个字节用八位二进制补码表示,用于跳转当前执行的程序。
PC中的当前地址称为基地址第二个字节的数据称为偏移量
目的地址=指令存放地址+指令字节数+rel
* **位寻址**
对RAM的位寻址区或可为寻址的特殊功能寄存器的某些位进行操纵。
SETB 3DH;将27H.5 位置置为1。
------
> Rn 表示工作寄存器之一
> Ri 工作寄存器RO或R1
> \#data 表示8位立即数
> \#data16 表示16位立即数
> direct 表示RAM或SFR的地址
> bit 片内RAM或SFR的位地址
> addr11 11位目的地址
> addr16 16位目的地址
> rel 补码形式的8位地址偏移量
> / 位操作指令,该位求反后参与操作,不影响该位
> X RAM的直接地址
> (X) 表示地质单元的内容
> -> 左边内容送入右边内容
-------------
[1] CISC complex instruction set computer 复杂指令计算机
[2] RISC reduced instruction set computer 精简指令计算机

View File

@@ -0,0 +1,56 @@
# 单片机程序设计
## &gt;编程语言背景
-----
* **编程语言**
1. 机器语言,
2. 汇编语言,需要通过汇编生成机器语言,不同单片机的汇编语言不能通用。
3. 高级语言,通过编译编程机器语言
* **汇编结构**
1. 四部分:标号:操作码 操作数;注释
* **汇编伪指令**
1. 作用:不产生可执行的目标代码,帮助进行汇编的指令。指定程序或数据的起始位置,给出存放数据的地址。为中间运算保留有份存储空间,表示源程序结束等。
2. 起始指令ORG,重新制定了目标程序的起始位置不再是OOOOH可以多次使用定义不同程序段的起始地址
3. 结束指令END,只能有一个end指令
4. 定义字节的伪指令DB,定义从指定单元开始的若干个字节的数据,用于定义数据常数表。
- ORG 2000H
- DB 30H,8AH,7FH,'a'
5. 定义数据字的伪指令DW,定义从指定单元开始存储若干个字的数据(双字节称为字)
- DB 'a','b' == DB 61H,62H == DW 6162H;
5. 等值伪指令EQU,赋值指令用特定的字符代替某一个常数。AA EQU 30H;
6. 位地址定义伪指令BIT,用于给指定位定义一个标号。
- ABC BIT P1.1;P1.1 可以用ABC标号代替
7. 表示目前地址的伪指令$
## &gt; 汇编语言程序设计
-----
> 加深对面向过程的理解觉得需要补充C语言的一些知识。
> 单片机可以实现电脑完全仿真如果日后对汇编和51单片机有兴趣的话可以使用Proteus模拟51单片机
> 但是以及用keil进行编程和开发。
* **程序流程图**
1. 画图
- 开始框,动作框, 判断框,结束框。
- 顺序结构
- 分支结构程序
- 循环结构
- 子程序结构
2. 图文翻译
> 感觉汇编面向过程的时候,用程序流程图,可以直接翻译为汇编代码。
## &gt; 汇编语言与机器语言
-----
* **汇编**
汇编的指令能够被 指令存储器翻译成为特定的机器码
数据能够被 数据存储器储存。
每一条汇编语言,都有一个对应的机器码。

View File

@@ -0,0 +1,98 @@
#MCS-51 单片机的基础知识介绍
## &gt;单片机内部基本组成
-----
* **功能结构原理图**
这里有一张图片
主要部分:中央处理器、特殊功能寄存器、存储器系统、定时/计数器、并行接口,串行接口、中断系统。
* **51单片机内部细化图**
这里也有一张图片
* **SFR特殊功能寄存器**
这里还有一张图片
## &gt;mcs-51单片机-中央处理器cpu-运算部件
-----
* **ALU 算数逻辑运算单元**
1. 八位二进制加减乘除算术运算
2. 逻辑与、或、异或、循环移位、补、清零等逻辑运算
3. 置位、清零、求反、测试转移、位逻辑与或非等位运算在内部的位运算器C/CY当中
* **ACC 八位寄存器累加器**
1. 加法运算
* **B 辅助寄存器**
1. 乘法存放被乘数
2. 除法存放除数
* **PSW 标志寄存器**
1. psw.7 进位标志位C
2. psw.6 辅助进位标志位AC
3. psw.5 用户自定义标志位F0
4. psw.4/psw.3 寄存器组RS1/RA0 选择位(选择正在工作的寄存器组)
5. psw.2 溢出标识位OV
6. psw.0 奇偶标志位P
## &gt;mcs-51单片机-中央处理器cpu-控制部件
-----
* **控制电路**
* **时序电路**
* **指令寄存器**
* **指令译码器**
* **计数器PC**
* **堆栈指针SP**
* **数据指针DPTR**
* **信息传送控制部件**
## &gt;mcs-51单片机-存储结构
-----
* **程序存储器**
1. 用于存储单片机工作时的程序。程序计数器寄存器PC用于存放要执行的指令的地址并依次取出执行。使用ROM作为程序存储器。程序计数器有16位有2<sup>16</sup>个地址码对应64k的寻址空间。
2. 物理结构上分为片内存程序储器和片外程序存储器。内部程序存储器大小为0/4kB/8kB对应寻址地址为0/0000H-0FFFH/0000H-1FFFH,片外程序存储器的寻址地址为片内存储器之后的部分多余部分的片外存储器不进行寻址。共64KB的地址区域。物理上通过片外程序存储器引脚EA点评的高低来确定。高电平片内去指令执行低电平片外取指令执行。
3. 0000H为单片机系统程序的系统地址。
* **数据存储器**
1. 程序执行时所需要的数据片内数据存储器和片外数据存储器。数据计数器有8位地址2<sup>8</sup>个地址码用两个16进制数FFH表示对应256K的寻址空间。
2. 片内数据存储器SFR特殊寄存器、RAM程序存储器具有相同的地址空间。51系列单片机内部数据RAM128字节地址编码为00H-7FH寄存器SFR数据128字节地址编码80H-FFH地址不重叠。
3. 片内数据存储器RAM分割为工作寄存器区地址码00-1FH、位寻址区20-2FH、RAM区30-7FH堆栈区80-FFH
- 工作寄存器区32个地址码对应32个字节的空间分为四组每组8个字节储存有8个寄存器的地址码对应8个寄存器淡定点默认工作的寄存器组由程序状态字PSW.4/.3RS0和RS1来决定。
- 位寻址区16个地址码对应16个字节的空间128位支持按位寻址以前的寻址结果是字节现在是以为即一个地址码对应一位
- 一般RAM区
- 堆栈区和堆栈指针SP按照先入后出的原则进行内存管理。mcs-51单片机为向上生长型存入数据从低端向高端延伸push取出数据从高端向低端延伸pop。
4. 特殊功能寄存器SFR这里需要一张图如果地址码对应寻址空间中的字节仍是一个地址码则相当于地址指针的嵌套。
5. 片外数据存储器最多扩展为64K空间数据指针DPTR数据计数器DPH和DPL256个字节称为一个页面即一个字节八位所构成的所有的地址码能形成一个页面的数据。
* **常见的存储器类型**
1. RAM存储器
2. ROM存储器
3. PROM存储器、EPROM存储器、EEPROM存储器
4. FLASHI存储器
> 存储结构可以分为冯诺依曼结构和哈弗结构,前者将程序的指令存储器和数据村粗器放在一块,后者将指令存储器和数据存储器分离了。
## &gt;mcs-51单片机-单片机的输入输出接口
-----
* **I/O接口构成**
1. 涉及到电路的很多知识,无能为力了。但是感觉都是数字电子技术课上的知识(好多都是诶)。
2. 四个8位I/O并行接口输入时具有锁存能力输出时具有缓存能力。
3. 具体的每一个口的电路实现和功能等以后在了解吧。
> 感觉这里的51单片机不能理解为单片机的一个时代并非其他的单片机都是从这一代产品发展而来的也并非必须继承51单片机的特点。
> mcs-51单片机只能说是单片机的某个生产厂商的某个型号与飞思卡尔系列Dallas系列飞利浦系列Motorola系列等具有并列关系。
> 单片机的分类一种方式时按位分类8/16/32位单片机。或者按照公司及其型号来分。每种单片机具有相同的语言标准汇编语言通用也有各自的C高级语言开发环境其功能大同小异所以应该针对某个通用程度比较高的单片机学习即可mcs-51单片机
> 这里的地址编码访问指令时访问的是字节编码而非位编码。64KB的寻址空间=2<sup>16</sup>位地址码=2<sup>16</sup>个地址码=4个16进制数FFFFH=两个字节的地址码
> 寻址空间就是能通过地址码找到的空间的大小其中每个地址码对应一个字节两个字节16位的地址码最多能寻址64K个字节的空间。单个字节8位的地址码最多能寻址256个字节的空间。
英文简称解读
[1] SFR special function register 特殊功能寄存器
[2] ALU arithmetic logical unit 算数/逻辑运算单元
[3] FIFO first in,first out FIFO队列先进先出
[4] MUX multiplexer 数据选择器/多路开关/多路选择器(数电上有所染指)

View File

@@ -0,0 +1,28 @@
# 单片机的外部结构
## &gt;mcs-51单片机-外部引脚
------
* **引脚图**
(这里应该有一张图)
* **输入输出**
1. PO口标准输入输出口I/O扩展口骗完存储器接口分时复用为第八位地址总线。
2. P1口
3. P2口
4. P3口每一个引脚有独立的功能此处有一张图
* **控制线**
1. ALE/<span style="TEXT-DECORATION: overline">PROG</span>地址锁存器信号输出端
2. <span style="TEXT-DECORATION: overline">PSEN</span>片外存储器控制端
3. RST/V<sub>pd</sub>重置或备用电源。
4. <span style="TEXT-DECORATION: overline">EA</span>/V<sub>pp</sub>片外程序存储器。
5. V<sub>cc</sub>/V<sub>ss</sub>电源正负
6. XTAL1/XTAL2外接晶振引脚。
## &gt;mcs-51单片机-外部扩展总线的形成
------
> 以后补充

View File

@@ -0,0 +1,70 @@
# 单片机的工作方式
## &gt; mcs-51单片机-复位方式
-------
RST 端2个机器周期以上的高电位。
包括按键复位(通过手动按键决定)、上电复位(通过电路决定)
## &gt; mcs-51单片机-程序执行方式
-------
PC程序计数器非特殊cpu内部寄存器指针指向最开始的程序地址逐条进行取指令译码执行操作
## &gt; mcs-51单片机-单步执行方式
-------
用于调试,可以通过汇编语言实现,可以等待按键
## &gt; mcs-51单片机-掉电和节电方式
-------
掉电方式,主电源掉至下限->中断操作->备用电源供RAM保留数据->主电源回复->重启运行
节电方式,很多器件不懂
## &gt; mcs-51单片机-编程和校验方式
-------
相关的系统运行要求
## &gt; mcs-51单片机-工作过程及时序
-------
震荡电路 产生时钟脉冲 主频的晶振频率
两个震荡周期为一个状态周期SP1,P2
6个状态周期为一个机器周期
1或者2个机器周期为一个指令周期
**单片机如何读取外部指令**
1. 涉及到时序逻辑(以后再深入了解)
## &gt; mcs-51单片机-单片机的选型策略和常见cpu的封装方式
-------
选型
* 功能
* 存储容量
* 速度
* 功耗
* 封装与管脚
* 抗干扰能力
* 特殊应用需求
封装
* **DIP封装**
* **QFP封装**
* **PFP封装**
* **PGA封装**
* **BGA封装**

View File

@@ -0,0 +1,63 @@
# 单片机学习
## &gt; 单片机的背景知识
*****
* **单片机概述**
1. 注意一下几个名词:冯诺依曼计算机,存储程序计算机,通用计算机,运算器,控制器,存储器,输入设备,位数,容量,字长,外存和内存,输入设备,电子管计算机,晶体管计算机,集成电路计算机,量子计算机,工作站,服务器,个人计算机,嵌入式计算机,云计算机。
2. 嵌入式系统是一种完全嵌入空间内部,为特定应用而设计的专用计算机。
* **单片机的特点**
1. 存储结构上采用哈弗结构ROM和RAM完全分开功能和寻址方式不同。
2. 芯片引脚,采用分时复用技术,有程序决定引脚在当前起什么作用
3. 内部资源访问使用寄存器SFR。
4. 采用面向控制流的指令系统。
5. 内部集成全双工的串行接口,用于同其他外设进行通信。
6. 具有很强的扩展能力,很方便地在外部扩展各种电路,与许多微机接口芯片兼容。
* **单片机与DSPCPLDFPGA的区别**
1. DSP digital signal processor 数字信号处理器,独特的微处理器。强大的数据处理能力和高运行速度。
2. 单片机主要操纵的是控制流对数据处理能力不如DSP
3. FPGA field programmable gate array 综合了PALGALCPLD发展而来可编程门阵列。可编程逻辑器件CPLD和FPGA。硬件描述语言VerilogVHDL。从数电实验课上得到的启发这个FPGA就是一堆电路元件的阵列可以通过某些设计软件或者硬件描述语言对这些阵列进行编程使他们具有一定的逻辑性然后烧录到FPGA当中使他们具有一定的功能。这个也是嵌入式系统地一部分吧。他针对的不是程序而是一种硬件的逻辑。
4. FPGA是对CPLD的电路规模功能性能等方面的强化之后的产物。
## &gt; 数制与编码
****
* **机器码的理解**
1. 原码,正数不变,负数在正数的最后一个值得基础上加负数的绝对值,中间没有零做间隔。特点:正数变大,原码变大;负数变小,原码变大(单调性不统一)
2. 反码正数不变负数绝对值按位取反相当于在机器码最大的情况下减去负数的绝对值即加上负数。特点正数变大反码变大负数变大反码变大但是有两个零0和0的按位取反都是零。
3. 不骂,正数不变,负数是反码加一。特点:正数变大,补码变大,负数变大,补码变大,单调性相同,只有一个零。最小值为最大正数的按位取反,也是最大正数的补码加一后形成的补码。
* **信息编码**
1. 8421BCD编码ascii码
## &gt;单片机的其他知识
-----
* **51单片机的系列**
1. 8031无内部存储器、8051ROM不可擦除、8751EPROM紫外线擦除、8951EEPROM电擦除
2. ATM公司flash闪存集成到单片机内部。
3. 飞利浦公司添加了can总线
4. 32/52加强系列增加了可擦除存储器增加了数据存储器的大小怎加了数模转化器。
* **微控制器(单片机)的改进**
1. 增加cpu内核数
2. 采用多级流水线结构取指令、译码、执行三级流水线结构可以在任何时候都有cpu执行代码。
* **对并行接口和串行接口的理解**
1. 并行接口再多跟数据献上同时传送信息,串行接口是在一根数据线以一位数据为单位进行数据传送。并行适用于近距离告诉的场合。
2. 并口存在的问题干扰问题并口多条数据线之间会产生耦合电容增大传输速率会导致错误如果加强屏蔽会消耗更多的金属截面面积更大。同步问题八条线的延迟不同如果单线传输速率变高的话可能会出现数据撞车不同步的现象并口单线100Mb/s时不能再增加二串行传输可以达到1Gb/s
* **io口的改进**
1. 增加io的驱动能力
2. 增强逻辑控制能力,一秒钟亮,一秒钟灭,通过一个管脚即可实现控制能力,控制一个输出位,然后一秒钟翻转一次。
3. 增加特殊的串行接口。
4. 外围电路内装化
> ADC analog Digital Converter 数模转换器
> PWM pulse width modulation 脉冲宽度调制
> WDT watch dog timer 程序监控定时器,看门狗电路
>

158
单片机/汇编指令.md Normal file
View File

@@ -0,0 +1,158 @@
#汇编语言学习(真的做梦都没想到,居然在看汇编语言)
## &gt;数据传送指令
-----
* **累加器 目的操作数**
MOV A,#data/direct/Rn/@Rn
* **寄存器 目的操作书**
MOV Rn,direct/Rn/#data;
* **直接地址 目的操作数**
MOV direct,#data/direct2/Rn/@Ri;
* **简介寻址 目的操作数**
MOV @Ri,#data/direct/Rn;
* **十六位数 传递**
MOV DPTR,#DATA16;只有DPTR能被16位赋值。
MOV DPTR,#1234H;执行后DPH=12H,DPL=34H;
* **片外数据传送**
MOVX A,@Ri;
> 只有A累加器可以与外部RAM打交道
> Ri是八位寄存器只能存放低八位地址通过p0口提供高八位
> 使用前先将地址送入DPTR或者ri中
MOV DPTR,#0100H;
MOVX A,@DPTR;
MOV DPTR,#0200H;
MOVX @DPTR,A;
* **读取程序存储器指令**
MOVC A,@A+DPTR;
* **堆栈操作**
PUSH direct
POP direct
* **数据交换指令**
XCH A Rn交换值
## &gt; 算数运算类指令
-----
* **无进位加法指令**
ADD A,#data;A=A+#DATA
ADD A,direct;
* **带进位加法指令**
ADDC A,RN;A=A+RN+PSW.CY
> 对于PSW中CY和OV的介绍
> 当进行二进制无符号运算时只要使用PSW.CY位就能判定是否有溢出或者进位。
> 当进行二进制补码运算时PSW.CY表示进位PSW.OV表示是否错误或者溢出。是最高两位的抑或如果是负数且有溢出CY时相加后不应该更大而是更小。如果是整数相加后不应该更小所以最高两位的抑或ov能够实现是否错误的判定)
* **加一指令**
INC A;
* **十进制调整指令**
DA A;
> DA是按照BCD码调整相加后的二进制数。BCD码需要四位二进制来表示但是这四位的进位和二进制四位的进位不同BCD满十进位导致二进制码相加后并不是规范的BCD码所以根据PSW.AC进行调整。
* **带借位的减法指令**
SUBB A,RN;A=A-RN-CY
* **减一指令**
DEC A;A=A-1
* **乘法指令**
MUL AB;BA=A*B
> 8位无符号数相乘两数相乘结果较大高八位存放在B中第八位存放在A中。
## &gt;逻辑运算指令
-----
* **逻辑或**
ORL A,RN;
* **逻辑与**
ANL A,RN;
* **逻辑异或**
XRL A,RN;
> 读改写指令对并行端口P0P1P2P3操作是读取并行端口锁存器中的数据而非管处的数据。
> 非读改写操作,读取引脚处数据,而非锁存器数据。
* **清零**
CLR A;
* **循环移位**
RL A; rotate left
RR A; rotate right
RLC A; rotate left with cy
RRC A; rotate right with cy
## &gt;控制转移类指令
-----
>特点不影响psw。实现了分支、循环、调用。是控制程序的相关指令而非更改数据的指令。
* **无条件转移指令**
AJMP addr11;短转移指令11位地址指令长度两个字节
LJMP addr16;长转移指令16位地址指令长度三个字节
SJMP rel; 相对转移指令8位二进制补码地址
JMP @A+DPTR;间接转移指令
> 以上指令通过间接修改pc值实现。前两条直接给出类跳转的目标地址。短转移指令只修改PC的低八位地址高五位不变转移范围2kB长转移指令转移范围64KB相对转移指令当前指令PC+rel附近的128B地址。
> 前三个指令可以直接给出行号。
> 间接转移指令可以根据A寄存器中不同的值进行跳转散转指令功能相当于C中的swich语句。
* **条件转移指令-A寄存器判断**
JZ rel;A==0则转移否则顺序执行。
JNZ rel;A=0则转移否则顺序执行。
JZ 标号; 转移到标号出。
> 当前PC值=PC+指令长度
> 转移后的PC值=当前PC值+rel
* **条件转移指令-比较转移**
CJNE A,#datarel/标号;比较不等转移
* **调用返回指令**
ACALL addr11;指令长度两个字节
LCALL addr16;指令长度三个字节
RET;子程序返回指令
RETI;中断子程序返回指令
> 调用子程序原来的PC指针值压栈返回时出栈执行。
> 嵌套太多是堆栈溢出,压栈出栈配对。
* **空操作指令**
NOP;指令执行时间是一个机器周期,用来做软件延时。
## &gt;位操作指令
------
> 由位处理器负责运算
> 可以进行位操作的区域20H-2FH特殊功能寄存器都可以。
> CY自动用作位累加器
> 字节地址、寄存器名字后面添加点操作运算符对位进行操作psw.4;
> 直接使用位名称(一般特殊功能寄存器都有相应的位名称,只是不知道)
> 可以直接定义位地址
* **位传送指令**
MOV C,bit; bit to C
MOV bit,C; C->bit
> 实现了位累加器CY和其他地址之间的数据传递
> C代表了PSW.CY或者PSW.C
* **位清零指令**
CLR C;
CLR bit;
SETB bit;
SETB C; 置位为1
* **位逻辑运算指令**
ANL C,bit;
ANL C,/bit;
ORL C,bit;
CPL C;
* **位条件转移指令**
JC rel
JNC rel根据CY判断是否转移
JB bit,rel;
JNB bit,rel; 根据bit判定是否转移
JBC bitrel 根据bit判定是否转移判定后该位清零。