STM32

什么是STM32

  • STM32名字的代表

  • STM32芯片内部可以粗略划分两部分:内核+片上外设。如果与电脑类比,内核与片上外设就如同电脑的CPU与主板、内存、显卡、硬盘的关系。

  • ARM公司只设计内核不生产芯片,他会将有关内核的技术授权给各半导体厂商,这些厂商都是基于这个内核自己设计片上外设如SRAM、ROM、FLASH、USART、GPIO等,然后集成到一个硅片上,这就是我们现在用的芯片。

  • ROM和RAM (半导体存储器)

    1. ROM在系统停止供电的时候仍然可以保持数据
    2. RAM通常都是在掉电之后就丢失数据,典型的RAM就是计算机的内存
    3. RAM分为静态RAM(Static RAM/SRAM)和动态RAM(Dynamic RAM/DRAM
    4. SRAM速度非常快,常用于CPU的一级缓冲,二级缓冲
    5. DRAM保留数据的时间很短,速度也比SRAM慢,不过它还是比任何的ROM都要快,但从价格上来说DRAM相比SRAM要便宜很多,计算机内存就是DRAM的。
    6. DRAM分为很多种,这里介绍其中的一种DDR RAM
  • GPIO (general purpose intput output )

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

    2. GPIO接口至少有两个寄存器,即“通用IO控制寄存器”与“通用IO数据寄存器”。

    3. 可以配置8种输入输出模式

    4. 引脚电平:0V-3.3V

    5. 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序

    6. 输入模式下可以读取端口的高低电平或电压,用于读取按键输入,外接模块电平信号输入,ADC电压采集,模拟通信协议接受数据等

    7. GPIO基本结构

    8. 每个GPIO外设总共有16个引脚,编号是从0到15,PA0-PA15

    9. 1代表高电平,0代表低电平,输入和读取同高低

    10. GPIO位结构

    11. 输入部分:VDD接3.3V  Vss接0V  两个二极管的主要作用是保护电路

    12. 上拉输入模式:上面导通 下面断开 默认为高电平的输入模式

      下拉输入模式:下面导通 上面断开 默认为低电平的输入模式

      浮空输入模式:两个都断开

    13. 上拉电阻和下拉电阻的阻值都很大,目的是尽量不影响正常的输入操作

    14. 施密特触发器:对输入电压进行整形 如果输入电压大于某一阈值,输出就会瞬间升为高电平 如果输入电压小于某一阈值,输出就会瞬间降为低电平

    15. P-MOS N-MOS 是一种导通开关

    16. 推挽模式输出: 两种均有效

    17. 强推挽输出模式:数据寄存器为1时,上管导通,下管断开,输出直接到VDD,输出高电平 

    18. 开漏模式输出:数据寄存器为0时,上管断开,下管导通,输出直接到VSS,输出低电平

    19. 开漏模式可以作为通信协议的驱动方式,比如IIC通信的引脚,就是使用的开漏模式。在多机通信的情况下,该模式还可以避免各个设备的相互干扰。开漏模式还可以用于5V的电平信号

    20. 输入


  • 片上资源

  • 开发方式

  1. 基于标准库(库函数的方式)
  2. 基于HAL库的方式(图形化界面)
  3. 基于寄存器方式

串口通信

串口协议

通信接口

串口时最简单的通信协议,相比于IIC和SPI

  • 通信的目的:将一个设备的数据传送到另一个设备,扩展硬件一同

  • 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发

  • 通信协议

  • 同步通信靠时钟线,异步通信靠比特率

  • 使用差分信号可以极大的提高抗干扰特性,差分信号传送速度和距离都很高

  • 串口通信一般都是点对点,两个设备的互相通信

  • 简单的串口通信电路

  • 电平标准:数据1和数据0的表达方式,人为规定的电压与数据的对应关系

    • TTL电平:+3.3V或+5V表示1   0V表示0
    • RS232电平:-3V到-15V表示1 +3V到+15V表示0
    • RS485电平:两线电压差+2到+6V表示1 -2到-6V表示0(差分信号)
  • 波特率:串口通信的速率 (每隔多久发送一位数据

  • 起始位:标志一个数据帧的开始,固定为低电平

  • 数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行从右往左取数

    就是例如: 01000101 第一位就是1

    01000100 第一位就是 0

  • 校验位:用于数据验证,根据数据位计算得来

    • 奇校验和偶校验(只能保证一定程度上的数据校验)
    • 奇校验:补一位要求1的总数为奇数
    • 偶校验:补一位要求1的总数为偶数
    • CRC校验:
  • 停止位:用于数据帧间隔,固定为高电平

  • 串口参数及时序

USART外设

通用同步/异步收发器

USART简介

一般选用停止位长度为1

中断系统

  • 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
  • 使用中断系统能够 极大的提高程序的效率
  • 中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
  • 中断嵌套:当中断程序正在运行时,又有新的更高优先级的中断资源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回
  • 中断执行流程
  • STM32中断:

STM32库函数

1.void USART_DeInit(USART_TypeDef* USARTx)

功能:将USART寄存器重置为默认值

注释:主要是调用了RCC_APBxPeriphResetCmd函数对寄存器进行复位

例如:USART_DeInit(USART1);

2.void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)
功能:根据结构体的参数配置来对USARTx外设进行初始化

注释:流控制可以控制数据传输的进程,解决接收端数据缓冲区已满,再传输则数据丢失的问题

例如:USART_Init(USART1,&USART_InitStructure);

void USART_StructInit(USART_InitTypeDef* USART_InitStruct)
功能:将USART_InitStructure结构体变量成员按默认值填充

注释:只是填充数据,没有Init的操作部分,没有涉及寄存器写入的操作

例如:USART_StructInit(&USART_InitStructure);

  • void USART_ClockInit void USART_ClockStructInit
  • 功能:配置同步时钟输出 包括时钟是不是要输出,时钟的极性相位等参数 也是用结构体方式配置
  • void USART_Cmd
  • 功能:使能或者失能USART外设 例如:USART_Cmd(USART1 , ENABLE);
  • void USART_ITConfig
  • 功能:配置指定的USART中断 例如:****USART_ITConfig(USART1 , USART_IT_RXNE , ENABLE);
  • void USART_DMACmd
  • 功能:可以开启USART到DMA的触法通道
  • void USART_SendData
  • 功能:SendData 发送数据 Tx
  • uint16_t USART_ReceiveData
  • 功能:ReceiceData 接收数据
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//USART1的TX是PA9 RX是PA10 开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//开启GPIO时钟

RCC初始化:
这里我们使用HSE(外部时钟),正常使用的时候也都是使用外部时钟

使用HSE时钟,程序设置时钟参数流程:
1、将RCC寄存器重新设置为默认值 RCC_DeInit;
2、打开外部高速时钟晶振HSE RCC_HSEConfig(RCC_HSE_ON);
3、等待外部高速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp();
4、设置AHB时钟 RCC_HCLKConfig;
5、设置高速AHB时钟 RCC_PCLK2Config;
6、设置低速速AHB时钟 RCC_PCLK1Config;
7、设置PLL RCC_PLLConfig;
8、打开PLL RCC_PLLCmd(ENABLE);
9、等待PLL工作 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
10、设置系统时钟 RCC_SYSCLKConfig;
11、判断是否PLL是系统时钟 while(RCC_GetSYSCLKSource() != 0x08)
12、打开要使用的外设时钟 RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()

RCC时钟特性

代码实现:

对RCC的配置函数(使用外部8MHz晶振)

系统时钟72MHz,APH 72MHz,APB2 72MHz,APB1 32MHz,USB 48MHz TIMCLK=72M

void RCC_Configuration(void)
{
//----------使用外部RC晶振-----------
RCC_DeInit(); //初始化为缺省值
RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer
FLASH_SetLatency(FLASH_Latency_2);
//Flash 2 wait state

RCC_HCLKConfig(RCC_SYSCLK_Div1);
//HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1);
//PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div2);
//PCLK1 = HCLK/2
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ
RCC_PLLCmd(ENABLE);
//Enable PLLCLK

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//Select PLL as system clock
while(RCC_GetSYSCLKSource()!=0x08);
//Wait till PLL is used as system clock source

//---------打开相应外设时钟--------------------
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能APB2外设的GPIOA的时钟
}

GPIO初始化

   GPIO_InitTypeDef GPIO_InitStructure;
//申明一个结构体,名字GPIO_InitStructure
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//设置输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
//设定要操作的管脚位
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//IO口速度为50MHZ
GPIO_Init(GPIOA, &GPIO_InitStructure);
//根据设定参数配置GPIO

GPIO的工作模式主要有八种4种输入方式,4种输出方式,分别为输入浮空,输入上拉,输入下拉,模拟输入;输出方式为开漏输出,开漏复用输出,推挽输出,推挽复用输出。
(1)GPIO_Mode_AIN 模拟输入 (应用ADC模拟输入,或者低功耗下省电)
(2)GPIO_Mode_IN_FLOATING 浮空输入 (浮空就是浮在半空,可以被其他物体拉上或者拉下,可以用于按键输入)
(3)GPIO_Mode_IPD 下拉输入 (IO内部下拉电阻输入)
(4)GPIO_Mode_IPU 上拉输入 (IO内部上拉电阻输入)
(5)GPIO_Mode_Out_OD 开漏输出(开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行)
(6)GPIO_Mode_Out_PP 推挽输出 (推挽就是有推有拉电平都是确定的,不需要上拉和下拉,IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的 )
(7)GPIO_Mode_AF_OD 复用开漏输出(片内外设功能(I2C的SCL,SDA))
(8)GPIO_Mode_AF_PP 复用推挽输出 (片内外设功能(TX1,MOSI,MISO.SCK.SS))
————————————————
配置USART

USART_InitTypeDef USART_InitStruture;
//结构体参数初始化
USART_InitStruture.USART_BaudRate = 9600;
//波特率
USART_InitStruture.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//硬件流控制
USART_InitStruture.USART_Mode = USART_Mode_Tx;
//发送模式Tx和接收模式Rx
USART_InitStruture.USART_Parity = USART_Parity_No;
//校验位 无校验No 奇校验Odd 偶校验Even
USART_InitStruture.USART_StopBits = USART_StopBits_1;
//停止位 0.5 1 1.5 2
USART_InitStruture.USART_WordLength = USART_WordLength_8b;
//字长 8位或者9位 有无校验 8b 9b
USART_Init(USART1,&USART_InitStruture);