0%

计算机网络学习笔记

网络

局域网和广域网的区别

广域网(wide area network,WAN)也是由具有通信能力的设备相互连接而形成的。可是,局域网和广域网有一些不同。局域网通常覆盖范围受限,可以覆盖一间办公室、一栋大楼或一个校园;广域网则具有更广的地理覆盖范围,可以覆盖一个城市、一个省、一个国家甚至整个世界。局域网互联主机;广域网互联交换机、路由器、调制解调器等连接设备。局域网通常由使用它的组织拥有;广域网通常由通信公司建设和运营,使用它的组织进行租用。我们看看目前使用的两种典型的广域网:点到点广域网和交换式广域网。

网络层次结构

1563355028570

应用层

俩个应用层之间的逻辑连接是端到端的,其通信处于两个进程之间。应用层交换的数据成为消息(message)

其常见的协议有http,ssh,smtp,ftp等

传输层

两个传输层的逻辑连接也是端到端的。其常见协议有tcp,udp,sctp。TCP中的数据称为段(segment),UDP中的数据称为用户报文(user datagram)

TCP是面向连接的协议,,其提供流量控制、差错控制、拥塞控制

UDP是无连接协议,其尽最大努力交付数据,但不保证对端一定接收到完整数据。

可靠传输

TCP的可靠数据传输形式如下所示,发送端按序发送数据分组,接收方接受到一个数据分组后发送一个ACK确认,接受方收到ACK后才开始发送下一个数据分组。

1563416125171

发送方在规定时间内未收到ACK时,会重发当前数据分组。在此过程中数据分组和ACK均可能在传输过程中丢失,丢失数据分组会导致接收方无法收到数据分组而不发送ACK,丢失ACK会导致发送方无法收到ACK,两者中的任意一者丢失都会导致发送方无法接收到ACK。此外,由于网络影响,ACK可能会延时到达,甚至在发送端超时重发后到达,对于延时到达的重复的数据分组和ACK,发送方和接收方均不在做出反应。

接收方会对接收到的数据分组进行差错检验,若检验出错,接收方不发送ACK,等待发送方超时重传。

上述形式会导致发送方和接收方花费大量时间等待对方应答,对带宽利用率低,因此,实际使用时采用流水线的方式对数据进行传输。

1563417379179

在上图中,发送方一次发送多个数据分组,接受方同时接收多个数据分组并针对每个数据分组发送ACK,当发送方收到所有ACK后,开始发送下一批数据分组。为了解决丢包问题,流水线采用回退N步和选择重传的方式。

回退N步:接收方按序接收数据分组,若接收到一个失序分组(即此分组前存在未接收到的分组)则丢弃分组,同时接收方只为按序分组发送ACK,若发送方收到某分组的ACK而未收到下一个分组的ACK,则认为此数据分组之前的数据全部传输成功,此分组之后的数据全部丢失,发送方开始重传之后的数据。

选择重传:接收方能够接收失序数据分组,且为每个数据分组发送ACK,接收方只重传为收到ACK的数据分组而不重传其之后的数据分组。

拥塞控制和流量控制

流量控制是针对接收方的接收能力的,当接收方无法及时处理发送方发送的大量数据从而导致数据丢失时,发送方会根据流量控制减少数据发送量。流量控制主要靠接收窗口实现,接收方通过接收窗口告知发送方接收能力。

拥塞控制是针对网络传输能力的,当网络繁忙时,发送的数据可能出现大量的丢包或延时,这时发送方会控制数据发送量以减轻网络负担。TCP采用拥塞窗口来解决拥塞问题,拥塞窗口会限制 数据发送速率。TCP采用的拥塞控制算法包括慢启动,拥塞避免,快恢复

慢启动,传输开始时,发送方会以大小为1的拥塞窗口开始,并以指数级增加拥塞窗口大小,直至发现网络拥塞达到某一程度时,结束指数增长,转为拥塞避免。

拥塞避免:以较平缓的方法增加拥塞窗口,当丢包率达到某种程度时,将拥塞窗口减半,并启动快恢复

快恢复:拥塞窗口不再从1开始,但执行与慢启动和拥塞避免中相同的操作

网络层

网络层的通信时主机到主机的。其主要的协议时IP协议,IP协议是无连接协议,不提供流量控制和差错控制。网络中的数据称为数据报(datagram)

网络层还包括ICMP、IGMP、DHCP、ARP等辅助协议帮助完成 IP转发和路由工作。

数据链路层

数据链路层中的数据单元称为帧。

交换机、网桥与路由器

网桥(Bridge)也称为桥接器,是连接两个局域网的存储转发设备,用它可以使完全具有相同或相似体系结构网络系统的连接,这样不但能扩展网络的距离或范围,而且可提高网络的性能、可靠性和安全性。网桥工作在OSI参考模型的数据链路层(第二层),将两个LAN连起来,根据MAC地址来转发帧,可以看作一个“低层的路由器”(路由器工作在网络层,根据网络地址如IP地址进行转发)。

交换机位于链路层,其自身对子网中的主机和路由器时透明的,交换机实质是一个多接口的网桥。交换机具有并行性,能够同时连通多对接口,使多台主机同时通信且彼此之间独占传输媒体,无碰撞发生,而网桥只能一次分析和转发一个帧。

在数据传输过程中,交换机在数据链路层上对数据进行转发,通过识别目标主体的MAC地址决定将数据传输到哪个链路上 ;路由器在网络层对数据进行转发,也就是说路由器在转发过程中会识别传输数据的IP地址,并在链路层将IP地址转化为MAC地址传递给一个数据接收主体。对于路由器和交换机来说,其最终都是通过mac来唯一区分一个主体的,但在路由器中,会将mac地址映射为在该局域网内唯一的ip地址,作为设备的标记。

1563354050330

上述过程中,交换机不会改变数据的内容,但路由器可能会修改网络层以下的的数据内容,比如将数据分组切片。路由器不能修改网络层以上的数据内容,也就是说,对于两台主机而言,无论中间经过多少路由器,其接收端从网络层获取的数据一定与发送端传输到网络层的数据一致。

1563354812934

网络隧道

隧道协议(Tunneling Protocol)是一类网络协议,它是一种数据包封装技术,它是将原始IP包(其报头包含原始发送者和最终目的地)封装在另一个数据包(称为封装的IP包)的数据净荷中进行传输。使用隧道的原因是在不兼容的网络上传输数据,或在不安全网络上提供一个安全路径。隧道协议通常(但并非总是)在一个比负载协议还高的层级,或同一层。

搭建博客

使用github搭建博客

创建仓库

在自己的GitHub账号下创建仓库<账号名>.github.io

1563075883725.png

在仓库的设置里面可以看到github pages内容,其中可以看到博客对应的链接,如下图的https://zdzh.github.io/.

1563076098501.png

选择主题

点击choose a theme 可以选择博客显示主题

1563076525871.png
在上面一栏中选择自己喜欢的主题,然后点击selecet theme选择主题

安装node.js和Hexo

  1. 在Node.js官网上下载node.js,按提示安装软件。安装完成后输入node -v可以查看是否安装成功以及安装的版本

  2. 安装hexo

    Hexo是一个简单、快速、强大的基于 Github Pages 的博客发布工具,支持Markdown格式,有众多优秀插件和主题。hexo官网 hexo GitHub

    在自己的电脑中创建一个空文件夹作为博客文件存放地址。使用命令行进入该目录下,输入以下指令安装Hexo

1
npm install -g hexo

初始化

使用命令行在上述路径中输入hexo init初始化文件夹,该文件夹必须是空文件夹否则初始化失败,指令运行成功后,会在该文件夹下创建若干文件

1563083345803.png

其中scaffolds是模板文件夹,当您新建文章时,Hexo 会根据 scaffold 来建立文件。Hexo的模板是指在新建的markdown文件中默认填充的内容。例如,如果您修改scaffold/post.md中的Front-matter内容,那么每次新建一篇文章时都会包含这个修改。

source资源文件夹是存放用户资源的地方。除 _posts 文件夹之外,开头命名为 _ (下划线)的文件 / 文件夹和隐藏的文件将会被忽略。Markdown 和 HTML 文件会被解析并放到 public 文件夹,而其他文件会被拷贝过去。

themes主题文件夹。Hexo 会根据主题来生成静态页面。

之后,输入以下指令打开服务器

1
2
hexo g 		# 生成静态网页
hexo s #打开本地服务器

1563083467390

打开浏览器,输入http://localhost:4000/,可以查看hexo预先生成的网页。若网页无法打开,则有可能是端口占用问题,可以查看文档如何修改端口。

修改主题

完成以上步骤后,网站的基本框架已经搭建完成,下一步是将网站的主题更换为自己喜欢的样式

可以自行在网上搜索自己喜欢的主题,选中主题后,找到其对应的仓库地址,将其克隆到当前目录的themes下

1
git clone https://github.com/idhyt/hexo-theme-next.git

克隆完成后,在themes可以看到克隆下来的文件

1563114908429

修改_config.yml文件,将theme对应字段改为主题名,及上面克隆下来的文件名

1
theme: hexo-theme-next

执行hexo g重新生成。若这一步出现问题,可以执行hexo clean清除之前的内容,之后再重新生成和发布。

添加页面

使用hexo new page <filename>可以在网站上添加页面,现在使用以下语句添加关于,标签和分类页面

1
2
3
hexo new page about                //关于界面
hexo new page categories //分类界面
hexo new page tags //标签界面

执行以上语句后会在_posts路径下生成相应的文件夹和目录,在里面的文件中编辑即可修改相应页面

在categories.md中添加type: "categories",如下所示

1563279199674.png

按同样的方法在about.md中添加type:about,在tags.md中添加type:tags

上传到github

上传前首先需要下载一个插件

1
npm install hexo-deployer-git --save

配置_config.yml,修改deploy字段为以下内容

1
2
3
4
5
6
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repository: git@github.com:zdzh/zdzh.github.io.git #在github中生成的仓库链接
branch: master

最后输入hexo -d上传到GitHub即可

编写文章

编写文章时,使用hexo n <filename>生成空白markdown文档,在markdown文档中输入自己的博客内容。

在文档的开头处,Front-matter 是文件最上方以 --- 分隔的区域,用于指定个别文件的变量,举例来说:

1
---title: Hello Worlddate: 2013/7/13 20:46:25---

以下是预先定义的参数,您可在模板中使用这些参数值并加以利用。

参数 描述 默认值
layout 布局
title 标题
date 建立日期 文件建立日期
updated 更新日期 文件更新日期
comments 开启文章的评论功能 true
tags 标签(不适用于分页)
categories 分类(不适用于分页)
permalink 覆盖文章网址

只有文章支持分类和标签,您可以在 Front-matter 中设置。在其他系统中,分类和标签听起来很接近,但是在 Hexo 中两者有着明显的差别:分类具有顺序性和层次性,也就是说 Foo, Bar 不等于 Bar, Foo;而标签没有顺序和层次。

1
2
3
4
5
categories:
- Diary
tags:
- PS3
- Games

发布文章

使用hexo n <filename>自动创建markdown文件,文件位于..\source\_posts下。也可以自己新建markdown文件。

文章编写完成后,重新运行以下指令

1
2
hexo g
hexo d

EXTI—外部中断/事件控制器

EXTI(External interrupt/event controller)—外部中断/事件控制器,管理了控制器的20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
EXTI可分为两大部分功能,一个是==产生中断==,另一个是==产生事件==。
EXTI功能框图

红色线路是一个==产生中断==的线路,最终信号流到NVIC控制器内。

  1. 输入线: 可通过寄存器设置为任意一个GPIO,也可以是一些外设事件
  2. 边缘检测电路:根据上升沿触发选择 寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR) 对应位的设置来控制信号触发。检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号1给编号3电路,否则输出无效信号0.可以是只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发.
  3. 实际就是一个或门电路,一个输入来自编号2电路,另外一个输入来自软件中断事件寄存器(EXTI_SWIER)。EXTI_SWIER允许我们通过程序控制就可以启动中断/事件线.
  4. 一个与门电路,它一个输入是编号3电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR).简单的控制EXTI_IMR来实现是否产生中断的目的。编号4电路输出的信号会被保存到挂起寄存器(EXTI_PR) 内,如果确定编号4电路输出为1就会把EXTI_PR对应位置1。
  5. 将EXTI_PR寄存器内容输出到NVIC内,从而实现系统中断事件控制.

虚线指示的电路流程。它是一个产生事件的线路,最终输出一个==脉冲信号==。
6. 6电路是一个与门,它一个输入来自编号3电路,另外一个输入来自事件屏蔽寄存器(EXTI_EMR)。简单的控制EXTI_EMR来实现是否产生事件的目的。
7. 一个脉冲发生器电路,当它的输入端,即编号6电路的输出端,是一个有效信号1时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
8. 个脉冲信号,就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器TIM、模拟数字转换器ADC等等,这样的脉冲信号一般用来触发TIM或者ADC开始转换。

  • 产生中断线路目的是把输入信号输入到NVIC,进一步会运行中断服务函数,实现功能,这样是==软件级==的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于==硬件级==的。
  • EXTI是在APB2总线上的。

中断|事件线

中断|事件
XTI0至EXTI15用于GPIO,通过编程控制可以实现任意一个GPIO作为EXTI的输入源。由表18-1可知,EXTI0可以通过AFIO的外部中断配置寄存器1(AFIO_EXTICR1)的EXTI0[3:0]位选择配置为PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0或者PI0.

EXTI初始化结构体详解

1
2
3
4
5
6
7
typedefstruct 
{
uint32_tEXTI_Line; // 中断/事件线
EXTIMode_TypeDef EXTI_Mode; // EXTI模式
EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
FunctionalState EXTI_LineCmd; // EXTI使能
} EXTI_InitTypeDef;

1) EXTI_Line:EXTI中断/事件线选择,可选EXTI0至EXTI19。
2) EXTI_Mode:EXTI模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
3) EXTI_Trigger:EXTI边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发(EXTI_Trigger_Falling)或 者 上 升 沿 和 下 降 沿 都 触 发(EXTI_Trigger_Rising_Falling) 。
4) EXTI_LineCmd:控制是否使能EXTI线,可选使能EXTI线(ENABLE)或禁用(DISABLE)。

存储器和总线框架

系统构架

  • 四个驱动单元
  1. Cortex™-M3内核DCode总线(D-bus),和系统总线(S-bus)
  2. 通用DMA1和通用DMA2
  • 四个被动单元
  1. 内部SARM
  2. 内部闪存存储器
  3. FSMC
  4. AHB到APB的桥,它连接支持所有APB设备
    1563448621651

  • ICode总线
    该总线将Cortex™-M3内核的指令总线闪存指令接口相连接。指令预取在此总线上完成。
  • DCode总线
    该总线将Cortex™-M3内核的DCode总线与闪存存储器的数据接口相连接(常量加载和调试访问)。
  • 系统总线
    此总线连接Cortex™-M3内核的系统总线(外设总线)到总线矩阵,总线矩阵协调着内核和DMA间的访问。
  • DMA总线
    此总线将DMA的AHB主控接口与总线矩阵相联,总线矩阵协调着CPU的DCode和DMA到SRAM、闪存和外设的访问。
  • 总线矩阵
    总线矩阵协调内核系统总线和DMA主控总线之间的访问仲裁,仲裁利用轮换算法。
  • AHB/APB桥(APB)
    两个AHB/APB桥在AHB和2个APB总线间提供同步连接。APB1操作速度限于36MHz,APB2操作于全速(最高72MHz)。在每一次复位以后,所有除SRAM和FLITF以外的外设都被关闭,在使用一个外设之前,必须设置寄存器RCC_AHBENR来打开该外设的时钟。

GPIO

GPIO 是通用输入输出端口的简称,简单来说就是STM32 可控制的引脚,STM32 芯片的GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。

GPIO结构框图

基本结构

保护二极管及上、下拉电阻

引脚的两保护个二级管可以防止引脚外部过高或过低的电压输入,当引脚电压高于VDD_FT时,上方的二极管导通,当引脚电压低于VSS时,下方的二极管导通,防止不正常电压引入芯片导致芯片烧毁。
上拉、下拉电阻,从它的结构我们可以看出,通过上、下拉对应的开关配置,我们可以控制引脚默认状态的电压,开启上拉的时候引脚电压为高电平,开启下拉的时候引脚电压为低电平,这样可以消除引脚不定状态的影响。如引脚外部没有外接器件,或者外部的器件不干扰该引脚电压时,STM32的引脚都会有这个默认状态。
可以设置“既不上拉也不下拉模式”,称为浮空模式。 *
*
STM32 的内部上拉是“弱上拉”,即通过此上拉输出的电流是很弱的,如要求大电流还是需要外部上拉。**

P-MOS 管和N-MOS管

GPIO 引脚线路经过上、下拉电阻结构后,向上流向“输入模式”结构,向下流向“输出模式”结构。先看输出模式部分,线路经过一个由P-MOS 和N-MOS 管组成的单元电路。这个结构使GPIO 具有了==“推挽输出”==和==“开漏输出”==两种模式。image

高电平时,上方的P-MOS 导通,下方的N-MOS关闭,对外输出高电平;而在该结构中输入低电平时,N-MOS管导通,P-MOS关闭,对外输出低电平。当引脚高低电平切换时,两个管子轮流导通,一个负责灌电流,一个负责拉电流,使其负载能力和开关速度都比普通的方式有很大的提高。
推挽输出的低电平为0 伏,高电平为3.3伏,它是推挽输出模式时的等效电路。而在开漏输出模式时,上方的P-MOS 管完全不工作。如果我们控制输出为0,低电平,则P-MOS 管关闭,N-MOS 管导通,使输出接地,若控制输出为1 (它无法直接输出高电平) 时,则P-MOS 管和N-MOS 管都关闭,所以引脚既不输出高电平,也不输出低电平,为高阻态。为正常使用时必须接上拉电阻(可用STM32 的内部上拉,但建议在STM32外部再接一个上拉电阻),。它具“线与”特性,也就是说,若有很多个开漏模式引脚连接到一起时,只有当所有引脚都输出高阻态,才由上拉电阻提供高电平,此高电平的电压为外部上拉电阻所接的电源的电压。若其中一个引脚为低电平,那线路就相当于短路接地,使得整条线路都为低电平,0 伏。推挽输出模式一般应用在输出电平为0 和3.3 伏而且需要高速切换开关状态的场合。
在STM32的应用中,除了必须用开漏模式的场合,我们都习惯使用推挽输出模式。

输出数据寄存器

双MOS 管结构电路的输入信号,是由GPIO“输出数据寄存器GPIOx_ODR”提供的,因此我们通过修改输出数据寄存器的值就可以修改GPIO引脚的输出电平。而“置位/复位寄存器GPIOx_BSRR”可以通过修改输出数据寄存器的值从而影响电路的输出。

复用功能输出

“复用功能输出”中的“复用”是指STM32 的其它片上外设对GPIO 引脚进行控制,此时GPIO 引脚用作该外设功能的一部分,算是第二用途。从其它外设引出来的“复用功能输出信号”与GPIO 本身的数据据寄存器都连接到双MOS 管结构的输入中,通过图中的梯形结构作为开关切换选择。

输入数据寄存器

看GPIO 结构框图的上半部分,它是GPIO引脚经过上、下拉电阻后引入的,它连接到施密特触发器,信号经过触发器后,模拟信号转化为0、1的数字信号,然后存储在“输入数据寄存器GPIOx_IDR”中,通过读取该寄存器就可以了解GPIO引脚的电平状态。

复用功能输入

与“复用功能输出”模式类似,在“复用功能输出模式”时,GPIO 引脚的信号传输到STM32 其它片上外设,由该外设读取引脚状态。同样,如我们使用USART 串口通讯时,需要用到某个GPIO 引脚作为通讯通讯接收引脚,这个时候就可以把该GPIO 引脚配置成USART 串口复用功能,使USART 可以通过该通讯引脚的接收远端数据。

模拟输入输出

GPIO 引脚用于ADC 采集电压的输入通道时,用作“模拟输入”功能,此时信号是不经过施密特触发器的,因为经过施密特触发器后信号只有0、1 两种状态,所以ADC 外设要采集到原始的模拟信号,信号源输入必须在施密特触发器之前。类似地,当GPIO 引脚用于DAC 作为模拟电压输出通道时,此时作为“模拟输出”功能,DAC 的模拟信号输出就不经过双MOS 管结构了,在GPIO 结构框图的右下角处,模拟信号直接输出到引脚。同时,当GPIO 用于模拟功能时(包括输入输出),引脚的上、下拉电阻是不起作用的,这个时候即使在寄存器配置了上拉或下拉模式,也不会影响到模拟信号的输入输出

GPIO 工作模式

输入模式(上拉、下拉、浮空)

在输入模式时,施密特触发器打开,输出被禁止。数据寄存器每隔1 个AHB1 时钟周期更新一次,可通过输入数据寄存器GPIOx_IDR 读取I/O 状态。

输出模式(推挽/开漏,上拉/下拉)

于输出模式时,可使用上拉、下拉模式或浮空模式。但此时由于输出模式时引脚电平会受到ODR 寄存器影响,而ODR 寄存器对应引脚的位为0,即引脚初始化后默认输出低电平,所以在这种情况下,上拉只起到小幅提高输出电流能力,但不会影响引脚的默认状态.

复用功能(推挽/开漏,上拉/下拉)

复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,但是输出信号源于其它外设,输出数据寄存器GPIOx_ODR 无效;输入可用,通过输入数据寄存器可获取I/O 实际状态,但一般直接用外设的寄存器来获取该数据信号。用于复用功能时,可使用上拉、下拉模式或浮空模式。同输出模式,在这种情况下,初始化后引脚默认输出低电平,上拉只起到小幅提高输出电流能力,但不会影响引脚的默认状态

模拟输入输出

模拟输入输出模式中,双MOS 管结构被关闭,施密特触发器停用,上/下拉也被禁止。其它外设通过模拟通道进行输入输出。

寄存器

  • 什么是寄存器?什么是寄存器映射?
  • 什么是存储器映射和存储器重映射?
  • 为什么存储器要重映射?

存储器映射

存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址 的过程就称为存储器映射。==如果给存储器再分配一个地址就叫存储器重映射。

存储器映射

存储器区域功能划分

在这 4GB的地址空间中,ARM已经粗线条的平均分成了 8个块,每块 512MB,每个 块也都规定了用途
存储器功能分类
Boock0用来设 计成内部 FLASH,Block1用来设计成内部 RAM,Block2用来设计成片上的外设。

寄存器外设

在存储器 Block2这块区域,设计的是片上外设,它们以四个字节为一个单元,共 32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可 以找到每个单元的起始地址,然后通过 C语言指针的操作方式来访问这些单元,如果每次 都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元
功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器, 这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫==寄存器映射==。

外设地址映射

片上外设区分为四条总线,根据外设速度的不同,不同总线挂载着不同的外设,APB 挂载低速外设,AHB挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线 基地址也是挂载在该总线上的首个外设的地址。其中 APB1总线的地址最低,片上外设从 这里开始,也叫外设基地址。

外设基地址

总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的首个地址称为 “XX外设基地址”,也叫 XX外设的边界地址8。

外设寄存器

在 XX外设的地址范围内,分布着的就是该外设的寄存器。以 GPIO 外设为例,GPIO 是通用输入输出端口的简称,简单来说就是 STM32可控制的引脚,基本功能是控制引脚输 出高电平或者低电平。

寄存器说明

  • 名称

  • 偏移地址
    是指本寄存器相对于这个外设的基地址的偏移。

  • 寄存器位表

  • 功能说明
    详细介绍寄存器每一位的功能。

     GPIO 端口置位/复位寄存器说明


  • 存储器block2上设计的是片上外设,以四个字节为一个单元,每个单元负责不同功能。根据每个单元功能的不同,以功能为名给内存单元取别名,别名即为寄存器。给分配好地址的有特定功能的内存单元取名的过程为寄存器映射。

寄存器是特定功能的内存单元的别称,方便我们使用该内存单元。寄存器映射是给内存单元取别名的过程。

  • 存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址 的过程就称为存储器映射,如果给存储器再分配一个地址就叫存储器重映射。

存储器映射是指厂商或用户给存储器分配空间的过程,存储器重映射是指在存 储器映射的基础上,给存储器再分配地 址的过程

  • 存储器重映射就是为了快速响应中断或者快速完成某个任务,将同一地址段映射到不同速度的两个存储块,然后将低速存储块中的代码段复制到高速存储块中,对低速存储块的访问将被重映射为对高速存储块的访问。

    存储器映射是在复位之前由CPU自动完成的,存储器重映射是在复位之后由系统程序完成的。通常的顺序是:上电->存储器映射->复位->存储器重映射->系统初始化->启动OS。

STM32库

什么是STM32库

STM32 库是由 ST公司针对 STM32 提供的 函数接口,即 API ( Application Program Interface ) ,开发者可调用这些函数接口来配置 STM32 的寄存器,使开发人员得以 脱离最底层的寄存器操作,有开发快速,易 于阅读,维护成本低等优点。
==库是架设在寄存器与用户驱动层之间的代码,向下处理与寄存器
直接相关的配置,向上为用户提供配置寄存器的接口
==

库目录,文件简介

Libraries 文件夹下是驱动库的源代码及启动文件。
Project 文件夹下是用驱动库写的例子跟一个工程模板。

  • core_cm3.c 文件
    在CoreSupport 中的是位于 CMSIS 标准的 核内设备函数层 的 M3 核通用
    的源文件
    cor e_cm3.c
    和头文件
    core_cm3.h ,它们的作用是为那些采用 Cortex-M3 核设计 SOC 的芯片商设计的芯片外设提供一个进入 M3 内核的接 口。这两个文件在其它公司的 M3 系列芯片也是相同的。

core_cm3.c
文件还有一些与编译器相关条件编译语句,用于屏蔽不同编
译器的差异

  • system_stm32f10x.c
    在DeviceSupport文件夹下的是==启动文件、 外设寄存器定义 & 中断向量 定义层==的一些文件,这是由 ST公司提供的。
    system_stm32f10x.c遵守CMSIS标准。该文件的功能是==设置系统时钟和总线时钟==。
    还要通过 M3 核的核内寄存器来对时钟进行倍频,分频

  • stm32f10x.h
    Libraries \ CMSIS \ Core \ CM3 \ startup \ arm
    文件夹下是由汇编编写的系统启动文件不同的文件对应不同的芯片型号,在使用时要注意

文件名的英文缩写的意义如下:
cl:互联型产品,stm32f105/107 系列
vl:超值型产品,stm32f100 系列
xl:超高密度(容量)产品,stm32f101/103 系列
ld:低密度产品,FLASH 小于 64K
md:中等密度产品,FLASH=64 or 128
hd:高密度产品,FLASH 大于 128

启动文件是任何处理器在上点复位之后最先运行的一段汇编程序。在我们 编写的 c 语言代码运行之前,需要由汇编为 c 语言的运行建立一个合适的环
境,接下来才能运行我们的程序。

启动文件的作用是

  1. 初始化堆栈指针 SP;
  2. 初始化程序计数器指针 PC;
  3. 设置堆、栈的大小;
  4. 设置异常向量表的入口地址;
  5. 配置外部 SRAM 作为数据存储器(这个由用户配置,一般的开发板可没 有外部 SRAM);
  6. 设置 C库的分支入口__main(最终用来调用 main 函数);
  7. 在 3.5 版的启动文件还调用了在
    system_stm32f10x.c
    文件中的
    SystemIn i () 函数配置系统时钟,在旧版本的工程中要用户进入 main 函数自己调用SystemIni () 函数。
  • STM32F10x_StdPeriph_Driver
    Libraries \ STM32F10x_StdPeriph_Driver 文件夹下有
    inc (include 的
    缩写)跟
    src (source 的简写)这两个文件夹,这都属于 CMSIS 的 设备外设函
    数 部分。 src 里面是每个设备外设的驱动程序,这些外设是芯片制造商在 Cortex-M3 核外加进去的.

特别的misc.c 文件,这个文件提供了外设 对内核中的 NVIC(中断向量控制器)的访问函数,在配置中断时,我们必须把这 个文件添加到工程中。

  • stm32f10x_it.c、stm32f10x_conf.h
    在库目录的 \Project\STM32F10x_StdPeriph_Template 目录下,存放了官方的一个库工程模板,我们在用库建立一个完整的工程时,还需要添加这个目录下的stm32f10x_it.c 、 stm32f10x_it.h、stm32f10x_conf.h 这三
    个文件。
    stm32f10x_it.c,是专门用来编写==中断服务函数==的,在我们修改前,这个文件已经定义了一些系统异常的接口,其它普通中断服务函数由我们自己添加。

    库各文件间的关系

STM32 库文件结构

STM32结构及库层次关系

CMSIS标准

image
内核函数层: 包含用于访问内核寄存器的名称、地址定义,主要有ARM公司(生产内核)提供;
设备外设访问层: 提供片上的核外外设的地址和中断定义,由芯片生产商提供。

stm32时钟系统

时钟系统图

时钟系统图

时钟源

在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。从时钟频率来分可以分为==高速时钟源==和==低速时钟源==,在这5个中HIS,HSE以及PLL是高速时钟,LSI和LSE是低速时钟。从来源可分为==外部时钟源==和==内部时钟源==,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中HSE和LSE是外部时钟源,其他的是内部时钟源。

  1. HSI是高速内部时钟,RC振荡器,频率为8MHz。
  2. HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。我们的开发板接的是8M的晶振。
  3. LSI是低速内部时钟,RC振荡器,频率为40kHz。独立看门狗的时钟源只能是LSI,同时LSI还可以作为RTC的时钟源。
  4. LSE是低速外部时钟,接频率为32.768kHz的石英晶体。这个主要是RTC的时钟源。
  5. PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。

A. MCO是STM32的一个时钟输出IO(PA8),它可以选择一个时钟信号输出,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。这个时钟可以用来给外部其他系统提供时钟源

B.这里是RTC时钟源,从图上可以看出,RTC的时钟源可以选择LSI,LSE,以及HSE的128分频。

C.从图中可以看出C处USB的时钟是来自PLL时钟源。STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,==当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz==。

D.D处就是==STM32的系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源==。系统时钟可选择为PLL输出、HSI或者HSE。系统时钟最大频率为72MHz,当然你也可以超频,不过一般情况为了系统稳定性是没有必要冒风险去超频的。

E.这里的E处是指其他所有外设了。从时钟图上可以看出,其他所有外设的时钟最终来源都是SYSCLK。SYSCLK通过AHB分频器分频后送给各模块使用。这些模块包括:
①、AHB总线、内核、内存和DMA使用的HCLK时钟。
②、通过8分频后送给Cortex的系统定时器时钟,也就是systick了。
③、直接送给Cortex的空闲运行时钟FCLK。
④、送给APB1分频器。APB1分频器输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。
⑤、送给APB2分频器。APB2分频器分频输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给定时器(Timer)1倍频器使用。
APB1和APB2的区别,APB1上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3等等,APB2上面连接的是高速外设包括UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口等。


STM32时钟系统的配置除了初始化的时候在system_stm32f10x.c中的SystemInit()函数中外,其他的配置主要在stm32f10x_rcc.c文件中,
统时钟,默认情况下是在SystemInit函数的SetSysClock()函数中间判断的,而设置是通过宏定义设置的。
SystemInit()函数中设置的系统时钟大小:
SYSCLK(系统时钟) =72MHz
AHB总线时钟(使用SYSCLK) =72MHz
APB1总线时钟(PCLK1) =36MHz
APB2总线时钟(PCLK2) =72MHz
PLL时钟 =72MHz


RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。ADC时钟由高速APB2时钟经2、4、6或8分频后获得。定时器时钟频率分配由硬件按以下2种情况自动设置:

  1. 如果相应的APB预分频系数是1,定时器的时钟频率与所在APB总线频率一致。
  2. 否则,定时器的时钟频率被设为与其相连的APB总线频率的2倍。

串口操作

[TOC]

CreateFile方式

函数说明

  1. 函数功能
    这个函数的功能是创建或者打开一个文件或者I/O设备,通常使用的I/O形式有文件、文件流、目录、物理磁盘、卷、终端流等。如执行成功,则返回文件句柄。 INVALID_HANDLE_VALUE 表示出错,会设置 GetLastError 。
    1. 函数原型
      1
      2
      3
      4
      5
      6
      7
      8
      9
      HANDLE CreateFile(
        LPCTSTR lpFileName, //指向文件名的指针
        DWORD dwDesiredAccess, //访问模式(写/读)
        DWORD dwShareMode, //共享模式
        LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
        DWORD dwCreationDisposition, //如何创建
        DWORD dwFlagsAndAttributes, //文件属性
        HANDLE hTemplateFile //用于复制文件句柄
        );
    2. 参数列表
参数 类型 作用
lpFileName String 要打开的文件的名字
dwDesiredAccess Long 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息
dwShareMode Long 零表示不共享; FILE_SHARE_READ 和/或 FILE_SHARE_WRITE 表示允许对文件进行共享访问
LPSECURITY_ATTRIBUTES SECURITY_ATTRIBUTES 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)
dwCreationDisposition Long 下述常数之一:
CREATE_NEW创建文件;如文件存在则会出错;
CREATE_ALWAYS创建文件,会改写前一个文件;
OPEN_EXISTING文件必须已经存在。由设备提出要求;
OPEN_ALWAYS如文件不存在则创建它;
TRUNCATE_EXISTING 将现有文件缩短为零长度
dwFlagsAndAttributes Long 一个或多个下述常数:
FILE_ATTRIBUTE_ARCHIVE标记归档属性;
FILE_ATTRIBUTE_COMPRESSED:将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式;
FILE_ATTRIBUTE_NORMAL默认属性;
FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录;
FILE_ATTRIBUTE_READONLY 文件为只读;
FILE_ATTRIBUTE_SYSTEM 文件为系统文件;
FILE_FLAG_WRITE_THROUGH操作系统不得推迟对文件的写操作;
FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作;
FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块;
FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化;
FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化;
FILE_FLAG_DELETE_ON_CLOSE; 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件;
也可在Windows NT下组合使用下述常数标记:
SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY
hTemplateFile Long 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性
返回值
如执行成功,则返回文件句柄。
INVALID_HANDLE_VALUE表示出错,会设置GetLastError
即使函数成功,但若文件存在,且指定了CREATE_ALWAYS **或 OPEN_ALWAYS,GetLastError也会设为ERROR_ALREADY_EXISTS
  1. 配置
  • dwShareMode: 指定端口共享属性
    该参数是由那些应用程序共享的文件提供。对于串口来说,是不能共享的,因此,必须设置为0,这是通信设备与文件的特殊差别。
    如果当前的应用程序调用CreateFile打开一个串口,另外一个程序如果已经打开了该串口,此时CreateFile会返回一个错误代码。
    然而,同一个应用程序的多个线程是可以共享CreateFile返回的端口句柄。并且根据安全属性设置,该句柄可以打开端口的应用程序的子程序来继承。
  • lpSecurityAttributes:安全属性
    一般该参数为NULL,即该端口被设置为缺省的安全属性。缺省安全属性下,端口的句柄是不能继承的。
  • wCreationDisposition:指定此端口正在被其他程序占用采取的动作
    因为串口总是存在的,因此必须设置为OPEN_EXISTing, 该标志高速Windows不要创建新的端口。而是打开一个已经存在的端口。
  • dwFlagsAndSttributes:描述了端口的各种属性
    对于文件来说有很多属性,但是对于串口来说,唯一的意义是FILE_FLAG _OVERLAPPED 属性,当设置该属性时,端口IO可以在后台进行,称为异步IO重叠结构。
  • hTemplateFile: 指定模板的文件句柄
    对于串口来说,此参数必须设置为0;

    DCB结构体

    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
    typedef struct _DCB { 
    DWORD DCBlength;
    DWORD BaudRate;
    DWORD fBinary: 1;
    DWORD fParity: 1;
    DWORD fOutxCtsFlow:1;
    DWORD fOutxDsrFlow:1;
    DWORD fDtrControl:2;
    DWORD fDsrSensitivity:1;
    DWORD fTXContinueOnXoff:1;
    DWORD fOutX: 1;
    DWORD fInX: 1;
    DWORD fErrorChar: 1;
    DWORD fNull: 1;
    DWORD fRtsControl:2;
    DWORD fAbortOnError:1;
    DWORD fDummy2:17;
    WORD wReserved;
    WORD XonLim;
    WORD XoffLim;
    BYTE ByteSize;
    BYTE Parity;
    BYTE StopBits;
    char XonChar;
    char XoffChar;
    char ErrorChar;
    char EofChar;
    char EvtChar;
    WORD wReserved1;
    } DCB;
    成员 说明
    DCBlength DCB结构大小,即sizeof (DCB),在调用SetConmState来更新DCB前必须作设置

    BaudRate

    指定当前采用的波特率,应与所连接的通讯设备相匹配

    fBinary

    指定是否允许二进制模式。Win32 API不支持非二进制模式传输,应设置为true

    fParity

    指定奇偶校验是否允许,在为true时具体采用何种校验看Parity设置

    Parity

    指定端口数据传输的校验方法。以下是可取值及其意义:

    取值

    意义

    EVENPARITY

    偶校验(2)

    MARKPARITY

    标记校验,所发信息帧第9位恒为1 (3)

    N0PARITY

    无校验(0)

    ODDPARITY

    奇校验(1)

    StopBits

    指定端口当前使用的停止位数,可取值:

    取值

    意义

    0NEST0PBIT

    1停止位(0)

    0NE5ST0PBITS

    1.5停止位(1)

    TW0ST0PBITS

    2停止位(2)

    fErrorChar

    该值为TRUE,则用ErrorChar指定的字符代替奇偶校验错误的接收字符

    ErrorChar

    指定ErrorChar字符(代替接收到的奇偶校验发生错误时的字节)

    EvtChar

    当接收到此字符时,会产生一个EV_RXFLAG事件,如果用SetCommMask函数中指定了 EV_RXFLAG,则可用WaitCommEvent来监测该事件

    EofChar

    指定用于标示数据结束的字符

    fNull

    为TRUE时,接收时自动去掉空(0值)字节

    fAbortOnError

    读写操作发生错误时是否取消操作。若设置为true,则当发生读写错误时,将取消 所有读写操作(错误状态置为ERR0R_I0_AB0RTm)),直到调用ClearConmError函数 后才能重新进行通讯操作

    fOutxCtsFlow

    是否监控CTS(clear-to-send)信号来做输出流控。当设置为true时:

    若CTS为低电平,则数据发送将被挂起,直至CTS变为高。

    CTS的信号一般由DCE (通常是一个Modem)来控制,而DTE (通常是计算机)发送数 据时监测CTS信号。也就是说DCE通过把CTS置高来表明自己可以接收数据了

    fRtsControl

    设置 RTS (reciiiest-to-send)流控,若为 0 则缺省取值 RTS_CONTROL_HANDSHAKE。以 下是可取值及其意义:

    取值

    意义

    RTS_CONTROL_DISABLE

    打开设备时置RTS信号为低电平,应用程序可通过调用 EscapeCoranFunction函数来改变RTS线电平状态

    RTS_CONTROL_ENABLE

    打开设备时置RTS信号为高电平,应用程序可通过调用 EscapeCoranFunction函数来改变RTS线电平状态

    RTS_CONTROL_HANDSHAKE

    允许RTS信号握手,此时应用程序不能调用 EscapeCoranFunction函数。当输入缓冲区己经有足够空间 接收数据时,驱动程序置RTS为高以便允许DCE来发送; 1之置RTS为低以阻止DCE发送数据。

    RTS_C0NTR0L_T0GGLE

    有字节要发送时RTS变高,当所有缓冲字节己经被发送完 毕后,RTS变低。此时应用程序不能调用 EscapeCoranFunction函数。该值在Windows 95系统被忽略

    fOutxDsrFlow

    是否监控DSR (data-set-ready)信号来做输出流控。当设置为true时:

    若DSR为低电平,则数据发送将被挂起,直至DSR变为高。DSR的信号一般由DCE来 控制

    fDtrControl

    DTR (data-terminal-ready)流控,可取值如下:

    取值

    意义

    DTR_CONTROL_DISABLE

    打开设备时置DTR信号为低电平,应用程序可通过调用 EscapeCoranFunction函数来改变DTR线电平状态

    DTR_CONTROL_ENABLE

    打开设备时置DTR信号为高电平,应用程序可通过调用 EscapeCoranFunction函数来改变DTR线电平状态

    DTR_CONTROL_HANDSHAKE

    允许DTR信号握手,此时应用程序不能调用 EscapeCoranFunction 函数

    fDsrSensitivity i 1

    通讯设备是否对DSR信号敏感。若设置为TRUE,则当DSR为低时将会忽略所有接收 亟字节

    fTXCont inueOnXoff

    当输入缓冲区满且驱动程序己发出XOFF字符时,是否停止发送。当为TRUE时,X0FF 被发送后发送仍然会继续;为FALSE时,发送停止,直至输入缓冲区有XonLim字节 的空余空间、驱动程序己发送X0N字符之后发送继续。

    fOutX

    X0N/X0FF流量控制在发送时是否可用。如果为TRUE,当X0FF值被收到的时候,发 送停止;当X0N值被收到的时候,发送继续

    flnX

    X0N/X0FF流量控制在接收时是否可用。如果为TRUE,当输入缓冲区己接收满 XoffLim字节时,发送X0FF字符;当输入缓冲区己经有XonLim字节的空余容量时, 发送X0N字符

    XonLim

    在X0N字符发送前接收缓冲区内可允许的最小字节数

    XoffLim

    在X0FF字符发送前接收缓冲区内可允许的最大字节数

    XonChar

    指定X0N字符

    XoffChar

    指定X0FF字符

    fDummy2

    保留,未启用

    wReserved

    未启用,i须设置为0
    wReservedl 保留,未启用

串口通信

串口通信有并行和串行两种,多采用串行

1. 并行通信

将数据字节的各位用多条数据线同时进行传送。

2. 串行通信

  • 串行通信将数据字节分为一位一位的形式在一条传输线上逐个传递,外加一条公共信号地线和若干控制信号线。

  • 串行通信可分为异步串行通信和同步串行通信。

    1. 异步串行通信
      • 异步串行通信是指通信的发送与接受使用各自的时钟控制数据的发送和接受过程。为使双方收、发协调,要求发送设备和接受设备时钟经可能一致。
      • 异步通信是以字符为单位进行传送,字符与字符间的间隙是任意的。
      • 异步通信一帧字符信息有4部分构成:起始位、数据位、奇偶校验位和停止位。
      • 单片机与计算机之间通常采用异步通信。
    2. 同步串行通信
      • 同步串行通信要求发送方时钟对接收方时钟的直接控制,使双方达到完全同步。
      • 传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。
      • 发送方对接收方的同步可以通过外同步和自同步两种方法实现。

        串行通信制式

      1. 单工。数据只沿一个方向传递,不能实现反向传输。
      2. 半双工。数据可以沿两个方向传输,但需要分时进行。
      3. 全双工。 数据可以同时进行双向传输。

        错误校验

      • 奇偶校验
      • 代码和校验
      • 循环冗余校验