stm32库开发集


前言

野火笔记


绪论

1.新建工程

1. 新建工程选择我们的芯片型号之后,再选择一些其他的帮助文件(这里不用选):

命名了新建工程之后会生成“工程名.uvprojx”文件,相当于makefile,之后在keil中操作添加文件等会在这个文件中做记录,也就是管理工程的工作。生成Listings文件夹、Objects文件夹,编译生成的文件会在文件夹中。
2. 然后将库添加到文件中即可,我的文件目录(led为例):

led
├── Libraries
│   ├── CMSIS
│   │   ├── core_cm3.c					//内核相关
│   │   ├── core_cm3.h					//内核中外设的寄存器映射
│   │   ├── startup_stm32f10x_hd.s		//起始文件
│   │   ├── stm32f10x.h
│   │   ├── system_stm32f10x.c
│   │   └── system_stm32f10x.h
│   └── FWlib
│       ├── inc						//库的头文件
│       └── src						//库目录,里面放了一众操作外设的库
├── Project
│   └── RVMDK(uv5)
│       ├── BH-F103.uvoptx
│       └── BH-F103.uvprojx
└── User							//放我们自己写的bsp,bsp也可以单独放在一个文件夹下
    ├── bsp_led.c
    ├── bsp_led.h
    ├── main.c
    ├── stm32f10x_conf.h
    ├── stm32f10x_it.c
    └── stm32f10x_it.h

其实以上文件随便怎么放,只要keil中添加需要的文件即可,也就是帮助生成工程管理文件。
3. 将需要的文件添加到工程中:

4. 配置一些内容:
Target 中选中微库“ Use MicroLib”,为的是在日后编写串口驱动的时候可以使用printf 函数。

生成hex文件可供串口烧录:

添加头文件:

为stm32f10x_conf.h添加宏定义:
在stm32f10x.h中有过定义:

#ifdef USE_STDPERIPH_DRIVER
  #include "stm32f10x_conf.h"
#endif

为了方便在工程中添加宏定义:

我们用的是hd,可在下面将注释打开,也可以添加宏定义STM32F10X_HD 如上图所示:

#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL) 
  /* #define STM32F10X_LD */     /*!< STM32F10X_LD: STM32 Low density devices */
  /* #define STM32F10X_LD_VL */  /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */  
  /* #define STM32F10X_MD */     /*!< STM32F10X_MD: STM32 Medium density devices */
  /* #define STM32F10X_MD_VL */  /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */  
  /* #define STM32F10X_HD */     /*!< STM32F10X_HD: STM32 High density devices */
  /* #define STM32F10X_HD_VL */  /*!< STM32F10X_HD_VL: STM32 High density value line devices */  
  /* #define STM32F10X_XL */     /*!< STM32F10X_XL: STM32 XL-density devices */
  /* #define STM32F10X_CL */     /*!< STM32F10X_CL: STM32 Connectivity line devices */
#endif

配置好之后,写完用户代码,编译,就可以进行烧录了,我使用串口烧录,串口烧录参数配置如下:

2.和中断相关的几个文件:

startup_stm32f10x_hd.s
中断向量表
core_cm3.h
NVIC_Type 寄存器
SCB_Type系统控制块
stm32f10x.h
IRQn中断号
misc.h
NVIC_InitTypeDef
stm32f10x_exti.h
EXTI_InitTypeDef
stm32f10x_it.h
中断处理函数

配置中断需要做的事情:

1.配置嵌套向量中断控制器NVIC
2.中断初始化
2.在stm32f10x_it.c中注册中断处理函数(注意包含头文件)

外设

1.RCC

在时钟树中基本可以看出所有外设配置时钟的过程

2.外部中断:

EXTI功能框图:

如上图所示,exti可以产生中断,也可以产生事件。产生中断的线路最终信 号流入到 NVIC 控制器内。产生中断的线路,最终信 号流入到 NVIC 控制器内。产生中断线路目的是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这样是 软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号 传输,属于硬件级的。

3.SysTick:和TIM功能类似

系统定时器一般用于操作系统,用于产生时基,维 持操作系统的心跳。系统定时器是一个 24bit 的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 72M。

4.USART:

其数据寄存器9位有效,一般我们将数据设置为8位。发送时低位在前,高位在后。

5.DMA:

请求,通道,仲裁器
当为内存时,可使用任何通道
当为外设时,其通道选择遵循:

仲裁器:当有多个DMA请求时,有优先级,通过控制寄存器配置

6.I2C

硬件i2c只需要调用库函数即可,模拟i2c需要自己产生波形,通过将gpio拉低和拉高。
一般stm32都作为主模式进行通信(作为从机可细看数据手册),当通过START位在总线上产生了起始条件,设备就进入了主模式。也就是每次通信时需要调用库函数I2C_GenerateSTART();结束时调用I2C_GenerateSTOP();
我们看i2c作为主机时的收发时序图:
作为发送器时:
在这里插入图片描述

作为接收器时:在这里插入图片描述

关键:调用硬件后产生的回应是我们最关注的,也就是事件,作为主模式,有EV5,EV6,EV9,EV7,EV8,EV8_2六个事件。
EV5:通信启动
发送启动条件(I2C_GenerateSTART()函数)后,主机必须等待此事件。这意味着I2C总线上的启动条件已正确释放(总线空闲,没有其他设备通信)。
EV6:地址确认事件
在调用I2C_Send7bitAddress后,主机获取此事件,此事件包含发送还是接收的信息。
EV7:数据接收完毕
EV8:正在发送
EV8_2:数据发送完毕
以上是硬件iic,接下来讲模拟i2c。
模拟i2c:
通过SDA的电平信号来表达数据,从机只要读这根总线就可以收到数据。

7.SPI

STM32有三组SPI。
编程时主要注意:
SPI模式、波特率、LSB先行、主从模式、单双项模式。
SPI模式由时钟极性和时钟相位决定,组合有4种模式,主机和从机的模式必须相同。

如果不写入数据SCK引脚不会产生时钟,所以即使在不需要发送只需要接收的情况下,也需要发送数数据。

8.FSMC

是用来扩展静态内存的STM32内的外设,其接口也可以用来进行其他通信,比如LCD的通信。框图如下:不同种类的存储单元的地址不一样:

其有控制总线,地址总线,数据总线。SRAM的信号线如下:

本SRAM 比较小,没有列地址线,它的数据宽度为 16 位,即一个行地址对应 2 字节空间。那么一个行地址就有高位字节和低位字节的区别,想要写进相对应的字节,则需要UB和LB这两个信号线来告诉控制电路。
读写时序如图:

读写时序的流程很类似:
(1) 主机使用地址信号线发出要访问的存储器目标地址;
(2) 控制片选信号 CS1# 及 CS2# 使能存储器芯片;
(3) 若是要进行读操作,则控制读使能信号 OE# 表示要读数据,若进行写操作则控制写使能信号
WE# 表示要写数据;
(4) 使用掩码信号 LB# 与 UB# 指示要访问目标地址的高、低字节部分;
(5) 若是读取过程,存储器会通过数据线向主机输出目标数据,若是写入过程,主要使用数据线向存储器传输目标数据。

不同的存储器使用不同的通信模式,分为模式1、A、2/B、C、D,具体见数据手册。

9.ADC

功能框图:

每个ADC都有18个通道:

typedef struct
{
  uint32_t ADC_Mode;
  FunctionalState ADC_ScanConvMode; 
  FunctionalState ADC_ContinuousConvMode;
  uint32_t ADC_ExternalTrigConv;      
  uint32_t ADC_DataAlign;    
  uint8_t ADC_NbrOfChannel;      
}ADC_InitTypeDef;

如上,需要对adc的模式、通道等进行选择,模式有双模式和单模式选择,双模式代表ADC1和ADC2一起工作(和ADC3无关),双模式选择配置如下:ADC_CR1的DUALMOD位

限制:ADC2没有DMA功能,ADC3没有18个通道号,双通道模式指的是ADC1+ADC2

10.DAC

stm32具有两个 DAC输出通道,分辨率可配置为 8 位或 12 位的数字输入信号,功能框图:

11.TIM

分为基本定时器、通用定时器、高级定时器。

基本定时器:计数器为16位的,只能向上计时,TIM6、TIM7,没有外部的GPIO,只能用来计时,时钟来自PCLK1,72M,可实现1~65536分频。

高级定时器:定时、输出比较、输入捕获、断路输出+互补输出。有一个重复计数器RCR,4个GPIO,时钟来自PCLK2。
高级定时器的基本功能框图:

1.PWM
2.专门用于驱动数模转换器 (DAC)(关于驱动 DAC 具体应用参考 DAC 章节)

基本定时器只能使用内部时钟
重要的寄存器:计数器寄存器 (TIMx_CNT)、预分频器寄存器 (TIMx_PSC)、自动重载寄存器 (TIMx_ARR)

重要的两个功能:1.输入捕获。2.输出比较
1.输入捕获:
(1)测量脉冲宽度:
涉及到两个结构体:时基结构体TIM_TimeBaseInitTypeDef,输入捕获结构体TIM_ICInitTypeDef
可以测得跳变的脉冲宽度和周期
(2)捕获pwm信号
2.输出比较:
(1)生成pwm,带死区以及刹车
涉及到三个结构体:时基结构体TIM_TimeBaseInitTypeDef、输出比较结构TIM_OCInitTypeDef、刹车和死区结构体TIM_BDTRInitTypeDef
(2)多路pwm输出

12.wdt

iwdt独立看门狗

12 位的递减计数器,当计数器的值从某个值一直减到 0 的时候,系统就会产生一个复位信号,即 IWDG_RESET。时钟由独立的 RC 振荡器 LSI 提供,即使主时钟发生故障它仍然有效(LSI 的频率一般在 30~60KHZ 之间,根据温度和工作场合会有一定的漂移,一般取 40KHZ,定时时间并不一定非常精确)

wwdt窗口看门狗

当减到一个固定值 0X40时还不喂狗的话,产生复位,这个值叫窗口的下限,是固定的值,不能改变。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗:如图WR为用户设置

13.SDIO

 CLK:时钟线,由 SDIO 主机产生,即由 STM32 控制器输出;
 CMD:命令控制线,SDIO 主机通过该线发送命令控制 SD 卡,如果命令要求 SD 卡提
供应答(响应),SD 卡也是通过该线传输应答信息;
 D0-3:数据线,传输读写数据;SD 卡可将 D0 拉低表示忙状态;
 VDD、VSS1、VSS2:电源和地信号。

SD卡寄存器:SDIO 定义了 64 个命令,通过八个寄存器来操作

总线拓扑:

SD 卡操作过程会使用两种不同频率的时钟同步数据,一个是识别卡阶段时钟频率 FOD,最高为 400kHz,另外一个是数据传输模式下时钟频率 FPP,默认最高为 25MHz,如果通过相关寄存器配置使 SDIO 工作在高速模式,此时数据传输模式最高频率为 50MHz。

命令与响应交互如下:

命令除了SSR的sd状态之外(如果有返回值),都是通过命令线返回的,但是他是通过数据线返回的,因为数据比较大。

数据传输:
SDHC 卡数据块长度一般为 512 字节,数据块需要 CRC 位来保证数据传输成功(CRC位由SD卡系统硬件生成)。(STM32 控制器可以控制使用单线或 4 线传输)

四根线发送数据有两种格式:

另外一种数据包发送格式是宽位数据包格式,对SD卡而言宽位数据包发送方式是针对SD卡 SSR(SD状态)寄存器内容发送的,SSR寄存器总共有 512bit,在主机发出 ACMD13命令后 SD 卡将 SSR 寄存器内容通过 DAT 线发送给主机,其格式:

命令
SD 命令由主机发出,以广播命令和寻址命令为例,广播命令是针对与 SD 主机总线连接的所有从设备发送的,寻址命令是指定某个地址设备进行命令传输。
格式:SD 命令格式固定为 48bit,都是通过 CMD 线连续传输的

传输标志:用于区分传输方向,该位为 1 时表示命令,方向为主机传输到 SD卡,该位为 0 时表示响应,方向为 SD 卡传输到主机。
命令号:它固定占用 6bit,所以总共有 64 个命令(代号:CMD0~CMD63),每个命令都有特定的用途,部分命令不适用于 SD 卡操作,只是专门用于 MMC 卡或者SD I/O 卡。
地址/参数:每个命令有 32bit 地址信息/参数用于命令附加内容,(例如广播命令没有地址信息,这 32bit 用于指定参数,而寻址命令这 32bit 用于指定目标 SD 卡的地址。)

命令有 4 种类型:
 无响应广播命令(bc),发送到所有卡,不返回任务响应;
 带响应广播命令(bcr),发送到所有卡,同时接收来自所有卡响应;
 寻址命令(ac),发送到选定卡,DAT 线无数据传输;
 寻址数据传输命令(adtc),发送到选定卡,DAT 线有数据传输。
除了常规命令,还有特定应用命令ACMD,具体命令列表略。

响应
有 7 个响应类型(代号:R1~R7),其中 SD 卡没有 R4、R5 类型响应。


sd卡的操作模式及切换

识别模式下状态转换:

数据传输模式下状态转换:


适配器框图:

适配器命令路径:

适配器数据路径:

SDIO 适配器数据状态转换(DPSM):

14.CAN

总述:

1.消息的发送:
两个以上的单元同时开始发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。在同一网络中所有的单元必须设定成统一的速度。
2.远程数据请求:可通过发送“遥控帧” 请求其他单元发送数据。
3.错误检测、错误通知、错误恢复功能:
所有的单元都可以检测错误(错误检测功能)。
检测出错误的单元会立即同时通知其他所有单元(错误通知功能)。
正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。
4.故障封闭:
CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
5.连接:
数目受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。

错误:
错误状态种类:主动错误状态、被动错误状态、总线关闭状态。
单元始终处于三种状态之一(具体略)错误累加会导致状态改变:
0~127次收发错误:主动错误状态
128~255收或发:被动错误状态
256~:总线关闭状态
错误种类:
位错误、填充错误、CRC错误、格式错误、ACK错误。
错误检测如图所示:

CAN和ISO:

数据链路层分为 MAC 子层和 LLC 子层,MAC 子层是 CAN 协议的核心部分。数据链路层的功能是将物理层收到的信号组织成有意义的消息,并提供传送错误控制等传输控制的流程。具体地说,就是消息的帧化、仲裁、应答、错误的检测或报告。数据链路层的功能通常在 CAN 控制器的硬件中执行。
在物理层定义了信号实际的发送方式、位时序、位的编码方式及同步的步骤。但具体地说,信号电平、通信速度、采样点、驱动器和总线的电气特性、连接器的形态等均未定义*1。这些必须由用户根据系统需求自行确定。

CAN协议

帧:
can通过帧来通信,一共有5类:
数据帧,遥控帧,错误帧,过载帧,帧间隔。(数据帧和遥控帧有标准格式和扩展格式。标准格式有 11 个位的标识符( ID),扩展格式有 29 个位的 ID。)
数据帧:

遥控帧:

显性电平和隐性电平:
总线上执行逻辑上的线“与”时,显性电平的逻辑值为“0”,隐性电平为“1”。“显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平。并且,“隐性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平。

优先级的决定:
1.发送单元的优先级:发送单元从第一位开始仲裁,连续输出显性电平多的单元拥有优先权。
2.数据帧和遥控帧优先级争夺:ID相同,数据帧具有优先权(数据帧仲裁段的最后一位(RTR)为显性)
3.标准格式和扩展格式优先级争夺:标准格式

位填充:
位填充是为防止突发错误而设定的功能。当同样的电平持续 5 位时则添加一个位的反型数据。所以此时发送单元和接受单元需要做相应的工作:
(1) 发送单元的工作
在发送数据帧和遥控帧时,SOF~CRC 段间的数据,相同电平如果持续 5 位,在下一个位(第 6 个位)则要插入 1 位与前 5 位反型的电平。
(2) 接收单元的工作
在接收数据帧和遥控帧时,SOF~CRC 段间的数据,相同电平如果持续 5 位,需要删除下一个位(第 6 个位)再接收。如果这个第 6 个位的电平与前 5 位相同,将被视为错误并发送错误帧。

位时序:
由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。一个位可分为 4 段:同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)、相位缓冲段2(PBS2)
1 位分为 4 个段,每个段又由若干个 Tq 构成,这称为位时序。1 位由多少个 Tq 构成、每个段又由多少个 Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。
段及其作用:

一个位可能如下构成:我们可以看到采样点在PBS1结尾处(所谓采样点是读取总线电平,并将读到的电平作为位值的点。)

就像往邮箱里发右邮件:

stm32的can控制器

主要包括两个寄存器: 主控制寄存器CAN_MCR:主要负责初始化一些功能 DBF 调试冻结功能、TTCM 时间触发模式、ABOM 自动离线管理、AWUM 自动唤醒、AWUM 自动唤醒、RFLM 锁定模式、TXFP 报文发送优先级的判定方法(不细说)。 位时序寄存器 CAN_BTR:可以控制一下四种工作模式:

15.其他

BKP介绍

备份寄存器,多用于侵入检测,保护IC的知识产权。可设置bootloader开始时读取BKP中的内容,BKP就像一把钥匙,如果其中的内容被破坏,bootloader就无法启动板子,并且可以删除核心代码。防止有人打开芯片抄袭。

电源管理PWR

如图所示,上电复位状态电压POR比掉电复位状态电压PDR大。

MDK

### flash 必须先擦除再写入,擦除单位是块 norflash:可以一个字节一个字节的读写 nandflash:必须以扇区为单位读写 w25q64bv的命令:(其中有主机传给flash的,也有flash传给主机的)
#define			sFLASH_ID			0xef4017
//命令定义
#define W25X_WriteEnable		      0x06 
#define W25X_WriteDisable		      0x04 
#define W25X_ReadStatusReg		    0x05 
#define W25X_WriteStatusReg		    0x01 
#define W25X_ReadData			        0x03 
#define W25X_FastReadData		      0x0B 
#define W25X_FastReadDual		      0x3B 
#define W25X_PageProgram		      0x02 
#define W25X_BlockErase			      0xD8 
#define W25X_SectorErase		      0x20 
#define W25X_ChipErase			      0xC7 
#define W25X_PowerDown			      0xB9 
#define W25X_ReleasePowerDown	    0xAB 
#define W25X_DeviceID			        0xAB 
#define W25X_ManufactDeviceID   	0x90 
#define W25X_JedecDeviceID		    0x9F

#define 	WIP_Flag		0x01
#define		Dummy_Byte	0xff

RS485

RS485主将RS232的电平信号改成了差分信号,让其拥有长距离传输和强大的抗干扰能力。和CAN十分类似,也是将tx,rx信号通过转换电路转换成差分信号。

摄像头OV7725

支持使用VGA时序输出图像数据,图像数据格式支持YUV(422/420)、YCbCr422、RGB565格式。
引脚:

触摸屏

LCD

两类液晶屏如图所示:

液晶屏信号线如下所示:

LCD控制的关键是LCD控制器,ILI9341控制器的原理图如图所示:

ILI连接stm32的信号线如图所示:

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值