STM32 HAL库开发——入门篇(1)

目录

一、GPIO

1.1 什么是GPIO 

1.2 GPIO简介 

1.2.1 GPIO特点 

1.2.2 GPIO电气特性 

1.2.3 GPIO引脚分布

1.3 IO端口基本结构介绍 

1.4 GPIO的八种模式 

1.5 GPIO的寄存器介绍

1.6 通用外设驱动模型(四步法)

1.7 GPIO配置步骤 

1.8 编程实战:点灯

1.9 编程实战:按键点灯 

二、中断

2.1 什么是中断

2.2 NVIC

2.2.1 NVIC基本概念 

2.2.2 NVIC相关寄存器

2.2.3 NVIC工作原理 

2.2.4 STM32中断优先级基本概念

2.2.5 STM32中断优先级分组

2.2.6 STM32 NVIC的使用 

2.3 EXTI

2.3.1 EXTI基本概念

2.3.2 EXTI主要特性

2.3.3 EXTI工作原理 

2.4 EXTI和IO映射关系

2.5 如何使用中断

2.6 通用外设驱动模型

2.7 HAL库中断回调处理机制介绍 

2.8 编程实战:外部中断控制LED

三、串口通信

3.1 数据通信的基本概念

3.2 串口(RS-232)

3.3 STM32的USART

3.3.1 STM32的USART简介

3.3.2 STM32的USART主要特征 

3.3.3 STM32 F1/F4/F7的USART框图 

3.3.4 设置USART/UART波特率(F1)

3.3.5 USART寄存器介绍

3.4 HAL库外设初始化MSP回调机制

3.5 HAL库中断回调机制

3.6 USART/UART异步通信配置步骤

3.7 IO引脚复用功能

3.8 编程实战:串口接收或发送一个字符 

3.9 串口实验源码解读 

四、IWDG独立看门狗

4.1 IWDG简介 

4.2 IWDG工作原理

4.3 IWDG框图

4.4 IWDG寄存器

4.5 IWDG溢出时间计算

4.6 IWDG配置步骤

4.7 编程实战:验证不及时喂狗

五、WWDG窗口看门狗

5.1 WWDG简介 

5.2 WWDG工作原理

5.3 WWDG框图

5.4 WWDG寄存器

5.5 WWDG超时时间计算 

5.6 WWDG配置步骤

5.7 编程实战:验证窗口看门狗功能

5.8 IWDG和WWDG的区别

用的是正点原子STM32F103ZET6精英版

一、GPIO

STM32 HAL库开发——入门篇(1)_第1张图片

1.1 什么是GPIO 

STM32 HAL库开发——入门篇(1)_第2张图片

1.2 GPIO简介 

STM32 HAL库开发——入门篇(1)_第3张图片

1.2.1 GPIO特点 

STM32 HAL库开发——入门篇(1)_第4张图片超频时才会达到最高50MHz

STM32 HAL库开发——入门篇(1)_第5张图片

1.2.2 GPIO电气特性 

STM32 HAL库开发——入门篇(1)_第6张图片芯片数据手册中,标了FT的就是TTL端口,TTL端口兼容5v和3.3v

STM32 HAL库开发——入门篇(1)_第7张图片

不会每个IO口都是25mA,因为最大电流150mA 

其他用大电流外设要考虑扩流 

1.2.3 GPIO引脚分布

STM32 HAL库开发——入门篇(1)_第8张图片

1.3 IO端口基本结构介绍 

STM32 HAL库开发——入门篇(1)_第9张图片F1只有输入才选择上下拉,F4、F7、H7输入输出都可以选择上下拉

STM32 HAL库开发——入门篇(1)_第10张图片 STM32 HAL库开发——入门篇(1)_第11张图片

STM32 HAL库开发——入门篇(1)_第12张图片STM32 HAL库开发——入门篇(1)_第13张图片STM32 HAL库开发——入门篇(1)_第14张图片 

STM32 HAL库开发——入门篇(1)_第15张图片STM32 HAL库开发——入门篇(1)_第16张图片STM32 HAL库开发——入门篇(1)_第17张图片 

1.4 GPIO的八种模式 

前面4个输入。后面4个输出 

IIC:数据SDA,时钟SCL

STM32 HAL库开发——入门篇(1)_第18张图片

输入: 

STM32 HAL库开发——入门篇(1)_第19张图片STM32 HAL库开发——入门篇(1)_第20张图片STM32 HAL库开发——入门篇(1)_第21张图片STM32 HAL库开发——入门篇(1)_第22张图片输出:

STM32 HAL库开发——入门篇(1)_第23张图片STM32 HAL库开发——入门篇(1)_第24张图片STM32 HAL库开发——入门篇(1)_第25张图片 

输出控制这里有一个反相器 

STM32 HAL库开发——入门篇(1)_第26张图片STM32 HAL库开发——入门篇(1)_第27张图片STM32 HAL库开发——入门篇(1)_第28张图片4中输出模式下,外接一个5v的上拉电阻才可以输出5v的电平 

1.5 GPIO的寄存器介绍

STM32 HAL库开发——入门篇(1)_第29张图片

STM32 HAL库开发——入门篇(1)_第30张图片

STM32 HAL库开发——入门篇(1)_第31张图片CRL+CRH一共64位,16个 引脚,每个脚4个位控制

STM32 HAL库开发——入门篇(1)_第32张图片STM32 HAL库开发——入门篇(1)_第33张图片上拉还是下拉输入模式就要通过ODR寄存器控制

STM32 HAL库开发——入门篇(1)_第34张图片STM32 HAL库开发——入门篇(1)_第35张图片STM32 HAL库开发——入门篇(1)_第36张图片STM32 HAL库开发——入门篇(1)_第37张图片STM32 HAL库开发——入门篇(1)_第38张图片后面是F4,F7,H7的 

STM32 HAL库开发——入门篇(1)_第39张图片总的来说,建议使用BSRR寄存器

1.6 通用外设驱动模型(四步法)

STM32 HAL库开发——入门篇(1)_第40张图片

1.7 GPIO配置步骤 

STM32 HAL库开发——入门篇(1)_第41张图片STM32 HAL库开发——入门篇(1)_第42张图片STM32 HAL库开发——入门篇(1)_第43张图片STM32 HAL库开发——入门篇(1)_第44张图片STM32 HAL库开发——入门篇(1)_第45张图片 

1.8 编程实战:点灯

       0805贴片发光二极管 

STM32 HAL库开发——入门篇(1)_第46张图片STM32 HAL库开发——入门篇(1)_第47张图片       该电流的计算忽略了发光二极管的内阻,不过内阻也很小 ,得到约2.88mA与官方的5~8mA还是有差距,不过没关系就是亮度暗一些

STM32 HAL库开发——入门篇(1)_第48张图片       该led原理图显示led是共阳的,设置开漏输出的话,因为没有外接的上拉电阻,所以只能输出低电平,输出0的时候可以亮,想输出1的时候就是高阻态,PB5断开,led就灭,所以开漏也可以,如果是共阴则不可以 ,共阴如下 

STM32 HAL库开发——入门篇(1)_第49张图片

// PB5; PE5

void led_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    gpio_init_struct.Pin = GPIO_PIN_5;
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; // F1里面输出是禁止使用上下拉的,设置了也是无效的
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &gpio_init_struct);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);  // 初始led为灭
}

正点原子跑马灯的代码,看的我太舒服了!

STM32 HAL库开发——入门篇(1)_第50张图片STM32 HAL库开发——入门篇(1)_第51张图片 

1.9 编程实战:按键点灯 

按键有物理上的抖动,所以需要延时5~10ms消抖,一般就10ms了 

STM32 HAL库开发——入门篇(1)_第52张图片KEY_UP:下拉输入

KEY0、1、2:上拉输入 

精英版没有KEY2

STM32 HAL库开发——入门篇(1)_第53张图片

void key_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    __HAL_RCC_GPIOE_CLK_ENABLE();
    
    gpio_init_struct.Pin = GPIO_PIN_3;
    gpio_init_struct.Mode = GPIO_MODE_INPUT;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);


}

/* 按键扫描  */
uint8_t key_scan(void)
{
    if (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == 0) // 按下了
    {
        delay_ms(10); // 消抖
        if (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == 0)
        {
            while(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == 0); // 松开后才返回1
            return 1; // 按键按下了
        
        }    
        
    }
    return 0; // 按键没有按下


}

按键输入例程:

STM32 HAL库开发——入门篇(1)_第54张图片

二、中断

STM32 HAL库开发——入门篇(1)_第55张图片

2.1 什么是中断

STM32 HAL库开发——入门篇(1)_第56张图片STM32 HAL库开发——入门篇(1)_第57张图片STM32 HAL库开发——入门篇(1)_第58张图片 

2.2 NVIC

STM32 HAL库开发——入门篇(1)_第59张图片

2.2.1 NVIC基本概念 

STM32 HAL库开发——入门篇(1)_第60张图片

中断服务函数被定义在中断向量表里面 

STM32 HAL库开发——入门篇(1)_第61张图片10个内核中断: 

STM32 HAL库开发——入门篇(1)_第62张图片60个外部中断:

STM32 HAL库开发——入门篇(1)_第63张图片STM32 HAL库开发——入门篇(1)_第64张图片 

2.2.2 NVIC相关寄存器

       32*8=256, 一共有240个外部中断,所以有16个位保留了

STM32 HAL库开发——入门篇(1)_第65张图片

2.2.3 NVIC工作原理 

STM32 HAL库开发——入门篇(1)_第66张图片

2.2.4 STM32中断优先级基本概念

STM32 HAL库开发——入门篇(1)_第67张图片STM32 HAL库开发——入门篇(1)_第68张图片

2.2.5 STM32中断优先级分组

STM32 HAL库开发——入门篇(1)_第69张图片

如果AIRCR设置优先级分组为3,那么IPR中的bit7、6、5是设定抢占的,bit4是设定响应的 

STM32 HAL库开发——入门篇(1)_第70张图片如果设置了多次,则已最后一次为准 

STM32 HAL库开发——入门篇(1)_第71张图片

STM32 HAL库开发——入门篇(1)_第72张图片

2.2.6 STM32 NVIC的使用 

STM32 HAL库开发——入门篇(1)_第73张图片 

这里若是 IP[0] 指的就是编号为 0 的WWDG寄存器,共240个,f103只用了60个

STM32 HAL库开发——入门篇(1)_第74张图片

2.3 EXTI

STM32 HAL库开发——入门篇(1)_第75张图片

2.3.1 EXTI基本概念

STM32 HAL库开发——入门篇(1)_第76张图片因为F1不是互联型开发板,所以没有EXTI19,重点就是0~15

STM32 HAL库开发——入门篇(1)_第77张图片

2.3.2 EXTI主要特性

STM32 HAL库开发——入门篇(1)_第78张图片

2.3.3 EXTI工作原理 

STM32 HAL库开发——入门篇(1)_第79张图片

上升沿触发选择寄存器(EXTI_RTSR) 

STM32 HAL库开发——入门篇(1)_第80张图片下降沿触发选择寄存器(EXTI_FTSR) 

STM32 HAL库开发——入门篇(1)_第81张图片

中断屏蔽寄存器(EXTI_IMR) 

STM32 HAL库开发——入门篇(1)_第82张图片

挂机寄存器(EXTI_PR) 

STM32 HAL库开发——入门篇(1)_第83张图片

2.4 EXTI和IO映射关系

STM32 HAL库开发——入门篇(1)_第84张图片

STM32 HAL库开发——入门篇(1)_第85张图片STM32 HAL库开发——入门篇(1)_第86张图片STM32 HAL库开发——入门篇(1)_第87张图片STM32 HAL库开发——入门篇(1)_第88张图片STM32 HAL库开发——入门篇(1)_第89张图片 

参考中文参考手册:9.2.5 

STM32 HAL库开发——入门篇(1)_第90张图片STM32 HAL库开发——入门篇(1)_第91张图片 

2.5 如何使用中断

STM32 HAL库开发——入门篇(1)_第92张图片STM32 HAL库开发——入门篇(1)_第93张图片分:EXTI中断 和 其他外设中断 

STM32 HAL库开发——入门篇(1)_第94张图片STM32 HAL库开发——入门篇(1)_第95张图片STM32 HAL库开发——入门篇(1)_第96张图片共有7个中断服务函数,0~4有5个,5~9共1个,10~15也共1个,一共7个 

2.6 通用外设驱动模型

STM32 HAL库开发——入门篇(1)_第97张图片

2.7 HAL库中断回调处理机制介绍 

STM32 HAL库开发——入门篇(1)_第98张图片

2.8 编程实战:外部中断控制LED

#include "./BSP/EXTI/exti.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./SYSTEM/usart/usart.h"

void EXTI4_IRQHandler(void)
{
    printf("1\r\n");
    if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4) != RESET)
    {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
        
    }
}

/*
    按键按下后,触发中断,调用中断服务函数 EXIT4_IRQHandler;
    然后调用公共处理函数 HAL_GPIO_EXTI_IRQHandler;
    公共处理函数再调用 callback 函数;
    此时,按键 KEY0:PE4 已经按下

*/

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(00);  // 消抖
    printf("2\r\n");
    
    if(GPIO_Pin == GPIO_PIN_4) // 判断是否是我们的中断线触发了中断
    {
        if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == 0)
        {
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);  // LED0,RED
        
        }
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);
    }    
    

}

void exti_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    __HAL_RCC_GPIOE_CLK_ENABLE();

    gpio_init_struct.Pin = GPIO_PIN_4;                  
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;          
    gpio_init_struct.Pull = GPIO_PULLUP;                   
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);      

    HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 2);
    HAL_NVIC_EnableIRQ(EXTI4_IRQn);  // 使能
}



       注意代码的细节不要出错, 博主就因为EXTI4_IRQHandler函数,写成了EXIT4_IRQHandler,没跑出结果,编译并没有报错还找了好一阵错误

三、串口通信

STM32 HAL库开发——入门篇(1)_第99张图片

3.1 数据通信的基本概念

STM32 HAL库开发——入门篇(1)_第100张图片

STM32 HAL库开发——入门篇(1)_第101张图片

STM32 HAL库开发——入门篇(1)_第102张图片STM32 HAL库开发——入门篇(1)_第103张图片STM32 HAL库开发——入门篇(1)_第104张图片编码方式很多 

码元:在数字通信中常常用时间间隔相同的符号来表示一个二进制数字,这样的时间间隔内的信号称为(二进制)码元。而这个间隔被称为码元长度。值得注意的是当码元的离散状态有大于2个时(如M大于2个)时,此时码元为M进制码元。(百度百科)

  这里说的比较官方,一下子没反应过来。在谢希仁这本书中有一个实例,假定基带信号为101011000110111010…如果直接传送,则每个码元携带的信息是1bit(可以理解为每个二进制都是一个码元),而将上面的信号分为 101 011 000 110 111 010,则视为6个码元,每个码元为3bit,8种表现形式,2^3.这种表现形式就是说接收方要唯一确定这个码元,官方点就是8种不同的振幅或者频率或者相位。你也可以分为1010 1100 0110 1110 10…这种为5个码元,16种表现形式。

  总结:码元说白了就是你以怎样的形式去定义你要发的信息,传输多个bit,还是一个码元。

波特率又称码元率,是指每秒传输码元的数目,单位波特(Band)
比特率为每秒传输的比特(bit)数。

  前面已经解释过,码元的大小可以自己定义,如果码元大小定义为1时,码元率(波特率)= 比特率。

由此可得波特率和比特率的关系

波特率 = 比特率/每符号含的比特数。(比特率也叫数据率)

STM32 HAL库开发——入门篇(1)_第105张图片STM32 HAL库开发——入门篇(1)_第106张图片 

3.2 串口(RS-232)

STM32 HAL库开发——入门篇(1)_第107张图片STM32 HAL库开发——入门篇(1)_第108张图片STM32 HAL库开发——入门篇(1)_第109张图片STM32 HAL库开发——入门篇(1)_第110张图片STM32 HAL库开发——入门篇(1)_第111张图片现在的电脑基本没有 DB9 的接口了,而是使用 USB 接口 

STM32 HAL库开发——入门篇(1)_第112张图片STM32 HAL库开发——入门篇(1)_第113张图片PC端需要安装 CH340 USB 虚拟串口驱动

LSB:最低有效位,这里就是位0

MSB: 最高有效位,这里就是位1

STM32 HAL库开发——入门篇(1)_第114张图片

异步通信没有 SCLK 时钟 

3.3 STM32的USART

STM32 HAL库开发——入门篇(1)_第115张图片

3.3.1 STM32的USART简介

STM32 HAL库开发——入门篇(1)_第116张图片

3.3.2 STM32的USART主要特征 

STM32 HAL库开发——入门篇(1)_第117张图片STM32 HAL库开发——入门篇(1)_第118张图片STM32 HAL库开发——入门篇(1)_第119张图片 

STM32 HAL库开发——入门篇(1)_第120张图片STM32 HAL库开发——入门篇(1)_第121张图片STM32 HAL库开发——入门篇(1)_第122张图片 

3.3.3 STM32 F1/F4/F7的USART框图 

       这里的框图是F1的 

       SW-RX是芯片内部的引脚,不用管他

STM32 HAL库开发——入门篇(1)_第123张图片STM32 HAL库开发——入门篇(1)_第124张图片 

STM32 HAL库开发——入门篇(1)_第125张图片

STM32 HAL库开发——入门篇(1)_第126张图片

3.3.4 设置USART/UART波特率(F1)

       F4/F7/H7等型号在后面几讲

STM32 HAL库开发——入门篇(1)_第127张图片baud = f_ck / 16 / usartdiv分频 

STM32 HAL库开发——入门篇(1)_第128张图片STM32 HAL库开发——入门篇(1)_第129张图片STM32 HAL库开发——入门篇(1)_第130张图片存放在 USART_BRR 寄存器

STM32 HAL库开发——入门篇(1)_第131张图片

+0.5 起到四舍五入的作用

fraction 的 *16 就是左移4位的意思 ,以整数的方式保存小数点后面的部分

STM32 HAL库开发——入门篇(1)_第132张图片STM32 HAL库开发——入门篇(1)_第133张图片 

3.3.5 USART寄存器介绍

STM32 HAL库开发——入门篇(1)_第134张图片STM32 HAL库开发——入门篇(1)_第135张图片STM32 HAL库开发——入门篇(1)_第136张图片STM32 HAL库开发——入门篇(1)_第137张图片STM32 HAL库开发——入门篇(1)_第138张图片STM32 HAL库开发——入门篇(1)_第139张图片STM32 HAL库开发——入门篇(1)_第140张图片

如果 CR1 寄存器选择 8 个数据位,那么这里 DR 寄存器就用 0~7 的8位;9位就是 0~8

STM32 HAL库开发——入门篇(1)_第141张图片RXNEIE就是CR1的位5:使能接收缓冲区非空中断

STM32 HAL库开发——入门篇(1)_第142张图片

STM32 HAL库开发——入门篇(1)_第143张图片STM32 HAL库开发——入门篇(1)_第144张图片 

3.4 HAL库外设初始化MSP回调机制

       PPP 是指任意外设 ,HAL_PPP_MspInit()实际是个空函数且允许重定义

STM32 HAL库开发——入门篇(1)_第145张图片STM32 HAL库开发——入门篇(1)_第146张图片多个外设共用MSP回调函数时,会有3个 .c 文件,此时就不确定在哪个文件中定义 

STM32 HAL库开发——入门篇(1)_第147张图片

3.5 HAL库中断回调机制

STM32 HAL库开发——入门篇(1)_第148张图片STM32 HAL库开发——入门篇(1)_第149张图片STM32 HAL库开发——入门篇(1)_第150张图片 

3.6 USART/UART异步通信配置步骤

STM32 HAL库开发——入门篇(1)_第151张图片STM32 HAL库开发——入门篇(1)_第152张图片STM32 HAL库开发——入门篇(1)_第153张图片STM32 HAL库开发——入门篇(1)_第154张图片 

3.7 IO引脚复用功能

STM32 HAL库开发——入门篇(1)_第155张图片STM32 HAL库开发——入门篇(1)_第156张图片STM32 HAL库开发——入门篇(1)_第157张图片STM32 HAL库开发——入门篇(1)_第158张图片STM32 HAL库开发——入门篇(1)_第159张图片有重映射的IO才进行重映射解决冲突,不然没有办法 

STM32 HAL库开发——入门篇(1)_第160张图片STM32 HAL库开发——入门篇(1)_第161张图片STM32 HAL库开发——入门篇(1)_第162张图片 

3.8 编程实战:串口接收或发送一个字符 

STM32 HAL库开发——入门篇(1)_第163张图片

uint8_t g_usart1_rx_flag = 0;   /* 串口接收到数据标志 */
uint8_t g_rx_buffer[1];          /* HAL库使用的串口接收缓冲 ,接收1个字节*/
UART_HandleTypeDef g_uart1_handle;  /* UART句柄 */

/**
 * @brief       串口X初始化函数
 * @param       baudrate: 波特率, 根据自己需要设置波特率值
 * @note        注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
 *              这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
 * @retval      无
 */
 
 
 
 /* 串口1初始化函数 */
void usart_init(uint32_t baudrate)
{
    /*UART 初始化设置*/
    g_uart1_handle.Instance = USART1;                                         /* USART_UX */
    g_uart1_handle.Init.BaudRate = baudrate;                                  /* 波特率 */
    g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;                      /* 字长为8位数据格式 */
    g_uart1_handle.Init.StopBits = UART_STOPBITS_1;                           /* 一个停止位 */
    g_uart1_handle.Init.Parity = UART_PARITY_NONE;                            /* 无奇偶校验位 */
    g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;                      /* 无硬件流控 */
    g_uart1_handle.Init.Mode = UART_MODE_TX_RX;                               /* 收发模式 */
    HAL_UART_Init(&g_uart1_handle);                                           /* HAL_UART_Init()会使能UART1 */

    /* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
    HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, 1); // 开启接收中断
    
}






/**
 * @brief       UART底层初始化函数
 * @param       huart: UART句柄类型指针
 * @note        此函数会被HAL_UART_Init()调用
 *              完成时钟使能,引脚配置,中断配置
 * @retval      无
 */
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    GPIO_InitTypeDef gpio_init_struct;

    if (huart->Instance == USART1)                            /* 如果是串口1,进行串口1 MSP初始化 */
    {
        /* (1)使能USART1和对应IO时钟;(2)初始化IO;(3)使能USART1中断,设置优先级 */

        __HAL_RCC_GPIOA_CLK_ENABLE();                                   /* 使能串口RX、TX脚时钟 */
        __HAL_RCC_USART1_CLK_ENABLE();                                  /* 使能串口时钟 */

        gpio_init_struct.Pin = GPIO_PIN_9;                      /* 串口发送引脚号 */
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;                /* 复用推挽输出 */
        gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 ,输出可以不设置上下拉*/
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* IO速度设置为高速 */
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);
                
        gpio_init_struct.Pin = GPIO_PIN_10;                      /* 串口接收引脚号 */
        gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;                /* 复用推挽输入 */
        gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* IO速度设置为高速 ,可以不设置速度*/
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);
        
        HAL_NVIC_SetPriority(USART1_IRQn, 0, 2);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
        
        
        

    }
}




/**
 * @brief       串口数据接收回调函数
                数据处理在这里进行
 * @param       huart:串口句柄
 * @retval      无
 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    g_usart1_rx_flag = 1;
}





/**
 * @brief       串口X中断服务函数
                注意,读取USARTx->SR能避免莫名其妙的错误
 * @param       无
 * @retval      无
 */
void USART1_IRQHandler(void)
{
  

    HAL_UART_IRQHandler(&g_uart1_handle);                               /* 调用HAL库中断处理公用函数 */
    /* 上述函数会清除中断标志位并调用回调函数,这里会失能 接收中断使能函数,所以下面重新调用一次 */
    
    HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, 1);
    
//    while (HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE) != HAL_OK)     /* 重新开启中断并接收数据 */
//    {
//        /* 如果出错会卡死在这里 */
//    }

}

3.9 串口实验源码解读 

STM32 HAL库开发——入门篇(1)_第164张图片2^14 B = 16KB

STM32 HAL库开发——入门篇(1)_第165张图片STM32 HAL库开发——入门篇(1)_第166张图片

STM32 HAL库开发——入门篇(1)_第167张图片

STM32 HAL库开发——入门篇(1)_第168张图片实际就不用 printf了,可以测试代码的时候用 

四、IWDG独立看门狗

STM32 HAL库开发——入门篇(1)_第169张图片

4.1 IWDG简介 

STM32 HAL库开发——入门篇(1)_第170张图片STM32 HAL库开发——入门篇(1)_第171张图片

RC振荡器的时间精度会差一点 

STM32 HAL库开发——入门篇(1)_第172张图片

4.2 IWDG工作原理

STM32 HAL库开发——入门篇(1)_第173张图片LSI 就是RC振荡器 

4.3 IWDG框图

STM32 HAL库开发——入门篇(1)_第174张图片STM32 HAL库开发——入门篇(1)_第175张图片LSI 输入经过8分频后进入 12位递减计数器 

4.4 IWDG寄存器

STM32 HAL库开发——入门篇(1)_第176张图片STM32 HAL库开发——入门篇(1)_第177张图片STM32 HAL库开发——入门篇(1)_第178张图片psc 为预分频系数

prer 就是低三位的值

STM32 HAL库开发——入门篇(1)_第179张图片STM32 HAL库开发——入门篇(1)_第180张图片STM32 HAL库开发——入门篇(1)_第181张图片 

4.5 IWDG溢出时间计算

STM32 HAL库开发——入门篇(1)_第182张图片STM32 HAL库开发——入门篇(1)_第183张图片STM32 HAL库开发——入门篇(1)_第184张图片STM32 HAL库开发——入门篇(1)_第185张图片 

4.6 IWDG配置步骤

STM32 HAL库开发——入门篇(1)_第186张图片STM32 HAL库开发——入门篇(1)_第187张图片

右边的结构体 F1/F4 和 F7/H7 有些许差异,F7/H7 多一个 Window ,就是窗口寄存器 

STM32 HAL库开发——入门篇(1)_第188张图片

STM32 HAL库开发——入门篇(1)_第189张图片

HAL_IWDG_Init()函数 

STM32 HAL库开发——入门篇(1)_第190张图片

STM32 HAL库开发——入门篇(1)_第191张图片

4.7 编程实战:验证不及时喂狗

STM32 HAL库开发——入门篇(1)_第192张图片

#include "./BSP/WDG/wdg.h"


IWDG_HandleTypeDef g_iwdg_handle;


/* IWDG初始化函数 */
void iwdg_init(uint8_t prer, uint16_t rlr)  /* prer只占用了3位,重装载值是12个位 */
{
    g_iwdg_handle.Instance = IWDG;
    g_iwdg_handle.Init.Prescaler = prer;
    g_iwdg_handle.Init.Reload = rlr;
    HAL_IWDG_Init(&g_iwdg_handle);


}

/* 喂狗函数 */
void iwdg_feed(void)
{
    HAL_IWDG_Refresh(&g_iwdg_handle);
}

int main(void)
{


    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟为72Mhz */
    delay_init(72);                         /* 延时初始化 */
    usart_init(115200);                     /* 串口初始化为115200 */
    led_init();                             /* 初始化LED */
    iwdg_init(IWDG_PRESCALER_32, 1250);     /* 1s的溢出时间,rlr=1*40000/32=1250 */
     
    
    printf("您还没喂狗,请及时喂狗!!!\r\n");
    while (1)
    {
        delay_ms(1000);
        iwdg_feed();
        printf("已经喂狗!\r\n");
            
    }
}

五、WWDG窗口看门狗

STM32 HAL库开发——入门篇(1)_第193张图片

5.1 WWDG简介 

STM32 HAL库开发——入门篇(1)_第194张图片STM32 HAL库开发——入门篇(1)_第195张图片窗口看门狗时钟来自系统总线的时钟 

5.2 WWDG工作原理

STM32 HAL库开发——入门篇(1)_第196张图片       窗口下限值是固定的,窗口上限值和计数器初始值是由用户编程决定的 ,计数值低于窗口上限值时才可以进行喂狗,若在窗口上限值上面就喂狗,系统会复位

STM32 HAL库开发——入门篇(1)_第197张图片STM32 HAL库开发——入门篇(1)_第198张图片 

5.3 WWDG框图

STM32 HAL库开发——入门篇(1)_第199张图片T6位时判断是否从64到63,所以是6位递减计数器 

STM32 HAL库开发——入门篇(1)_第200张图片

5.4 WWDG寄存器

STM32 HAL库开发——入门篇(1)_第201张图片STM32 HAL库开发——入门篇(1)_第202张图片STM32 HAL库开发——入门篇(1)_第203张图片

5.5 WWDG超时时间计算 

STM32 HAL库开发——入门篇(1)_第204张图片STM32 HAL库开发——入门篇(1)_第205张图片 

5.6 WWDG配置步骤

STM32 HAL库开发——入门篇(1)_第206张图片STM32 HAL库开发——入门篇(1)_第207张图片 

5.7 编程实战:验证窗口看门狗功能

STM32 HAL库开发——入门篇(1)_第208张图片STM32 HAL库开发——入门篇(1)_第209张图片STM32 HAL库开发——入门篇(1)_第210张图片

#include "./BSP/WDG/wdg.h"
#include "./BSP/LED/led.h"


WWDG_HandleTypeDef g_wwdg_handle;

/* 窗口看门狗初始化函数 */
void wwdg_init(uint8_t tr, uint8_t wr, uint32_t fprer)
{
    
    g_wwdg_handle.Instance = WWDG;
    g_wwdg_handle.Init.Counter = tr;
    g_wwdg_handle.Init.Window = wr;
    g_wwdg_handle.Init.Prescaler = fprer;
    g_wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE;
    
    HAL_WWDG_Init(&g_wwdg_handle);

}



/* WWDG MSP回调函数 */
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{
    __HAL_RCC_WWDG_CLK_ENABLE();
    
    HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3);
    HAL_NVIC_EnableIRQ(WWDG_IRQn);

}


/* WWDG中断服务函数 */
void WWDG_IRQHandler(void)
{
    HAL_WWDG_IRQHandler(&g_wwdg_handle);

}


/* WWDG提前唤醒回调函数 */
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
    //delay_ms(1); // 会超时,1个周期是0.9ms
    HAL_WWDG_Refresh(&g_wwdg_handle);  // 在 0x40=64的时候喂狗
    LED1_TOGGLE();

}


#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/WDG/wdg.h"


int main(void)
{
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    usart_init(115200);
    
    if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET)
    {
        printf("窗口看门狗复位\r\n\r\n");
        __HAL_RCC_CLEAR_RESET_FLAGS();
    }
    else
    {
        printf("外部复位\r\n");
    }
    
    delay_ms(500);    
    printf("请在窗口期内喂狗\r\n");
    wwdg_init(0x7F, 0X5F, WWDG_PRESCALER_8);
    
    while(1)
    {
        
        delay_ms(57);
        //HAL_WWDG_Refresh(&g_wwdg_handle);
        
//        delay_ms(90);
//        HAL_WWDG_Refresh(&g_wwdg_handle);
//        LED1_TOGGLE();
        
        
    }
}

5.8 IWDG和WWDG的区别

STM32 HAL库开发——入门篇(1)_第211张图片

你可能感兴趣的:(STM32,stm32,单片机,嵌入式硬件)