Lazy loaded image
嵌入式软件开发
📘STM32-HAL库学习笔记
字数 44782阅读时长 112 分钟
2024-10-1
2026-9-15
😀
一个简单的开头

介绍

此笔记为观看B站UP:超子说物联网所写,感谢老师。老师的架构真的特别好!
我在学习HAL库之前有标准库基础,所以学习稍快,但会尽量详细记录
笔记和项目文件在gitee开源了
大家可以在我的gitee仓库 中下载笔记源文件、STM32F1C8T6资料等
笔记源文件可以在Notion中导入
正在更新~
超子物联网 HAL库学习 写作不易,如果您觉得写的不错,欢迎给博主来一波点赞、收藏~让博主更有动力吧!

内容导航

子页面开头

超子物联网 HAL库学习 汇总入口:超子物联网HAL库笔记:[汇总] 写作不易,如果您觉得写的不错,欢迎给博主来一波点赞、收藏~让博主更有动力吧!
 

准备篇

1. HAL库简介

HAL库
  • HAL库(Hardware Abstraction Layer)是STMicroelectronics提供的STM32微控制器的硬件抽象层库。
  • 它通过一套统一的API接口,简化了对STM32外设的配置和操作,使开发者能够更快速地进行嵌入式系统开发,而不必深入了解底层硬件细节。
HAL库的优点
  • 高层次抽象:HAL库提供了高层次的抽象接口,简化了对硬件外设的操作。开发者可以通过调用库函数完成复杂的硬件配置,而不必直接操作寄存器。
  • 易于使用:由于提供了丰富的库函数和示例代码,开发者可以快速上手进行开发,减少了开发时间。
  • 一致性和移植性:HAL库在不同的STM32系列中保持了一致的API接口,增强了代码的移植性和重用性。如果需要更换STM32系列微控制器,代码的修改量较小。
  • 简化调试:由于HAL库屏蔽了底层的寄存器操作,调试过程中更容易定位和解决问题,减少了开发和维护的复杂性。
  • 代码维护性好:HAL库的高层次封装和良好的代码结构使得代码更容易维护和更新。
对比标准固件库的不同
  1. 抽象层次:
      • 标准固件库:直接操作寄存器,提供底层硬件访问,要求开发者对STM32微控制器的寄存器有较深入的理解。
      • HAL库:提供高层次的抽象接口,屏蔽底层寄存器操作,使开发者可以更快速地进行开发。
  1. 码复杂性:
      • 标准固件库:代码较复杂,涉及大量的寄存器配置,开发者需要处理更多的细节。
      • HAL库:代码简洁易读,通过调用库函数进行配置和操作,减少了代码量和复杂性。
  1. 学习曲线:
  • 标准固件库:学习曲线较陡,需要花费较多时间了解和掌握硬件细节。
  • HAL库:学习曲线较缓,提供了丰富的示例代码和文档,开发者可以快速上手。
  1. 开发效率:
  • 标准固件库:适合对性能和功耗有严格要求的项目,但开发和调试时间较长。
  • HAL库:提高了开发效率,适合快速开发和原型设计,缩短了开发周期。
  1. 移植性:
  • 标准固件库:不同系列的STM32微控制器之间存在较大的差异,代码移植工作量较大。
  • HAL库:提供一致的API接口,增强了代码的移植性和重用性,不同系列之间的移植工作量较小。

2. 创建HAL库工程模板

1. 制作文件模板

  • 先找一个位置,存放工程模板
  • 在工程模板中 添加 User、Library 、 Hardware 、 CMSIS 文件夹:
    • User:
      • main.c
    • Library:
      • Include
      • Source
    • Hardware:
      • Include
      • Source
    • CMSIS :
      • Include
      • Source
  • 解压并打开
  • 拷贝HAL库(Library)
      1. 进入\STM32Cube_FW_F1_V1.8.0\Drivers\STM32F1xx_HAL_Driver 把头文件夹 Inc 和源文件夹 Src 移动到自己的Library的对应的文件中
  • 拷贝启动文件(CMSIS\Include)
      1. 先进入内核文件\STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS
      1. 进入头文件\CMSIS\Include 把所有文件拷贝到自己的CMSIS/Include文件中 再进入\CMSIS\Device\ST\STM32F1xx\Include 把所有文件拷贝到自己的CMSIS/Include文件中
  • 拷贝源文件(CMSYS\Source)
      1. 进入\STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates
      1. \Templates 文件的的system_stm32f1xx.c拷贝到自己的CMSIS/Source文件中
      1. 再进入/arm文件下,把所有文件拷贝到自己的CMSIS/Source文件中
  • 编辑Hardware文件夹
    • 分别在源文件家和头文件夹添加stm32f1xx_it.c 和stm32f1xx_it.h 代码如下

stm32f1xx_it.c

stm32f1xx_it.h

CMSIS
Include
cmsis_armcc.h
cmsis_armclang.h
cmsis_compiler.h
cmsis_gcc.h
cmsis_iccarm.h
cmsis_version.h
core_armv8mbl.h
core_armv8mml.h
core_cm0.h
core_cm0plus.h
core_cm1.h
core_cm23.h
core_cm3.h
core_cm33.h
core_cm4.h
core_cm7.h
core_sc000.h
core_sc300.h
mpu_armv7.h
mpu_armv8.h
stm32f100xb.h
stm32f100xe.h
stm32f101x6.h
stm32f101xb.h
stm32f101xe.h
stm32f101xg.h
stm32f102x6.h
stm32f102xb.h
stm32f103x6.h
stm32f103xb.h
stm32f103xe.h
stm32f103xg.h
stm32f105xc.h
stm32f107xc.h
stm32f1xx.h
system_stm32f1xx.h
tz_context.h
Source
startup_stm32f100xb.s
startup_stm32f100xe.s
startup_stm32f101x6.s
startup_stm32f101xb.s
startup_stm32f101xe.s
startup_stm32f101xg.s
startup_stm32f102x6.s
startup_stm32f102xb.s
startup_stm32f103x6.s
startup_stm32f103xb.s
startup_stm32f103xe.s
startup_stm32f103xg.s
startup_stm32f105xc.s
startup_stm32f107xc.s
system_stm32f1xx.c
DebugConfig
Project_STM32F103C8_1.0.0.dbgconf
Target_1_STM32F103C8_1.0.0.dbgconf
Hardware
Include
stm32f1xx_it.h
Source
stm32f1xx_it.c
Library
Include
Legacy
stm32f1xx_hal_can_ex_legacy.h
stm32f1xx_hal_can_legacy.h
stm32_hal_legacy.h
stm32f1xx_hal.h
stm32f1xx_hal_adc.h
stm32f1xx_hal_adc_ex.h
stm32f1xx_hal_can.h
stm32f1xx_hal_cec.h
stm32f1xx_hal_conf.h
stm32f1xx_hal_cortex.h
stm32f1xx_hal_crc.h
stm32f1xx_hal_dac.h
stm32f1xx_hal_dac_ex.h
stm32f1xx_hal_def.h
stm32f1xx_hal_dma.h
stm32f1xx_hal_dma_ex.h
stm32f1xx_hal_eth.h
stm32f1xx_hal_exti.h
stm32f1xx_hal_flash.h
stm32f1xx_hal_flash_ex.h
stm32f1xx_hal_gpio.h
stm32f1xx_hal_gpio_ex.h
stm32f1xx_hal_hcd.h
stm32f1xx_hal_i2c.h
stm32f1xx_hal_i2s.h
stm32f1xx_hal_irda.h
stm32f1xx_hal_iwdg.h
stm32f1xx_hal_mmc.h
stm32f1xx_hal_nand.h
stm32f1xx_hal_nor.h
stm32f1xx_hal_pccard.h
stm32f1xx_hal_pcd.h
stm32f1xx_hal_pcd_ex.h
stm32f1xx_hal_pwr.h
stm32f1xx_hal_rcc.h
stm32f1xx_hal_rcc_ex.h
stm32f1xx_hal_rtc.h
stm32f1xx_hal_rtc_ex.h
stm32f1xx_hal_sd.h
stm32f1xx_hal_smartcard.h
stm32f1xx_hal_spi.h
stm32f1xx_hal_sram.h
stm32f1xx_hal_tim.h
stm32f1xx_hal_tim_ex.h
stm32f1xx_hal_uart.h
stm32f1xx_hal_usart.h
stm32f1xx_hal_wwdg.h
stm32f1xx_ll_adc.h
stm32f1xx_ll_bus.h
stm32f1xx_ll_cortex.h
stm32f1xx_ll_crc.h
stm32f1xx_ll_dac.h
stm32f1xx_ll_dma.h
stm32f1xx_ll_exti.h
stm32f1xx_ll_fsmc.h
stm32f1xx_ll_gpio.h
stm32f1xx_ll_i2c.h
stm32f1xx_ll_iwdg.h
stm32f1xx_ll_pwr.h
stm32f1xx_ll_rcc.h
stm32f1xx_ll_rtc.h
stm32f1xx_ll_sdmmc.h
stm32f1xx_ll_spi.h
stm32f1xx_ll_system.h
stm32f1xx_ll_tim.h
stm32f1xx_ll_usart.h
stm32f1xx_ll_usb.h
stm32f1xx_ll_utils.h
stm32f1xx_ll_wwdg.h
stm32_assert_template.h
Source
Legacy
stm32f1xx_hal_can.c
stm32f1xx_hal.c
stm32f1xx_hal_adc.c
stm32f1xx_hal_adc_ex.c
stm32f1xx_hal_can.c
stm32f1xx_hal_cec.c
stm32f1xx_hal_cortex.c
stm32f1xx_hal_crc.c
stm32f1xx_hal_dac.c
stm32f1xx_hal_dac_ex.c
stm32f1xx_hal_dma.c
stm32f1xx_hal_eth.c
stm32f1xx_hal_exti.c
stm32f1xx_hal_flash.c
stm32f1xx_hal_flash_ex.c
stm32f1xx_hal_gpio.c
stm32f1xx_hal_gpio_ex.c
stm32f1xx_hal_hcd.c
stm32f1xx_hal_i2c.c
stm32f1xx_hal_i2s.c
stm32f1xx_hal_irda.c
stm32f1xx_hal_iwdg.c
stm32f1xx_hal_mmc.c
stm32f1xx_hal_msp_template.c
stm32f1xx_hal_nand.c
stm32f1xx_hal_nor.c
stm32f1xx_hal_pccard.c
stm32f1xx_hal_pcd.c
stm32f1xx_hal_pcd_ex.c
stm32f1xx_hal_pwr.c
stm32f1xx_hal_rcc.c
stm32f1xx_hal_rcc_ex.c
stm32f1xx_hal_rtc.c
stm32f1xx_hal_rtc_ex.c
stm32f1xx_hal_sd.c
stm32f1xx_hal_smartcard.c
stm32f1xx_hal_spi.c
stm32f1xx_hal_sram.c
stm32f1xx_hal_tim.c
stm32f1xx_hal_timebase_rtc_alarm_template.c
stm32f1xx_hal_timebase_tim_template.c
stm32f1xx_hal_tim_ex.c
stm32f1xx_hal_uart.c
stm32f1xx_hal_usart.c
stm32f1xx_hal_wwdg.c
stm32f1xx_ll_adc.c
stm32f1xx_ll_crc.c
stm32f1xx_ll_dac.c
stm32f1xx_ll_dma.c
stm32f1xx_ll_exti.c
stm32f1xx_ll_fsmc.c
stm32f1xx_ll_gpio.c
stm32f1xx_ll_i2c.c
stm32f1xx_ll_pwr.c
stm32f1xx_ll_rcc.c
stm32f1xx_ll_rtc.c
stm32f1xx_ll_sdmmc.c
stm32f1xx_ll_spi.c
stm32f1xx_ll_tim.c
stm32f1xx_ll_usart.c
stm32f1xx_ll_usb.c
stm32f1xx_ll_utils.c
Listings
Objects
main.d
main.o
Project.axf
Project.htm
Project.lnp
Project.sct
Project_Project.dep
startup_stm32f101xb.o
stm32f1xx_hal.d
stm32f1xx_hal.o
stm32f1xx_hal_cortex.d
stm32f1xx_hal_cortex.o
stm32f1xx_hal_gpio.d
stm32f1xx_hal_gpio.o
stm32f1xx_hal_gpio_ex.d
stm32f1xx_hal_gpio_ex.o
stm32f1xx_hal_rcc.d
stm32f1xx_hal_rcc.o
stm32f1xx_hal_rcc_ex.d
stm32f1xx_hal_rcc_ex.o
system_stm32f1xx.d
system_stm32f1xx.o
User
main.c
HAL_Init();//初始化HAL库
HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);//PA8引脚输出、系统时钟、不分频
#include "stm32f1xx_hal.h"
#include "rcc.h"
/*函 数 名:hal库rcc输出内部8Mhz方波
*参 数:
*返 回 值:
*注意事项:
*/
uint32_t HCLKFreq = 0;//显示时钟树三处频率
uint32_t PCLK1Freq = 0;
uint32_t PCLK2Freq = 0;
int main (void)
{
HAL_Init();//初始化HAL库
RCC_ClockInit();//配置时钟树初始化
HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);//PA8引脚输出、系统时钟、不分频
HCLKFreq = HAL_RCC_GetHCLKFreq();
PCLK1Freq = HAL_RCC_GetPCLK1Freq();
PCLK2Freq = HAL_RCC_GetPCLK2Freq();
while(1)
{
}
}
#include "stm32f1xx_hal.h"
#include "rcc.h"
void RCC_ClockInit()
{
RCC_OscInitTypeDef RCC_OsInitStructure; //设置内外部时钟源配置结构体
RCC_ClkInitTypeDef RCC_ClkInitStructure;//设置总线时钟结构体
RCC_OsInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI; //选择震荡电路为内部高速
RCC_OsInitStructure.HSIState = RCC_HSI_ON; //打开时钟
RCC_OsInitStructure.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; //设置微调值 默认
RCC_OsInitStructure.PLL.PLLState = RCC_PLL_ON; //设置PLL为打开
RCC_OsInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; //选择PLL输入为内部高速时钟
RCC_OsInitStructure.PLL.PLLMUL = RCC_PLL_MUL16; //设置16倍频
HAL_RCC_OscConfig(&RCC_OsInitStructure); //传给话务员..
RCC_ClkInitStructure.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 |RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_SYSCLK;//需要配置的时钟
RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //SYSCLK系统时钟输入源 PLL作为系统时钟
RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB预分频 1分频
RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV2; //APB1预分频 2分频
RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV1; //APB2预分频 1分频
HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2);//传给话务员,并且根据频率设置FLASH等待周期为2
//话务员相关配置可以在API函数中找到。结构体相关配置在结构体和成员中可找到
}
#include "stm32f1xx_hal.h"
#include "rcc.h"
void RCC_ClockInit()
{
RCC_OscInitTypeDef RCC_OsInitStructure; //设置内外部时钟源配置结构体
RCC_ClkInitTypeDef RCC_ClkInitStructure;//设置总线时钟结构体
RCC_OsInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE; //选择震荡电路为外部高速
RCC_OsInitStructure.HSEState = RCC_HSE_ON; //打开HSE时钟
RCC_OsInitStructure.HSEPredivValue = RCC_HSE_PREDIV_DIV1; //不分频
RCC_OsInitStructure.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; //设置微调值 默认
RCC_OsInitStructure.PLL.PLLState = RCC_PLL_ON; //设置PLL为打开
RCC_OsInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE; //选择PLL输入为外部高速时钟
RCC_OsInitStructure.PLL.PLLMUL = RCC_PLL_MUL9; //设置9倍频
HAL_RCC_OscConfig(&RCC_OsInitStructure); //传给话务员..
RCC_ClkInitStructure.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 |RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_SYSCLK;//需要配置的时钟
RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //SYSCLK系统时钟输入源 PLL作为系统时钟
RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB预分频 1分频
RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV2; //APB1预分频 2分频
RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV1; //APB2预分频 1分频
HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2);//传给话务员,并且根据频率设置FLASH等待周期为2
//话务员相关配置可以在API函数中找到。结构体相关配置在结构体和成员中可找到
}
//stm启动文件中已经定义的中断服务函数
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)//帮我们判断标志位
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);//帮我们清除标志位
HAL_GPIO_EXTI_Callback(GPIO_Pin);//执行回调函数
}
}
// 弱声明 的回调函数 只是为了防止报错用
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
UNUSED(GPIO_Pin);//什么都不执行,只是为了防止编译时报错:没有使用xxx
}
void EXTI15_10_IRQHandler (void) //如果发生了这个中断
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);//跳转到HAL库的中断处理
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);//跳转到HAL库的中断处理
}
/ 注册回调函数 /
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_13) // 判断是不是13线
{
// 执行13线程序
// ...
}
else if (GPIO_Pin == GPIO_PIN_12) // 判断是不是12线
{
// 执行12线程序
// ...
}
}

串口篇

这篇文章介绍了HAL库大多的使用方法,并配有详细的思路和注释。

一、介绍

HAL库在 异步通信UART 串口部分提供了三种方式:
  • 轮询阻塞
  • 非阻塞中断 或者 DMA
  • 所以在使用串口时,也要添加DMA.c到库
以STM32C8T6为例,有三个串口资源:
  • USART1
    • TX:PA9 可重映射为 PB 6
    • RX:PA10 可重映射为 PB 7
  • USART2
    • TX:PA2
    • RX:PA3
  • USART3
    • TX:PB10
    • RX:PB11

二、HAL库:阻塞轮询方式 实现USART1 串口 异步收发

1. 引脚定义

  • USART1
    • TX:PA9
    • RX:PA10

2. 补充:为什么在while循环接收时,没必要对HAL_ERROR、HAL_BUSY进行处理

HAL_ERROR:
  • 用于判断buff为空指针或者数据长度为0的情况
HAL_BUSY:
  • 用于判断Busy状态
所以我们只需要判断他的另外两种状态,HAL_OK(在规定时间内接收到n个数据)、和HAL_TIMEOUT(未在规定时间接收到n个数据,导致超时退出接收)

3. 注意事项:

  • HAL库的串口初始化, 硬件部分的时钟以及GPIO口的配置,需要我们自己来配置
    • HAL_UART_Init(&Uart1); 函数被调用时。 会调用一个weak弱声明的void HAL_UART_MspInit(UART_HandleTypeDef *huart) 函数。 这个函数就是留给我们强声明 配置硬件用的。我们需要在里边打开 串口1 和 GPIO的 时钟。
  • 需要注意的是USART1与定时器的引脚有冲突。 如果发生冲突 可以重映射 串口到别的引脚。
  • RxXferSiZe是用来记录接收总量的
  • RxXferCount是用来记录剩余需要接收数量的
    • 注意,这里的RxXferCount 进到while中就先减1 了。这个知识点后面会用到

4. 串口1初始化部分:

5. 串口1配置硬件部分

6. 主函数部分

  • 主函数中。需要使用接收串口的函数:HAL_UART_Receive(&Uart1,Buff,Rx_Size,200)
    • 他的参数分别为:串口配置结构体地址、接收缓冲区(我们自己定义的数组)、预计接收的字节个数(我们自己定义)、超时时间(单位为ms)
      这里的 Rx_Size 为 200
      因此我们需要在UART.h 头文件中添加结构体对外声明extern UART_HandleTypeDef Uart1;
  • 接收串口的函数会有 四个返回值:
    • HAL_OK、 代表此次在200ms内接受到了 200 字节。 (也就是与预计相等)
    • HAL_ERROR 、代表传参错误、 比如超时时间为0、或者数据缓冲区地址为空
    • HAL_TIMEOUT 、代表未能在规定时间内接收到 200 个字节
      • 往往分为两种情况: 1、接收了但没接收完、2、一点没接收
    • HAL_BUSY、代表已经在接受了。你别来烦我
下面可以看代码来分析

三、HAL库:阻塞轮询方式 实现串口2、3 和串口1重映射

1. 引脚定义

  • USART1
    • TX:PA9 可重映射为 PB 6
    • RX:PA10 可重映射为 PB 7
  • USART2
    • TX:PA2
    • RX:PA3
  • USART3
    • TX:PB10
    • RX:PB11

2. 关键代码:

  • 如果需要重映射,则还需要打开AFIO的时钟和 使用重映射 API:

    3. 串口1、2、3、初始化部分:

    与之前的无异,只是添加拷贝了三次

    4. 主函数部分

    • 与之前的一样,想使用什么修改下”UartX“参数就行,

    四、HAL库:中断方式 实现串口1 定长数组异步收发

    我们就使用上一小节所讲的多指针定位+循环收发缓冲区方案设计,来实现这次的中断接收~

    1. 注意事项

    1. HAL库为 串口中断提供了很多回调函数。 比如 错误回调、半完成回调、Rx、Tx完成回调。你需要用什么回调,就声明什么回调~
        • 这里只用了接收完成回调函数:void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
          • 其中“RxCpltCallback” 可以分解为以下部分:
          • “Rx” 通常代表 “Receive”,即接收。
          • “Cplt” 通常代表 “Complete”,即完成。
          • “Callback” 即回调,指的是当某个特定事件发生时被调用的函数。
    1. 我们在回调函数中。 我们将接收缓冲区的数据memcpy到 发送缓冲区。 并置 接收完成标志位。 在主函数中,只需要循环检测 标志位 后 并发送发送缓冲区中的数据就可以完成接收并发送数据了。 中断接收在接收到数据之后 需要在回调函数中要重新打开。 因为中断接收一次会自动关闭
    1. 在使用UART 的IT 接收时。要配置NVIC :USART 线的 优先级和 使能USART线
      1. 这里的定长,是因为中断只有接收到20个字节之后,才会进入回调函数

      2. 初始化UART1部分

      • 主要关注中断 完成接收回调函数部分。 主要完成了数据cpy 和置位接收状态以及 重新启动接收数据。
      • 以及关注定义的接收、发送缓冲区和Rx_Date接收状态标志位

      3. UART硬件初始化回调

      3. 回调函数部分

      / 强声明的错误回调函数 /
      void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的发送完成回调函数 /
      void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      #include "stm32f1xx_hal.h"
      #include "rcc.h"
      #include "led.h"
      #include "key.h"
      #include "Uart.h"
      /函 数 名:HAL库:中断方式。实现UART串口数据收发。 定长 20字节 /
      int main (void)
      {
      HAL_Init();//初始化HAL库
      RccClock_Init();//配置时钟树72M
      LED_Init();
      Uart1_Init(921600);//初始化串口1
      while(1)
      {
      if(Rx_Date == 1) //如果接收标志位置1
      {
      Rx_Date = 0;
      HAL_UART_Transmit_IT(&Uart1,Tx_Buff,20);//发送 发送缓冲区的20个字节
      }
      }
      }
      / 缓冲区宏定义 /
      #define U1_RX_SIZE 2048
      #define U1_TX_SIZE 2048
      #define U1_RX_MAX 256 //这里需要注意,我们是利用空闲中断对数据进行处理,不能单次发送256字节,否则进入完成中断
      / 缓冲区 /
      uint8_t U1_Rx_Buff[U1_RX_SIZE];
      uint8_t U1_Tx_Buff[U1_TX_SIZE];
      / Location Ctrl Block /
      / (接收/发送)位置控制块 /
      typedef struct{
      uint8_t* start;
      uint8_t* end;
      }LCB;
      / Uart Ctrl Block /
      / 串口控制块 /
      typedef struct{
      uint32_t rxCount; //记录接收缓冲区中当前已有的数据量
      uint32_t txCount; //记录发送缓冲区中当前已有的数据量
      LCB rxLocation[10]; //记录接收缓冲区每次接收的位置
      LCB txLocation[10]; //记录发送缓冲区每次接收的位置
      LCB* rxInPtr; //指向下次接收缓冲区存放位置
      LCB* rxOutPtr; //指向下次接收缓冲区读取位置
      LCB* rxEndPtr; //指向接收缓冲区结束位置
      LCB* txInPtr; //指向下次发送缓冲区存放位置
      LCB* txOutPtr; //指向下次发送缓冲区读取位置
      LCB* txEndPtr; //指向发送缓冲区结束位置
      UART_HandleTypeDef uart; //串口总控结构体
      uint8_t TxState; //发送忙碌标志位
      }UCB;
      / 初始化 /
      void U1_Init(uint32_t bandrate);
      / 初始化UCB控制块指针 /
      void U1_PtrInit(void);
      / 转移RxBuff数据到TxBuff /
      void U1_DataRxToTx(uint8_t* data, uint32_t data_len);
      / 总控结构体 /
      extern UCB uart1;
      / 缓冲区 /
      extern uint8_t U1_Rx_Buff[U1_RX_SIZE];
      extern uint8_t U1_Tx_Buff[U1_TX_SIZE];
      / 状态位 /
      extern uint8_t rxState;
      #ifndef __UART_H
      #define __UART_H
      #include "stm32f1xx_hal.h"
      #include "stdint.h"
      #include "string.h"
      / 缓冲区宏定义 /
      #define U1_RX_SIZE 2048
      #define U1_TX_SIZE 2048
      #define U1_RX_MAX 256 //这里需要注意,我们是利用空闲中断对数据进行处理,不能单次发送256字节,否则进入完成中断
      / Location Ctrl Block /
      / (接收/发送)位置控制块 /
      typedef struct{
      uint8_t* start;
      uint8_t* end;
      }LCB;
      / Uart Ctrl Block /
      / 串口控制块 /
      typedef struct{
      uint32_t rxCount; //记录接收缓冲区中当前已有的数据量
      uint32_t txCount; //记录发送缓冲区中当前已有的数据量
      LCB rxLocation[10]; //记录接收缓冲区每次接收的位置
      LCB txLocation[10]; //记录发送缓冲区每次接收的位置
      LCB* rxInPtr; //指向下次接收缓冲区存放位置
      LCB* rxOutPtr; //指向下次接收缓冲区读取位置
      LCB* rxEndPtr; //指向接收缓冲区结束位置
      LCB* txInPtr; //指向下次发送缓冲区存放位置
      LCB* txOutPtr; //指向下次发送缓冲区读取位置
      LCB* txEndPtr; //指向发送缓冲区结束位置
      UART_HandleTypeDef uart; //串口总控结构体
      uint8_t TxState; //发送忙碌标志位
      }UCB;
      / 初始化 /
      void U1_Init(uint32_t bandrate);
      / 初始化UCB控制块指针 /
      void U1_PtrInit(void);
      / 转移RxBuff数据到TxBuff /
      void U1_DataRxToTx(uint8_t* data, uint32_t data_len);
      / 总控结构体 /
      extern UCB uart1;
      / 缓冲区 /
      extern uint8_t U1_Rx_Buff[U1_RX_SIZE];
      extern uint8_t U1_Tx_Buff[U1_TX_SIZE];
      / 状态位 /
      extern uint8_t rxState;
      #endif
      #include "uart.h"
      / 创建串口总控结构体 /
      UCB uart1;
      / 缓冲区 /
      uint8_t U1_Rx_Buff[U1_RX_SIZE];
      uint8_t U1_Tx_Buff[U1_TX_SIZE];
      / 初始化串口 /
      void U1_Init(uint32_t bandrate){
      uart1.uart.Instance = USART1; //使用那个串口
      uart1.uart.Init.BaudRate = bandrate; //波特率
      uart1.uart.Init.WordLength = UART_WORDLENGTH_8B; //数据位长度
      uart1.uart.Init.StopBits = UART_STOPBITS_1; //停止位
      uart1.uart.Init.Parity = UART_PARITY_NONE; //校验模式
      uart1.uart.Init.Mode = UART_MODE_TX_RX; //传输模式
      uart1.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE; //流控
      HAL_UART_Init(&uart1.uart);
      / 初始化UCB控制块指针 /
      U1_PtrInit();
      / 打开空闲中断 /
      __HAL_UART_ENABLE_IT(&uart1.uart,UART_IT_IDLE);
      / 开始接收数据 /
      HAL_UART_Receive_IT(&uart1.uart, uart1.rxInPtr->start, U1_RX_MAX); //接收位置为当前LCB位置控制块的In指针所指向的缓冲区的位置
      }
      / 初始化U1_UCB控制块指针 /
      void U1_PtrInit(void){
      uart1.rxCount = 0;
      uart1.rxInPtr = &uart1.rxLocation[0];
      uart1.rxOutPtr = &uart1.rxLocation[0];
      uart1.rxEndPtr = &uart1.rxLocation[9];
      uart1.rxInPtr->start = &U1_Rx_Buff[0]; //让当前接收位置控制块的start,指向下一次接收到的数据将要存放的位置
      uart1.txCount = 0;
      uart1.txInPtr = &uart1.txLocation[0];
      uart1.txOutPtr = &uart1.txLocation[0];
      uart1.txEndPtr = &uart1.txLocation[9];
      uart1.txInPtr->start = &U1_Tx_Buff[0]; //让当前发送位置控制块的start,指向下一次需要发送的数据的存放位置
      }
      / 转移U1_Rx_Buff数据到 U1_Tx_Buff /
      void U1_DataRxToTx(uint8_t* data, uint32_t data_len){
      / 判断剩余空间是否足够,要不要回卷 /
      if((U1_TX_SIZE - uart1.txCount) > data_len){
      / 如果够 /
      uart1.txInPtr->start = &U1_Tx_Buff[uart1.txCount];
      }
      else{/ 如果剩余空间不够 /
      uart1.txCount = 0;
      uart1.txInPtr->start = &U1_Tx_Buff[0];
      }
      / 复制data到U1_Tx_Buff缓冲区 /
      memcpy(uart1.txInPtr->start, data, data_len);
      / 累加txCount /
      uart1.txCount += data_len;
      / 标记这次的发送数据的结束位置 /
      uart1.txInPtr->end = &U1_Tx_Buff[uart1.txCount - 1];
      / 移动txIn /
      uart1.txInPtr++;
      / 判断txIn指针是否需要回卷 /
      if(uart1.txInPtr == uart1.txEndPtr){
      uart1.txInPtr = &uart1.txLocation[0];
      }
      }
      / UART硬件初始化回调 /
      void HAL_UART_MspInit(UART_HandleTypeDef *huart){
      GPIO_InitTypeDef GPIO_InitType;
      if(huart->Instance == USART1){ //判断那个串口在进行初始化
      __HAL_RCC_USART1_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_9;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_10;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      //打开了串口1的总中断
      HAL_NVIC_SetPriority(USART1_IRQn,3,0);
      HAL_NVIC_EnableIRQ(USART1_IRQn);
      }else if(huart->Instance == USART2){
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_USART2_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_2;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_3;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      }else if(huart->Instance == USART3){
      __HAL_RCC_GPIOB_CLK_ENABLE();
      __HAL_RCC_USART3_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_10;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOB,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_11;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOB,&GPIO_InitType);
      }
      }
      / 强声明的接收完成回调函数 /
      void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的错误回调函数 /
      void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的发送完成回调函数 /
      void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      / 发送完成,标志位清零 /
      uart1.TxState = 0;
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的接收终止回调函数 /
      void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      / 标记结束位置 /
      uart1.rxInPtr->end = &U1_Rx_Buff[uart1.rxCount - 1];
      / 挪动rxIn指针 /
      uart1.rxInPtr++;
      / 判断rxIn指针是否需要回卷 /
      if(uart1.rxInPtr == uart1.rxEndPtr){
      uart1.rxInPtr = &uart1.rxLocation[0];
      }
      / 判断接收缓冲区是否需要回卷 /
      if((U1_RX_SIZE - uart1.rxCount) < U1_RX_MAX){
      uart1.rxCount = 0;
      uart1.rxInPtr->start = &U1_Rx_Buff[0];
      }else{
      / 剩余位置够 /
      uart1.rxInPtr->start = &U1_Rx_Buff[uart1.rxCount];
      }
      / 重新开启中断接收 /
      HAL_UART_Receive_IT(&uart1.uart, uart1.rxInPtr->start, U1_RX_MAX);
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      /-------------------------------------------------/
      / /
      / 实现各种中断服务函数的源文件 /
      / /
      /-------------------------------------------------/
      #include "stm32f1xx_hal.h"
      #include "stm32f1xx_it.h"
      #include "uart.h"
      void EXTI15_10_IRQHandler(void)
      {
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
      }
      void EXTI0_IRQHandler(void)
      {
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
      }
      /-------------------------------------------------/
      /函数名:不可屏蔽中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void NMI_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:硬件出错后进入的中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void HardFault_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:软中断,SWI 指令调用的处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void SVC_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:可挂起的系统服务处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void PendSV_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:SysTic系统嘀嗒定时器处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void SysTick_Handler(void)
      {
      HAL_IncTick();
      }
      /-------------------------------------------------/
      /函数名:串口1中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void USART1_IRQHandler(void)
      {
      HAL_UART_IRQHandler(&uart1.uart);
      / 在每次进入中断后,判断是否为空闲中断 /
      if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
      / 清除空闲标志位 /
      //__HAL_UART_CLEAR_FLAG(&uart1.uart, UART_FLAG_IDLE);
      __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
      / 获取这次传输了多少字节 /
      uart1.rxCount += (U1_RX_MAX - uart1.uart.RxXferCount);
      / 终止当前的接收(会把RxferCount清零) /
      HAL_UART_AbortReceive_IT(&uart1.uart);
      }
      }
      #include "stm32f1xx_hal.h"
      #include "rcc.h"
      #include "led.h"
      #include "sw.h"
      #include "uart.h"
      int main(void){
      HAL_Init();
      RccClock_Init();
      U1_Init(921600);
      while(1){
      / 判断接收缓冲区是否有数据 /
      if(uart1.rxInPtr != uart1.rxOutPtr){
      / 转移这次接收的一段数据到发送缓冲区 /
      U1_DataRxToTx(uart1.rxOutPtr->start, (uart1.rxOutPtr->end - uart1.rxOutPtr->start + 1));
      / 移动rxOutPtr到下一次cpy的地址 /
      uart1.rxOutPtr++;
      / 判断rxOutPtr是否需要回卷 /
      if(uart1.rxOutPtr == uart1.rxEndPtr){
      uart1.rxOutPtr = &uart1.rxLocation[0];
      }
      }
      / 判断发送缓冲区是否有数据 /
      if((uart1.txInPtr != uart1.txOutPtr) && (uart1.TxState == 0) ){
      uart1.TxState = 1;
      / 发送数据 /
      HAL_UART_Transmit_IT(&uart1.uart, uart1. txOutPtr->start, (uart1.txOutPtr->end - uart1.txOutPtr->start + 1));
      / 移动txOutPtr到下一次cpy的地址 /
      uart1.txOutPtr++;
      / 判断txOutPtr是否需要回卷 /
      if(uart1.txOutPtr == uart1.txEndPtr){
      uart1.txOutPtr = &uart1.txLocation[0];
      }
      }
      }
      }
      #ifndef __UART_H
      #define __UART_H
      #include "stm32f1xx_hal.h"
      #include "stdint.h"
      #include "string.h"
      / 缓冲区宏定义 /
      #define U1_RX_SIZE 2048 //接收缓冲区长度
      #define U1_TX_SIZE 2048 //发送缓冲区长度
      #define U1_RX_MAX 256 //最大单次发送量(实际值 - 1 = 255字节)
      #define U2_RX_SIZE 2048
      #define U2_TX_SIZE 2048
      #define U2_RX_MAX 256
      #define U3_RX_SIZE 2048
      #define U3_TX_SIZE 2048
      #define U3_RX_MAX 256
      / Location Ctrl Block /
      / (接收/发送)位置控制块 /
      typedef struct{
      uint8_t* start;
      uint8_t* end;
      }LCB;
      / Uart Ctrl Block /
      / 串口控制块 /
      typedef struct{
      uint32_t rxCount; //记录接收缓冲区中当前已有的数据量
      uint32_t txCount; //记录发送缓冲区中当前已有的数据量
      LCB rxLocation[10]; //记录接收缓冲区每次接收的位置
      LCB txLocation[10]; //记录发送缓冲区每次接收的位置
      LCB* rxInPtr; //指向下次接收缓冲区存放位置
      LCB* rxOutPtr; //指向下次接收缓冲区读取位置
      LCB* rxEndPtr; //指向接收缓冲区结束位置
      LCB* txInPtr; //指向下次发送缓冲区存放位置
      LCB* txOutPtr; //指向下次发送缓冲区读取位置
      LCB* txEndPtr; //指向发送缓冲区结束位置
      UART_HandleTypeDef uart; //串口总控结构体
      uint8_t TxState; //发送忙碌标志位
      }UCB;
      / 初始化 /
      void U1_Init(uint32_t bandrate);
      void U2_Init(uint32_t bandrate);
      void U3_Init(uint32_t bandrate);
      / 初始化UCB控制块指针 /
      void U1_PtrInit(void);
      void U2_PtrInit(void);
      void U3_PtrInit(void);
      / 转移RxBuff数据到TxBuff /
      void U1_DataRxToTx(uint8_t* data, uint32_t data_len);
      void U2_DataRxToTx(uint8_t* data, uint32_t data_len);
      void U3_DataRxToTx(uint8_t* data, uint32_t data_len);
      / 总控结构体 /
      extern UCB uart1;
      extern UCB uart2;
      extern UCB uart3;
      / 缓冲区 /
      extern uint8_t U1_Rx_Buff[U1_RX_SIZE];
      extern uint8_t U1_Tx_Buff[U1_TX_SIZE];
      extern uint8_t U2_Rx_Buff[U2_RX_SIZE];
      extern uint8_t U2_Tx_Buff[U2_TX_SIZE];
      extern uint8_t U3_Rx_Buff[U3_RX_SIZE];
      extern uint8_t U3_Tx_Buff[U3_TX_SIZE];
      #endif
      #include "uart.h"
      / 创建串口总控结构体 /
      UCB uart1;
      UCB uart2;
      UCB uart3;
      / 缓冲区 /
      uint8_t U1_Rx_Buff[U1_RX_SIZE];
      uint8_t U1_Tx_Buff[U1_TX_SIZE];
      uint8_t U2_Rx_Buff[U2_RX_SIZE];
      uint8_t U2_Tx_Buff[U2_TX_SIZE];
      uint8_t U3_Rx_Buff[U3_RX_SIZE];
      uint8_t U3_Tx_Buff[U3_TX_SIZE];
      / 初始化串口 /
      void U1_Init(uint32_t bandrate){
      uart1.uart.Instance = USART1; //使用那个串口
      uart1.uart.Init.BaudRate = bandrate; //波特率
      uart1.uart.Init.WordLength = UART_WORDLENGTH_8B; //数据位长度
      uart1.uart.Init.StopBits = UART_STOPBITS_1; //停止位
      uart1.uart.Init.Parity = UART_PARITY_NONE; //校验模式
      uart1.uart.Init.Mode = UART_MODE_TX_RX; //传输模式
      uart1.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE; //流控
      HAL_UART_Init(&uart1.uart);
      / 初始化UCB控制块指针 /
      U1_PtrInit();
      }
      / 初始化串口 /
      void U2_Init(uint32_t bandrate){
      uart2.uart.Instance = USART2; //使用那个串口
      uart2.uart.Init.BaudRate = bandrate; //波特率
      uart2.uart.Init.WordLength = UART_WORDLENGTH_8B; //数据位长度
      uart2.uart.Init.StopBits = UART_STOPBITS_1; //停止位
      uart2.uart.Init.Parity = UART_PARITY_NONE; //校验模式
      uart2.uart.Init.Mode = UART_MODE_TX_RX; //传输模式
      uart2.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE; //流控
      HAL_UART_Init(&uart2.uart);
      / 初始化UCB控制块指针 /
      U2_PtrInit();
      }
      / 初始化串口 /
      void U3_Init(uint32_t bandrate){
      uart3.uart.Instance = USART3; //使用那个串口
      uart3.uart.Init.BaudRate = bandrate; //波特率
      uart3.uart.Init.WordLength = UART_WORDLENGTH_8B; //数据位长度
      uart3.uart.Init.StopBits = UART_STOPBITS_1; //停止位
      uart3.uart.Init.Parity = UART_PARITY_NONE; //校验模式
      uart3.uart.Init.Mode = UART_MODE_TX_RX; //传输模式
      uart3.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE; //流控
      HAL_UART_Init(&uart3.uart);
      / 初始化UCB控制块指针 /
      U3_PtrInit();
      }
      / 初始化U1_UCB控制块指针 /
      void U1_PtrInit(void){
      uart1.rxCount = 0;
      uart1.rxInPtr = &uart1.rxLocation[0];
      uart1.rxOutPtr = &uart1.rxLocation[0];
      uart1.rxEndPtr = &uart1.rxLocation[9];
      uart1.rxInPtr->start = &U1_Rx_Buff[0];
      uart1.txCount = 0;
      uart1.txInPtr = &uart1.txLocation[0];
      uart1.txOutPtr = &uart1.txLocation[0];
      uart1.txEndPtr = &uart1.txLocation[9];
      uart1.txInPtr->start = &U1_Tx_Buff[0];
      __HAL_UART_ENABLE_IT(&uart1.uart,UART_IT_IDLE);
      HAL_UART_Receive_IT(&uart1.uart, uart1.rxInPtr->start, U1_RX_MAX);
      }
      void U2_PtrInit(void){
      uart2.rxCount = 0;
      uart2.rxInPtr = &uart2.rxLocation[0];
      uart2.rxOutPtr = &uart2.rxLocation[0];
      uart2.rxEndPtr = &uart2.rxLocation[9];
      uart2.rxInPtr->start = &U2_Rx_Buff[0];
      uart2.txCount = 0;
      uart2.txInPtr = &uart2.txLocation[0];
      uart2.txOutPtr = &uart2.txLocation[0];
      uart2.txEndPtr = &uart2.txLocation[9];
      uart2.txInPtr->start = &U2_Tx_Buff[0];
      __HAL_UART_ENABLE_IT(&uart2.uart,UART_IT_IDLE);
      HAL_UART_Receive_IT(&uart2.uart, uart2.rxInPtr->start, U2_RX_MAX);
      }
      void U3_PtrInit(void){
      uart3.rxCount = 0;
      uart3.rxInPtr = &uart3.rxLocation[0];
      uart3.rxOutPtr = &uart3.rxLocation[0];
      uart3.rxEndPtr = &uart3.rxLocation[9];
      uart3.rxInPtr->start = &U3_Rx_Buff[0];
      uart3.txCount = 0;
      uart3.txInPtr = &uart3.txLocation[0];
      uart3.txOutPtr = &uart3.txLocation[0];
      uart3.txEndPtr = &uart3.txLocation[9];
      uart3.txInPtr->start = &U3_Tx_Buff[0];
      __HAL_UART_ENABLE_IT(&uart3.uart,UART_IT_IDLE);
      HAL_UART_Receive_IT(&uart3.uart, uart3.rxInPtr->start, U3_RX_MAX);
      }
      / 转移Rx_Buff数据到 Tx_Buff /
      void U1_DataRxToTx(uint8_t* data, uint32_t data_len){
      if((U1_TX_SIZE - uart1.txCount) > data_len){
      uart1.txInPtr->start = &U1_Tx_Buff[uart1.txCount];
      }
      else{
      uart1.txCount = 0;
      uart1.txInPtr->start = &U1_Tx_Buff[0];
      }
      memcpy(uart1.txInPtr->start, data, data_len);
      uart1.txCount += data_len;
      uart1.txInPtr->end = &U1_Tx_Buff[uart1.txCount - 1];
      uart1.txInPtr++;
      if(uart1.txInPtr == uart1.txEndPtr){
      uart1.txInPtr = &uart1.txLocation[0];
      }
      }
      void U2_DataRxToTx(uint8_t* data, uint32_t data_len){
      if((U2_TX_SIZE - uart2.txCount) > data_len){
      uart2.txInPtr->start = &U2_Tx_Buff[uart2.txCount];
      }
      else{
      uart2.txCount = 0;
      uart2.txInPtr->start = &U2_Tx_Buff[0];
      }
      memcpy(uart2.txInPtr->start, data, data_len);
      uart2.txCount += data_len;
      uart2.txInPtr->end = &U2_Tx_Buff[uart2.txCount - 1];
      uart2.txInPtr++;
      if(uart2.txInPtr == uart2.txEndPtr){
      uart2.txInPtr = &uart2.txLocation[0];
      }
      }
      void U3_DataRxToTx(uint8_t* data, uint32_t data_len){
      if((U3_TX_SIZE - uart3.txCount) > data_len){
      uart3.txInPtr->start = &U3_Tx_Buff[uart3.txCount];
      }
      else{
      uart3.txCount = 0;
      uart3.txInPtr->start = &U3_Tx_Buff[0];
      }
      memcpy(uart3.txInPtr->start, data, data_len);
      uart3.txCount += data_len;
      uart3.txInPtr->end = &U3_Tx_Buff[uart3.txCount - 1];
      uart3.txInPtr++;
      if(uart3.txInPtr == uart3.txEndPtr){
      uart3.txInPtr = &uart3.txLocation[0];
      }
      }
      / UART硬件初始化回调 /
      void HAL_UART_MspInit(UART_HandleTypeDef *huart){
      GPIO_InitTypeDef GPIO_InitType;
      if(huart->Instance == USART1){
      __HAL_RCC_USART1_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_9;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_10;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      HAL_NVIC_SetPriority(USART1_IRQn,3,0);
      HAL_NVIC_EnableIRQ(USART1_IRQn);
      }else if(huart->Instance == USART2){
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_USART2_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_2;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_3;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      HAL_NVIC_SetPriority(USART2_IRQn,3,0);
      HAL_NVIC_EnableIRQ(USART2_IRQn);
      }else if(huart->Instance == USART3){
      __HAL_RCC_GPIOB_CLK_ENABLE();
      __HAL_RCC_USART3_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_10;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOB,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_11;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOB,&GPIO_InitType);
      HAL_NVIC_SetPriority(USART3_IRQn,3,0);
      HAL_NVIC_EnableIRQ(USART3_IRQn);
      }
      }
      / 强声明的接收完成回调函数 /
      void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的错误回调函数 /
      void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的发送完成回调函数 /
      void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      / 发送完成,标志位清零 /
      uart1.TxState = 0;
      }else if(huart->Instance == USART2){
      uart2.TxState = 0;
      }else if(huart->Instance == USART3){
      uart3.TxState = 0;
      }
      }
      / 强声明的接收终止回调函数 /
      void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      uart1.rxInPtr->end = &U1_Rx_Buff[uart1.rxCount - 1];
      uart1.rxInPtr++;
      if(uart1.rxInPtr == uart1.rxEndPtr){
      uart1.rxInPtr = &uart1.rxLocation[0];
      }
      if((U1_RX_SIZE - uart1.rxCount) < U1_RX_MAX){
      uart1.rxCount = 0;
      uart1.rxInPtr->start = &U1_Rx_Buff[0];
      }else{
      uart1.rxInPtr->start = &U1_Rx_Buff[uart1.rxCount];
      }
      HAL_UART_Receive_IT(&uart1.uart, uart1.rxInPtr->start, U1_RX_MAX);
      }else if(huart->Instance == USART2){
      uart2.rxInPtr->end = &U2_Rx_Buff[uart2.rxCount - 1];
      uart2.rxInPtr++;
      if(uart2.rxInPtr == uart2.rxEndPtr){
      uart2.rxInPtr = &uart2.rxLocation[0];
      }
      if((U2_RX_SIZE - uart2.rxCount) < U2_RX_MAX){
      uart2.rxCount = 0;
      uart2.rxInPtr->start = &U2_Rx_Buff[0];
      }else{
      uart2.rxInPtr->start = &U2_Rx_Buff[uart2.rxCount];
      }
      HAL_UART_Receive_IT(&uart2.uart, uart2.rxInPtr->start, U2_RX_MAX);
      }else if(huart->Instance == USART3){
      uart3.rxInPtr->end = &U3_Rx_Buff[uart3.rxCount - 1];
      uart3.rxInPtr++;
      if(uart3.rxInPtr == uart3.rxEndPtr){
      uart3.rxInPtr = &uart3.rxLocation[0];
      }
      if((U3_RX_SIZE - uart3.rxCount) < U3_RX_MAX){
      uart3.rxCount = 0;
      uart3.rxInPtr->start = &U3_Rx_Buff[0];
      }else{
      uart3.rxInPtr->start = &U3_Rx_Buff[uart3.rxCount];
      }
      HAL_UART_Receive_IT(&uart3.uart, uart3.rxInPtr->start, U3_RX_MAX);
      }
      }
      /-------------------------------------------------/
      / /
      / 实现各种中断服务函数的源文件 /
      / /
      /-------------------------------------------------/
      #include "stm32f1xx_hal.h"
      #include "stm32f1xx_it.h"
      #include "uart.h"
      void EXTI15_10_IRQHandler(void)
      {
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
      }
      void EXTI0_IRQHandler(void)
      {
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
      }
      /-------------------------------------------------/
      /函数名:不可屏蔽中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void NMI_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:硬件出错后进入的中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void HardFault_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:软中断,SWI 指令调用的处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void SVC_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:可挂起的系统服务处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void PendSV_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:SysTic系统嘀嗒定时器处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void SysTick_Handler(void)
      {
      HAL_IncTick();
      }
      /-------------------------------------------------/
      /函数名:串口1中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void USART1_IRQHandler(void)
      {
      HAL_UART_IRQHandler(&uart1.uart);
      / 在每次进入中断后,判断是否为空闲中断 /
      if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
      / 清除空闲标志位 /
      //__HAL_UART_CLEAR_FLAG(&uart1.uart, UART_FLAG_IDLE);
      __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
      / 获取这次传输了多少字节 /
      uart1.rxCount += (U1_RX_MAX - uart1.uart.RxXferCount);
      / 终止当前的接收(会把RxferCount清零) /
      HAL_UART_AbortReceive_IT(&uart1.uart);
      }
      }
      /-------------------------------------------------/
      /函数名:串口2中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void USART2_IRQHandler(void)
      {
      HAL_UART_IRQHandler(&uart2.uart);
      if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
      __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
      uart2.rxCount += (U2_RX_MAX - uart2.uart.RxXferCount);
      HAL_UART_AbortReceive_IT(&uart2.uart);
      }
      }
      /-------------------------------------------------/
      /函数名:串口3中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void USART3_IRQHandler(void)
      {
      HAL_UART_IRQHandler(&uart3.uart);
      if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
      __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
      uart3.rxCount += (U3_RX_MAX - uart3.uart.RxXferCount);
      HAL_UART_AbortReceive_IT(&uart3.uart);
      }
      }
      #include "stm32f1xx_hal.h"
      #include "rcc.h"
      #include "led.h"
      #include "sw.h"
      #include "uart.h"
      int main(void){
      HAL_Init();
      RccClock_Init();
      U1_Init(921600);
      U2_Init(921600);
      U3_Init(921600);
      while(1){
      / ------------------UART1------------------ /
      / 判断接收缓冲区是否有数据 /
      if(uart1.rxInPtr != uart1.rxOutPtr){
      U1_DataRxToTx(uart1.rxOutPtr->start, (uart1.rxOutPtr->end - uart1.rxOutPtr->start + 1));
      uart1.rxOutPtr++;
      if(uart1.rxOutPtr == uart1.rxEndPtr){
      uart1.rxOutPtr = &uart1.rxLocation[0];
      }
      }
      / 判断发送缓冲区是否有数据 /
      if((uart1.txInPtr != uart1.txOutPtr) && (uart1.TxState == 0) ){
      uart1.TxState = 1;
      HAL_UART_Transmit_IT(&uart1.uart, uart1. txOutPtr->start, (uart1.txOutPtr->end - uart1.txOutPtr->start + 1));
      uart1.txOutPtr++;
      if(uart1.txOutPtr == uart1.txEndPtr){
      uart1.txOutPtr = &uart1.txLocation[0];
      }
      }
      / ------------------UART2------------------ /
      if(uart2.rxInPtr != uart2.rxOutPtr){
      U2_DataRxToTx(uart2.rxOutPtr->start, (uart2.rxOutPtr->end - uart2.rxOutPtr->start + 1));
      uart2.rxOutPtr++;
      if(uart2.rxOutPtr == uart2.rxEndPtr){
      uart2.rxOutPtr = &uart2.rxLocation[0];
      }
      }
      / 判断发送缓冲区是否有数据 /
      if((uart2.txInPtr != uart2.txOutPtr) && (uart2.TxState == 0) ){
      uart2.TxState = 1;
      HAL_UART_Transmit_IT(&uart2.uart, uart2. txOutPtr->start, (uart2.txOutPtr->end - uart2.txOutPtr->start + 1));
      uart2.txOutPtr++;
      if(uart2.txOutPtr == uart2.txEndPtr){
      uart2.txOutPtr = &uart2.txLocation[0];
      }
      }
      / ------------------UART3------------------ /
      if(uart3.rxInPtr != uart3.rxOutPtr){
      U3_DataRxToTx(uart3.rxOutPtr->start, (uart3.rxOutPtr->end - uart3.rxOutPtr->start + 1));
      uart3.rxOutPtr++;
      if(uart3.rxOutPtr == uart3.rxEndPtr){
      uart3.rxOutPtr = &uart3.rxLocation[0];
      }
      }
      / 判断发送缓冲区是否有数据 /
      if((uart3.txInPtr != uart3.txOutPtr) && (uart3.TxState == 0) ){
      uart3.TxState = 1;
      HAL_UART_Transmit_IT(&uart3.uart, uart3. txOutPtr->start, (uart3.txOutPtr->end - uart3.txOutPtr->start + 1));
      uart3.txOutPtr++;
      if(uart3.txOutPtr == uart3.txEndPtr){
      uart3.txOutPtr = &uart3.txLocation[0];
      }
      }
      }
      }
      1. 可以利用__HAL_DMA_GET_COUNTER函数来获得当前DMA的未搬运的量

      uart.h

      uart.c

      / UART硬件初始化回调 /
      void HAL_UART_MspInit(UART_HandleTypeDef *huart){
      GPIO_InitTypeDef GPIO_InitType;
      if(huart->Instance == USART1){
      __HAL_RCC_USART1_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_DMA1_CLK_ENABLE(); //打开DMA时钟
      GPIO_InitType.Pin = GPIO_PIN_9;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_10;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      HAL_NVIC_SetPriority(USART1_IRQn,3,0);
      HAL_NVIC_EnableIRQ(USART1_IRQn);
      / DMA配置 /
      // 发送配置
      uart1.dmaTx.Instance = DMA1_Channel4; //DMA通道:4
      uart1.dmaTx.Init.Direction = DMA_MEMORY_TO_PERIPH; //方向:存储区到外设
      uart1.dmaTx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //存储区数据宽度
      uart1.dmaTx.Init.MemInc = DMA_MINC_ENABLE; //存储区是否递增?
      uart1.dmaTx.Init.Mode = DMA_NORMAL; //工作模式(正常或循环)
      uart1.dmaTx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据宽度
      uart1.dmaTx.Init.PeriphInc = DMA_PINC_DISABLE; //目标地址是否递增?
      uart1.dmaTx.Init.Priority = DMA_PRIORITY_MEDIUM; //优先级
      //链接
      __HAL_LINKDMA(huart, hdmatx, uart1.dmaTx);
      //初始化
      HAL_DMA_Init(&uart1.dmaTx);
      //打开DMA通道中断
      HAL_NVIC_SetPriority(DMA1_Channel4_IRQn,3,0);
      HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
      // 接收配置
      uart1.dmaRx.Instance = DMA1_Channel5; //DMA通道:5
      uart1.dmaRx.Init.Direction = DMA_PERIPH_TO_MEMORY; //方向:外设区到存储
      uart1.dmaRx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
      uart1.dmaRx.Init.MemInc = DMA_MINC_ENABLE;
      uart1.dmaRx.Init.Mode = DMA_NORMAL;
      uart1.dmaRx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
      uart1.dmaRx.Init.PeriphInc = DMA_PINC_DISABLE;
      uart1.dmaRx.Init.Priority = DMA_PRIORITY_MEDIUM;
      //链接
      __HAL_LINKDMA(huart, hdmarx, uart1.dmaRx);
      //初始化
      HAL_DMA_Init(&uart1.dmaRx);
      //打开DMA中断
      HAL_NVIC_SetPriority(DMA1_Channel5_IRQn,3,0);
      HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
      }else if(huart->Instance == USART2){
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_USART2_CLK_ENABLE();
      __HAL_RCC_DMA1_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_2;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_3;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA,&GPIO_InitType);
      HAL_NVIC_SetPriority(USART2_IRQn,3,0);
      HAL_NVIC_EnableIRQ(USART2_IRQn);
      / DMA配置 /
      uart2.dmaTx.Instance = DMA1_Channel7;
      uart2.dmaTx.Init.Direction = DMA_MEMORY_TO_PERIPH;
      uart2.dmaTx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
      uart2.dmaTx.Init.MemInc = DMA_MINC_ENABLE;
      uart2.dmaTx.Init.Mode = DMA_NORMAL;
      uart2.dmaTx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
      uart2.dmaTx.Init.PeriphInc = DMA_PINC_DISABLE;
      uart2.dmaTx.Init.Priority = DMA_PRIORITY_MEDIUM;
      __HAL_LINKDMA(huart, hdmatx, uart2.dmaTx);
      HAL_DMA_Init(&uart2.dmaTx);
      HAL_NVIC_SetPriority(DMA1_Channel7_IRQn,3,0);
      HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
      uart2.dmaRx.Instance = DMA1_Channel6;
      uart2.dmaRx.Init.Direction = DMA_PERIPH_TO_MEMORY;
      uart2.dmaRx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
      uart2.dmaRx.Init.MemInc = DMA_MINC_ENABLE;
      uart2.dmaRx.Init.Mode = DMA_NORMAL;
      uart2.dmaRx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
      uart2.dmaRx.Init.PeriphInc = DMA_PINC_DISABLE;
      uart2.dmaRx.Init.Priority = DMA_PRIORITY_MEDIUM;
      __HAL_LINKDMA(huart, hdmarx, uart2.dmaRx);
      HAL_DMA_Init(&uart2.dmaRx);
      HAL_NVIC_SetPriority(DMA1_Channel6_IRQn,3,0);
      HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
      }else if(huart->Instance == USART3){
      __HAL_RCC_GPIOB_CLK_ENABLE();
      __HAL_RCC_USART3_CLK_ENABLE();
      __HAL_RCC_DMA1_CLK_ENABLE();
      GPIO_InitType.Pin = GPIO_PIN_10;
      GPIO_InitType.Mode = GPIO_MODE_AF_PP;
      GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
      HAL_GPIO_Init(GPIOB,&GPIO_InitType);
      GPIO_InitType.Pin = GPIO_PIN_11;
      GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
      GPIO_InitType.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOB,&GPIO_InitType);
      HAL_NVIC_SetPriority(USART3_IRQn,3,0);
      HAL_NVIC_EnableIRQ(USART3_IRQn);
      / DMA配置 /
      uart3.dmaTx.Instance = DMA1_Channel2;
      uart3.dmaTx.Init.Direction = DMA_MEMORY_TO_PERIPH;
      uart3.dmaTx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
      uart3.dmaTx.Init.MemInc = DMA_MINC_ENABLE;
      uart3.dmaTx.Init.Mode = DMA_NORMAL;
      uart3.dmaTx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
      uart3.dmaTx.Init.PeriphInc = DMA_PINC_DISABLE;
      uart3.dmaTx.Init.Priority = DMA_PRIORITY_MEDIUM;
      __HAL_LINKDMA(huart, hdmatx, uart3.dmaTx);
      HAL_DMA_Init(&uart3.dmaTx);
      HAL_NVIC_SetPriority(DMA1_Channel2_IRQn,3,0);
      HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
      uart3.dmaRx.Instance = DMA1_Channel3;
      uart3.dmaRx.Init.Direction = DMA_PERIPH_TO_MEMORY;
      uart3.dmaRx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
      uart3.dmaRx.Init.MemInc = DMA_MINC_ENABLE;
      uart3.dmaRx.Init.Mode = DMA_NORMAL;
      uart3.dmaRx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
      uart3.dmaRx.Init.PeriphInc = DMA_PINC_DISABLE;
      uart3.dmaRx.Init.Priority = DMA_PRIORITY_MEDIUM;
      __HAL_LINKDMA(huart, hdmarx, uart3.dmaRx);
      HAL_DMA_Init(&uart3.dmaRx);
      HAL_NVIC_SetPriority(DMA1_Channel3_IRQn,3,0);
      HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
      }
      }
      / 强声明的接收完成回调函数 /
      void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的错误回调函数 /
      void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      }else if(huart->Instance == USART2){
      }else if(huart->Instance == USART3){
      }
      }
      / 强声明的发送完成回调函数 /
      void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      / 发送完成,标志位清零 /
      uart1.TxState = 0;
      }else if(huart->Instance == USART2){
      uart2.TxState = 0;
      }else if(huart->Instance == USART3){
      uart3.TxState = 0;
      }
      }
      / 强声明的接收终止回调函数 /
      void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
      {
      if(huart->Instance == USART1){
      uart1.rxInPtr->end = &U1_Rx_Buff[uart1.rxCount - 1];
      uart1.rxInPtr++;
      if(uart1.rxInPtr == uart1.rxEndPtr){
      uart1.rxInPtr = &uart1.rxLocation[0];
      }
      if((U1_RX_SIZE - uart1.rxCount) < U1_RX_MAX){
      uart1.rxCount = 0;
      uart1.rxInPtr->start = &U1_Rx_Buff[0];
      }else{
      uart1.rxInPtr->start = &U1_Rx_Buff[uart1.rxCount];
      }
      HAL_UART_Receive_DMA(&uart1.uart, uart1.rxInPtr->start, U1_RX_MAX);
      }else if(huart->Instance == USART2){
      uart2.rxInPtr->end = &U2_Rx_Buff[uart2.rxCount - 1];
      uart2.rxInPtr++;
      if(uart2.rxInPtr == uart2.rxEndPtr){
      uart2.rxInPtr = &uart2.rxLocation[0];
      }
      if((U2_RX_SIZE - uart2.rxCount) < U2_RX_MAX){
      uart2.rxCount = 0;
      uart2.rxInPtr->start = &U2_Rx_Buff[0];
      }else{
      uart2.rxInPtr->start = &U2_Rx_Buff[uart2.rxCount];
      }
      HAL_UART_Receive_DMA(&uart2.uart, uart2.rxInPtr->start, U2_RX_MAX);
      }else if(huart->Instance == USART3){
      uart3.rxInPtr->end = &U3_Rx_Buff[uart3.rxCount - 1];
      uart3.rxInPtr++;
      if(uart3.rxInPtr == uart3.rxEndPtr){
      uart3.rxInPtr = &uart3.rxLocation[0];
      }
      if((U3_RX_SIZE - uart3.rxCount) < U3_RX_MAX){
      uart3.rxCount = 0;
      uart3.rxInPtr->start = &U3_Rx_Buff[0];
      }else{
      uart3.rxInPtr->start = &U3_Rx_Buff[uart3.rxCount];
      }
      HAL_UART_Receive_DMA(&uart3.uart, uart3.rxInPtr->start, U3_RX_MAX);
      }
      }
      /-------------------------------------------------/
      / /
      / 实现各种中断服务函数的源文件 /
      / /
      /-------------------------------------------------/
      #include "stm32f1xx_hal.h"
      #include "stm32f1xx_it.h"
      #include "uart.h"
      void EXTI15_10_IRQHandler(void)
      {
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
      }
      void EXTI0_IRQHandler(void)
      {
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
      }
      /-------------------------------------------------/
      /函数名:不可屏蔽中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void NMI_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:硬件出错后进入的中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void HardFault_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:软中断,SWI 指令调用的处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void SVC_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:可挂起的系统服务处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void PendSV_Handler(void)
      {
      }
      /-------------------------------------------------/
      /函数名:SysTic系统嘀嗒定时器处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void SysTick_Handler(void)
      {
      HAL_IncTick();
      }
      /-------------------------------------------------/
      /函数名:串口1中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void USART1_IRQHandler(void)
      {
      HAL_UART_IRQHandler(&uart1.uart);
      / 在每次进入中断后,判断是否为空闲中断 /
      if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
      / 清除空闲标志位 /
      //__HAL_UART_CLEAR_FLAG(&uart1.uart, UART_FLAG_IDLE);
      __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
      / 获取这次传输了多少字节 /
      //uart1.rxCount += (U1_RX_MAX - uart1.uart.RxXferCount);
      uart1.rxCount += (U1_RX_MAX - (__HAL_DMA_GET_COUNTER(&uart1.dmaRx))); //利用DMA的api 获取剩余未发送数据量
      / 终止当前的接收(会把RxferCount清零) /
      HAL_UART_AbortReceive_IT(&uart1.uart);
      }
      }
      /-------------------------------------------------/
      /函数名:串口2中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void USART2_IRQHandler(void)
      {
      HAL_UART_IRQHandler(&uart2.uart);
      if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
      __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
      uart2.rxCount += (U2_RX_MAX - (__HAL_DMA_GET_COUNTER(&uart2.dmaRx)));
      HAL_UART_AbortReceive_IT(&uart2.uart);
      }
      }
      /-------------------------------------------------/
      /函数名:串口3中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void USART3_IRQHandler(void)
      {
      HAL_UART_IRQHandler(&uart3.uart);
      if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
      __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
      uart3.rxCount += (U3_RX_MAX - (__HAL_DMA_GET_COUNTER(&uart3.dmaRx)));
      HAL_UART_AbortReceive_IT(&uart3.uart);
      }
      }
      /-------------------------------------------------/
      /函数名:DMA通道4中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void DMA1_Channel4_IRQHandler(void) //Uart1 Tx通道
      {
      HAL_DMA_IRQHandler(&uart1.dmaTx);
      }
      /-------------------------------------------------/
      /函数名:DMA通道5中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void DMA1_Channel5_IRQHandler(void) //Uart1 Rx通道
      {
      HAL_DMA_IRQHandler(&uart1.dmaRx);
      }
      /-------------------------------------------------/
      /函数名:DMA通道7中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void DMA1_Channel7_IRQHandler(void) //Uart2 Tx通道
      {
      HAL_DMA_IRQHandler(&uart2.dmaTx);
      }
      /-------------------------------------------------/
      /函数名:DMA通道6中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void DMA1_Channel6_IRQHandler(void) //Uart2 Rx通道
      {
      HAL_DMA_IRQHandler(&uart2.dmaRx);
      }
      /-------------------------------------------------/
      /函数名:DMA通道2中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void DMA1_Channel2_IRQHandler(void) //Uart3 Tx通道
      {
      HAL_DMA_IRQHandler(&uart3.dmaTx);
      }
      /-------------------------------------------------/
      /函数名:DMA通道3中断处理函数 /
      /参 数:无 /
      /返回值:无 /
      /-------------------------------------------------/
      void DMA1_Channel3_IRQHandler(void) //Uart3 Rx通道
      {
      HAL_DMA_IRQHandler(&uart3.dmaRx);
      }
      #include "stm32f1xx_hal.h"
      #include "rcc.h"
      #include "led.h"
      #include "sw.h"
      #include "uart.h"
      int main(void){
      HAL_Init();
      RccClock_Init();
      U1_Init(921600);
      U2_Init(921600);
      U3_Init(921600);
      while(1){
      / ------------------UART1------------------ /
      / 判断接收缓冲区是否有数据 /
      if(uart1.rxInPtr != uart1.rxOutPtr){
      U1_DataRxToTx(uart1.rxOutPtr->start, (uart1.rxOutPtr->end - uart1.rxOutPtr->start + 1));
      uart1.rxOutPtr++;
      if(uart1.rxOutPtr == uart1.rxEndPtr){
      uart1.rxOutPtr = &uart1.rxLocation[0];
      }
      }
      / 判断发送缓冲区是否有数据 /
      if((uart1.txInPtr != uart1.txOutPtr) && (uart1.TxState == 0) ){
      uart1.TxState = 1;
      HAL_UART_Transmit_DMA(&uart1.uart, uart1. txOutPtr->start, (uart1.txOutPtr->end - uart1.txOutPtr->start + 1));
      uart1.txOutPtr++;
      if(uart1.txOutPtr == uart1.txEndPtr){
      uart1.txOutPtr = &uart1.txLocation[0];
      }
      }
      / ------------------UART2------------------ /
      if(uart2.rxInPtr != uart2.rxOutPtr){
      U2_DataRxToTx(uart2.rxOutPtr->start, (uart2.rxOutPtr->end - uart2.rxOutPtr->start + 1));
      uart2.rxOutPtr++;
      if(uart2.rxOutPtr == uart2.rxEndPtr){
      uart2.rxOutPtr = &uart2.rxLocation[0];
      }
      }
      / 判断发送缓冲区是否有数据 /
      if((uart2.txInPtr != uart2.txOutPtr) && (uart2.TxState == 0) ){
      uart2.TxState = 1;
      HAL_UART_Transmit_DMA(&uart2.uart, uart2. txOutPtr->start, (uart2.txOutPtr->end - uart2.txOutPtr->start + 1));
      uart2.txOutPtr++;
      if(uart2.txOutPtr == uart2.txEndPtr){
      uart2.txOutPtr = &uart2.txLocation[0];
      }
      }
      / ------------------UART3------------------ /
      if(uart3.rxInPtr != uart3.rxOutPtr){
      U3_DataRxToTx(uart3.rxOutPtr->start, (uart3.rxOutPtr->end - uart3.rxOutPtr->start + 1));
      uart3.rxOutPtr++;
      if(uart3.rxOutPtr == uart3.rxEndPtr){
      uart3.rxOutPtr = &uart3.rxLocation[0];
      }
      }
      / 判断发送缓冲区是否有数据 /
      if((uart3.txInPtr != uart3.txOutPtr) && (uart3.TxState == 0) ){
      uart3.TxState = 1;
      HAL_UART_Transmit_DMA(&uart3.uart, uart3. txOutPtr->start, (uart3.txOutPtr->end - uart3.txOutPtr->start + 1));
      uart3.txOutPtr++;
      if(uart3.txOutPtr == uart3.txEndPtr){
      uart3.txOutPtr = &uart3.txLocation[0];
      }
      }
      }
      }
      在本机 按键按下时,进入中断。在中断回调中使用UART1 发送数据LED_ON或LED_OFF
      在UART1接收到数据时,进行判断,使用strcmp函数
      插线的话,两个设备 TX对RX RX对TX, GND对GND就Ok了
       

      十、HAL库:单线半双工,双机通信,DMA方式收发 控制对方LED灯

      在上面的基础上进行修改

      1. 单线半双工简介

      两个单片机之间通过串口,单线半双工通信。
      半双工:同一时间只能发送或者接收,此时仅使用TX引脚
      注意:此时TX引脚需要配置为OD模式,外接上拉电阻

      2. 大概思路

      在本机 按键按下时,进入中断。在中断回调中使用UART1 发送数据LED_ON或LED_OFF
      在UART1接收到数据时,进行判断,使用strcmp函数
      插线的话,两个设备 TX对RX RX对TX, GND对GND就Ok了

      3. 注意

      • 在初始化时,要使用HAL_HalfDuplex_Init 来初始化
      • 单线半双工用的是串口的Tx引脚, 注意Tx引脚要初始化为AF_OD 模式,并且接上拉电阻
      • 一般在初始化的时候,默认为单线半双工的接收状态,只有在使用发送的时候,才使用HAL_HalfDuplex_EnableTransmitter(&uart1.uart);来使能单线半双工的发射模式。并且在发送完成之后,(一般使用发送完成回调)把发射模式重置为默认的接收模式。HAL_HalfDuplex_EnableReceiver(&uart1.uart);

      十一、HAL库:多主机通信 地址检测唤醒 定时器超时 DMA不定长接收

      1. 设备唤醒介绍

      1.1 唤醒方式:

      • 三个及以上单片机之间通过串口,相互通信收发数据时。
      • 此时我们需要涉及到主机和从机之分,从机的唤醒有分为:地址 or 空闲唤醒

      1.2 地址唤醒:

      • 每个从机会具备一个硬件的从机地址, 地址会记录在USART_CR2寄存器的ADD,占用了4个二进制位。范围0x00~0x0F
      • 但是主机在发送时,需要区分地址 还是数据:如果最高位为1,表示地址,为0表示数据。 所以主机发送的数据,首个字节是从机的地址,范围应该是0x80~0x8F, 8表示最高位7为1。 所以在发送数据时,最高位为 0 数据的有效位为 bit0~bit6 7位数据

      1.3 多处理器通信:

      与I2C类似,主机Tx为PP模式
      • 主机的tx,接到各个从设备的Rx引脚。 从机的tx输出逻辑 地与(线与)在一起,
      • 注意:
        • 从机的Tx不能为PP模式,否则两个从机输出1 、0会形成短路。
        • 从机的Tx‘应该为OD模式,外接上拉电阻。
        • 并且上拉电阻尽量选择外部上拉电阻,否则选择内部上拉,在波特率比较高的时候,电压上拉速度慢,导致检测为0等情况。
      • USART_CR1寄存器的RWU位
        • RWU可以被硬件自动控制或在某个条件先由软件写入
        • RWU高电平表示从机为静默模式,不会接收数据
        • RWU低电平表示从机为正常模式,会接收数据
        • 从机通过判断地址,切换到正常模式
        • 未匹配的地址可以把正常模式的从机返回为静默模式,也可以手动返回为静默模式,
        • 在初始化从机之后 需要手动把RWU变为高电平:静默模式

      2. 特别注意:

      1. DMA在搬运UART的的数据时,会顺便把RXNE的标志位硬件清除。所以在开启DMA接收时,RXNE在软件上检测不到标志位为1
      1. 多处理器有空闲总线唤醒机制,只要用了多处理器的模式,那么空闲中断就不会产生了
        1. 就不能使用空闲中断来进行数据的不定长接收,可以换一种方式:使用定时器的超时判断,来进行数据的不定长接收。

      2.1 使用定时器的超时判断,来进行数据的不定长接收思路详解

      假设波特率为9600 ,那么一秒钟最快能发送960个字节,也就是1ms多点。也就是在一个连续的数据流中,每个字节的传输间隔为1ms。
      现在开一个定时器,定时时间为大于1ms的值,比如 15 ms。
      在每次接收一个字节之后,都清空定时器的计数值。 当定时器超时时,就代表当前一次的数据已经传输完毕。
      优点:利用空闲中断时,如果数据发生波动,那么会把一个数据分成两次数据。 而定时器不会,定时器时通过时间判断。 初始化定时器 用于超时计时TIM4_TimerInit(300,7200); 30ms超时时间
      需要 打开接收中断 __HAL_UART_ENABLE_IT(&uart2.uart,UART_IT_RXNE);
      判断接收标志位 if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_RXNE)){
      文件部分
      • 需要修改hal_uart.c(虽然不建议,但是只能这样了)
      • 关闭了RXNE中断和发生空闲中断,让每次接收字节后都进入自己的函数中stm32f1xx_hal_uart.c
        uint32_t cr1its = READ_REG(huart->Instance->CR1);
        uint32_t cr3its = READ_REG(huart->Instance->CR3);
        uint32_t errorflags = 0x00U;
        uint32_t dmarequest = 0x00U;
        / If no error occurs /
        errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
        //删除 RXNE中断
        //if (errorflags == RESET)
        //{
        // / UART in mode Receiver -------------------------------------------------/
        // if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
        // {
        // UART_Receive_IT(huart);
        // return;
        // }
        //}
        / If some errors occur /
        if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
        {
        / UART parity error interrupt occurred ----------------------------------/
        if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_PE;
        }
        / UART noise error interrupt occurred -----------------------------------/
        if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_NE;
        }
        / UART frame error interrupt occurred -----------------------------------/
        if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_FE;
        }
        / UART Over-Run interrupt occurred --------------------------------------/
        if (((isrflags & USART_SR_ORE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_ORE;
        }
        / Call UART Error Call back function if need be --------------------------/
        if (huart->ErrorCode != HAL_UART_ERROR_NONE)
        {
        / UART in mode Receiver -----------------------------------------------/
        if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
        {
        UART_Receive_IT(huart);
        }
        /* If Overrun error occurs, or if any error occurs in DMA mode reception,
        consider error as blocking */
        dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
        if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
        {
        /* Blocking error : transfer is aborted
        Set the UART state ready to be able to start again the process,
        Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
        UART_EndRxTransfer(huart);
        / Disable the UART DMA Rx request if enabled /
        if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
        {
        CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
        / Abort the UART DMA Rx channel /
        if (huart->hdmarx != NULL)
        {
        /* Set the UART DMA Abort callback :
        will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
        huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
        if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
        {
        / Call Directly XferAbortCallback function in case of error /
        huart->hdmarx->XferAbortCallback(huart->hdmarx);
        }
        }
        else
        {
        / Call user error callback /
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        }
        }
        else
        {
        / Call user error callback /
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        }
        }
        else
        {
        /* Non Blocking error : transfer could go on.
        Error is notified to user through user error callback */
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        huart->ErrorCode = HAL_UART_ERROR_NONE;
        }
        }
        return;
        } / End if some error occurs /
        / UART in mode Transmitter ------------------------------------------------/
        //删除 发送缓冲区空的中断
        // if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
        // {
        // UART_Transmit_IT(huart);
        // return;
        // }
        / UART in mode Transmitter end --------------------------------------------/
        if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
        {
        UART_EndTransmit_IT(huart);
        return;
        }
        / 写自己的中断回调,现在只能进入我们这个了。 /
        #include "uart.h"
        #include "timer.h"
        else
        {
        if(uart2.RxState == 0){ / 首字节 /
        __HAL_TIM_ENABLE(&htim4); //打开tim4的计数
        uart2.RxStat = 1; //标记接收
        }else{/ 后续字节 /
        __HAL_TIM_SET_COUNTER(&htim4, 0)//清除tim4的计数
        }
        }
        }
        #include "stm32f1xx_hal.h"
        #include "uart.h"
        UCB uart1;
        UCB uart2;
        UCB uart3;
        uint8_t U1_RxBuff[U1_RX_SIZE];
        uint8_t U1_TxBuff[U1_TX_SIZE];
        uint8_t U2_RxBuff[U2_RX_SIZE];
        uint8_t U2_TxBuff[U2_TX_SIZE];
        uint8_t U3_RxBuff[U3_RX_SIZE];
        uint8_t U3_TxBuff[U3_TX_SIZE];
        void U1_Init(uint32_t bandrate){
        uart1.uart.Instance = USART1;
        uart1.uart.Init.BaudRate = bandrate;
        uart1.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart1.uart.Init.StopBits = UART_STOPBITS_1;
        uart1.uart.Init.Parity = UART_PARITY_NONE;
        uart1.uart.Init.Mode = UART_MODE_TX_RX;
        uart1.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_UART_Init(&uart1.uart);
        U1_PtrInit();
        }
        void U1_PtrInit(void){
        uart1.RxInPtr = &uart1.RxLocation[0];
        uart1.RxOutPtr = &uart1.RxLocation[0];
        uart1.RxEndPtr = &uart1.RxLocation[9];
        uart1.RxCounter = 0;
        uart1.RxInPtr->start = U1_RxBuff;
        uart1.TxInPtr = &uart1.TxLocation[0];
        uart1.TxOutPtr = &uart1.TxLocation[0];
        uart1.TxEndPtr = &uart1.TxLocation[9];
        uart1.TxCounter = 0;
        uart1.TxInPtr->start = U1_TxBuff;
        __HAL_UART_ENABLE_IT(&uart1.uart, UART_IT_IDLE);
        HAL_UART_Receive_DMA(&uart1.uart,uart1.RxInPtr->start,U1_RX_MAX);
        }
        void U1_Txdata(uint8_t *data, uint32_t data_len){
        if((U1_TX_SIZE - uart1.TxCounter )>=data_len){
        uart1.TxInPtr->start = &U1_TxBuff[uart1.TxCounter];
        }else{
        uart1.TxCounter = 0;
        uart1.TxInPtr->start = U1_TxBuff;
        }
        memcpy(uart1.TxInPtr->start,data,data_len);
        uart1.TxCounter += data_len;
        uart1.TxInPtr->end = &U1_TxBuff[uart1.TxCounter - 1];
        uart1.TxInPtr++;
        if(uart1.TxInPtr == uart1.TxEndPtr){
        uart1.TxInPtr = &uart1.TxLocation[0];
        }
        }
        void U2_Init(uint32_t bandrate){
        uart2.uart.Instance = USART2;
        uart2.uart.Init.BaudRate = bandrate;
        uart2.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart2.uart.Init.StopBits = UART_STOPBITS_1;
        uart2.uart.Init.Parity = UART_PARITY_NONE;
        uart2.uart.Init.Mode = UART_MODE_TX_RX;
        uart2.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_HalfDuplex_Init(&uart2.uart);
        HAL_HalfDuplex_EnableReceiver(&uart2.uart);
        U2_PtrInit();
        }
        void U2_PtrInit(void){
        uart2.RxInPtr = &uart2.RxLocation[0];
        uart2.RxOutPtr = &uart2.RxLocation[0];
        uart2.RxEndPtr = &uart2.RxLocation[9];
        uart2.RxCounter = 0;
        uart2.RxInPtr->start = U2_RxBuff;
        uart2.TxInPtr = &uart2.TxLocation[0];
        uart2.TxOutPtr = &uart2.TxLocation[0];
        uart2.TxEndPtr = &uart2.TxLocation[9];
        uart2.TxCounter = 0;
        uart2.TxInPtr->start = U2_TxBuff;
        __HAL_UART_ENABLE_IT(&uart2.uart, UART_IT_IDLE);
        HAL_UART_Receive_DMA(&uart2.uart,uart2.RxInPtr->start,U2_RX_MAX);
        }
        void U2_Txdata(uint8_t *data, uint32_t data_len){
        if((U2_TX_SIZE - uart2.TxCounter )>=data_len){
        uart2.TxInPtr->start = &U2_TxBuff[uart2.TxCounter];
        }else{
        uart2.TxCounter = 0;
        uart2.TxInPtr->start = U2_TxBuff;
        }
        memcpy(uart2.TxInPtr->start,data,data_len);
        uart2.TxCounter += data_len;
        uart2.TxInPtr->end = &U2_TxBuff[uart2.TxCounter - 1];
        uart2.TxInPtr++;
        if(uart2.TxInPtr == uart2.TxEndPtr){
        uart2.TxInPtr = &uart2.TxLocation[0];
        }
        }
        void U3_Init(uint32_t bandrate){
        uart3.uart.Instance = USART3;
        uart3.uart.Init.BaudRate = bandrate;
        uart3.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart3.uart.Init.StopBits = UART_STOPBITS_1;
        uart3.uart.Init.Parity = UART_PARITY_NONE;
        uart3.uart.Init.Mode = UART_MODE_TX_RX;
        uart3.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_HalfDuplex_Init(&uart3.uart);
        HAL_HalfDuplex_EnableReceiver(&uart3.uart);
        U3_PtrInit();
        }
        void U3_PtrInit(void){
        uart3.RxInPtr = &uart3.RxLocation[0];
        uart3.RxOutPtr = &uart3.RxLocation[0];
        uart3.RxEndPtr = &uart3.RxLocation[9];
        uart3.RxCounter = 0;
        uart3.RxInPtr->start = U3_RxBuff;
        uart3.TxInPtr = &uart3.TxLocation[0];
        uart3.TxOutPtr = &uart3.TxLocation[0];
        uart3.TxEndPtr = &uart3.TxLocation[9];
        uart3.TxCounter = 0;
        uart3.TxInPtr->start = U3_TxBuff;
        __HAL_UART_ENABLE_IT(&uart3.uart, UART_IT_IDLE);
        HAL_UART_Receive_DMA(&uart3.uart,uart3.RxInPtr->start,U3_RX_MAX);
        }
        void U3_Txdata(uint8_t *data, uint32_t data_len){
        if((U3_TX_SIZE - uart3.TxCounter )>=data_len){
        uart3.TxInPtr->start = &U3_TxBuff[uart3.TxCounter];
        }else{
        uart3.TxCounter = 0;
        uart3.TxInPtr->start = U3_TxBuff;
        }
        memcpy(uart3.TxInPtr->start,data,data_len);
        uart3.TxCounter += data_len;
        uart3.TxInPtr->end = &U3_TxBuff[uart3.TxCounter - 1];
        uart3.TxInPtr++;
        if(uart3.TxInPtr == uart3.TxEndPtr){
        uart3.TxInPtr = &uart3.TxLocation[0];
        }
        }
        void HAL_UART_MspInit(UART_HandleTypeDef *huart){
        GPIO_InitTypeDef GPIO_InitType;
        if(huart->Instance == USART1){
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_USART1_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_9;
        GPIO_InitType.Mode = GPIO_MODE_AF_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        GPIO_InitType.Pin = GPIO_PIN_10;
        GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART1_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
        uart1.dmatx.Instance = DMA1_Channel4;
        uart1.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart1.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart1.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart1.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart1.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart1.dmatx.Init.Mode = DMA_NORMAL;
        uart1.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart1.dmatx);
        HAL_DMA_Init(&uart1.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel4_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
        uart1.dmarx.Instance = DMA1_Channel5;
        uart1.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart1.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart1.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart1.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart1.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart1.dmarx.Init.Mode = DMA_NORMAL;
        uart1.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart1.dmarx);
        HAL_DMA_Init(&uart1.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel5_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
        }else if(huart->Instance == USART2){
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_USART2_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_2;
        GPIO_InitType.Mode = GPIO_MODE_AF_OD;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART2_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART2_IRQn);
        uart2.dmatx.Instance = DMA1_Channel7;
        uart2.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart2.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart2.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart2.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart2.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart2.dmatx.Init.Mode = DMA_NORMAL;
        uart2.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart2.dmatx);
        HAL_DMA_Init(&uart2.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel7_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
        uart2.dmarx.Instance = DMA1_Channel6;
        uart2.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart2.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart2.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart2.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart2.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart2.dmarx.Init.Mode = DMA_NORMAL;
        uart2.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart2.dmarx);
        HAL_DMA_Init(&uart2.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel6_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
        }else if(huart->Instance == USART3){
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_USART3_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_10;
        GPIO_InitType.Mode = GPIO_MODE_AF_OD;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOB,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART3_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART3_IRQn);
        uart3.dmatx.Instance = DMA1_Channel2;
        uart3.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart3.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart3.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart3.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart3.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart3.dmatx.Init.Mode = DMA_NORMAL;
        uart3.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart3.dmatx);
        HAL_DMA_Init(&uart3.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel2_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
        uart3.dmarx.Instance = DMA1_Channel3;
        uart3.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart3.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart3.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart3.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart3.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart3.dmarx.Init.Mode = DMA_NORMAL;
        uart3.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart3.dmarx);
        HAL_DMA_Init(&uart3.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel3_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
        }
        }
        void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        }
        }
        void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        }
        }
        void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        uart1.TxState = 0;
        }else if(huart->Instance == USART2){
        uart2.TxState = 0;
        }else if(huart->Instance == USART3){
        uart3.TxState = 0;
        }
        }
        void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        uart1.RxInPtr->end = &U1_RxBuff[uart1.RxCounter - 1];
        uart1.RxInPtr++;
        if(uart1.RxInPtr == uart1.RxEndPtr){
        uart1.RxInPtr = &uart1.RxLocation[0];
        }
        if((U1_RX_SIZE - uart1.RxCounter)<U1_RX_MAX){
        uart1.RxCounter = 0;
        uart1.RxInPtr->start = U1_RxBuff;
        }else{
        uart1.RxInPtr->start = &U1_RxBuff[uart1.RxCounter];
        }
        HAL_UART_Receive_DMA(&uart1.uart,uart1.RxInPtr->start,U1_RX_MAX);
        }else if(huart->Instance == USART2){
        uart2.RxInPtr->end = &U2_RxBuff[uart2.RxCounter - 1];
        uart2.RxInPtr++;
        if(uart2.RxInPtr == uart2.RxEndPtr){
        uart2.RxInPtr = &uart2.RxLocation[0];
        }
        if((U2_RX_SIZE - uart2.RxCounter)<U2_RX_MAX){
        uart2.RxCounter = 0;
        uart2.RxInPtr->start = U2_RxBuff;
        }else{
        uart2.RxInPtr->start = &U2_RxBuff[uart2.RxCounter];
        }
        HAL_UART_Receive_DMA(&uart2.uart,uart2.RxInPtr->start,U2_RX_MAX);
        }else if(huart->Instance == USART3){
        uart3.RxInPtr->end = &U3_RxBuff[uart3.RxCounter - 1];
        uart3.RxInPtr++;
        if(uart3.RxInPtr == uart3.RxEndPtr){
        uart3.RxInPtr = &uart3.RxLocation[0];
        }
        if((U3_RX_SIZE - uart3.RxCounter)<U3_RX_MAX){
        uart3.RxCounter = 0;
        uart3.RxInPtr->start = U3_RxBuff;
        }else{
        uart3.RxInPtr->start = &U3_RxBuff[uart3.RxCounter];
        }
        HAL_UART_Receive_DMA(&uart3.uart,uart3.RxInPtr->start,U3_RX_MAX);
        }
        }
        #ifndef __UART_H
        #define __UART_H
        #include "string.h"
        #include "stdint.h"
        #include "stm32f1xx_hal_uart.h"
        #include "stm32f1xx_hal_dma.h"
        #define U1_TX_SIZE 2048
        #define U1_RX_SIZE 2048
        #define U1_RX_MAX 256
        #define U2_TX_SIZE 2048
        #define U2_RX_SIZE 2048
        #define U2_RX_MAX 256
        #define U3_TX_SIZE 2048
        #define U3_RX_SIZE 2048
        #define U3_RX_MAX 256
        typedef struct{
        uint8_t *start;
        uint8_t *end;
        }LCB;
        typedef struct{
        uint32_t RxCounter;
        uint32_t TxCounter;
        uint32_t TxState;
        LCB RxLocation[10];
        LCB TxLocation[10];
        LCB *RxInPtr;
        LCB *RxOutPtr;
        LCB *RxEndPtr;
        LCB *TxInPtr;
        LCB *TxOutPtr;
        LCB *TxEndPtr;
        UART_HandleTypeDef uart;
        DMA_HandleTypeDef dmatx;
        DMA_HandleTypeDef dmarx;
        }UCB;
        void U1_Init(uint32_t bandrate);
        void U2_Init(uint32_t bandrate);
        void U3_Init(uint32_t bandrate);
        void U1_PtrInit(void);
        void U2_PtrInit(void);
        void U3_PtrInit(void);
        void U1_Txdata(uint8_t *data, uint32_t data_len);
        void U2_Txdata(uint8_t *data, uint32_t data_len);
        void U3_Txdata(uint8_t *data, uint32_t data_len);
        extern UCB uart1;
        extern UCB uart2;
        extern UCB uart3;
        #endif
        #include "stm32f1xx_hal.h"
        #include "sw.h"
        #include "uart.h"
        uint8_t sw1_sta,sw2_sta; //0:没有按下 1:按下了
        void SW_Init(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        GPIO_InitType.Mode = GPIO_MODE_INPUT;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        GPIO_InitType.Mode = GPIO_MODE_INPUT;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        }
        void SW_InitEvent(void){
        GPIO_InitTypeDef GPIO_InitType;
        //SW1
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_2;
        GPIO_InitType.Mode = GPIO_MODE_EVT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        }
        void SW_InitEventOut(void){
        GPIO_InitTypeDef GPIO_InitType;
        //PA3
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_AFIO_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_3;
        GPIO_InitType.Mode = GPIO_MODE_AF_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_GPIOEx_ConfigEventout(AFIO_EVENTOUT_PORT_A,AFIO_EVENTOUT_PIN_3);
        HAL_GPIOEx_EnableEventout();
        }
        //mode 0:按下执行 1:抬起执行
        void SW_Init_IT(uint8_t mode){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        if(mode == 0)
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING;
        else
        GPIO_InitType.Mode = GPIO_MODE_IT_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,4,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        if(mode == 0)
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING;
        else
        GPIO_InitType.Mode = GPIO_MODE_IT_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI0_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI0_IRQn);
        }
        void SW_Init_IT2(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,4,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI0_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI0_IRQn);
        }
        //返回值 0:无按键触发 8:SW8触发
        //mode 0:按下执行 1:抬起执行
        uint8_t SW_Scan(uint8_t mode){
        uint32_t i;
        /-------------SW8------------------/
        if((SW1_IN == 1)&&(sw1_sta == 0)){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 0){
        return 0;
        }
        }
        sw1_sta = 1;
        if(mode == 0){
        return 8;
        }
        }else if((SW1_IN == 0)&&(sw1_sta == 1)){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 1){
        return 0;
        }
        }
        sw1_sta = 0;
        if(mode == 1){
        return 8;
        }
        }
        /-------------SW11------------------/
        if((SW2_IN == 0)&&(sw2_sta == 0)){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 1){
        return 0;
        }
        }
        sw2_sta = 1;
        if(mode == 0){
        return 11;
        }
        }else if((SW2_IN == 1)&&(sw2_sta == 1)){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return 0;
        }
        }
        sw2_sta = 0;
        if(mode == 1){
        return 11;
        }
        }
        return 0;
        }
        void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
        {
        uint32_t i;
        //SW8:PC13 SW11:PA0(抢占优先级高)
        switch(GPIO_Pin){
        case GPIO_PIN_14: if(SW1_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 0){
        return;
        }
        }
        U1_Txdata((uint8_t *)"x81S1_LED",7);
        //U2_Txdata((uint8_t *)"LED_ON",6);
        //U3_Txdata((uint8_t *)"LED_ON",6);
        }else if(SW1_IN == 0){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 1){
        return;
        }
        }
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
        }
        break;
        case GPIO_PIN_0: if(SW2_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return;
        }
        }
        U1_Txdata((uint8_t *)"x82S2_LED",7);
        //U2_Txdata((uint8_t *)"LED_OFF",7);
        //U3_Txdata((uint8_t *)"LED_OFF",7);
        }else if(SW2_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return;
        }
        }
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
        }
        break;
        }
        }
        #ifndef __SW_H
        #define __SW_H
        #include "stdint.h"
        #define SW1_IN HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)
        #define SW2_IN HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
        void SW_Init(void);
        uint8_t SW_Scan(uint8_t mode);
        void SW_Init_IT(uint8_t mode);
        void SW_Init_IT2(void);
        void SW_InitEvent(void);
        void SW_InitEventOut(void);
        #endif
        #include "stm32f1xx_hal.h"
        #include "led.h"
        void LED_Init(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_13;
        GPIO_InitType.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        void LED_ON(void){
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
        }
        void LED_OFF(void){
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        void LED_Toggle(void){
        HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
        }
        #ifndef __LED_H
        #define __LED_H
        void LED_Init(void);
        void LED_ON(void);
        void LED_OFF(void);
        void LED_Toggle(void);
        #endif
        /-------------------------------------------------/
        / /
        / 实现各种中断服务函数的源文件 /
        / /
        /-------------------------------------------------/
        #include "stm32f1xx_hal.h"
        #include "stm32f1xx_it.h"
        #include "uart.h"
        void EXTI15_10_IRQHandler(void)
        {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
        }
        void EXTI0_IRQHandler(void)
        {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
        }
        void USART1_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart1.uart);
        if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
        __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
        uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
        HAL_UART_AbortReceive_IT(&uart1.uart);
        }
        }
        void USART2_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart2.uart);
        if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
        __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
        uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
        HAL_UART_AbortReceive_IT(&uart2.uart);
        }
        }
        void USART3_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart3.uart);
        if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
        __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
        uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
        HAL_UART_AbortReceive_IT(&uart3.uart);
        }
        }
        void DMA1_Channel4_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart1.dmatx);
        }
        void DMA1_Channel5_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart1.dmarx);
        }
        void DMA1_Channel7_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart2.dmatx);
        }
        void DMA1_Channel6_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart2.dmarx);
        }
        void DMA1_Channel2_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart3.dmatx);
        }
        void DMA1_Channel3_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart3.dmarx);
        }
        /-------------------------------------------------/
        /函数名:不可屏蔽中断处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void NMI_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:硬件出错后进入的中断处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void HardFault_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:软中断,SWI 指令调用的处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void SVC_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:可挂起的系统服务处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void PendSV_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:SysTic系统嘀嗒定时器处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void SysTick_Handler(void)
        {
        HAL_IncTick();
        }
        #include "stm32f1xx_hal.h"
        #include "rcc.h"
        #include "led.h"
        #include "sw.h"
        #include "uart.h"
        int main(void){
        HAL_Init();
        RccClock_Init();
        SW_Init_IT(0);
        LED_Init();
        U1_Init(921600);
        U2_Init(921600);
        U3_Init(921600);
        while(1){
        //串口1收发
        if(uart1.RxOutPtr != uart1.RxInPtr){
        if(((uart1.RxOutPtr->end - uart1.RxOutPtr->start + 1)==6)&&(memcmp(uart1.RxOutPtr->start,"LED_ON",6) == 0)){
        LED_ON();
        }else if(((uart1.RxOutPtr->end - uart1.RxOutPtr->start + 1)==7)&&(memcmp(uart1.RxOutPtr->start,"LED_OFF",7) == 0)){
        LED_OFF();
        }
        uart1.RxOutPtr++;
        if(uart1.RxOutPtr == uart1.RxEndPtr){
        uart1.RxOutPtr = &uart1.RxLocation[0];
        }
        }
        if((uart1.TxOutPtr != uart1.TxInPtr)&&(uart1.TxState==0)){
        uart1.TxState = 1;
        HAL_UART_Transmit_DMA(&uart1.uart,uart1.TxOutPtr->start,uart1.TxOutPtr->end - uart1.TxOutPtr->start + 1);
        uart1.TxOutPtr++;
        if(uart1.TxOutPtr == uart1.TxEndPtr){
        uart1.TxOutPtr = &uart1.TxLocation[0];
        }
        }
        //串口2收发
        if(uart2.RxOutPtr != uart2.RxInPtr){
        if(((uart2.RxOutPtr->end - uart2.RxOutPtr->start + 1)==6)&&(memcmp(uart2.RxOutPtr->start,"LED_ON",6) == 0)){
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
        }else if(((uart2.RxOutPtr->end - uart2.RxOutPtr->start + 1)==7)&&(memcmp(uart2.RxOutPtr->start,"LED_OFF",7) == 0)){
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
        }
        uart2.RxOutPtr++;
        if(uart2.RxOutPtr == uart2.RxEndPtr){
        uart2.RxOutPtr = &uart2.RxLocation[0];
        }
        }
        if((uart2.TxOutPtr != uart2.TxInPtr)&&(uart2.TxState==0)){
        uart2.TxState = 1;
        HAL_HalfDuplex_EnableTransmitter(&uart2.uart);
        HAL_UART_Transmit_DMA(&uart2.uart,uart2.TxOutPtr->start,uart2.TxOutPtr->end - uart2.TxOutPtr->start + 1);
        uart2.TxOutPtr++;
        if(uart2.TxOutPtr == uart2.TxEndPtr){
        uart2.TxOutPtr = &uart2.TxLocation[0];
        }
        }
        //串口3收发
        if(uart3.RxOutPtr != uart3.RxInPtr){
        if(((uart3.RxOutPtr->end - uart3.RxOutPtr->start + 1)==6)&&(memcmp(uart3.RxOutPtr->start,"LED_ON",6) == 0)){
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
        }else if(((uart3.RxOutPtr->end - uart3.RxOutPtr->start + 1)==7)&&(memcmp(uart3.RxOutPtr->start,"LED_OFF",7) == 0)){
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
        }
        uart3.RxOutPtr++;
        if(uart3.RxOutPtr == uart3.RxEndPtr){
        uart3.RxOutPtr = &uart3.RxLocation[0];
        }
        }
        if((uart3.TxOutPtr != uart3.TxInPtr)&&(uart3.TxState==0)){
        uart3.TxState = 1;
        HAL_HalfDuplex_EnableTransmitter(&uart3.uart);
        HAL_UART_Transmit_DMA(&uart3.uart,uart3.TxOutPtr->start,uart3.TxOutPtr->end - uart3.TxOutPtr->start + 1);
        uart3.TxOutPtr++;
        if(uart3.TxOutPtr == uart3.TxEndPtr){
        uart3.TxOutPtr = &uart3.TxLocation[0];
        }
        }
        }
        }
        #include "stm32f1xx_hal.h"
        #include "uart.h"
        UCB uart1;
        UCB uart2;
        UCB uart3;
        uint8_t U1_RxBuff[U1_RX_SIZE];
        uint8_t U1_TxBuff[U1_TX_SIZE];
        uint8_t U2_RxBuff[U2_RX_SIZE];
        uint8_t U2_TxBuff[U2_TX_SIZE];
        uint8_t U3_RxBuff[U3_RX_SIZE];
        uint8_t U3_TxBuff[U3_TX_SIZE];
        void U1_Init(uint32_t bandrate){
        uart1.uart.Instance = USART1;
        uart1.uart.Init.BaudRate = bandrate;
        uart1.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart1.uart.Init.StopBits = UART_STOPBITS_1;
        uart1.uart.Init.Parity = UART_PARITY_NONE;
        uart1.uart.Init.Mode = UART_MODE_TX_RX;
        uart1.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_UART_Init(&uart1.uart);
        U1_PtrInit();
        }
        void U1_PtrInit(void){
        uart1.RxInPtr = &uart1.RxLocation[0];
        uart1.RxOutPtr = &uart1.RxLocation[0];
        uart1.RxEndPtr = &uart1.RxLocation[9];
        uart1.RxCounter = 0;
        uart1.RxInPtr->start = U1_RxBuff;
        uart1.TxInPtr = &uart1.TxLocation[0];
        uart1.TxOutPtr = &uart1.TxLocation[0];
        uart1.TxEndPtr = &uart1.TxLocation[9];
        uart1.TxCounter = 0;
        uart1.TxInPtr->start = U1_TxBuff;
        __HAL_UART_ENABLE_IT(&uart1.uart, UART_IT_IDLE);
        HAL_UART_Receive_DMA(&uart1.uart,uart1.RxInPtr->start,U1_RX_MAX);
        }
        void U1_Txdata(uint8_t *data, uint32_t data_len){
        if((U1_TX_SIZE - uart1.TxCounter )>=data_len){
        uart1.TxInPtr->start = &U1_TxBuff[uart1.TxCounter];
        }else{
        uart1.TxCounter = 0;
        uart1.TxInPtr->start = U1_TxBuff;
        }
        memcpy(uart1.TxInPtr->start,data,data_len);
        uart1.TxCounter += data_len;
        uart1.TxInPtr->end = &U1_TxBuff[uart1.TxCounter - 1];
        uart1.TxInPtr++;
        if(uart1.TxInPtr == uart1.TxEndPtr){
        uart1.TxInPtr = &uart1.TxLocation[0];
        }
        }
        void U2_Init(uint32_t bandrate){
        uart2.uart.Instance = USART2;
        uart2.uart.Init.BaudRate = bandrate;
        uart2.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart2.uart.Init.StopBits = UART_STOPBITS_1;
        uart2.uart.Init.Parity = UART_PARITY_NONE;
        uart2.uart.Init.Mode = UART_MODE_TX_RX;
        uart2.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_MultiProcessor_Init(&uart2.uart, 0x01, UART_WAKEUPMETHOD_ADDRESSMARK); //多设备初始化
        HAL_MultiProcessor_EnterMuteMode(&uart2.uart); //手动进入静默模式
        TIM4_TimerInit(300, 7200); //定时器超时时间30ms
        U2_PtrInit();
        }
        void U2_PtrInit(void){
        uart2.RxInPtr = &uart2.RxLocation[0];
        uart2.RxOutPtr = &uart2.RxLocation[0];
        uart2.RxEndPtr = &uart2.RxLocation[9];
        uart2.RxCounter = 0;
        uart2.RxInPtr->start = U2_RxBuff;
        uart2.TxInPtr = &uart2.TxLocation[0];
        uart2.TxOutPtr = &uart2.TxLocation[0];
        uart2.TxEndPtr = &uart2.TxLocation[9];
        uart2.TxCounter = 0;
        uart2.TxInPtr->start = U2_TxBuff;
        uart2.RxState = 0; //初始化接受状态为0
        __HAL_UART_ENABLE_IT(&uart2.uart, UART_IT_RXNE); //打开接收中断
        HAL_UART_Receive_DMA(&uart2.uart,uart2.RxInPtr->start,U2_RX_MAX);
        }
        void U2_Txdata(uint8_t *data, uint32_t data_len){
        if((U2_TX_SIZE - uart2.TxCounter )>=data_len){
        uart2.TxInPtr->start = &U2_TxBuff[uart2.TxCounter];
        }else{
        uart2.TxCounter = 0;
        uart2.TxInPtr->start = U2_TxBuff;
        }
        memcpy(uart2.TxInPtr->start,data,data_len);
        uart2.TxCounter += data_len;
        uart2.TxInPtr->end = &U2_TxBuff[uart2.TxCounter - 1];
        uart2.TxInPtr++;
        if(uart2.TxInPtr == uart2.TxEndPtr){
        uart2.TxInPtr = &uart2.TxLocation[0];
        }
        }
        void U3_Init(uint32_t bandrate){
        uart3.uart.Instance = USART3;
        uart3.uart.Init.BaudRate = bandrate;
        uart3.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart3.uart.Init.StopBits = UART_STOPBITS_1;
        uart3.uart.Init.Parity = UART_PARITY_NONE;
        uart3.uart.Init.Mode = UART_MODE_TX_RX;
        uart3.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_HalfDuplex_Init(&uart3.uart);
        HAL_HalfDuplex_EnableReceiver(&uart3.uart);
        U3_PtrInit();
        }
        void U3_PtrInit(void){
        uart3.RxInPtr = &uart3.RxLocation[0];
        uart3.RxOutPtr = &uart3.RxLocation[0];
        uart3.RxEndPtr = &uart3.RxLocation[9];
        uart3.RxCounter = 0;
        uart3.RxInPtr->start = U3_RxBuff;
        uart3.TxInPtr = &uart3.TxLocation[0];
        uart3.TxOutPtr = &uart3.TxLocation[0];
        uart3.TxEndPtr = &uart3.TxLocation[9];
        uart3.TxCounter = 0;
        uart3.TxInPtr->start = U3_TxBuff;
        __HAL_UART_ENABLE_IT(&uart3.uart, UART_IT_IDLE);
        HAL_UART_Receive_DMA(&uart3.uart,uart3.RxInPtr->start,U3_RX_MAX);
        }
        void U3_Txdata(uint8_t *data, uint32_t data_len){
        if((U3_TX_SIZE - uart3.TxCounter )>=data_len){
        uart3.TxInPtr->start = &U3_TxBuff[uart3.TxCounter];
        }else{
        uart3.TxCounter = 0;
        uart3.TxInPtr->start = U3_TxBuff;
        }
        memcpy(uart3.TxInPtr->start,data,data_len);
        uart3.TxCounter += data_len;
        uart3.TxInPtr->end = &U3_TxBuff[uart3.TxCounter - 1];
        uart3.TxInPtr++;
        if(uart3.TxInPtr == uart3.TxEndPtr){
        uart3.TxInPtr = &uart3.TxLocation[0];
        }
        }
        void HAL_UART_MspInit(UART_HandleTypeDef *huart){
        GPIO_InitTypeDef GPIO_InitType;
        if(huart->Instance == USART1){
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_USART1_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_9;
        GPIO_InitType.Mode = GPIO_MODE_AF_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        GPIO_InitType.Pin = GPIO_PIN_10;
        GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART1_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
        uart1.dmatx.Instance = DMA1_Channel4;
        uart1.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart1.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart1.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart1.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart1.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart1.dmatx.Init.Mode = DMA_NORMAL;
        uart1.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart1.dmatx);
        HAL_DMA_Init(&uart1.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel4_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
        uart1.dmarx.Instance = DMA1_Channel5;
        uart1.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart1.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart1.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart1.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart1.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart1.dmarx.Init.Mode = DMA_NORMAL;
        uart1.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart1.dmarx);
        HAL_DMA_Init(&uart1.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel5_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
        }else if(huart->Instance == USART2){
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_USART2_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_2;
        GPIO_InitType.Mode = GPIO_MODE_AF_OD; //OD模式
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        GPIO_InitType.Pin = GPIO_PIN_3;
        GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
        GPIO_InitType.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART2_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART2_IRQn);
        uart2.dmatx.Instance = DMA1_Channel7;
        uart2.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart2.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart2.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart2.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart2.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart2.dmatx.Init.Mode = DMA_NORMAL;
        uart2.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart2.dmatx);
        HAL_DMA_Init(&uart2.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel7_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
        uart2.dmarx.Instance = DMA1_Channel6;
        uart2.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart2.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart2.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart2.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart2.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart2.dmarx.Init.Mode = DMA_NORMAL;
        uart2.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart2.dmarx);
        HAL_DMA_Init(&uart2.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel6_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
        }else if(huart->Instance == USART3){
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_USART3_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_10;
        GPIO_InitType.Mode = GPIO_MODE_AF_OD;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOB,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART3_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART3_IRQn);
        uart3.dmatx.Instance = DMA1_Channel2;
        uart3.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart3.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart3.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart3.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart3.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart3.dmatx.Init.Mode = DMA_NORMAL;
        uart3.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart3.dmatx);
        HAL_DMA_Init(&uart3.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel2_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
        uart3.dmarx.Instance = DMA1_Channel3;
        uart3.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart3.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart3.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart3.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart3.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart3.dmarx.Init.Mode = DMA_NORMAL;
        uart3.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart3.dmarx);
        HAL_DMA_Init(&uart3.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel3_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
        }
        }
        void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        }
        }
        void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        }
        }
        void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        uart1.TxState = 0;
        }else if(huart->Instance == USART2){
        uart2.TxState = 0;
        }else if(huart->Instance == USART3){
        uart3.TxState = 0;
        }
        }
        / 接收终止回调 /
        void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        uart1.RxInPtr->end = &U1_RxBuff[uart1.RxCounter - 1];
        uart1.RxInPtr++;
        if(uart1.RxInPtr == uart1.RxEndPtr){
        uart1.RxInPtr = &uart1.RxLocation[0];
        }
        if((U1_RX_SIZE - uart1.RxCounter)<U1_RX_MAX){
        uart1.RxCounter = 0;
        uart1.RxInPtr->start = U1_RxBuff;
        }else{
        uart1.RxInPtr->start = &U1_RxBuff[uart1.RxCounter];
        }
        HAL_UART_Receive_DMA(&uart1.uart,uart1.RxInPtr->start,U1_RX_MAX);
        }else if(huart->Instance == USART2){
        uart2.RxInPtr->end = &U2_RxBuff[uart2.RxCounter - 1];
        uart2.RxInPtr++;
        if(uart2.RxInPtr == uart2.RxEndPtr){
        uart2.RxInPtr = &uart2.RxLocation[0];
        }
        if((U2_RX_SIZE - uart2.RxCounter)<U2_RX_MAX){
        uart2.RxCounter = 0;
        uart2.RxInPtr->start = U2_RxBuff;
        }else{
        uart2.RxInPtr->start = &U2_RxBuff[uart2.RxCounter];
        }
        HAL_MultiProcessor_EnterMuteMode(&uart2.uart); //手动进入静默模式
        __HAL_UART_ENABLE_IT(&uart2.uart, UART_IT_RXNE); //打开接收中断
        HAL_UART_Receive_DMA(&uart2.uart,uart2.RxInPtr->start,U2_RX_MAX);
        }else if(huart->Instance == USART3){
        uart3.RxInPtr->end = &U3_RxBuff[uart3.RxCounter - 1];
        uart3.RxInPtr++;
        if(uart3.RxInPtr == uart3.RxEndPtr){
        uart3.RxInPtr = &uart3.RxLocation[0];
        }
        if((U3_RX_SIZE - uart3.RxCounter)<U3_RX_MAX){
        uart3.RxCounter = 0;
        uart3.RxInPtr->start = U3_RxBuff;
        }else{
        uart3.RxInPtr->start = &U3_RxBuff[uart3.RxCounter];
        }
        HAL_UART_Receive_DMA(&uart3.uart,uart3.RxInPtr->start,U3_RX_MAX);
        }
        }
        /-----------------------------------------------------/
        / 程序结构 /
        /-----------------------------------------------------/
        /USER :包含程序的 main 函数,是整个程序的入 /
        /HW :包含开发板各种功能外设的驱动程序 /
        /LIB :官方提供的 HAL 库文件 /
        /CMSIS :CM3 内核相关的启动文件系统文件 /
        /-----------------------------------------------------/
        / /
        / 实现定时器功能的头文件 /
        / /
        /-----------------------------------------------------/
        #ifndef _TIMER_H
        #define _TIMER_H
        #include "stdint.h"
        #include "stm32f1xx_hal_tim.h"
        extern TIM_HandleTypeDef htim4; //外部变量声明
        void TIM4_TimerInit(uint16_t, uint16_t); //函数声明
        #endif
        #include "stm32f1xx_hal.h"
        #include "sw.h"
        #include "uart.h"
        uint8_t sw1_sta,sw2_sta; //0:没有按下 1:按下了
        void SW_Init(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        GPIO_InitType.Mode = GPIO_MODE_INPUT;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        GPIO_InitType.Mode = GPIO_MODE_INPUT;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        }
        void SW_InitEvent(void){
        GPIO_InitTypeDef GPIO_InitType;
        //SW1
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_2;
        GPIO_InitType.Mode = GPIO_MODE_EVT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        }
        void SW_InitEventOut(void){
        GPIO_InitTypeDef GPIO_InitType;
        //PA3
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_AFIO_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_3;
        GPIO_InitType.Mode = GPIO_MODE_AF_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_GPIOEx_ConfigEventout(AFIO_EVENTOUT_PORT_A,AFIO_EVENTOUT_PIN_3);
        HAL_GPIOEx_EnableEventout();
        }
        //mode 0:按下执行 1:抬起执行
        void SW_Init_IT(uint8_t mode){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        if(mode == 0)
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING;
        else
        GPIO_InitType.Mode = GPIO_MODE_IT_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,4,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        if(mode == 0)
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING;
        else
        GPIO_InitType.Mode = GPIO_MODE_IT_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI0_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI0_IRQn);
        }
        void SW_Init_IT2(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,4,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI0_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI0_IRQn);
        }
        //返回值 0:无按键触发 8:SW8触发
        //mode 0:按下执行 1:抬起执行
        uint8_t SW_Scan(uint8_t mode){
        uint32_t i;
        /-------------SW8------------------/
        if((SW1_IN == 1)&&(sw1_sta == 0)){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 0){
        return 0;
        }
        }
        sw1_sta = 1;
        if(mode == 0){
        return 8;
        }
        }else if((SW1_IN == 0)&&(sw1_sta == 1)){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 1){
        return 0;
        }
        }
        sw1_sta = 0;
        if(mode == 1){
        return 8;
        }
        }
        /-------------SW11------------------/
        if((SW2_IN == 0)&&(sw2_sta == 0)){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 1){
        return 0;
        }
        }
        sw2_sta = 1;
        if(mode == 0){
        return 11;
        }
        }else if((SW2_IN == 1)&&(sw2_sta == 1)){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return 0;
        }
        }
        sw2_sta = 0;
        if(mode == 1){
        return 11;
        }
        }
        return 0;
        }
        void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
        {
        uint32_t i;
        //SW8:PC13 SW11:PA0(抢占优先级高)
        switch(GPIO_Pin){
        case GPIO_PIN_14: if(SW1_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 0){
        return;
        }
        }
        //U1_Txdata((uint8_t *)"x81S1_LED",7);
        U2_Txdata((uint8_t *)"LED_ON",6);
        //U3_Txdata((uint8_t *)"LED_ON",6);
        }else if(SW1_IN == 0){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 1){
        return;
        }
        }
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
        }
        break;
        case GPIO_PIN_0: if(SW2_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return;
        }
        }
        //U1_Txdata((uint8_t *)"x82S2_LED",7);
        U2_Txdata((uint8_t *)"LED_OFF",7);
        //U3_Txdata((uint8_t *)"LED_OFF",7);
        }else if(SW2_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return;
        }
        }
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
        }
        break;
        }
        }
        #ifndef __SW_H
        #define __SW_H
        #include "stdint.h"
        #define SW1_IN HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)
        #define SW2_IN HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
        void SW_Init(void);
        uint8_t SW_Scan(uint8_t mode);
        void SW_Init_IT(uint8_t mode);
        void SW_Init_IT2(void);
        void SW_InitEvent(void);
        void SW_InitEventOut(void);
        #endif
        #include "stm32f1xx_hal.h"
        #include "led.h"
        void LED_Init(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_13;
        GPIO_InitType.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        void LED_ON(void){
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
        }
        void LED_OFF(void){
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        void LED_Toggle(void){
        HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
        }
        #ifndef __LED_H
        #define __LED_H
        void LED_Init(void);
        void LED_ON(void);
        void LED_OFF(void);
        void LED_Toggle(void);
        #endif
        /-------------------------------------------------/
        / /
        / 实现各种中断服务函数的源文件 /
        / /
        /-------------------------------------------------/
        #include "stm32f1xx_hal.h"
        #include "stm32f1xx_it.h"
        #include "uart.h"
        #include "timer.h"
        void EXTI15_10_IRQHandler(void)
        {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
        }
        void EXTI0_IRQHandler(void)
        {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
        }
        void USART1_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart1.uart);
        if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
        __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
        uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
        HAL_UART_AbortReceive_IT(&uart1.uart);
        }
        }
        int aaa;
        void USART2_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart2.uart);
        //if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
        // __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
        // uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
        // HAL_UART_AbortReceive_IT(&uart2.uart);
        //}
        aaa++;
        }
        void USART3_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart3.uart);
        if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
        __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
        uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
        HAL_UART_AbortReceive_IT(&uart3.uart);
        }
        }
        void DMA1_Channel4_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart1.dmatx);
        }
        void DMA1_Channel5_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart1.dmarx);
        }
        void DMA1_Channel7_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart2.dmatx);
        }
        void DMA1_Channel6_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart2.dmarx);
        }
        void DMA1_Channel2_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart3.dmatx);
        }
        void DMA1_Channel3_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart3.dmarx);
        }
        //定时器中断处理函数
        void TIM4_IRQHandler(void)
        {
        HAL_TIM_IRQHandler(&htim4);
        }
        /-------------------------------------------------/
        /函数名:不可屏蔽中断处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void NMI_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:硬件出错后进入的中断处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void HardFault_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:软中断,SWI 指令调用的处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void SVC_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:可挂起的系统服务处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void PendSV_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:SysTic系统嘀嗒定时器处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void SysTick_Handler(void)
        {
        HAL_IncTick();
        }
        /-----------------------------------------------------/
        / 程序结构 /
        /-----------------------------------------------------/
        /USER :包含程序的 main 函数,是整个程序的入 /
        /HW :包含开发板各种功能外设的驱动程序 /
        /LIB :官方提供的 HAL 库文件 /
        /CMSIS :CM3 内核相关的启动文件系统文件 /
        /-----------------------------------------------------/
        / /
        / 实现定时器功能的源文件 /
        / /
        /-----------------------------------------------------/
        #include "stm32f1xx_hal.h"
        #include "timer.h"
        #include "uart.h"
        TIM_HandleTypeDef htim4; //定时器4总控制结构体
        /-------------------------------------------------/
        /函数名:定时器4 定时初始化 /
        /参 数:arr:自动重装值 /
        /参 数:psc:时钟预分频数 /
        /返回值:无 /
        /-------------------------------------------------/
        void TIM4_TimerInit(uint16_t arr, uint16_t psc)
        {
        htim4.Instance = TIM4; //设置使用哪个定时器
        htim4.Init.Prescaler = psc - 1; //设置预分频器的值
        htim4.Init.Period = arr - 1; //设置自动重载值
        htim4.Init.CounterMode = TIM_COUNTERMODE_UP; //设置计数模式
        htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; //自动重载预装载 禁止
        HAL_TIM_Base_Init(&htim4); //配置,如果失败进入if
        __HAL_TIM_CLEAR_IT(&htim4, TIM_IT_UPDATE); //清除定时器4的中断标志
        __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE); //打开更新中断
        }
        /-------------------------------------------------/
        /函数名:定时器底层驱动,开启时钟,设置中断优先级 /
        /参 数:htim:定时器句柄 /
        /返回值:无 /
        /说 明:此函数会被HAL_TIM_Base_Init()函数调用 /
        /-------------------------------------------------/
        void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
        {
        if(htim->Instance==TIM4){ //判断是哪个定时器
        __HAL_RCC_TIM4_CLK_ENABLE(); //使能定时器时钟
        HAL_NVIC_SetPriority(TIM4_IRQn,4,0); //设置中断优先级,中断分组在HAL_Init()函数中,被设置为4
        HAL_NVIC_EnableIRQ(TIM4_IRQn); //开启定时器中断
        }
        }
        /---------------------------------------------------/
        /函数名:定时器中断回调函数 /
        /参 数:htim:定时器句柄 /
        /返回值:无 /
        /说 明:此函数会被HAL_TIM_IRQHandler()中断函数调用 /
        /---------------------------------------------------/
        //超时回调函数
        void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
        {
        if(htim->Instance==TIM4){ //判断是哪个定时器
        __HAL_TIM_DISABLE(htim); //关闭定时器4的计数
        __HAL_TIM_SET_COUNTER(htim,0); //清零定时器4计数器
        uart2.RxState = 0; //恢复首字节接收标志位
        uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx)); //记录剩余未发送
        HAL_UART_AbortReceive_IT(&uart2.uart); //终止接收
        }
        }
        void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
        {
        uint32_t isrflags = READ_REG(huart->Instance->SR);
        uint32_t cr1its = READ_REG(huart->Instance->CR1);
        uint32_t cr3its = READ_REG(huart->Instance->CR3);
        uint32_t errorflags = 0x00U;
        uint32_t dmarequest = 0x00U;
        / If no error occurs /
        errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
        //删除 RXNE中断
        //if (errorflags == RESET)
        //{
        // / UART in mode Receiver -------------------------------------------------/
        // if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
        // {
        // UART_Receive_IT(huart);
        // return;
        // }
        //}
        / If some errors occur /
        if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
        {
        / UART parity error interrupt occurred ----------------------------------/
        if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_PE;
        }
        / UART noise error interrupt occurred -----------------------------------/
        if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_NE;
        }
        / UART frame error interrupt occurred -----------------------------------/
        if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_FE;
        }
        / UART Over-Run interrupt occurred --------------------------------------/
        if (((isrflags & USART_SR_ORE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_ORE;
        }
        / Call UART Error Call back function if need be --------------------------/
        if (huart->ErrorCode != HAL_UART_ERROR_NONE)
        {
        / UART in mode Receiver -----------------------------------------------/
        if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
        {
        UART_Receive_IT(huart);
        }
        /* If Overrun error occurs, or if any error occurs in DMA mode reception,
        consider error as blocking */
        dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
        if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
        {
        /* Blocking error : transfer is aborted
        Set the UART state ready to be able to start again the process,
        Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
        UART_EndRxTransfer(huart);
        / Disable the UART DMA Rx request if enabled /
        if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
        {
        CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
        / Abort the UART DMA Rx channel /
        if (huart->hdmarx != NULL)
        {
        /* Set the UART DMA Abort callback :
        will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
        huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
        if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
        {
        / Call Directly XferAbortCallback function in case of error /
        huart->hdmarx->XferAbortCallback(huart->hdmarx);
        }
        }
        else
        {
        / Call user error callback /
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        }
        }
        else
        {
        / Call user error callback /
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        }
        }
        else
        {
        /* Non Blocking error : transfer could go on.
        Error is notified to user through user error callback */
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        huart->ErrorCode = HAL_UART_ERROR_NONE;
        }
        }
        return;
        } / End if some error occurs /
        / UART in mode Transmitter ------------------------------------------------/
        //删除 发送缓冲区空的中断
        // if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
        // {
        // UART_Transmit_IT(huart);
        // return;
        // }
        / UART in mode Transmitter end --------------------------------------------/
        if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
        {
        UART_EndTransmit_IT(huart);
        return;
        }
        / 写自己的中断回调,现在只能进入我们这个了。 /
        #include "uart.h"
        #include "timer.h"
        else
        {
        if(uart2.RxState == 0){ / 首字节 /
        __HAL_TIM_ENABLE(&htim4); //打开tim4的计数
        uart2.RxStat = 1; //标记接收
        }else{/ 后续字节 /
        __HAL_TIM_SET_COUNTER(&htim4, 0)//清除tim4的计数
        }
        }
        }
        #include "stm32f1xx_hal.h"
        #include "rcc.h"
        #include "led.h"
        #include "sw.h"
        #include "uart.h"
        int main(void){
        HAL_Init();
        RccClock_Init();
        SW_Init_IT(0);
        LED_Init();
        U1_Init(9600);
        U2_Init(9600);
        U3_Init(9600);
        while(1){
        //串口1收发
        if(uart1.RxOutPtr != uart1.RxInPtr){
        if(((uart1.RxOutPtr->end - uart1.RxOutPtr->start + 1)==6)&&(memcmp(uart1.RxOutPtr->start,"LED_ON",6) == 0)){
        LED_ON();
        }else if(((uart1.RxOutPtr->end - uart1.RxOutPtr->start + 1)==7)&&(memcmp(uart1.RxOutPtr->start,"LED_OFF",7) == 0)){
        LED_OFF();
        }
        uart1.RxOutPtr++;
        if(uart1.RxOutPtr == uart1.RxEndPtr){
        uart1.RxOutPtr = &uart1.RxLocation[0];
        }
        }
        if((uart1.TxOutPtr != uart1.TxInPtr)&&(uart1.TxState==0)){
        uart1.TxState = 1;
        HAL_UART_Transmit_DMA(&uart1.uart,uart1.TxOutPtr->start,uart1.TxOutPtr->end - uart1.TxOutPtr->start + 1);
        uart1.TxOutPtr++;
        if(uart1.TxOutPtr == uart1.TxEndPtr){
        uart1.TxOutPtr = &uart1.TxLocation[0];
        }
        }
        //串口2收发
        if(uart2.RxOutPtr != uart2.RxInPtr){
        if(((uart2.RxOutPtr->end - uart2.RxOutPtr->start + 1)==7)&&(memcmp(uart2.RxOutPtr->start,"x81S1_LED",7) == 0)){
        LED_Toggle();
        }
        uart2.RxOutPtr++;
        if(uart2.RxOutPtr == uart2.RxEndPtr){
        uart2.RxOutPtr = &uart2.RxLocation[0];
        }
        }
        if((uart2.TxOutPtr != uart2.TxInPtr)&&(uart2.TxState==0)){
        uart2.TxState = 1;
        HAL_UART_Transmit_DMA(&uart2.uart,uart2.TxOutPtr->start,uart2.TxOutPtr->end - uart2.TxOutPtr->start + 1);
        uart2.TxOutPtr++;
        if(uart2.TxOutPtr == uart2.TxEndPtr){
        uart2.TxOutPtr = &uart2.TxLocation[0];
        }
        }
        //串口3收发
        if(uart3.RxOutPtr != uart3.RxInPtr){
        if(((uart3.RxOutPtr->end - uart3.RxOutPtr->start + 1)==6)&&(memcmp(uart3.RxOutPtr->start,"LED_ON",6) == 0)){
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
        }else if(((uart3.RxOutPtr->end - uart3.RxOutPtr->start + 1)==7)&&(memcmp(uart3.RxOutPtr->start,"LED_OFF",7) == 0)){
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
        }
        uart3.RxOutPtr++;
        if(uart3.RxOutPtr == uart3.RxEndPtr){
        uart3.RxOutPtr = &uart3.RxLocation[0];
        }
        }
        if((uart3.TxOutPtr != uart3.TxInPtr)&&(uart3.TxState==0)){
        uart3.TxState = 1;
        HAL_HalfDuplex_EnableTransmitter(&uart3.uart);
        HAL_UART_Transmit_DMA(&uart3.uart,uart3.TxOutPtr->start,uart3.TxOutPtr->end - uart3.TxOutPtr->start + 1);
        uart3.TxOutPtr++;
        if(uart3.TxOutPtr == uart3.TxEndPtr){
        uart3.TxOutPtr = &uart3.TxLocation[0];
        }
        }
        }
        }
        #include "stm32f1xx_hal.h"
        #include "uart.h"
        UCB uart1;
        UCB uart2;
        UCB uart3;
        uint8_t U1_RxBuff[U1_RX_SIZE];
        uint8_t U1_TxBuff[U1_TX_SIZE];
        uint8_t U2_RxBuff[U2_RX_SIZE];
        uint8_t U2_TxBuff[U2_TX_SIZE];
        uint8_t U3_RxBuff[U3_RX_SIZE];
        uint8_t U3_TxBuff[U3_TX_SIZE];
        void U1_Init(uint32_t bandrate){
        uart1.uart.Instance = USART1;
        uart1.uart.Init.BaudRate = bandrate;
        uart1.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart1.uart.Init.StopBits = UART_STOPBITS_1;
        uart1.uart.Init.Parity = UART_PARITY_NONE;
        uart1.uart.Init.Mode = UART_MODE_TX_RX;
        uart1.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_UART_Init(&uart1.uart);
        U1_PtrInit();
        }
        void U1_PtrInit(void){
        uart1.RxInPtr = &uart1.RxLocation[0];
        uart1.RxOutPtr = &uart1.RxLocation[0];
        uart1.RxEndPtr = &uart1.RxLocation[9];
        uart1.RxCounter = 0;
        uart1.RxInPtr->start = U1_RxBuff;
        uart1.TxInPtr = &uart1.TxLocation[0];
        uart1.TxOutPtr = &uart1.TxLocation[0];
        uart1.TxEndPtr = &uart1.TxLocation[9];
        uart1.TxCounter = 0;
        uart1.TxInPtr->start = U1_TxBuff;
        __HAL_UART_ENABLE_IT(&uart1.uart, UART_IT_IDLE);
        HAL_UART_Receive_DMA(&uart1.uart,uart1.RxInPtr->start,U1_RX_MAX);
        }
        void U1_Txdata(uint8_t *data, uint32_t data_len){
        if((U1_TX_SIZE - uart1.TxCounter )>=data_len){
        uart1.TxInPtr->start = &U1_TxBuff[uart1.TxCounter];
        }else{
        uart1.TxCounter = 0;
        uart1.TxInPtr->start = U1_TxBuff;
        }
        memcpy(uart1.TxInPtr->start,data,data_len);
        uart1.TxCounter += data_len;
        uart1.TxInPtr->end = &U1_TxBuff[uart1.TxCounter - 1];
        uart1.TxInPtr++;
        if(uart1.TxInPtr == uart1.TxEndPtr){
        uart1.TxInPtr = &uart1.TxLocation[0];
        }
        }
        void U2_Init(uint32_t bandrate){
        uart2.uart.Instance = USART2;
        uart2.uart.Init.BaudRate = bandrate;
        uart2.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart2.uart.Init.StopBits = UART_STOPBITS_1;
        uart2.uart.Init.Parity = UART_PARITY_NONE;
        uart2.uart.Init.Mode = UART_MODE_TX_RX;
        uart2.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_MultiProcessor_Init(&uart2.uart, 0x01, UART_WAKEUPMETHOD_ADDRESSMARK); //多设备初始化
        HAL_MultiProcessor_EnterMuteMode(&uart2.uart); //手动进入静默模式
        TIM4_TimerInit(300, 7200); //定时器超时时间30ms
        U2_PtrInit();
        }
        void U2_PtrInit(void){
        uart2.RxInPtr = &uart2.RxLocation[0];
        uart2.RxOutPtr = &uart2.RxLocation[0];
        uart2.RxEndPtr = &uart2.RxLocation[9];
        uart2.RxCounter = 0;
        uart2.RxInPtr->start = U2_RxBuff;
        uart2.TxInPtr = &uart2.TxLocation[0];
        uart2.TxOutPtr = &uart2.TxLocation[0];
        uart2.TxEndPtr = &uart2.TxLocation[9];
        uart2.TxCounter = 0;
        uart2.TxInPtr->start = U2_TxBuff;
        uart2.RxState = 0; //初始化接受状态为0
        __HAL_UART_ENABLE_IT(&uart2.uart, UART_IT_RXNE); //打开接收中断
        HAL_UART_Receive_DMA(&uart2.uart,uart2.RxInPtr->start,U2_RX_MAX);
        }
        void U2_Txdata(uint8_t *data, uint32_t data_len){
        if((U2_TX_SIZE - uart2.TxCounter )>=data_len){
        uart2.TxInPtr->start = &U2_TxBuff[uart2.TxCounter];
        }else{
        uart2.TxCounter = 0;
        uart2.TxInPtr->start = U2_TxBuff;
        }
        memcpy(uart2.TxInPtr->start,data,data_len);
        uart2.TxCounter += data_len;
        uart2.TxInPtr->end = &U2_TxBuff[uart2.TxCounter - 1];
        uart2.TxInPtr++;
        if(uart2.TxInPtr == uart2.TxEndPtr){
        uart2.TxInPtr = &uart2.TxLocation[0];
        }
        }
        void U3_Init(uint32_t bandrate){
        uart3.uart.Instance = USART3;
        uart3.uart.Init.BaudRate = bandrate;
        uart3.uart.Init.WordLength = UART_WORDLENGTH_8B;
        uart3.uart.Init.StopBits = UART_STOPBITS_1;
        uart3.uart.Init.Parity = UART_PARITY_NONE;
        uart3.uart.Init.Mode = UART_MODE_TX_RX;
        uart3.uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        HAL_MultiProcessor_Init(&uart3.uart, 0x02, UART_WAKEUPMETHOD_ADDRESSMARK); //多设备初始化
        HAL_MultiProcessor_EnterMuteMode(&uart3.uart); //手动进入静默模式
        TIM4_TimerInit(300, 7200); //定时器超时时间30ms
        U3_PtrInit();
        }
        void U3_PtrInit(void){
        uart3.RxInPtr = &uart3.RxLocation[0];
        uart3.RxOutPtr = &uart3.RxLocation[0];
        uart3.RxEndPtr = &uart3.RxLocation[9];
        uart3.RxCounter = 0;
        uart3.RxInPtr->start = U3_RxBuff;
        uart3.TxInPtr = &uart3.TxLocation[0];
        uart3.TxOutPtr = &uart3.TxLocation[0];
        uart3.TxEndPtr = &uart3.TxLocation[9];
        uart3.TxCounter = 0;
        uart3.TxInPtr->start = U3_TxBuff;
        uart3.RxState = 0; //初始化接受状态为0
        __HAL_UART_ENABLE_IT(&uart3.uart, UART_IT_RXNE); //打开接收中断
        HAL_UART_Receive_DMA(&uart3.uart,uart3.RxInPtr->start,U3_RX_MAX);
        }
        void U3_Txdata(uint8_t *data, uint32_t data_len){
        if((U3_TX_SIZE - uart3.TxCounter )>=data_len){
        uart3.TxInPtr->start = &U3_TxBuff[uart3.TxCounter];
        }else{
        uart3.TxCounter = 0;
        uart3.TxInPtr->start = U3_TxBuff;
        }
        memcpy(uart3.TxInPtr->start,data,data_len);
        uart3.TxCounter += data_len;
        uart3.TxInPtr->end = &U3_TxBuff[uart3.TxCounter - 1];
        uart3.TxInPtr++;
        if(uart3.TxInPtr == uart3.TxEndPtr){
        uart3.TxInPtr = &uart3.TxLocation[0];
        }
        }
        void HAL_UART_MspInit(UART_HandleTypeDef *huart){
        GPIO_InitTypeDef GPIO_InitType;
        if(huart->Instance == USART1){
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_USART1_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_9;
        GPIO_InitType.Mode = GPIO_MODE_AF_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        GPIO_InitType.Pin = GPIO_PIN_10;
        GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART1_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
        uart1.dmatx.Instance = DMA1_Channel4;
        uart1.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart1.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart1.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart1.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart1.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart1.dmatx.Init.Mode = DMA_NORMAL;
        uart1.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart1.dmatx);
        HAL_DMA_Init(&uart1.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel4_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
        uart1.dmarx.Instance = DMA1_Channel5;
        uart1.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart1.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart1.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart1.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart1.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart1.dmarx.Init.Mode = DMA_NORMAL;
        uart1.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart1.dmarx);
        HAL_DMA_Init(&uart1.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel5_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
        }else if(huart->Instance == USART2){
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_USART2_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_2;
        GPIO_InitType.Mode = GPIO_MODE_AF_OD; //OD模式
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        GPIO_InitType.Pin = GPIO_PIN_3;
        GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
        GPIO_InitType.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART2_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART2_IRQn);
        uart2.dmatx.Instance = DMA1_Channel7;
        uart2.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart2.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart2.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart2.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart2.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart2.dmatx.Init.Mode = DMA_NORMAL;
        uart2.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart2.dmatx);
        HAL_DMA_Init(&uart2.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel7_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
        uart2.dmarx.Instance = DMA1_Channel6;
        uart2.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart2.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart2.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart2.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart2.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart2.dmarx.Init.Mode = DMA_NORMAL;
        uart2.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart2.dmarx);
        HAL_DMA_Init(&uart2.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel6_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
        }else if(huart->Instance == USART3){
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_USART3_CLK_ENABLE();
        __HAL_RCC_DMA1_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_10;
        GPIO_InitType.Mode = GPIO_MODE_AF_OD; //OD模式
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
        HAL_GPIO_Init(GPIOB,&GPIO_InitType);
        GPIO_InitType.Pin = GPIO_PIN_11;
        GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
        GPIO_InitType.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOB,&GPIO_InitType);
        HAL_NVIC_SetPriority(USART3_IRQn,3,0);
        HAL_NVIC_EnableIRQ(USART3_IRQn);
        uart3.dmatx.Instance = DMA1_Channel2;
        uart3.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        uart3.dmatx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart3.dmatx.Init.MemInc = DMA_MINC_ENABLE;
        uart3.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart3.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart3.dmatx.Init.Mode = DMA_NORMAL;
        uart3.dmatx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmatx, uart3.dmatx);
        HAL_DMA_Init(&uart3.dmatx);
        HAL_NVIC_SetPriority(DMA1_Channel2_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
        uart3.dmarx.Instance = DMA1_Channel3;
        uart3.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        uart3.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
        uart3.dmarx.Init.MemInc = DMA_MINC_ENABLE;
        uart3.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        uart3.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        uart3.dmarx.Init.Mode = DMA_NORMAL;
        uart3.dmarx.Init.Priority = DMA_PRIORITY_MEDIUM;
        __HAL_LINKDMA(huart, hdmarx, uart3.dmarx);
        HAL_DMA_Init(&uart3.dmarx);
        HAL_NVIC_SetPriority(DMA1_Channel3_IRQn,3,0);
        HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
        }
        }
        void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        }
        }
        void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        }
        }
        void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        uart1.TxState = 0;
        }else if(huart->Instance == USART2){
        uart2.TxState = 0;
        }else if(huart->Instance == USART3){
        uart3.TxState = 0;
        }
        }
        / 接收终止回调 /
        void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
        {
        if(huart->Instance == USART1){
        uart1.RxInPtr->end = &U1_RxBuff[uart1.RxCounter - 1];
        uart1.RxInPtr++;
        if(uart1.RxInPtr == uart1.RxEndPtr){
        uart1.RxInPtr = &uart1.RxLocation[0];
        }
        if((U1_RX_SIZE - uart1.RxCounter)<U1_RX_MAX){
        uart1.RxCounter = 0;
        uart1.RxInPtr->start = U1_RxBuff;
        }else{
        uart1.RxInPtr->start = &U1_RxBuff[uart1.RxCounter];
        }
        HAL_UART_Receive_DMA(&uart1.uart,uart1.RxInPtr->start,U1_RX_MAX);
        }else if(huart->Instance == USART2){
        uart2.RxInPtr->end = &U2_RxBuff[uart2.RxCounter - 1];
        uart2.RxInPtr++;
        if(uart2.RxInPtr == uart2.RxEndPtr){
        uart2.RxInPtr = &uart2.RxLocation[0];
        }
        if((U2_RX_SIZE - uart2.RxCounter)<U2_RX_MAX){
        uart2.RxCounter = 0;
        uart2.RxInPtr->start = U2_RxBuff;
        }else{
        uart2.RxInPtr->start = &U2_RxBuff[uart2.RxCounter];
        }
        HAL_MultiProcessor_EnterMuteMode(&uart2.uart); //手动进入静默模式
        __HAL_UART_ENABLE_IT(&uart2.uart, UART_IT_RXNE); //打开接收中断
        HAL_UART_Receive_DMA(&uart2.uart,uart2.RxInPtr->start,U2_RX_MAX);
        }else if(huart->Instance == USART3){
        uart3.RxInPtr->end = &U3_RxBuff[uart3.RxCounter - 1];
        uart3.RxInPtr++;
        if(uart3.RxInPtr == uart3.RxEndPtr){
        uart3.RxInPtr = &uart3.RxLocation[0];
        }
        if((U3_RX_SIZE - uart3.RxCounter)<U3_RX_MAX){
        uart3.RxCounter = 0;
        uart3.RxInPtr->start = U3_RxBuff;
        }else{
        uart3.RxInPtr->start = &U3_RxBuff[uart3.RxCounter];
        }
        HAL_MultiProcessor_EnterMuteMode(&uart3.uart); //手动进入静默模式
        __HAL_UART_ENABLE_IT(&uart3.uart, UART_IT_RXNE); //打开接收中断
        HAL_UART_Receive_DMA(&uart3.uart,uart3.RxInPtr->start,U3_RX_MAX);
        }
        }
        /-----------------------------------------------------/
        / 程序结构 /
        /-----------------------------------------------------/
        /USER :包含程序的 main 函数,是整个程序的入 /
        /HW :包含开发板各种功能外设的驱动程序 /
        /LIB :官方提供的 HAL 库文件 /
        /CMSIS :CM3 内核相关的启动文件系统文件 /
        /-----------------------------------------------------/
        / /
        / 实现定时器功能的头文件 /
        / /
        /-----------------------------------------------------/
        #ifndef _TIMER_H
        #define _TIMER_H
        #include "stdint.h"
        #include "stm32f1xx_hal_tim.h"
        extern TIM_HandleTypeDef htim4; //外部变量声明
        void TIM4_TimerInit(uint16_t, uint16_t); //函数声明
        #endif
        #include "stm32f1xx_hal.h"
        #include "sw.h"
        #include "uart.h"
        uint8_t sw1_sta,sw2_sta; //0:没有按下 1:按下了
        void SW_Init(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        GPIO_InitType.Mode = GPIO_MODE_INPUT;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        GPIO_InitType.Mode = GPIO_MODE_INPUT;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        }
        void SW_InitEvent(void){
        GPIO_InitTypeDef GPIO_InitType;
        //SW1
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_2;
        GPIO_InitType.Mode = GPIO_MODE_EVT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        }
        void SW_InitEventOut(void){
        GPIO_InitTypeDef GPIO_InitType;
        //PA3
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_AFIO_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_3;
        GPIO_InitType.Mode = GPIO_MODE_AF_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_GPIOEx_ConfigEventout(AFIO_EVENTOUT_PORT_A,AFIO_EVENTOUT_PIN_3);
        HAL_GPIOEx_EnableEventout();
        }
        //mode 0:按下执行 1:抬起执行
        void SW_Init_IT(uint8_t mode){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        if(mode == 0)
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING;
        else
        GPIO_InitType.Mode = GPIO_MODE_IT_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,4,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        if(mode == 0)
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING;
        else
        GPIO_InitType.Mode = GPIO_MODE_IT_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI0_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI0_IRQn);
        }
        void SW_Init_IT2(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_14;
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,4,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_0;
        GPIO_InitType.Mode = GPIO_MODE_IT_RISING_FALLING;
        GPIO_InitType.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOA,&GPIO_InitType);
        HAL_NVIC_SetPriority(EXTI0_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI0_IRQn);
        }
        //返回值 0:无按键触发 8:SW8触发
        //mode 0:按下执行 1:抬起执行
        uint8_t SW_Scan(uint8_t mode){
        uint32_t i;
        /-------------SW8------------------/
        if((SW1_IN == 1)&&(sw1_sta == 0)){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 0){
        return 0;
        }
        }
        sw1_sta = 1;
        if(mode == 0){
        return 8;
        }
        }else if((SW1_IN == 0)&&(sw1_sta == 1)){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 1){
        return 0;
        }
        }
        sw1_sta = 0;
        if(mode == 1){
        return 8;
        }
        }
        /-------------SW11------------------/
        if((SW2_IN == 0)&&(sw2_sta == 0)){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 1){
        return 0;
        }
        }
        sw2_sta = 1;
        if(mode == 0){
        return 11;
        }
        }else if((SW2_IN == 1)&&(sw2_sta == 1)){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return 0;
        }
        }
        sw2_sta = 0;
        if(mode == 1){
        return 11;
        }
        }
        return 0;
        }
        void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
        {
        uint32_t i;
        //SW8:PC13 SW11:PA0(抢占优先级高)
        switch(GPIO_Pin){
        case GPIO_PIN_14: if(SW1_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 0){
        return;
        }
        }
        //U1_Txdata((uint8_t *)"x81S1_LED",7);
        //U2_Txdata((uint8_t *)"LED_ON",6);
        U3_Txdata((uint8_t *)"LED_ON",6);
        }else if(SW1_IN == 0){
        for(i=0;i<0x7FFF;i++){
        if(SW1_IN == 1){
        return;
        }
        }
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
        }
        break;
        case GPIO_PIN_0: if(SW2_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return;
        }
        }
        //U1_Txdata((uint8_t *)"x82S2_LED",7);
        //U2_Txdata((uint8_t *)"LED_OFF",7);
        U3_Txdata((uint8_t *)"LED_OFF",7);
        }else if(SW2_IN == 1){
        for(i=0;i<0x7FFF;i++){
        if(SW2_IN == 0){
        return;
        }
        }
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
        }
        break;
        }
        }
        #ifndef __SW_H
        #define __SW_H
        #include "stdint.h"
        #define SW1_IN HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)
        #define SW2_IN HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
        void SW_Init(void);
        uint8_t SW_Scan(uint8_t mode);
        void SW_Init_IT(uint8_t mode);
        void SW_Init_IT2(void);
        void SW_InitEvent(void);
        void SW_InitEventOut(void);
        #endif
        #include "stm32f1xx_hal.h"
        #include "led.h"
        void LED_Init(void){
        GPIO_InitTypeDef GPIO_InitType;
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitType.Pin = GPIO_PIN_13;
        GPIO_InitType.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitType.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(GPIOC,&GPIO_InitType);
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        void LED_ON(void){
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
        }
        void LED_OFF(void){
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        void LED_Toggle(void){
        HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
        }
        #ifndef __LED_H
        #define __LED_H
        void LED_Init(void);
        void LED_ON(void);
        void LED_OFF(void);
        void LED_Toggle(void);
        #endif
        /-------------------------------------------------/
        / 超子说物联网STM32系列开发板 /
        /-------------------------------------------------/
        / /
        / 实现各种中断服务函数的源文件 /
        / /
        /-------------------------------------------------/
        #include "stm32f1xx_hal.h"
        #include "stm32f1xx_it.h"
        #include "uart.h"
        #include "timer.h"
        void EXTI15_10_IRQHandler(void)
        {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
        }
        void EXTI0_IRQHandler(void)
        {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
        }
        void USART1_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart1.uart);
        if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
        __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
        uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
        HAL_UART_AbortReceive_IT(&uart1.uart);
        }
        }
        void USART2_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart2.uart);
        //if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
        // __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
        // uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
        // HAL_UART_AbortReceive_IT(&uart2.uart);
        //}
        }
        void USART3_IRQHandler(void)
        {
        HAL_UART_IRQHandler(&uart3.uart);
        //if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
        // __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
        // uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
        // HAL_UART_AbortReceive_IT(&uart3.uart);
        //}
        }
        void DMA1_Channel4_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart1.dmatx);
        }
        void DMA1_Channel5_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart1.dmarx);
        }
        void DMA1_Channel7_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart2.dmatx);
        }
        void DMA1_Channel6_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart2.dmarx);
        }
        void DMA1_Channel2_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart3.dmatx);
        }
        void DMA1_Channel3_IRQHandler(void)
        {
        HAL_DMA_IRQHandler(&uart3.dmarx);
        }
        //定时器中断处理函数
        void TIM4_IRQHandler(void)
        {
        HAL_TIM_IRQHandler(&htim4);
        }
        /-------------------------------------------------/
        /函数名:不可屏蔽中断处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void NMI_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:硬件出错后进入的中断处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void HardFault_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:软中断,SWI 指令调用的处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void SVC_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:可挂起的系统服务处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void PendSV_Handler(void)
        {
        }
        /-------------------------------------------------/
        /函数名:SysTic系统嘀嗒定时器处理函数 /
        /参 数:无 /
        /返回值:无 /
        /-------------------------------------------------/
        void SysTick_Handler(void)
        {
        HAL_IncTick();
        }
        /-----------------------------------------------------/
        / 程序结构 /
        /-----------------------------------------------------/
        /USER :包含程序的 main 函数,是整个程序的入 /
        /HW :包含开发板各种功能外设的驱动程序 /
        /LIB :官方提供的 HAL 库文件 /
        /CMSIS :CM3 内核相关的启动文件系统文件 /
        /-----------------------------------------------------/
        / /
        / 实现定时器功能的源文件 /
        / /
        /-----------------------------------------------------/
        #include "stm32f1xx_hal.h"
        #include "timer.h"
        #include "uart.h"
        TIM_HandleTypeDef htim4; //定时器4总控制结构体
        /-------------------------------------------------/
        /函数名:定时器4 定时初始化 /
        /参 数:arr:自动重装值 /
        /参 数:psc:时钟预分频数 /
        /返回值:无 /
        /-------------------------------------------------/
        void TIM4_TimerInit(uint16_t arr, uint16_t psc)
        {
        htim4.Instance = TIM4; //设置使用哪个定时器
        htim4.Init.Prescaler = psc - 1; //设置预分频器的值
        htim4.Init.Period = arr - 1; //设置自动重载值
        htim4.Init.CounterMode = TIM_COUNTERMODE_UP; //设置计数模式
        htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; //自动重载预装载 禁止
        HAL_TIM_Base_Init(&htim4); //配置,如果失败进入if
        __HAL_TIM_CLEAR_IT(&htim4, TIM_IT_UPDATE); //清除定时器4的中断标志
        __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE); //打开更新中断
        }
        /-------------------------------------------------/
        /函数名:定时器底层驱动,开启时钟,设置中断优先级 /
        /参 数:htim:定时器句柄 /
        /返回值:无 /
        /说 明:此函数会被HAL_TIM_Base_Init()函数调用 /
        /-------------------------------------------------/
        void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
        {
        if(htim->Instance==TIM4){ //判断是哪个定时器
        __HAL_RCC_TIM4_CLK_ENABLE(); //使能定时器时钟
        HAL_NVIC_SetPriority(TIM4_IRQn,4,0); //设置中断优先级,中断分组在HAL_Init()函数中,被设置为4
        HAL_NVIC_EnableIRQ(TIM4_IRQn); //开启定时器中断
        }
        }
        /---------------------------------------------------/
        /函数名:定时器中断回调函数 /
        /参 数:htim:定时器句柄 /
        /返回值:无 /
        /说 明:此函数会被HAL_TIM_IRQHandler()中断函数调用 /
        /---------------------------------------------------/
        //超时回调函数
        void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
        {
        if(htim->Instance==TIM4){ //判断是哪个定时器
        __HAL_TIM_DISABLE(htim); //关闭定时器4的计数
        __HAL_TIM_SET_COUNTER(htim,0); //清零定时器4计数器
        uart3.RxState = 0; //恢复首字节接收标志位
        uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx)); //记录剩余未发送
        HAL_UART_AbortReceive_IT(&uart3.uart); //终止接收
        }
        }
        void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
        {
        uint32_t isrflags = READ_REG(huart->Instance->SR);
        uint32_t cr1its = READ_REG(huart->Instance->CR1);
        uint32_t cr3its = READ_REG(huart->Instance->CR3);
        uint32_t errorflags = 0x00U;
        uint32_t dmarequest = 0x00U;
        / If no error occurs /
        errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
        //删除 RXNE中断
        //if (errorflags == RESET)
        //{
        // / UART in mode Receiver -------------------------------------------------/
        // if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
        // {
        // UART_Receive_IT(huart);
        // return;
        // }
        //}
        / If some errors occur /
        if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
        {
        / UART parity error interrupt occurred ----------------------------------/
        if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_PE;
        }
        / UART noise error interrupt occurred -----------------------------------/
        if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_NE;
        }
        / UART frame error interrupt occurred -----------------------------------/
        if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_FE;
        }
        / UART Over-Run interrupt occurred --------------------------------------/
        if (((isrflags & USART_SR_ORE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
        {
        huart->ErrorCode |= HAL_UART_ERROR_ORE;
        }
        / Call UART Error Call back function if need be --------------------------/
        if (huart->ErrorCode != HAL_UART_ERROR_NONE)
        {
        / UART in mode Receiver -----------------------------------------------/
        if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
        {
        UART_Receive_IT(huart);
        }
        /* If Overrun error occurs, or if any error occurs in DMA mode reception,
        consider error as blocking */
        dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
        if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
        {
        /* Blocking error : transfer is aborted
        Set the UART state ready to be able to start again the process,
        Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
        UART_EndRxTransfer(huart);
        / Disable the UART DMA Rx request if enabled /
        if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
        {
        CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
        / Abort the UART DMA Rx channel /
        if (huart->hdmarx != NULL)
        {
        /* Set the UART DMA Abort callback :
        will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
        huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
        if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
        {
        / Call Directly XferAbortCallback function in case of error /
        huart->hdmarx->XferAbortCallback(huart->hdmarx);
        }
        }
        else
        {
        / Call user error callback /
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        }
        }
        else
        {
        / Call user error callback /
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        }
        }
        else
        {
        /* Non Blocking error : transfer could go on.
        Error is notified to user through user error callback */
        #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /Call registered error callback/
        huart->ErrorCallback(huart);
        #else
        /Call legacy weak error callback/
        HAL_UART_ErrorCallback(huart);
        #endif / USE_HAL_UART_REGISTER_CALLBACKS /
        huart->ErrorCode = HAL_UART_ERROR_NONE;
        }
        }
        return;
        } / End if some error occurs /
        / UART in mode Transmitter ------------------------------------------------/
        //删除 发送缓冲区空的中断
        // if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
        // {
        // UART_Transmit_IT(huart);
        // return;
        // }
        / UART in mode Transmitter end --------------------------------------------/
        if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
        {
        UART_EndTransmit_IT(huart);
        return;
        }
        / 写自己的中断回调,现在只能进入我们这个了。 /
        #include "uart.h"
        #include "timer.h"
        else
        {
        if(uart3.RxState == 0){ / 首字节 /
        __HAL_TIM_ENABLE(&htim4); //打开tim4的计数
        uart3.RxStat = 1; //标记接收
        }else{/ 后续字节 /
        __HAL_TIM_SET_COUNTER(&htim4, 0)//清除tim4的计数
        }
        }
        }
        #include "stm32f1xx_hal.h"
        #include "rcc.h"
        #include "led.h"
        #include "sw.h"
        #include "uart.h"
        int main(void){
        HAL_Init();
        RccClock_Init();
        SW_Init_IT(0);
        LED_Init();
        U1_Init(921600);
        U2_Init(921600);
        U3_Init(921600);
        while(1){
        //串口1收发
        if(uart1.RxOutPtr != uart1.RxInPtr){
        if(((uart1.RxOutPtr->end - uart1.RxOutPtr->start + 1)==6)&&(memcmp(uart1.RxOutPtr->start,"LED_ON",6) == 0)){
        LED_ON();
        }else if(((uart1.RxOutPtr->end - uart1.RxOutPtr->start + 1)==7)&&(memcmp(uart1.RxOutPtr->start,"LED_OFF",7) == 0)){
        LED_OFF();
        }
        uart1.RxOutPtr++;
        if(uart1.RxOutPtr == uart1.RxEndPtr){
        uart1.RxOutPtr = &uart1.RxLocation[0];
        }
        }
        if((uart1.TxOutPtr != uart1.TxInPtr)&&(uart1.TxState==0)){
        uart1.TxState = 1;
        HAL_UART_Transmit_DMA(&uart1.uart,uart1.TxOutPtr->start,uart1.TxOutPtr->end - uart1.TxOutPtr->start + 1);
        uart1.TxOutPtr++;
        if(uart1.TxOutPtr == uart1.TxEndPtr){
        uart1.TxOutPtr = &uart1.TxLocation[0];
        }
        }
        //串口2收发
        if(uart2.RxOutPtr != uart2.RxInPtr){
        if(((uart2.RxOutPtr->end - uart2.RxOutPtr->start + 1)==7)&&(memcmp(uart2.RxOutPtr->start,"x81S1_LED",7) == 0)){
        LED_Toggle();
        }
        uart2.RxOutPtr++;
        if(uart2.RxOutPtr == uart2.RxEndPtr){
        uart2.RxOutPtr = &uart2.RxLocation[0];
        }
        }
        if((uart2.TxOutPtr != uart2.TxInPtr)&&(uart2.TxState==0)){
        uart2.TxState = 1;
        HAL_UART_Transmit_DMA(&uart2.uart,uart2.TxOutPtr->start,uart2.TxOutPtr->end - uart2.TxOutPtr->start + 1);
        uart2.TxOutPtr++;
        if(uart2.TxOutPtr == uart2.TxEndPtr){
        uart2.TxOutPtr = &uart2.TxLocation[0];
        }
        }
        //串口3收发
        if(uart3.RxOutPtr != uart3.RxInPtr){
        if(((uart3.RxOutPtr->end - uart3.RxOutPtr->start + 1)==7)&&(memcmp(uart3.RxOutPtr->start,"x82S2_LED",7) == 0)){
        LED_Toggle();
        }
        uart3.RxOutPtr++;
        if(uart3.RxOutPtr == uart3.RxEndPtr){
        uart3.RxOutPtr = &uart3.RxLocation[0];
        }
        }
        if((uart3.TxOutPtr != uart3.TxInPtr)&&(uart3.TxState==0)){
        uart3.TxState = 1;
        HAL_UART_Transmit_DMA(&uart3.uart,uart3.TxOutPtr->start,uart3.TxOutPtr->end - uart3.TxOutPtr->start + 1);
        uart3.TxOutPtr++;
        if(uart3.TxOutPtr == uart3.TxEndPtr){
        uart3.TxOutPtr = &uart3.TxLocation[0];
        }
        }
        }
        }
        / 写自己的中断回调,现在只能进入我们这个了。 /
        if(uart2.RxState == 0){ / 首字节 /
        __HAL_TIM_ENABLE(&htim4); //打开tim4的计数
        uart2.RxState = 1; //标记接收
        / 判断地址 /
        if(*uart2.RxInPtr->start != 0x01){//判断第一个字节是不是自己的地址
        HAL_MultiProcessor_EnterMuteMode(&uart1.uart); //进入静默模式
        }
        }else{/ 后续字节 /
        __HAL_TIM_SET_COUNTER(&htim4, 0);//清除tim4的计数
        }
        void U3_Printf(char* format, ...){
        uint8_t tempbuff[256];
        va_list ap;
        va_start(ap, format);
        vsprintf((char*)tempbuff, format, ap);
        va_end(ap);
        uint16_t i;
        for(i = 0; i < strlen((char*)tempbuff); i++){
        while(!__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_TXE)); //发送寄存器空,才开始发送
        uart3.uart.Instance->DR = tempbuff[i]; //把数据依次放入DR 寄存器,发送出去
        }
        while(!__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_TC)); //发送完成,退出printf
        }
        notion image
        notion image
        1. 通道1 、2 上的滤波器解释
          1. notion image

        3. 相关函数

        • 重映射串口1
          • __HAL_RCC_AFIO_CLK_ENABLE();
          • __HAL_AFIO_REMAP_USART1_ENABLE();
        • TIM_ClockConfigTypeDef 时钟配置总控结构体
        • 基础的定时器配置初始化(定时器1通道 2举例)
          • 初始化硬件配置回调函数
            •  

          4. 程序

          time.c

          __HAL_TIM_ENABLE_IT(&tim4, TIM1_UP_IRQn);
          HAL_TIM_Base_Start_DMA(&tim4, (uint32_t*)tim4_dmaBuff, 4);
          }
          //定时器 硬件初始化回调函数
          void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
          __HAL_RCC_GPIOA_CLK_ENABLE();
          GPIO_InitTypeDef GPIO_InitType;
          GPIO_InitType.Pin = GPIO_PIN_9;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //上拉
          GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          //
          // HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
          // HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
          //
          // / DMA配置 /
          // tim1_dmaup.Instance = DMA1_Channel5;
          // tim1_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
          // tim1_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
          // tim1_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
          // tim1_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
          // tim1_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim1_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim1_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim1, hdma[TIM_DMA_ID_UPDATE], tim1_dmaup);
          // HAL_DMA_Init(&tim1_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
          //
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_ENABLE();
          __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM2_IRQn);
          / DMA配置 /
          tim2_dmaup.Instance = DMA1_Channel2;
          tim2_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim2_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim2_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim2_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim2_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim2_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim2, hdma[TIM_DMA_ID_UPDATE], tim2_dmaup);
          HAL_DMA_Init(&tim2_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_ENABLE();
          __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM3_IRQn);
          / DMA配置 /
          tim3_dmaup.Instance = DMA1_Channel3;
          tim3_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim3_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim3_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim3_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim3_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim3_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim3_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim3, hdma[TIM_DMA_ID_UPDATE], tim3_dmaup);
          HAL_DMA_Init(&tim3_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_ENABLE();
          __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM4_IRQn);
          / DMA配置 /
          tim4_dmaup.Instance = DMA1_Channel7;
          tim4_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim4_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim4_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim4_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim4_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim4_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim4_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim4, hdma[TIM_DMA_ID_UPDATE], tim4_dmaup);
          HAL_DMA_Init(&tim4_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
          }
          }
          //定时器 硬件 De 回调函数
          void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_DISABLE();
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_DISABLE();
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_DISABLE();
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_DISABLE();
          }
          }
          //更新中断 回调函数(同时也是DMA完成的回调函数)
          uint16_t time1 = 1;
          uint16_t time2 = 1;
          uint16_t time3 = 1;
          uint16_t time4 = 1;
          void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          / 判断TIM是否为Ready状态,如果是 则是DMA完成中断进入的回调函数 /
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA1 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 1 定时时间:%drn",time1++);
          }
          }else if(htim->Instance == TIM2){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA2 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 2 定时时间:%drn",time2++);
          }
          }else if(htim->Instance == TIM3){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA3 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 3 定时时间:%drn",time3++);
          }
          }else if(htim->Instance == TIM4){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA4 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 4 定时时间:%drn",time4++);
          }
          }
          }
          //DMA 半完成回调函数
          void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          U1_Printf("定时器 1 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM2){
          U1_Printf("定时器 2 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM3){
          U1_Printf("定时器 3 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM4){
          U1_Printf("定时器 4 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }
          }
          #ifndef __TIME_H
          #define __TIME_H
          #include "uart.h"
          / 对外声明总控结构体 /
          extern TIM_HandleTypeDef tim1;
          extern TIM_HandleTypeDef tim2;
          extern TIM_HandleTypeDef tim3;
          extern TIM_HandleTypeDef tim4;
          extern DMA_HandleTypeDef tim1_dmaup;
          extern DMA_HandleTypeDef tim2_dmaup;
          extern DMA_HandleTypeDef tim3_dmaup;
          extern DMA_HandleTypeDef tim4_dmaup;
          / 初始化函数 /
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
          void Timer2_Init(uint16_t arr, uint16_t psc);
          void Timer3_Init(uint16_t arr, uint16_t psc);
          void Timer4_Init(uint16_t arr, uint16_t psc);
          #endif
          while(1){
          / 获取更新标志位 /
          if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_UPDATE)){
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); ///清除标志位
          U1_Printf("定时器 1 更新事件rn");
          }
          if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_TRIGGER)){
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_TRIGGER); ///清除标志位
          U1_Printf("定时器 1 触发事件:%drn", __HAL_TIM_GET_COUNTER(&tim1)); //输出当前计数值
          }
          }
          //定时器 1
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
          {
          tim1.Instance = TIM1; // 实例
          tim1.Init.Period = arr; // 重装载值
          tim1.Init.Prescaler = psc; // 分频系数
          tim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数模式
          tim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 分频因子
          tim1.Init.RepetitionCounter = rep; // 重复计数值
          tim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;// 自动重装载值 预装载使能位(影子寄存器)
          HAL_TIM_Base_Init(&tim1); //初始化定时器
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); //手动 清除 定时器 更新事件
          / 外部模式1 ETR通道 /
          tim1_clock.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; //通道1 ETR
          tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_INVERTED; //ETR反向 (低电平或下降沿有效) 为了匹配IO和ETR,防止复位后按一下就产生触发事件
          //tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_NOINVERTED; //ETR不反向 (高电平或上升沿有效)
          tim1_clock.ClockPrescaler = TIM_CLOCKPRESCALER_DIV4; //ETR的预分频器配置
          tim1_clock.ClockFilter = 0x03; //滤波(注意是外部时钟的波)
          HAL_TIM_ConfigClockSource(&tim1, &tim1_clock); //初始化定时器时钟配置
          / 防止加大分频因子或滤波强度而导致的 复位后产生触发事件 /
          HAL_Delay(50);
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_TRIGGER); ///清除触发事件标志位
          __HAL_TIM_SET_COUNTER(&tim1, 0); // 清除计数值
          HAL_TIM_Base_Start(&tim1); //打开定时器(轮询方式)
          }
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
          __HAL_RCC_GPIOA_CLK_ENABLE();
          GPIO_InitTypeDef GPIO_InitType;
          GPIO_InitType.Pin = GPIO_PIN_9;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //上拉
          GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          #include "stm32f1xx_hal.h"
          #include "time.h"
          TIM_HandleTypeDef tim1; //(高级)定时器1总控结构体
          TIM_HandleTypeDef tim2;
          TIM_HandleTypeDef tim3;
          TIM_HandleTypeDef tim4;
          DMA_HandleTypeDef tim1_dmaup;
          DMA_HandleTypeDef tim2_dmaup;
          DMA_HandleTypeDef tim3_dmaup;
          DMA_HandleTypeDef tim4_dmaup;
          TIM_ClockConfigTypeDef tim1_clock; //时钟配置结构体
          uint16_t tim1_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim2_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim3_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim4_dmaBuff[4] = {20000, 30000, 40000, 50000};
          //定时器 1
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
          {
          tim1.Instance = TIM1; // 实例
          tim1.Init.Period = arr; // 重装载值
          tim1.Init.Prescaler = psc; // 分频系数
          tim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数模式
          tim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 分频因子
          tim1.Init.RepetitionCounter = rep; // 重复计数值
          tim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;// 自动重装载值 预装载使能位(影子寄存器)
          HAL_TIM_Base_Init(&tim1); //初始化定时器
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); //手动 清除 定时器 更新事件
          / 外部模式1 ETR通道 /
          tim1_clock.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; //通道1 ETR
          tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_INVERTED; //ETR反向 (低电平或下降沿有效) 为了匹配IO和ETR,防止复位后按一下就产生触发事件
          //tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_NOINVERTED; //ETR不反向 (高电平或上升沿有效)
          tim1_clock.ClockPrescaler = TIM_CLOCKPRESCALER_DIV4; //ETR的预分频器配置
          tim1_clock.ClockFilter = 0x03; //滤波(注意是外部时钟的波)
          HAL_TIM_ConfigClockSource(&tim1, &tim1_clock); //初始化定时器时钟配置
          / 防止加大分频因子或滤波强度而导致的 复位后产生触发事件 /
          HAL_Delay(50);
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_TRIGGER); ///清除触发事件标志位
          __HAL_TIM_SET_COUNTER(&tim1, 0); // 清除计数值
          HAL_TIM_Base_Start(&tim1); //打开定时器(轮询方式)
          }
          //定时器 2
          void Timer2_Init(uint16_t arr, uint16_t psc)
          {
          tim2.Instance = TIM2;
          tim2.Init.Period = arr;
          tim2.Init.Prescaler = psc;
          tim2.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim2);
          __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
          __HAL_TIM_ENABLE_IT(&tim2, TIM1_UP_IRQn);
          HAL_TIM_Base_Start_DMA(&tim2, (uint32_t*)tim2_dmaBuff, 4);
          }
          //定时器 3
          void Timer3_Init(uint16_t arr, uint16_t psc)
          {
          tim3.Instance = TIM3;
          tim3.Init.Period = arr;
          tim3.Init.Prescaler = psc;
          tim3.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim3);
          __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
          __HAL_TIM_ENABLE_IT(&tim3, TIM1_UP_IRQn);
          HAL_TIM_Base_Start_DMA(&tim3, (uint32_t*)tim3_dmaBuff, 4);
          }
          //定时器 4
          void Timer4_Init(uint16_t arr, uint16_t psc)
          {
          tim4.Instance = TIM4;
          tim4.Init.Period = arr;
          tim4.Init.Prescaler = psc;
          tim4.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim4);
          __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
          __HAL_TIM_ENABLE_IT(&tim4, TIM1_UP_IRQn);
          HAL_TIM_Base_Start_DMA(&tim4, (uint32_t*)tim4_dmaBuff, 4);
          }
          //定时器 硬件初始化回调函数
          void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
          __HAL_RCC_GPIOA_CLK_ENABLE();
          GPIO_InitTypeDef GPIO_InitType;
          GPIO_InitType.Pin = GPIO_PIN_12;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          GPIO_InitType.Speed = GPIO_SPEED_FREQ_MEDIUM;
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          //
          // HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
          // HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
          //
          // / DMA配置 /
          // tim1_dmaup.Instance = DMA1_Channel5;
          // tim1_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
          // tim1_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
          // tim1_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
          // tim1_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
          // tim1_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim1_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim1_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim1, hdma[TIM_DMA_ID_UPDATE], tim1_dmaup);
          // HAL_DMA_Init(&tim1_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
          //
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_ENABLE();
          __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM2_IRQn);
          / DMA配置 /
          tim2_dmaup.Instance = DMA1_Channel2;
          tim2_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim2_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim2_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim2_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim2_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim2_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim2, hdma[TIM_DMA_ID_UPDATE], tim2_dmaup);
          HAL_DMA_Init(&tim2_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_ENABLE();
          __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM3_IRQn);
          / DMA配置 /
          tim3_dmaup.Instance = DMA1_Channel3;
          tim3_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim3_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim3_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim3_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim3_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim3_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim3_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim3, hdma[TIM_DMA_ID_UPDATE], tim3_dmaup);
          HAL_DMA_Init(&tim3_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_ENABLE();
          __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM4_IRQn);
          / DMA配置 /
          tim4_dmaup.Instance = DMA1_Channel7;
          tim4_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim4_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim4_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim4_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim4_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim4_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim4_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim4, hdma[TIM_DMA_ID_UPDATE], tim4_dmaup);
          HAL_DMA_Init(&tim4_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
          }
          }
          //定时器 硬件 De 回调函数
          void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_DISABLE();
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_DISABLE();
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_DISABLE();
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_DISABLE();
          }
          }
          //更新中断 回调函数(同时也是DMA完成的回调函数)
          uint16_t time1 = 1;
          uint16_t time2 = 1;
          uint16_t time3 = 1;
          uint16_t time4 = 1;
          void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          / 判断TIM是否为Ready状态,如果是 则是DMA完成中断进入的回调函数 /
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA1 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 1 定时时间:%drn",time1++);
          }
          }else if(htim->Instance == TIM2){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA2 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 2 定时时间:%drn",time2++);
          }
          }else if(htim->Instance == TIM3){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA3 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 3 定时时间:%drn",time3++);
          }
          }else if(htim->Instance == TIM4){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA4 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 4 定时时间:%drn",time4++);
          }
          }
          }
          //DMA 半完成回调函数
          void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          U1_Printf("定时器 1 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM2){
          U1_Printf("定时器 2 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM3){
          U1_Printf("定时器 3 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM4){
          U1_Printf("定时器 4 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }
          }
          #ifndef __TIME_H
          #define __TIME_H
          #include "uart.h"
          / 对外声明总控结构体 /
          extern TIM_HandleTypeDef tim1;
          extern TIM_HandleTypeDef tim2;
          extern TIM_HandleTypeDef tim3;
          extern TIM_HandleTypeDef tim4;
          extern DMA_HandleTypeDef tim1_dmaup;
          extern DMA_HandleTypeDef tim2_dmaup;
          extern DMA_HandleTypeDef tim3_dmaup;
          extern DMA_HandleTypeDef tim4_dmaup;
          / 初始化函数 /
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
          void Timer2_Init(uint16_t arr, uint16_t psc);
          void Timer3_Init(uint16_t arr, uint16_t psc);
          void Timer4_Init(uint16_t arr, uint16_t psc);
          #endif
          while(1){
          / 获取更新标志位 /
          if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_UPDATE)){
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); ///清除标志位
          U1_Printf("定时器 1 更新事件rn");
          }
          if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_TRIGGER)){
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_TRIGGER); ///清除标志位
          U1_Printf("定时器 1 触发事件:%drn", __HAL_TIM_GET_COUNTER(&tim1)); //输出当前计数值
          }
          }
          #include "stm32f1xx_hal.h"
          #include "time.h"
          TIM_HandleTypeDef tim1; //定时器结构体
          TIM_HandleTypeDef tim2;
          TIM_HandleTypeDef tim3;
          TIM_HandleTypeDef tim4;
          DMA_HandleTypeDef tim1_dmaup; //DMA通道配置结构体
          DMA_HandleTypeDef tim2_dmaup;
          DMA_HandleTypeDef tim3_dmaup;
          DMA_HandleTypeDef tim4_dmaup;
          TIM_ClockConfigTypeDef tim1_clock; //时钟配置结构体
          TIM_ClockConfigTypeDef tim2_clock;
          TIM_ClockConfigTypeDef tim3_clock;
          TIM_ClockConfigTypeDef tim4_clock;
          uint16_t tim1_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim2_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim3_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim4_dmaBuff[4] = {20000, 30000, 40000, 50000};
          //定时器 1
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
          {
          tim1.Instance = TIM1; // 实例
          tim1.Init.Period = arr; // 重装载值
          tim1.Init.Prescaler = psc; // 分频系数
          tim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数模式
          tim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 分频因子
          tim1.Init.RepetitionCounter = rep; // 重复计数值
          tim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;// 自动重装载值 预装载使能位(影子寄存器)
          HAL_TIM_Base_Init(&tim1); //初始化定时器
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); //手动 清除 定时器 更新事件
          / 外部模式1 ETR通道 /
          tim1_clock.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; //通道1 ETR
          tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_INVERTED; //ETR反向 (低电平或下降沿有效)
          //tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_NOINVERTED; //ETR不反向 (高电平或上升沿有效)
          tim1_clock.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; //ETR的预分频器配置
          tim1_clock.ClockFilter = 0x03; //滤波(注意是外部时钟的波)
          HAL_TIM_ConfigClockSource(&tim1, &tim1_clock); //初始化定时器时钟配置
          HAL_TIM_Base_Start(&tim1); //打开定时器(轮询方式)
          }
          //定时器 2
          void Timer2_Init(uint16_t arr, uint16_t psc)
          {
          tim2.Instance = TIM2;
          tim2.Init.Period = arr;
          tim2.Init.Prescaler = psc;
          tim2.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim2);
          __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
          / 外部模式1 通道1 双边沿检测 重映射/
          tim2_clock.ClockSource = TIM_CLOCKSOURCE_TI1ED; //通道1 边沿检测
          HAL_TIM_ConfigClockSource(&tim2, &tim2_clock); //初始化定时器时钟配置
          HAL_TIM_Base_Start(&tim2); //打开定时器(轮询方式)
          }
          //定时器 3
          void Timer3_Init(uint16_t arr, uint16_t psc)
          {
          tim3.Instance = TIM3;
          tim3.Init.Period = arr;
          tim3.Init.Prescaler = psc;
          tim3.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; //中央对齐模式
          tim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim3);
          __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
          / 外部模式1 通道1 /
          tim3_clock.ClockSource = TIM_CLOCKSOURCE_TI1; // 通道1
          tim3_clock.ClockPolarity = TIM_CLOCKPOLARITY_RISING; // 上升沿
          tim3_clock.ClockFilter = 0x03; // 滤波
          HAL_TIM_ConfigClockSource(&tim3, &tim3_clock); //初始化定时器时钟配置
          HAL_TIM_Base_Start(&tim3); //打开定时器(轮询方式)
          }
          //定时器 4
          void Timer4_Init(uint16_t arr, uint16_t psc)
          {
          tim4.Instance = TIM4;
          tim4.Init.Period = arr;
          tim4.Init.Prescaler = psc;
          tim4.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim4);
          __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
          / 外部模式1 通道2 /
          tim4_clock.ClockSource = TIM_CLOCKSOURCE_TI2; // 通道2
          tim4_clock.ClockPolarity = TIM_CLOCKPOLARITY_FALLING; // 下降沿
          tim4_clock.ClockFilter = 0x03; // 滤波
          HAL_TIM_ConfigClockSource(&tim4, &tim4_clock); //初始化定时器时钟配置
          HAL_TIM_Base_Start(&tim4); //打开定时器(轮询方式)
          }
          //定时器 硬件初始化回调函数
          void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
          {
          GPIO_InitTypeDef GPIO_InitType;
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
          / 定时器1 外部模式1 ETR通道IO /
          __HAL_RCC_GPIOA_CLK_ENABLE();
          GPIO_InitType.Pin = GPIO_PIN_12;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          //
          // HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
          // HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
          //
          // / DMA配置 /
          // tim1_dmaup.Instance = DMA1_Channel5;
          // tim1_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
          // tim1_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
          // tim1_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
          // tim1_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
          // tim1_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim1_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim1_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim1, hdma[TIM_DMA_ID_UPDATE], tim1_dmaup);
          // HAL_DMA_Init(&tim1_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
          //
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_ENABLE();
          __HAL_RCC_GPIOA_CLK_ENABLE();
          __HAL_RCC_AFIO_CLK_ENABLE();
          __HAL_AFIO_REMAP_TIM2_ENABLE();
          //__HAL_AFIO_REMAP_TIM2_PARTIAL_1(); //(同样的功能)
          __HAL_AFIO_REMAP_SWJ_NOJTAG();
          / 定时器2 外部模式1 通道1 重映射/
          //GPIO_InitType.Pin = GPIO_PIN_0;
          GPIO_InitType.Pin = GPIO_PIN_15;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          // HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
          // HAL_NVIC_EnableIRQ(TIM2_IRQn);
          //
          // / DMA配置 /
          // tim2_dmaup.Instance = DMA1_Channel2;
          // tim2_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          // tim2_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          // tim2_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          // tim2_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          // tim2_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim2_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim2, hdma[TIM_DMA_ID_UPDATE], tim2_dmaup);
          // HAL_DMA_Init(&tim2_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_ENABLE();
          //__HAL_RCC_GPIOA_CLK_ENABLE();
          __HAL_RCC_GPIOB_CLK_ENABLE();
          __HAL_RCC_AFIO_CLK_ENABLE();
          __HAL_AFIO_REMAP_TIM3_PARTIAL(); //部分映射
          __HAL_AFIO_REMAP_SWJ_NONJTRST(); //完全SW+JATG 但没有NJTRST
          / 定时器3 外部模式1 通道1 重映射/
          //GPIO_InitType.Pin = GPIO_PIN_6;
          GPIO_InitType.Pin = GPIO_PIN_4;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOB,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          // HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
          // HAL_NVIC_EnableIRQ(TIM3_IRQn);
          //
          // / DMA配置 /
          // tim3_dmaup.Instance = DMA1_Channel3;
          // tim3_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          // tim3_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          // tim3_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          // tim3_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          // tim3_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim3_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim3_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim3, hdma[TIM_DMA_ID_UPDATE], tim3_dmaup);
          // HAL_DMA_Init(&tim3_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_ENABLE();
          / 定时器4 外部模式1 通道2 /
          __HAL_RCC_GPIOB_CLK_ENABLE();
          GPIO_InitType.Pin = GPIO_PIN_7;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOB, &GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          // HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
          // HAL_NVIC_EnableIRQ(TIM4_IRQn);
          //
          // / DMA配置 /
          // tim4_dmaup.Instance = DMA1_Channel7;
          // tim4_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          // tim4_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          // tim4_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          // tim4_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          // tim4_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim4_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim4_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim4, hdma[TIM_DMA_ID_UPDATE], tim4_dmaup);
          // HAL_DMA_Init(&tim4_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
          }
          }
          //定时器 硬件 De 回调函数
          void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_DISABLE();
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_DISABLE();
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_DISABLE();
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_DISABLE();
          }
          }
          //更新中断 回调函数(同时也是DMA完成的回调函数)
          uint16_t time1 = 1;
          uint16_t time2 = 1;
          uint16_t time3 = 1;
          uint16_t time4 = 1;
          void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          / 判断TIM是否为Ready状态,如果是 则是DMA完成中断进入的回调函数 /
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA1 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 1 定时时间:%drn",time1++);
          }
          }else if(htim->Instance == TIM2){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA2 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 2 定时时间:%drn",time2++);
          }
          }else if(htim->Instance == TIM3){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA3 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 3 定时时间:%drn",time3++);
          }
          }else if(htim->Instance == TIM4){
          if(htim->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA4 完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else{
          U1_Printf("定时器 4 定时时间:%drn",time4++);
          }
          }
          }
          //DMA 半完成回调函数
          void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          U1_Printf("定时器 1 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM2){
          U1_Printf("定时器 2 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM3){
          U1_Printf("定时器 3 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM4){
          U1_Printf("定时器 4 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }
          }
          #ifndef __TIME_H
          #define __TIME_H
          #include "uart.h"
          / 对外声明总控结构体 /
          extern TIM_HandleTypeDef tim1;
          extern TIM_HandleTypeDef tim2;
          extern TIM_HandleTypeDef tim3;
          extern TIM_HandleTypeDef tim4;
          extern DMA_HandleTypeDef tim1_dmaup;
          extern DMA_HandleTypeDef tim2_dmaup;
          extern DMA_HandleTypeDef tim3_dmaup;
          extern DMA_HandleTypeDef tim4_dmaup;
          / 初始化函数 /
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
          void Timer2_Init(uint16_t arr, uint16_t psc);
          void Timer3_Init(uint16_t arr, uint16_t psc);
          void Timer4_Init(uint16_t arr, uint16_t psc);
          #endif
          #include "stm32f1xx_hal.h"
          #include "rcc.h"
          #include "led.h"
          #include "sw.h"
          #include "uart.h"
          #include "time.h"
          int main(void){
          HAL_Init();
          RccClock_Init();
          U1_Init(921600);
          Timer1_Init(5 - 1, 0, 1 - 1); //5次有效边沿
          Timer2_Init(5 - 1, 0); // 5次
          Timer3_Init(5 - 1, 0); // 5次
          Timer4_Init(5 - 1, 0); // 5次
          // uint16_t time1 = 0;
          // uint16_t time2 = 0;
          // uint16_t time3 = 0;
          // uint16_t time4 = 0;
          while(1){
          / 获取更新标志位 /
          / TIM1 /
          if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_UPDATE)){
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); ///清除标志位
          U1_Printf("定时器 1 更新事件rn");
          }
          if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_TRIGGER)){
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_TRIGGER); ///清除标志位
          U1_Printf("定时器 1 触发事件:%drn", __HAL_TIM_GET_COUNTER(&tim1)); //输出当前计数值
          }
          / TIM2 /
          if(__HAL_TIM_GET_FLAG(&tim2, TIM_FLAG_UPDATE)){
          __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
          U1_Printf("定时器 2 更新事件rn");
          }
          if(__HAL_TIM_GET_FLAG(&tim2, TIM_FLAG_TRIGGER)){
          __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_TRIGGER);
          U1_Printf("定时器 2 触发事件:%drn", __HAL_TIM_GET_COUNTER(&tim2));
          }
          / TIM3 /
          if(__HAL_TIM_GET_FLAG(&tim3, TIM_FLAG_UPDATE)){
          __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
          U1_Printf("定时器 3 更新事件rn");
          }
          if(__HAL_TIM_GET_FLAG(&tim3, TIM_FLAG_TRIGGER)){
          __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_TRIGGER);
          U1_Printf("定时器 3 触发事件:%drn", __HAL_TIM_GET_COUNTER(&tim3));
          }
          / TIM4 /
          if(__HAL_TIM_GET_FLAG(&tim4, TIM_FLAG_UPDATE)){
          __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
          U1_Printf("定时器 4 更新事件rn");
          }
          if(__HAL_TIM_GET_FLAG(&tim4, TIM_FLAG_TRIGGER)){
          __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_TRIGGER);
          U1_Printf("定时器 4 触发事件:%drn", __HAL_TIM_GET_COUNTER(&tim4));
          }
          //
          // if(__HAL_TIM_GET_FLAG(&tim2, TIM_FLAG_UPDATE)){
          // __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
          // U1_Printf("定时器 2 定时时间:%drn",time2++);
          // }
          //
          // if(__HAL_TIM_GET_FLAG(&tim3, TIM_FLAG_UPDATE)){
          // __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
          // U1_Printf("定时器 3 定时时间:%drn",time3++);
          // }
          //
          // if(__HAL_TIM_GET_FLAG(&tim4, TIM_FLAG_UPDATE)){
          // __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
          // U1_Printf("定时器 4 定时时间:%drn",time4++);
          // }
          }
          }
          #include "stm32f1xx_hal.h"
          #include "time.h"
          TIM_HandleTypeDef tim1; //定时器结构体
          TIM_HandleTypeDef tim2;
          TIM_HandleTypeDef tim3;
          TIM_HandleTypeDef tim4;
          DMA_HandleTypeDef tim1_dmaup; //DMA通道配置结构体
          DMA_HandleTypeDef tim2_dmaup;
          DMA_HandleTypeDef tim3_dmaup;
          DMA_HandleTypeDef tim4_dmaup;
          TIM_ClockConfigTypeDef tim1_clock; //时钟配置结构体
          TIM_ClockConfigTypeDef tim2_clock;
          TIM_ClockConfigTypeDef tim3_clock;
          TIM_ClockConfigTypeDef tim4_clock;
          uint16_t tim1_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim2_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim3_dmaBuff[4] = {20000, 30000, 40000, 50000};
          uint16_t tim4_dmaBuff[4] = {20000, 30000, 40000, 50000};
          //定时器 1
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
          {
          tim1.Instance = TIM1; // 实例
          tim1.Init.Period = arr; // 重装载值
          tim1.Init.Prescaler = psc; // 分频系数
          tim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数模式
          tim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 分频因子
          tim1.Init.RepetitionCounter = rep; // 重复计数值
          tim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;// 自动重装载值 预装载使能位(影子寄存器)
          HAL_TIM_Base_Init(&tim1); //初始化定时器
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); //手动 清除 定时器 更新事件
          / 外部模式1 ETR通道 / //PA12 下降沿 按下计数 上拉
          tim1_clock.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; //通道1 ETR
          tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_INVERTED; //ETR反向 (低电平或下降沿有效)
          //tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_NOINVERTED; //ETR不反向 (高电平或上升沿有效)
          tim1_clock.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; //ETR的预分频器配置
          tim1_clock.ClockFilter = 0x03; //滤波(注意是外部时钟的波)
          HAL_TIM_ConfigClockSource(&tim1, &tim1_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim1, TIM_IT_TRIGGER); //手动打开触发中断
          HAL_TIM_Base_Start_IT(&tim1); //打开定时器(中断方式)
          }
          //定时器 2
          void Timer2_Init(uint16_t arr, uint16_t psc)
          {
          tim2.Instance = TIM2;
          tim2.Init.Period = arr;
          tim2.Init.Prescaler = psc;
          tim2.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim2);
          __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
          / 外部模式1 通道1 双边沿检测 重映射/ //PA15 双边边沿 上拉
          tim2_clock.ClockSource = TIM_CLOCKSOURCE_TI1ED; //通道1 边沿检测
          HAL_TIM_ConfigClockSource(&tim2, &tim2_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim2, TIM_IT_TRIGGER); //手动打开触发中断
          HAL_TIM_Base_Start_IT(&tim2); //打开定时器(中断方式)
          }
          //定时器 3
          void Timer3_Init(uint16_t arr, uint16_t psc)
          {
          tim3.Instance = TIM3;
          tim3.Init.Period = arr;
          tim3.Init.Prescaler = psc;
          tim3.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; //中央对齐模式
          tim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim3);
          __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
          / 外部模式1 通道1 / //PB4 上升沿 上拉 抬起计数
          tim3_clock.ClockSource = TIM_CLOCKSOURCE_TI1; // 通道1
          tim3_clock.ClockPolarity = TIM_CLOCKPOLARITY_RISING; // 上升沿
          tim3_clock.ClockFilter = 0x03; // 滤波
          HAL_TIM_ConfigClockSource(&tim3, &tim3_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim3, TIM_IT_TRIGGER); //手动打开触发中断
          HAL_TIM_Base_Start_IT(&tim3); //打开定时器(中断方式)
          }
          //定时器 4
          void Timer4_Init(uint16_t arr, uint16_t psc)
          {
          tim4.Instance = TIM4;
          tim4.Init.Period = arr;
          tim4.Init.Prescaler = psc;
          tim4.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim4);
          __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
          / 外部模式1 通道2 / //PB7 下降沿 上拉 按下计数
          tim4_clock.ClockSource = TIM_CLOCKSOURCE_TI2; // 通道2
          tim4_clock.ClockPolarity = TIM_CLOCKPOLARITY_FALLING; // 下降沿
          tim4_clock.ClockFilter = 0x03; // 滤波
          HAL_TIM_ConfigClockSource(&tim4, &tim4_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim4, TIM_IT_TRIGGER); //手动打开触发中断
          HAL_TIM_Base_Start_IT(&tim4); //打开定时器(中断方式)
          }
          //定时器 硬件初始化回调函数
          void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
          {
          GPIO_InitTypeDef GPIO_InitType;
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
          / 定时器1 外部模式1 ETR通道IO /
          __HAL_RCC_GPIOA_CLK_ENABLE();
          GPIO_InitType.Pin = GPIO_PIN_12;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          //
          HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
          HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
          HAL_NVIC_SetPriority(TIM1_TRG_COM_IRQn, 3, 0); //配置、打开 触发中断
          HAL_NVIC_EnableIRQ(TIM1_TRG_COM_IRQn);
          //
          // / DMA配置 /
          // tim1_dmaup.Instance = DMA1_Channel5;
          // tim1_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
          // tim1_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
          // tim1_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
          // tim1_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
          // tim1_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim1_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim1_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim1, hdma[TIM_DMA_ID_UPDATE], tim1_dmaup);
          // HAL_DMA_Init(&tim1_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
          //
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_ENABLE();
          __HAL_RCC_GPIOA_CLK_ENABLE();
          __HAL_RCC_AFIO_CLK_ENABLE();
          __HAL_AFIO_REMAP_TIM2_ENABLE();
          //__HAL_AFIO_REMAP_TIM2_PARTIAL_1(); //(同样的功能)
          __HAL_AFIO_REMAP_SWJ_NOJTAG();
          / 定时器2 外部模式1 通道1 重映射/
          //GPIO_InitType.Pin = GPIO_PIN_0;
          GPIO_InitType.Pin = GPIO_PIN_15;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM2_IRQn);
          //
          // / DMA配置 /
          // tim2_dmaup.Instance = DMA1_Channel2;
          // tim2_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          // tim2_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          // tim2_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          // tim2_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          // tim2_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim2_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim2, hdma[TIM_DMA_ID_UPDATE], tim2_dmaup);
          // HAL_DMA_Init(&tim2_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_ENABLE();
          //__HAL_RCC_GPIOA_CLK_ENABLE();
          __HAL_RCC_GPIOB_CLK_ENABLE();
          __HAL_RCC_AFIO_CLK_ENABLE();
          __HAL_AFIO_REMAP_TIM3_PARTIAL(); //部分映射
          __HAL_AFIO_REMAP_SWJ_NONJTRST(); //完全SW+JATG 但没有NJTRST
          / 定时器3 外部模式1 通道1 重映射/
          //GPIO_InitType.Pin = GPIO_PIN_6;
          GPIO_InitType.Pin = GPIO_PIN_4;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOB,&GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM3_IRQn);
          //
          // / DMA配置 /
          // tim3_dmaup.Instance = DMA1_Channel3;
          // tim3_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          // tim3_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          // tim3_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          // tim3_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          // tim3_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim3_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim3_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim3, hdma[TIM_DMA_ID_UPDATE], tim3_dmaup);
          // HAL_DMA_Init(&tim3_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_ENABLE();
          / 定时器4 外部模式1 通道2 /
          __HAL_RCC_GPIOB_CLK_ENABLE();
          GPIO_InitType.Pin = GPIO_PIN_7;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOB, &GPIO_InitType);
          // __HAL_RCC_DMA1_CLK_ENABLE();
          HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM4_IRQn);
          //
          // / DMA配置 /
          // tim4_dmaup.Instance = DMA1_Channel7;
          // tim4_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          // tim4_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          // tim4_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          // tim4_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          // tim4_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          // tim4_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          // tim4_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          // __HAL_LINKDMA(&tim4, hdma[TIM_DMA_ID_UPDATE], tim4_dmaup);
          // HAL_DMA_Init(&tim4_dmaup);
          //
          // HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0); //配置、打开 通道5的中断
          // HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
          }
          }
          //定时器 硬件 De 回调函数
          void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_DISABLE();
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_DISABLE();
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_DISABLE();
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_DISABLE();
          }
          }
          //更新中断 回调函数(同时也是DMA完成的回调函数)
          uint16_t time1 = 1;
          uint16_t time2 = 1;
          uint16_t time3 = 1;
          uint16_t time4 = 1;
          void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          // / 判断TIM是否为Ready状态,如果是 则是DMA完成中断进入的回调函数 /
          // if(htim->State == HAL_DMA_STATE_READY){
          // U1_Printf("DMA1 完成中断rn");
          // htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          // }else{
          // U1_Printf("定时器 1 定时时间:%drn",time1++);
          // }
          U1_Printf("定时器 1 更新事件rn");
          }else if(htim->Instance == TIM2){
          // if(htim->State == HAL_DMA_STATE_READY){
          // U1_Printf("DMA2 完成中断rn");
          // htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          // }else{
          // U1_Printf("定时器 2 定时时间:%drn",time2++);
          // }
          U1_Printf("定时器 2 更新事件rn");
          }else if(htim->Instance == TIM3){
          // if(htim->State == HAL_DMA_STATE_READY){
          // U1_Printf("DMA3 完成中断rn");
          // htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          // }else{
          // U1_Printf("定时器 3 定时时间:%drn",time3++);
          // }
          U1_Printf("定时器 3 更新事件rn");
          }else if(htim->Instance == TIM4){
          // if(htim->State == HAL_DMA_STATE_READY){
          // U1_Printf("DMA4 完成中断rn");
          // htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          // }else{
          // U1_Printf("定时器 4 定时时间:%drn",time4++);
          // }
          U1_Printf("定时器 4 更新事件rn");
          }
          }
          //触发中断 回调函数
          void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          U1_Printf("定时器 1 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }else if(htim->Instance == TIM2){
          U1_Printf("定时器 2 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }else if(htim->Instance == TIM3){
          U1_Printf("定时器 3 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }else if(htim->Instance == TIM4){
          U1_Printf("定时器 4 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }
          }
          //DMA 半完成回调函数
          void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          U1_Printf("定时器 1 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM2){
          U1_Printf("定时器 2 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM3){
          U1_Printf("定时器 3 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }else if(htim->Instance == TIM4){
          U1_Printf("定时器 4 DMA半完成中断rn");
          htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
          }
          }
          #ifndef __TIME_H
          #define __TIME_H
          #include "uart.h"
          / 对外声明总控结构体 /
          extern TIM_HandleTypeDef tim1;
          extern TIM_HandleTypeDef tim2;
          extern TIM_HandleTypeDef tim3;
          extern TIM_HandleTypeDef tim4;
          extern DMA_HandleTypeDef tim1_dmaup;
          extern DMA_HandleTypeDef tim2_dmaup;
          extern DMA_HandleTypeDef tim3_dmaup;
          extern DMA_HandleTypeDef tim4_dmaup;
          / 初始化函数 /
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
          void Timer2_Init(uint16_t arr, uint16_t psc);
          void Timer3_Init(uint16_t arr, uint16_t psc);
          void Timer4_Init(uint16_t arr, uint16_t psc);
          #endif
          #include "stm32f1xx_hal.h"
          #include "rcc.h"
          #include "led.h"
          #include "sw.h"
          #include "uart.h"
          #include "time.h"
          int main(void){
          HAL_Init();
          RccClock_Init();
          U1_Init(921600);
          Timer1_Init(5 - 1, 0, 1 - 1); //5次有效边沿
          Timer2_Init(5 - 1, 0); // 5次
          Timer3_Init(5 - 1, 0); // 5次
          Timer4_Init(5 - 1, 0); // 5次
          U1_Printf("初始化完成rn");
          while(1){
          }
          }
          /-------------------------------------------------/
          / /
          / 实现各种中断服务函数的源文件 /
          / /
          /-------------------------------------------------/
          #include "stm32f1xx_hal.h"
          #include "stm32f1xx_it.h"
          #include "uart.h"
          #include "time.h"
          void EXTI15_10_IRQHandler(void)
          {
          HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
          }
          void EXTI0_IRQHandler(void)
          {
          HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
          }
          void USART1_IRQHandler(void)
          {
          HAL_UART_IRQHandler(&uart1.uart);
          if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
          __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
          uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
          HAL_UART_AbortReceive_IT(&uart1.uart);
          }
          }
          void USART2_IRQHandler(void)
          {
          HAL_UART_IRQHandler(&uart2.uart);
          if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
          __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
          uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
          HAL_UART_AbortReceive_IT(&uart2.uart);
          }
          }
          void USART3_IRQHandler(void)
          {
          HAL_UART_IRQHandler(&uart3.uart);
          if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
          __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
          uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
          HAL_UART_AbortReceive_IT(&uart3.uart);
          }
          }
          void DMA1_Channel4_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&uart1.dmatx);
          }
          //void DMA1_Channel5_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart1.dmarx);
          //}
          //void DMA1_Channel7_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart2.dmatx);
          //}
          void DMA1_Channel6_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&uart2.dmarx);
          }
          //void DMA1_Channel2_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart3.dmatx);
          //}
          //void DMA1_Channel3_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart3.dmarx);
          //}
          void DMA1_Channel5_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim1_dmaup);
          }
          void DMA1_Channel2_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim2_dmaup);
          }
          void DMA1_Channel3_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim3_dmaup);
          }
          void DMA1_Channel7_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim4_dmaup);
          }
          void TIM1_UP_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim1);
          }
          void TIM1_TRG_COM_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim1);
          }
          void TIM2_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim2);
          }
          void TIM3_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim3);
          }
          void TIM4_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim4);
          }
          /-------------------------------------------------/
          /函数名:不可屏蔽中断处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void NMI_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:硬件出错后进入的中断处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void HardFault_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:软中断,SWI 指令调用的处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void SVC_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:可挂起的系统服务处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void PendSV_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:SysTic系统嘀嗒定时器处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void SysTick_Handler(void)
          {
          HAL_IncTick();
          }
          #include "stm32f1xx_hal.h"
          #include "time.h"
          TIM_HandleTypeDef tim1; //定时器结构体
          TIM_HandleTypeDef tim2;
          TIM_HandleTypeDef tim3;
          TIM_HandleTypeDef tim4;
          DMA_HandleTypeDef tim1_dmaup; //DMA通道配置结构体
          DMA_HandleTypeDef tim2_dmaup;
          DMA_HandleTypeDef tim3_dmaup;
          DMA_HandleTypeDef tim4_dmaup;
          TIM_ClockConfigTypeDef tim1_clock; //时钟配置结构体
          TIM_ClockConfigTypeDef tim2_clock;
          TIM_ClockConfigTypeDef tim3_clock;
          TIM_ClockConfigTypeDef tim4_clock;
          uint16_t tim1_dmaBuff[4] = {6, 7, 8, 9};
          uint16_t tim2_dmaBuff[4] = {6, 7, 8, 9};
          uint16_t tim3_dmaBuff[4] = {6, 7, 8, 9};
          uint16_t tim4_dmaBuff[4] = {6, 7, 8, 9};
          //定时器 1
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
          {
          tim1.Instance = TIM1; // 实例
          tim1.Init.Period = arr; // 重装载值
          tim1.Init.Prescaler = psc; // 分频系数
          tim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数模式
          tim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 分频因子
          tim1.Init.RepetitionCounter = rep; // 重复计数值
          tim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;// 自动重装载值 预装载使能位(影子寄存器)
          HAL_TIM_Base_Init(&tim1); //初始化定时器
          __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); //手动 清除 定时器 更新事件
          / 外部模式1 ETR通道 / //PA12 下降沿 按下计数 上拉
          tim1_clock.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; //通道1 ETR
          tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_INVERTED; //ETR反向 (低电平或下降沿有效)
          //tim1_clock.ClockPolarity = TIM_CLOCKPOLARITY_NOINVERTED; //ETR不反向 (高电平或上升沿有效)
          tim1_clock.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; //ETR的预分频器配置
          tim1_clock.ClockFilter = 0x03; //滤波(注意是外部时钟的波)
          HAL_TIM_ConfigClockSource(&tim1, &tim1_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim1, TIM_IT_TRIGGER | TIM_IT_UPDATE); //手动打开触发中断、更新中断
          HAL_TIM_Base_Start_DMA(&tim1, (uint32_t* )tim1_dmaBuff, 4); //打开定时器(DMA方式)
          }
          //定时器 2
          void Timer2_Init(uint16_t arr, uint16_t psc)
          {
          tim2.Instance = TIM2;
          tim2.Init.Period = arr;
          tim2.Init.Prescaler = psc;
          tim2.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim2);
          __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
          / 外部模式1 通道1 双边沿检测 重映射/ //PA15 双边边沿 上拉
          tim2_clock.ClockSource = TIM_CLOCKSOURCE_TI1ED; //通道1 边沿检测
          HAL_TIM_ConfigClockSource(&tim2, &tim2_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim2, TIM_IT_TRIGGER | TIM_IT_UPDATE); //手动打开触发中断、更新中断
          HAL_TIM_Base_Start_DMA(&tim2, (uint32_t* )tim2_dmaBuff, 4); //打开定时器(DMA方式)
          }
          //定时器 3
          void Timer3_Init(uint16_t arr, uint16_t psc)
          {
          tim3.Instance = TIM3;
          tim3.Init.Period = arr;
          tim3.Init.Prescaler = psc;
          tim3.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; //中央对齐模式
          tim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim3);
          __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
          / 外部模式1 通道1 / //PB4 上升沿 上拉 抬起计数
          tim3_clock.ClockSource = TIM_CLOCKSOURCE_TI1; // 通道1
          tim3_clock.ClockPolarity = TIM_CLOCKPOLARITY_RISING; // 上升沿
          tim3_clock.ClockFilter = 0x03; // 滤波
          HAL_TIM_ConfigClockSource(&tim3, &tim3_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim3, TIM_IT_TRIGGER | TIM_IT_UPDATE); //手动打开触发中断、更新中断
          HAL_TIM_Base_Start_DMA(&tim3, (uint32_t* )tim3_dmaBuff, 4); //打开定时器(DMA方式)
          }
          //定时器 4
          void Timer4_Init(uint16_t arr, uint16_t psc)
          {
          tim4.Instance = TIM4;
          tim4.Init.Period = arr;
          tim4.Init.Prescaler = psc;
          tim4.Init.CounterMode = TIM_COUNTERMODE_UP;
          tim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
          tim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
          HAL_TIM_Base_Init(&tim4);
          __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
          / 外部模式1 通道2 / //PB7 下降沿 上拉 按下计数
          tim4_clock.ClockSource = TIM_CLOCKSOURCE_TI2; // 通道2
          tim4_clock.ClockPolarity = TIM_CLOCKPOLARITY_FALLING; // 下降沿
          tim4_clock.ClockFilter = 0x03; // 滤波
          HAL_TIM_ConfigClockSource(&tim4, &tim4_clock); //初始化定时器时钟配置
          __HAL_TIM_ENABLE_IT(&tim4, TIM_IT_TRIGGER | TIM_IT_UPDATE); //手动打开触发中断、更新中断
          HAL_TIM_Base_Start_DMA(&tim4, (uint32_t* )tim4_dmaBuff, 4); //打开定时器(DMA方式)
          }
          //定时器 硬件初始化回调函数
          void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
          {
          GPIO_InitTypeDef GPIO_InitType;
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
          / 定时器1 外部模式1 ETR通道IO /
          __HAL_RCC_GPIOA_CLK_ENABLE();
          GPIO_InitType.Pin = GPIO_PIN_12;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
          HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
          HAL_NVIC_SetPriority(TIM1_TRG_COM_IRQn, 3, 0); //配置、打开 触发中断
          HAL_NVIC_EnableIRQ(TIM1_TRG_COM_IRQn);
          / DMA配置 /
          __HAL_RCC_DMA1_CLK_ENABLE();
          tim1_dmaup.Instance = DMA1_Channel5;
          tim1_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
          tim1_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
          tim1_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
          tim1_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
          tim1_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim1_dmaup.Init.Mode = DMA_NORMAL; //单次模式
          //tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim1_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim1, hdma[TIM_DMA_ID_UPDATE], tim1_dmaup);
          HAL_DMA_Init(&tim1_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_ENABLE();
          __HAL_RCC_GPIOA_CLK_ENABLE();
          __HAL_RCC_AFIO_CLK_ENABLE();
          __HAL_AFIO_REMAP_TIM2_ENABLE();
          //__HAL_AFIO_REMAP_TIM2_PARTIAL_1(); //(同样的功能)
          __HAL_AFIO_REMAP_SWJ_NOJTAG();
          / 定时器2 外部模式1 通道1 重映射/
          //GPIO_InitType.Pin = GPIO_PIN_0;
          GPIO_InitType.Pin = GPIO_PIN_15;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOA,&GPIO_InitType);
          HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM2_IRQn);
          / DMA配置 /
          __HAL_RCC_DMA1_CLK_ENABLE();
          tim2_dmaup.Instance = DMA1_Channel2;
          tim2_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim2_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim2_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim2_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim2_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim1_dmaup.Init.Mode = DMA_NORMAL; //单次模式
          //tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim2_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim2, hdma[TIM_DMA_ID_UPDATE], tim2_dmaup);
          HAL_DMA_Init(&tim2_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_ENABLE();
          //__HAL_RCC_GPIOA_CLK_ENABLE();
          __HAL_RCC_GPIOB_CLK_ENABLE();
          __HAL_RCC_AFIO_CLK_ENABLE();
          __HAL_AFIO_REMAP_TIM3_PARTIAL(); //部分映射
          __HAL_AFIO_REMAP_SWJ_NONJTRST(); //完全SW+JATG 但没有NJTRST
          / 定时器3 外部模式1 通道1 重映射/
          //GPIO_InitType.Pin = GPIO_PIN_6;
          GPIO_InitType.Pin = GPIO_PIN_4;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOB,&GPIO_InitType);
          HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM3_IRQn);
          / DMA配置 /
          __HAL_RCC_DMA1_CLK_ENABLE();
          tim3_dmaup.Instance = DMA1_Channel3;
          tim3_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim3_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim3_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim3_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim3_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim1_dmaup.Init.Mode = DMA_NORMAL; //单次模式
          //tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim3_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim3, hdma[TIM_DMA_ID_UPDATE], tim3_dmaup);
          HAL_DMA_Init(&tim3_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_ENABLE();
          / 定时器4 外部模式1 通道2 /
          __HAL_RCC_GPIOB_CLK_ENABLE();
          GPIO_InitType.Pin = GPIO_PIN_7;
          GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;
          GPIO_InitType.Pull = GPIO_PULLUP; //低电平按下,上拉
          HAL_GPIO_Init(GPIOB, &GPIO_InitType);
          HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
          HAL_NVIC_EnableIRQ(TIM4_IRQn);
          / DMA配置 /
          __HAL_RCC_DMA1_CLK_ENABLE();
          tim4_dmaup.Instance = DMA1_Channel7;
          tim4_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
          tim4_dmaup.Init.MemInc = DMA_MINC_ENABLE;
          tim4_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
          tim4_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
          tim4_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
          tim1_dmaup.Init.Mode = DMA_NORMAL; //单次模式
          //tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
          tim4_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
          __HAL_LINKDMA(&tim4, hdma[TIM_DMA_ID_UPDATE], tim4_dmaup);
          HAL_DMA_Init(&tim4_dmaup);
          HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0); //配置、打开 通道5的中断
          HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
          }
          }
          //定时器 硬件 De 回调函数
          void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          __HAL_RCC_TIM1_CLK_DISABLE();
          }else if(htim->Instance == TIM2){
          __HAL_RCC_TIM2_CLK_DISABLE();
          }else if(htim->Instance == TIM3){
          __HAL_RCC_TIM3_CLK_DISABLE();
          }else if(htim->Instance == TIM4){
          __HAL_RCC_TIM4_CLK_DISABLE();
          }
          }
          //更新中断 回调函数(同时也是DMA完成的回调函数)
          uint16_t time1 = 1;
          uint16_t time2 = 1;
          uint16_t time3 = 1;
          uint16_t time4 = 1;
          void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          / 判断DMA的状态是否为Ready状态,如果是 则是DMA完成中断进入的回调函数 /
          if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA1 完成中断rn");
          HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
          }else{
          U1_Printf("定时器 1 更新事件rn");
          }
          }else if(htim->Instance == TIM2){
          if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA2 完成中断rn");
          HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
          }else{
          U1_Printf("定时器 2 更新事件rn");
          }
          }else if(htim->Instance == TIM3){
          if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA3 完成中断rn");
          HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
          }else{
          U1_Printf("定时器 3 更新事件rn");
          }
          }else if(htim->Instance == TIM4){
          if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
          U1_Printf("DMA4 完成中断rn");
          HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
          }else{
          U1_Printf("定时器 4 更新事件rn");
          }
          }
          }
          //触发中断 回调函数
          void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          U1_Printf("定时器 1 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }else if(htim->Instance == TIM2){
          U1_Printf("定时器 2 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }else if(htim->Instance == TIM3){
          U1_Printf("定时器 3 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }else if(htim->Instance == TIM4){
          U1_Printf("定时器 4 触发事件:%drn", __HAL_TIM_GET_COUNTER(htim)); //输出当前计数值
          }
          }
          //DMA 半完成回调函数
          void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
          {
          if(htim->Instance == TIM1){
          U1_Printf("定时器 1 DMA半完成中断rn");
          }else if(htim->Instance == TIM2){
          U1_Printf("定时器 2 DMA半完成中断rn");
          }else if(htim->Instance == TIM3){
          U1_Printf("定时器 3 DMA半完成中断rn");
          }else if(htim->Instance == TIM4){
          U1_Printf("定时器 4 DMA半完成中断rn");
          }
          }
          #ifndef __TIME_H
          #define __TIME_H
          #include "uart.h"
          / 对外声明总控结构体 /
          extern TIM_HandleTypeDef tim1;
          extern TIM_HandleTypeDef tim2;
          extern TIM_HandleTypeDef tim3;
          extern TIM_HandleTypeDef tim4;
          extern DMA_HandleTypeDef tim1_dmaup;
          extern DMA_HandleTypeDef tim2_dmaup;
          extern DMA_HandleTypeDef tim3_dmaup;
          extern DMA_HandleTypeDef tim4_dmaup;
          / 初始化函数 /
          void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
          void Timer2_Init(uint16_t arr, uint16_t psc);
          void Timer3_Init(uint16_t arr, uint16_t psc);
          void Timer4_Init(uint16_t arr, uint16_t psc);
          #endif
          #include "stm32f1xx_hal.h"
          #include "rcc.h"
          #include "led.h"
          #include "sw.h"
          #include "uart.h"
          #include "time.h"
          int main(void){
          HAL_Init();
          RccClock_Init();
          U1_Init(921600);
          Timer1_Init(5 - 1, 0, 1 - 1); //5次有效边沿
          Timer2_Init(5 - 1, 0); // 5次
          Timer3_Init(5 - 1, 0); // 5次
          Timer4_Init(5 - 1, 0); // 5次
          U1_Printf("初始化完成rn");
          while(1){
          }
          }
          /-------------------------------------------------/
          / /
          / 实现各种中断服务函数的源文件 /
          / /
          /-------------------------------------------------/
          #include "stm32f1xx_hal.h"
          #include "stm32f1xx_it.h"
          #include "uart.h"
          #include "time.h"
          void EXTI15_10_IRQHandler(void)
          {
          HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
          }
          void EXTI0_IRQHandler(void)
          {
          HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
          }
          void USART1_IRQHandler(void)
          {
          HAL_UART_IRQHandler(&uart1.uart);
          if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
          __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
          uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
          HAL_UART_AbortReceive_IT(&uart1.uart);
          }
          }
          void USART2_IRQHandler(void)
          {
          HAL_UART_IRQHandler(&uart2.uart);
          if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
          __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
          uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
          HAL_UART_AbortReceive_IT(&uart2.uart);
          }
          }
          void USART3_IRQHandler(void)
          {
          HAL_UART_IRQHandler(&uart3.uart);
          if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
          __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
          uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
          HAL_UART_AbortReceive_IT(&uart3.uart);
          }
          }
          void DMA1_Channel4_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&uart1.dmatx);
          }
          //void DMA1_Channel5_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart1.dmarx);
          //}
          //void DMA1_Channel7_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart2.dmatx);
          //}
          void DMA1_Channel6_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&uart2.dmarx);
          }
          //void DMA1_Channel2_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart3.dmatx);
          //}
          //void DMA1_Channel3_IRQHandler(void)
          //{
          // HAL_DMA_IRQHandler(&uart3.dmarx);
          //}
          void TIM1_UP_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim1);
          }
          void TIM1_TRG_COM_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim1);
          }
          void DMA1_Channel5_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim1_dmaup);
          }
          void TIM2_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim2);
          }
          void DMA1_Channel2_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim2_dmaup);
          }
          void TIM3_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim3);
          }
          void DMA1_Channel3_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim3_dmaup);
          }
          void TIM4_IRQHandler(void)
          {
          HAL_TIM_IRQHandler(&tim4);
          }
          void DMA1_Channel7_IRQHandler(void)
          {
          HAL_DMA_IRQHandler(&tim4_dmaup);
          }
          /-------------------------------------------------/
          /函数名:不可屏蔽中断处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void NMI_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:硬件出错后进入的中断处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void HardFault_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:软中断,SWI 指令调用的处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void SVC_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:可挂起的系统服务处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void PendSV_Handler(void)
          {
          }
          /-------------------------------------------------/
          /函数名:SysTic系统嘀嗒定时器处理函数 /
          /参 数:无 /
          /返回值:无 /
          /-------------------------------------------------/
          void SysTick_Handler(void)
          {
          HAL_IncTick();
          }

          高级定时器(TIM1)

          • 时基单元包含:
            • 计数器寄存器(TIMx_CNT)
            • 预分频器寄存器(TIMx_PSC)
            • 自动装载寄存器(TIMx_ARR)
            • 重复次数寄存器(TIMx_RCR)

          通用定时器(TIM2、TIM3、TIM4)

          • 时基单元包含:
            • 计数器寄存器(TIMx_CNT)
            • 预分频器寄存器(TIMx_PSC)
            • 自动装载寄存器(TIMx_ARR)

          定时器 1 通道

          • 通道 1:PA8、 DMA1_Channel2
          • 通道 2:PA9、 DMA1_Channel3
          • 通道 3:PA10、 DMA1_Channel6
          • 通道 4:PA11、 DMA1_Channel4
          • 通道 ETR:PA12

          • 刹车: PB12、PA6(重映射)
          • 通道 1 互补:PB13、PA7(重映射)
          • 通道 2 互补:PB14、PB0(重映射)
          • 通道 3 互补:PB15、PB1(重映射)

          定时器 2 通道

          • 通道 1:PA0(重映射 PA15)、PA1(重映射 PB3)
          • 通道 2:PA2(重映射 PB10)
          • 通道 3:DMA1_Channel5、DMA1_Channel7、DMA1_Channel1、DMA1_Channel7
          • 通道 4:PA3(重映射 PB11)
          • 通道 ETR:PA0(重映射 PA15)

          定时器 3 通道

          • 通道 1:PA6(重映射 PB4)、DMA1_Channel6、DMA1_Channel2、DMA1_Channel3
          • 通道 2:PA7(重映射 PB5)
          • 通道 3:PB0
          • 通道 4:PB1
          • 通道 ETR:无

          定时器 4 通道

          • 通道1:PB6 DMA1 Channel1
          • 通道2:PB7 DMA1 Channel4
          • 通道3:PB8 DMA1 Channel5
          • 通道4:PB9
          • 通道ETR:无

          二、HAL库:TIM1234轮询方式 基础定时

          1. 相关函数

          • TIM_HandleTypeDef 定时器总控结构体
          • HAL_TIM_Base_Init(&tim3); 轮询 初始化定时器
          • __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE); 清除更新标志位
          • HAL_TIM_Base_Start(&tim3); 开启定时器
          • void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim) 定时器DeInit回调函数
          • 基础的初始化
          • void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) 定时器Init回调函数
          • 基础的初始化
            • 主循环while判断
              •  

            2. 程序

            time.c

            time.h

            void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
            void Timer2_Init(uint16_t arr, uint16_t psc);
            void Timer3_Init(uint16_t arr, uint16_t psc);
            void Timer4_Init(uint16_t arr, uint16_t psc);
            #endif
            #include "stm32f1xx_hal.h"
            #include "rcc.h"
            #include "led.h"
            #include "sw.h"
            #include "uart.h"
            #include "time.h"
            int main(void){
            HAL_Init();
            RccClock_Init();
            U1_Init(921600);
            Timer1_Init(20000 - 1, 3600 - 1, 4 - 1); // 72000000/3600/20000 = 1 * 4 = 4s
            Timer2_Init(30000 - 1, 7200 - 1); // 3s
            Timer3_Init(20000 - 1, 7200 - 1); // 2s
            Timer4_Init(10000 - 1, 7200 - 1); // 1s
            uint16_t time1 = 1;
            uint16_t time2 = 1;
            uint16_t time3 = 1;
            uint16_t time4 = 1;
            while(1){
            / 获取更新标志位 /
            if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_UPDATE)){
            __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); ///清除标志位
            U1_Printf("定时器 1 定时时间:%drn",time1++);
            if(time1 > 5){
            U1_Printf("定时器 1 关闭rn");
            HAL_TIM_Base_Stop(&tim1); //停止定时器
            HAL_TIM_Base_DeInit(&tim1); //释放
            }
            }
            if(__HAL_TIM_GET_FLAG(&tim2, TIM_FLAG_UPDATE)){
            __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
            U1_Printf("定时器 2 定时时间:%drn",time2++);
            }
            if(__HAL_TIM_GET_FLAG(&tim3, TIM_FLAG_UPDATE)){
            __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
            U1_Printf("定时器 3 定时时间:%drn",time3++);
            }
            if(__HAL_TIM_GET_FLAG(&tim4, TIM_FLAG_UPDATE)){
            __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
            U1_Printf("定时器 4 定时时间:%drn",time4++);
            }
            }
            }
            time.c
            #include "stm32f1xx_hal.h"
            #include "time.h"
            TIM_HandleTypeDef tim1; //(高级)定时器1总控结构体
            TIM_HandleTypeDef tim2;
            TIM_HandleTypeDef tim3;
            TIM_HandleTypeDef tim4;
            //定时器 1
            void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
            {
            tim1.Instance = TIM1; // 实例
            tim1.Init.Period = arr; // 重装载值
            tim1.Init.Prescaler = psc; // 分频系数
            tim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数模式
            tim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 分频因子
            tim1.Init.RepetitionCounter = rep; // 重复计数值
            tim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;// 自动重装载值 预装载使能位(影子寄存器)
            HAL_TIM_Base_Init(&tim1); //初始化定时器
            __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); //手动清除更新事件
            HAL_TIM_Base_Start_IT(&tim1); //打开定时器(IT方式)
            }
            //定时器 2
            void Timer2_Init(uint16_t arr, uint16_t psc)
            {
            tim2.Instance = TIM2;
            tim2.Init.Period = arr;
            tim2.Init.Prescaler = psc;
            tim2.Init.CounterMode = TIM_COUNTERMODE_UP;
            tim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            tim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            HAL_TIM_Base_Init(&tim2);
            __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
            HAL_TIM_Base_Start_IT(&tim2);
            }
            //定时器 3
            void Timer3_Init(uint16_t arr, uint16_t psc)
            {
            tim3.Instance = TIM3;
            tim3.Init.Period = arr;
            tim3.Init.Prescaler = psc;
            tim3.Init.CounterMode = TIM_COUNTERMODE_UP;
            tim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            tim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            HAL_TIM_Base_Init(&tim3);
            __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
            HAL_TIM_Base_Start_IT(&tim3);
            }
            //定时器 4
            void Timer4_Init(uint16_t arr, uint16_t psc)
            {
            tim4.Instance = TIM4;
            tim4.Init.Period = arr;
            tim4.Init.Prescaler = psc;
            tim4.Init.CounterMode = TIM_COUNTERMODE_UP;
            tim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            tim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            HAL_TIM_Base_Init(&tim4);
            __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
            HAL_TIM_Base_Start_IT(&tim4);
            }
            //定时器 硬件初始化回调函数
            void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
            HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
            HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
            }else if(htim->Instance == TIM2){
            __HAL_RCC_TIM2_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM2_IRQn);
            }else if(htim->Instance == TIM3){
            __HAL_RCC_TIM3_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM3_IRQn);
            }else if(htim->Instance == TIM4){
            __HAL_RCC_TIM4_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM4_IRQn);
            }
            }
            uint16_t time1 = 1;
            uint16_t time2 = 1;
            uint16_t time3 = 1;
            uint16_t time4 = 1;
            //更新中断 回调函数
            void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            U1_Printf("定时器 1 定时时间:%drn",time1++);
            }else if(htim->Instance == TIM2){
            U1_Printf("定时器 2 定时时间:%drn",time2++);
            }else if(htim->Instance == TIM3){
            U1_Printf("定时器 3 定时时间:%drn",time3++);
            }else if(htim->Instance == TIM4){
            U1_Printf("定时器 4 定时时间:%drn",time4++);
            }
            }
            //定时器 硬件De初始化回调函数
            void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            __HAL_RCC_TIM1_CLK_DISABLE();
            }else if(htim->Instance == TIM2){
            __HAL_RCC_TIM2_CLK_DISABLE();
            }else if(htim->Instance == TIM3){
            __HAL_RCC_TIM3_CLK_DISABLE();
            }else if(htim->Instance == TIM4){
            __HAL_RCC_TIM4_CLK_DISABLE();
            }
            }
            time.h
            #ifndef __TIME_H
            #define __TIME_H
            #include "uart.h"
            / 对外声明总控结构体 /
            extern TIM_HandleTypeDef tim1;
            extern TIM_HandleTypeDef tim2;
            extern TIM_HandleTypeDef tim3;
            extern TIM_HandleTypeDef tim4;
            / 初始化函数 /
            void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
            void Timer2_Init(uint16_t arr, uint16_t psc);
            void Timer3_Init(uint16_t arr, uint16_t psc);
            void Timer4_Init(uint16_t arr, uint16_t psc);
            #endif
            stm32f1xx_it.c
            /-------------------------------------------------/
            / /
            / 实现各种中断服务函数的源文件 /
            / /
            /-------------------------------------------------/
            #include "stm32f1xx_hal.h"
            #include "stm32f1xx_it.h"
            #include "uart.h"
            #include "time.h"
            //定时器相关
            void TIM1_UP_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim1);
            }
            void TIM2_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim2);
            }
            void TIM3_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim3);
            }
            void TIM4_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim4);
            }
            //其他
            void EXTI15_10_IRQHandler(void)
            {
            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
            }
            void EXTI0_IRQHandler(void)
            {
            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
            }
            void USART1_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart1.uart);
            if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
            uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
            HAL_UART_AbortReceive_IT(&uart1.uart);
            }
            }
            void USART2_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart2.uart);
            if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
            uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
            HAL_UART_AbortReceive_IT(&uart2.uart);
            }
            }
            void USART3_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart3.uart);
            if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
            uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
            HAL_UART_AbortReceive_IT(&uart3.uart);
            }
            }
            void DMA1_Channel4_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart1.dmatx);
            }
            void DMA1_Channel5_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart1.dmarx);
            }
            void DMA1_Channel7_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart2.dmatx);
            }
            void DMA1_Channel6_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart2.dmarx);
            }
            void DMA1_Channel2_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart3.dmatx);
            }
            void DMA1_Channel3_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart3.dmarx);
            }
            /-------------------------------------------------/
            /函数名:不可屏蔽中断处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void NMI_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:硬件出错后进入的中断处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void HardFault_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:软中断,SWI 指令调用的处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void SVC_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:可挂起的系统服务处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void PendSV_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:SysTic系统嘀嗒定时器处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void SysTick_Handler(void)
            {
            HAL_IncTick();
            }
            main.c
            #include "stm32f1xx_hal.h"
            #include "rcc.h"
            #include "led.h"
            #include "sw.h"
            #include "uart.h"
            #include "time.h"
            int main(void){
            HAL_Init();
            RccClock_Init();
            U1_Init(921600);
            Timer1_Init(20000 - 1, 3600 - 1, 4 - 1); // 72000000/3600/20000 = 1 * 4 = 4s
            Timer2_Init(30000 - 1, 7200 - 1); // 3s
            Timer3_Init(20000 - 1, 7200 - 1); // 2s
            Timer4_Init(10000 - 1, 7200 - 1); // 1s
            // uint16_t time1 = 0;
            // uint16_t time2 = 0;
            // uint16_t time3 = 0;
            // uint16_t time4 = 0;
            while(1){
            / 获取更新标志位 /
            // if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); ///清除标志位
            // U1_Printf("定时器 1 定时时间:%drn",time1++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim2, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 2 定时时间:%drn",time2++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim3, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 3 定时时间:%drn",time3++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim4, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 4 定时时间:%drn",time4++);
            // }
            }
            }
            #include "stm32f1xx_hal.h"
            #include "time.h"
            TIM_HandleTypeDef tim1; //(高级)定时器1总控结构体
            TIM_HandleTypeDef tim2;
            TIM_HandleTypeDef tim3;
            TIM_HandleTypeDef tim4;
            DMA_HandleTypeDef tim1_dmaup;
            DMA_HandleTypeDef tim2_dmaup;
            DMA_HandleTypeDef tim3_dmaup;
            DMA_HandleTypeDef tim4_dmaup;
            uint16_t tim1_dmaBuff[4] = {20000, 30000, 40000, 50000};
            uint16_t tim2_dmaBuff[4] = {20000, 30000, 40000, 50000};
            uint16_t tim3_dmaBuff[4] = {20000, 30000, 40000, 50000};
            uint16_t tim4_dmaBuff[4] = {20000, 30000, 40000, 50000};
            //定时器 1
            void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
            {
            tim1.Instance = TIM1; // 实例
            tim1.Init.Period = arr; // 重装载值
            tim1.Init.Prescaler = psc; // 分频系数
            tim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数模式
            tim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 分频因子
            tim1.Init.RepetitionCounter = rep; // 重复计数值
            tim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;// 自动重装载值 预装载使能位(影子寄存器)
            HAL_TIM_Base_Init(&tim1); //初始化定时器
            __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); //手动 清除 定时器 更新事件
            __HAL_TIM_ENABLE_IT(&tim1, TIM1_UP_IRQn); //手动 使能 定时器 更新中断
            HAL_TIM_Base_Start_DMA(&tim1, (uint32_t*)tim1_dmaBuff, 4); //打开定时器(DMA方式)
            }
            //定时器 2
            void Timer2_Init(uint16_t arr, uint16_t psc)
            {
            tim2.Instance = TIM2;
            tim2.Init.Period = arr;
            tim2.Init.Prescaler = psc;
            tim2.Init.CounterMode = TIM_COUNTERMODE_UP;
            tim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            tim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            HAL_TIM_Base_Init(&tim2);
            __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
            __HAL_TIM_ENABLE_IT(&tim2, TIM1_UP_IRQn);
            HAL_TIM_Base_Start_DMA(&tim2, (uint32_t*)tim2_dmaBuff, 4);
            }
            //定时器 3
            void Timer3_Init(uint16_t arr, uint16_t psc)
            {
            tim3.Instance = TIM3;
            tim3.Init.Period = arr;
            tim3.Init.Prescaler = psc;
            tim3.Init.CounterMode = TIM_COUNTERMODE_UP;
            tim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            tim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            HAL_TIM_Base_Init(&tim3);
            __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
            __HAL_TIM_ENABLE_IT(&tim3, TIM1_UP_IRQn);
            HAL_TIM_Base_Start_DMA(&tim3, (uint32_t*)tim3_dmaBuff, 4);
            }
            //定时器 4
            void Timer4_Init(uint16_t arr, uint16_t psc)
            {
            tim4.Instance = TIM4;
            tim4.Init.Period = arr;
            tim4.Init.Prescaler = psc;
            tim4.Init.CounterMode = TIM_COUNTERMODE_UP;
            tim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            tim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            HAL_TIM_Base_Init(&tim4);
            __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
            __HAL_TIM_ENABLE_IT(&tim4, TIM1_UP_IRQn);
            HAL_TIM_Base_Start_DMA(&tim4, (uint32_t*)tim4_dmaBuff, 4);
            }
            //定时器 硬件初始化回调函数
            void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            __HAL_RCC_TIM1_CLK_ENABLE(); //使能时钟
            __HAL_RCC_DMA1_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
            HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
            / DMA配置 /
            tim1_dmaup.Instance = DMA1_Channel5;
            tim1_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
            tim1_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
            tim1_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
            tim1_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
            tim1_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim1_dmaup.Init.Mode = DMA_NORMAL; //单次模式
            tim1_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim1, hdma[TIM_DMA_ID_UPDATE], tim1_dmaup);
            HAL_DMA_Init(&tim1_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
            }else if(htim->Instance == TIM2){
            __HAL_RCC_TIM2_CLK_ENABLE();
            __HAL_RCC_DMA1_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM2_IRQn);
            / DMA配置 /
            tim2_dmaup.Instance = DMA1_Channel2;
            tim2_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
            tim2_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
            tim2_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
            tim2_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
            tim2_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim2_dmaup.Init.Mode = DMA_NORMAL; //单次模式
            tim2_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim2, hdma[TIM_DMA_ID_UPDATE], tim2_dmaup);
            HAL_DMA_Init(&tim2_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
            }else if(htim->Instance == TIM3){
            __HAL_RCC_TIM3_CLK_ENABLE();
            __HAL_RCC_DMA1_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM3_IRQn);
            / DMA配置 /
            tim3_dmaup.Instance = DMA1_Channel3;
            tim3_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
            tim3_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
            tim3_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
            tim3_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
            tim3_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim3_dmaup.Init.Mode = DMA_NORMAL; //单次模式
            tim3_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim3, hdma[TIM_DMA_ID_UPDATE], tim3_dmaup);
            HAL_DMA_Init(&tim3_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
            }else if(htim->Instance == TIM4){
            __HAL_RCC_TIM4_CLK_ENABLE();
            __HAL_RCC_DMA1_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM4_IRQn);
            / DMA配置 /
            tim4_dmaup.Instance = DMA1_Channel7;
            tim4_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
            tim4_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
            tim4_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
            tim4_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
            tim4_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim4_dmaup.Init.Mode = DMA_NORMAL; //单次模式
            tim4_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim4, hdma[TIM_DMA_ID_UPDATE], tim4_dmaup);
            HAL_DMA_Init(&tim4_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
            }
            }
            //定时器 硬件 De 回调函数
            void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            __HAL_RCC_TIM1_CLK_DISABLE();
            }else if(htim->Instance == TIM2){
            __HAL_RCC_TIM2_CLK_DISABLE();
            }else if(htim->Instance == TIM3){
            __HAL_RCC_TIM3_CLK_DISABLE();
            }else if(htim->Instance == TIM4){
            __HAL_RCC_TIM4_CLK_DISABLE();
            }
            }
            //更新中断 回调函数(同时也是DMA完成的回调函数)
            uint16_t time1 = 1;
            uint16_t time2 = 1;
            uint16_t time3 = 1;
            uint16_t time4 = 1;
            void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            / 判断DMA是否为Ready状态,如果是则是DMA完成中断进入的回调函数 /
            if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA1 完成中断rn");
            HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
            }else{
            U1_Printf("定时器 1 定时时间:%drn",time1++);
            if(time1 >= 6){ //大于等于6 则关闭
            U1_Printf("定时器1 关闭rn");
            HAL_TIM_Base_Stop_DMA(htim);
            HAL_TIM_Base_DeInit(htim);
            }
            }
            }else if(htim->Instance == TIM2){
            if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA2 完成中断rn");
            HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
            }else{
            U1_Printf("定时器 2 定时时间:%drn",time2++);
            if(time2 >= 6){ //大于等于6 则关闭
            U1_Printf("定时器2 关闭rn");
            HAL_TIM_Base_Stop_DMA(htim);
            HAL_TIM_Base_DeInit(htim);
            }
            }
            }else if(htim->Instance == TIM3){
            if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA3 完成中断rn");
            HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
            }else{
            U1_Printf("定时器 3 定时时间:%drn",time3++);
            if(time3 >= 6){ //大于等于6 则关闭
            U1_Printf("定时器3 关闭rn");
            HAL_TIM_Base_Stop_DMA(htim);
            HAL_TIM_Base_DeInit(htim);
            }
            }
            }else if(htim->Instance == TIM4){
            if(htim->hdma[TIM_DMA_ID_UPDATE]->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA4 完成中断rn");
            HAL_DMA_DeInit(htim->hdma[TIM_DMA_ID_UPDATE]); //关闭DMA
            }else{
            U1_Printf("定时器 4 定时时间:%drn",time4++);
            if(time4 >= 6){ //大于等于6 则关闭
            U1_Printf("定时器4 关闭rn");
            HAL_TIM_Base_Stop_DMA(htim);
            HAL_TIM_Base_DeInit(htim);
            }
            }
            }
            }
            //DMA 半完成回调函数
            void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            U1_Printf("定时器 1 DMA半完成中断rn");
            }else if(htim->Instance == TIM2){
            U1_Printf("定时器 2 DMA半完成中断rn");
            }else if(htim->Instance == TIM3){
            U1_Printf("定时器 3 DMA半完成中断rn");
            }else if(htim->Instance == TIM4){
            U1_Printf("定时器 4 DMA半完成中断rn");
            }
            }
            #ifndef __TIME_H
            #define __TIME_H
            #include "uart.h"
            / 对外声明总控结构体 /
            extern TIM_HandleTypeDef tim1;
            extern TIM_HandleTypeDef tim2;
            extern TIM_HandleTypeDef tim3;
            extern TIM_HandleTypeDef tim4;
            extern DMA_HandleTypeDef tim1_dmaup;
            extern DMA_HandleTypeDef tim2_dmaup;
            extern DMA_HandleTypeDef tim3_dmaup;
            extern DMA_HandleTypeDef tim4_dmaup;
            / 初始化函数 /
            void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
            void Timer2_Init(uint16_t arr, uint16_t psc);
            void Timer3_Init(uint16_t arr, uint16_t psc);
            void Timer4_Init(uint16_t arr, uint16_t psc);
            #endif
            /-------------------------------------------------/
            / /
            / 实现各种中断服务函数的源文件 /
            / /
            /-------------------------------------------------/
            #include "stm32f1xx_hal.h"
            #include "stm32f1xx_it.h"
            #include "uart.h"
            #include "time.h"
            void EXTI15_10_IRQHandler(void)
            {
            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
            }
            void EXTI0_IRQHandler(void)
            {
            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
            }
            void USART1_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart1.uart);
            if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
            uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
            HAL_UART_AbortReceive_IT(&uart1.uart);
            }
            }
            void USART2_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart2.uart);
            if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
            uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
            HAL_UART_AbortReceive_IT(&uart2.uart);
            }
            }
            void USART3_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart3.uart);
            if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
            uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
            HAL_UART_AbortReceive_IT(&uart3.uart);
            }
            }
            void DMA1_Channel4_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart1.dmatx);
            }
            //void DMA1_Channel5_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart1.dmarx);
            //}
            //void DMA1_Channel7_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart2.dmatx);
            //}
            void DMA1_Channel6_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart2.dmarx);
            }
            //void DMA1_Channel2_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart3.dmatx);
            //}
            //void DMA1_Channel3_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart3.dmarx);
            //}
            void DMA1_Channel5_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim1_dmaup);
            }
            void DMA1_Channel2_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim2_dmaup);
            }
            void DMA1_Channel3_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim3_dmaup);
            }
            void DMA1_Channel7_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim4_dmaup);
            }
            void TIM1_UP_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim1);
            }
            void TIM2_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim2);
            }
            void TIM3_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim3);
            }
            void TIM4_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim4);
            }
            /-------------------------------------------------/
            /函数名:不可屏蔽中断处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void NMI_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:硬件出错后进入的中断处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void HardFault_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:软中断,SWI 指令调用的处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void SVC_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:可挂起的系统服务处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void PendSV_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:SysTic系统嘀嗒定时器处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void SysTick_Handler(void)
            {
            HAL_IncTick();
            }
            #include "stm32f1xx_hal.h"
            #include "rcc.h"
            #include "led.h"
            #include "sw.h"
            #include "uart.h"
            #include "time.h"
            int main(void){
            HAL_Init();
            RccClock_Init();
            U1_Init(921600);
            Timer1_Init(10000 - 1, 7200 - 1, 1 - 1); // 72000000/7200/10000 = 1s
            Timer2_Init(10000 - 1, 7200 - 1); // 1s
            Timer3_Init(10000 - 1, 7200 - 1); // 1s
            Timer4_Init(10000 - 1, 7200 - 1); // 1s
            // uint16_t time1 = 0;
            // uint16_t time2 = 0;
            // uint16_t time3 = 0;
            // uint16_t time4 = 0;
            while(1){
            / 获取更新标志位 /
            // if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); ///清除标志位
            // U1_Printf("定时器 1 定时时间:%drn",time1++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim2, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 2 定时时间:%drn",time2++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim3, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 3 定时时间:%drn",time3++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim4, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 4 定时时间:%drn",time4++);
            // }
            }
            }
            DMA循环方式,传输4次*n数据,改变定时时间:第一次定时1s(初始化),第二次定时2s,第三次定时3s,第四次定时4s第五次定时5s,然后第六次 2s,第七次3s,第八次4s,第、九次5s,第十次2s

            2. 如何判断DMA中断还是更新中断*

            1. 上一小节所说:DMA有半完成回调 和 完成回调
                • 其中完成回调,和定时器更新回调的函数是一个函数
                • 所以,如果要使用更新中断和DMA完成中断,则需要判断一下。
                  • 方法:通过判断DMA的状态,如果为Busy,则说明是更新中断进入的 定时器更新回调函数
            1. 那么在这一节是行不通的,因为DMA一直在循环模式,一直处于BUSY状态,所以不能判断了。但是 DMA的半完成中断和完成中断,在进入回调函数之前 就会把定时器设置成Ready状态,定时器更新中断 并不会设置定时器的状态为Ready。
                • 所以,着急需要判断定时器的更新中断,就可以判断这次中断是更新中断还是 DMA的中断。
                • 并且,判断过后,需要把定时器状态重新赋值为 BUSY, 这样是为了防止更新中断在进入时,仍然进入DMA完成的分支
                代码节选

            4. 相关函数

            • TIM_HandleTypeDef 定时器总控结构体
            • DMA_HandleTypeDef DMA总控结构体
            • __HAL_TIM_CLEAR_FLAG 清除标志位
            • __HAL_TIM_ENABLE_IT 使能中断
            • HAL_TIM_Base_Start_DMA DMA方式启动定时器
            • __HAL_LINKDMA DMA LINK

            4. 程序

            time.c

            HAL_NVIC_SetPriority(TIM1_UP_IRQn, 3, 0); //配置、打开 更新中断
            HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
            / DMA配置 /
            tim1_dmaup.Instance = DMA1_Channel5;
            tim1_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH; //存储区到外设
            tim1_dmaup.Init.MemInc = DMA_MINC_ENABLE; //存储区递增
            tim1_dmaup.Init.PeriphInc = DMA_PINC_DISABLE; //外设不递增
            tim1_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //半字 2字节
            tim1_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim1_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
            tim1_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim1, hdma[TIM_DMA_ID_UPDATE], tim1_dmaup);
            HAL_DMA_Init(&tim1_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
            }else if(htim->Instance == TIM2){
            __HAL_RCC_TIM2_CLK_ENABLE();
            __HAL_RCC_DMA1_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM2_IRQn);
            / DMA配置 /
            tim2_dmaup.Instance = DMA1_Channel2;
            tim2_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
            tim2_dmaup.Init.MemInc = DMA_MINC_ENABLE;
            tim2_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
            tim2_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
            tim2_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim2_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
            tim2_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim2, hdma[TIM_DMA_ID_UPDATE], tim2_dmaup);
            HAL_DMA_Init(&tim2_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
            }else if(htim->Instance == TIM3){
            __HAL_RCC_TIM3_CLK_ENABLE();
            __HAL_RCC_DMA1_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM3_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM3_IRQn);
            / DMA配置 /
            tim3_dmaup.Instance = DMA1_Channel3;
            tim3_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
            tim3_dmaup.Init.MemInc = DMA_MINC_ENABLE;
            tim3_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
            tim3_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
            tim3_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim3_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
            tim3_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim3, hdma[TIM_DMA_ID_UPDATE], tim3_dmaup);
            HAL_DMA_Init(&tim3_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
            }else if(htim->Instance == TIM4){
            __HAL_RCC_TIM4_CLK_ENABLE();
            __HAL_RCC_DMA1_CLK_ENABLE();
            HAL_NVIC_SetPriority(TIM4_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(TIM4_IRQn);
            / DMA配置 /
            tim4_dmaup.Instance = DMA1_Channel7;
            tim4_dmaup.Init.Direction = DMA_MEMORY_TO_PERIPH;
            tim4_dmaup.Init.MemInc = DMA_MINC_ENABLE;
            tim4_dmaup.Init.PeriphInc = DMA_PINC_DISABLE;
            tim4_dmaup.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
            tim4_dmaup.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            tim4_dmaup.Init.Mode = DMA_CIRCULAR; //循环模式
            tim4_dmaup.Init.Priority = DMA_PRIORITY_MEDIUM;
            __HAL_LINKDMA(&tim4, hdma[TIM_DMA_ID_UPDATE], tim4_dmaup);
            HAL_DMA_Init(&tim4_dmaup);
            HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 3, 0); //配置、打开 通道5的中断
            HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
            }
            }
            //定时器 硬件 De 回调函数
            void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            __HAL_RCC_TIM1_CLK_DISABLE();
            }else if(htim->Instance == TIM2){
            __HAL_RCC_TIM2_CLK_DISABLE();
            }else if(htim->Instance == TIM3){
            __HAL_RCC_TIM3_CLK_DISABLE();
            }else if(htim->Instance == TIM4){
            __HAL_RCC_TIM4_CLK_DISABLE();
            }
            }
            //更新中断 回调函数(同时也是DMA完成的回调函数)
            uint16_t time1 = 1;
            uint16_t time2 = 1;
            uint16_t time3 = 1;
            uint16_t time4 = 1;
            void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            / 判断TIM是否为Ready状态,如果是 则是DMA完成中断进入的回调函数 /
            if(htim->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA1 完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }else{
            U1_Printf("定时器 1 定时时间:%drn",time1++);
            }
            }else if(htim->Instance == TIM2){
            if(htim->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA2 完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }else{
            U1_Printf("定时器 2 定时时间:%drn",time2++);
            }
            }else if(htim->Instance == TIM3){
            if(htim->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA3 完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }else{
            U1_Printf("定时器 3 定时时间:%drn",time3++);
            }
            }else if(htim->Instance == TIM4){
            if(htim->State == HAL_DMA_STATE_READY){
            U1_Printf("DMA4 完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }else{
            U1_Printf("定时器 4 定时时间:%drn",time4++);
            }
            }
            }
            //DMA 半完成回调函数
            void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
            {
            if(htim->Instance == TIM1){
            U1_Printf("定时器 1 DMA半完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }else if(htim->Instance == TIM2){
            U1_Printf("定时器 2 DMA半完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }else if(htim->Instance == TIM3){
            U1_Printf("定时器 3 DMA半完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }else if(htim->Instance == TIM4){
            U1_Printf("定时器 4 DMA半完成中断rn");
            htim->State = HAL_TIM_STATE_BUSY; //设置定时器 BUSY状态
            }
            }
            #ifndef __TIME_H
            #define __TIME_H
            #include "uart.h"
            / 对外声明总控结构体 /
            extern TIM_HandleTypeDef tim1;
            extern TIM_HandleTypeDef tim2;
            extern TIM_HandleTypeDef tim3;
            extern TIM_HandleTypeDef tim4;
            extern DMA_HandleTypeDef tim1_dmaup;
            extern DMA_HandleTypeDef tim2_dmaup;
            extern DMA_HandleTypeDef tim3_dmaup;
            extern DMA_HandleTypeDef tim4_dmaup;
            / 初始化函数 /
            void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep);
            void Timer2_Init(uint16_t arr, uint16_t psc);
            void Timer3_Init(uint16_t arr, uint16_t psc);
            void Timer4_Init(uint16_t arr, uint16_t psc);
            #endif
            /-------------------------------------------------/
            / /
            / 实现各种中断服务函数的源文件 /
            / /
            /-------------------------------------------------/
            #include "stm32f1xx_hal.h"
            #include "stm32f1xx_it.h"
            #include "uart.h"
            #include "time.h"
            void EXTI15_10_IRQHandler(void)
            {
            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
            }
            void EXTI0_IRQHandler(void)
            {
            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
            }
            void USART1_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart1.uart);
            if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
            uart1.RxCounter += (U1_RX_MAX - __HAL_DMA_GET_COUNTER(&uart1.dmarx));
            HAL_UART_AbortReceive_IT(&uart1.uart);
            }
            }
            void USART2_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart2.uart);
            if(__HAL_UART_GET_FLAG(&uart2.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart2.uart);
            uart2.RxCounter += (U2_RX_MAX - __HAL_DMA_GET_COUNTER(&uart2.dmarx));
            HAL_UART_AbortReceive_IT(&uart2.uart);
            }
            }
            void USART3_IRQHandler(void)
            {
            HAL_UART_IRQHandler(&uart3.uart);
            if(__HAL_UART_GET_FLAG(&uart3.uart, UART_FLAG_IDLE)){
            __HAL_UART_CLEAR_IDLEFLAG(&uart3.uart);
            uart3.RxCounter += (U3_RX_MAX - __HAL_DMA_GET_COUNTER(&uart3.dmarx));
            HAL_UART_AbortReceive_IT(&uart3.uart);
            }
            }
            void DMA1_Channel4_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart1.dmatx);
            }
            //void DMA1_Channel5_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart1.dmarx);
            //}
            //void DMA1_Channel7_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart2.dmatx);
            //}
            void DMA1_Channel6_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&uart2.dmarx);
            }
            //void DMA1_Channel2_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart3.dmatx);
            //}
            //void DMA1_Channel3_IRQHandler(void)
            //{
            // HAL_DMA_IRQHandler(&uart3.dmarx);
            //}
            void DMA1_Channel5_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim1_dmaup);
            }
            void DMA1_Channel2_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim2_dmaup);
            }
            void DMA1_Channel3_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim3_dmaup);
            }
            void DMA1_Channel7_IRQHandler(void)
            {
            HAL_DMA_IRQHandler(&tim4_dmaup);
            }
            void TIM1_UP_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim1);
            }
            void TIM2_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim2);
            }
            void TIM3_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim3);
            }
            void TIM4_IRQHandler(void)
            {
            HAL_TIM_IRQHandler(&tim4);
            }
            /-------------------------------------------------/
            /函数名:不可屏蔽中断处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void NMI_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:硬件出错后进入的中断处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void HardFault_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:软中断,SWI 指令调用的处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void SVC_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:可挂起的系统服务处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void PendSV_Handler(void)
            {
            }
            /-------------------------------------------------/
            /函数名:SysTic系统嘀嗒定时器处理函数 /
            /参 数:无 /
            /返回值:无 /
            /-------------------------------------------------/
            void SysTick_Handler(void)
            {
            HAL_IncTick();
            }
            #include "stm32f1xx_hal.h"
            #include "rcc.h"
            #include "led.h"
            #include "sw.h"
            #include "uart.h"
            #include "time.h"
            int main(void){
            HAL_Init();
            RccClock_Init();
            U1_Init(921600);
            Timer1_Init(10000 - 1, 7200 - 1, 1 - 1); // 72000000/7200/10000 = 1s
            Timer2_Init(10000 - 1, 7200 - 1); // 1s
            Timer3_Init(10000 - 1, 7200 - 1); // 1s
            Timer4_Init(10000 - 1, 7200 - 1); // 1s
            // uint16_t time1 = 0;
            // uint16_t time2 = 0;
            // uint16_t time3 = 0;
            // uint16_t time4 = 0;
            while(1){
            / 获取更新标志位 /
            // if(__HAL_TIM_GET_FLAG(&tim1, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim1, TIM_FLAG_UPDATE); ///清除标志位
            // U1_Printf("定时器 1 定时时间:%drn",time1++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim2, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim2, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 2 定时时间:%drn",time2++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim3, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim3, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 3 定时时间:%drn",time3++);
            // }
            //
            // if(__HAL_TIM_GET_FLAG(&tim4, TIM_FLAG_UPDATE)){
            // __HAL_TIM_CLEAR_FLAG(&tim4, TIM_FLAG_UPDATE);
            // U1_Printf("定时器 4 定时时间:%drn",time4++);
            // }
            }
            }
            上一篇
            ESP8266模块学习
            下一篇
            STM32-标准库学习笔记

            评论
            Loading...