一、串口介绍

串口设置包含:开启串口时钟、设置响应的IO口模式、设置波特率、数据位长度、奇偶校验位、DMA等信息。
具体参看:STM32开发 – 串口详解

二、函数

1、串口参数初始化,并使能串口。

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);

该函数只有一个入口参数 huart,为UART_HandleTypeDef 结构体指针类型,我们俗称其为串口句柄,它的使用会贯穿整个串口程序。一般情况下,我们会定义一个UART_HandleTypeDef 结构体类型全局变量,然后初始化各个成员变量。
结构体UART_HandleTypeDef 定义:

/*** @brief  UART handle Structure definition*/
typedef struct __UART_HandleTypeDef
{USART_TypeDef                 *Instance;        /*!< UART registers base address        */UART_InitTypeDef              Init;             /*!< UART communication parameters      */uint8_t                       *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */__IO uint16_t                 TxXferCount;      /*!< UART Tx Transfer Counter           */uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */__IO uint16_t                 RxXferCount;      /*!< UART Rx Transfer Counter           */DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      */DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */HAL_LockTypeDef               Lock;             /*!< Locking object                     */__IO HAL_UART_StateTypeDef    gState;           /*!< UART state information related to global Handle managementand also related to Tx operations.This parameter can be a value of @ref HAL_UART_StateTypeDef */__IO HAL_UART_StateTypeDef    RxState;          /*!< UART state information related to Rx operations.This parameter can be a value of @ref HAL_UART_StateTypeDef */__IO uint32_t                 ErrorCode;        /*!< UART Error code                    */
} UART_HandleTypeDef;

该结构体成员变量非常多,一般情况下下载调用函数HAL_UART_Init对串口进行初始化的时候,我们只需要先设置Instance和Init两个成员变量的值。
Instance 是 USART_TypeDef 结构体指针类型的变量,它是执行寄存器基地址,实际上这个基地址HAL库已经定义好了,如果是串口1,取值为USART1即可。
Init是UART_InitTypeDef 结构体类型变量,它是用来设置串口的各个参数,包括波特率、停止位等。
UART_InitTypeDef 结构体定义如下:

typedef struct
{uint32_t BaudRate;                  /*!< This member configures the UART communication baud rate.The baud rate is computed using the following formula:- IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (huart->Init.BaudRate)))- FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 8 * (OVR8+1)) + 0.5Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */uint32_t WordLength;                /*!< Specifies the number of data bits transmitted or received in a frame.This parameter can be a value of @ref UART_Word_Length */uint32_t StopBits;                  /*!< Specifies the number of stop bits transmitted.This parameter can be a value of @ref UART_Stop_Bits */uint32_t Parity;                    /*!< Specifies the parity mode.This parameter can be a value of @ref UART_Parity@note When parity is enabled, the computed parity is insertedat the MSB position of the transmitted data (9th bit whenthe word length is set to 9 data bits; 8th bit when theword length is set to 8 data bits). */uint32_t Mode;                      /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.This parameter can be a value of @ref UART_Mode */uint32_t HwFlowCtl;                 /*!< Specifies whether the hardware flow control mode is enabled or disabled.This parameter can be a value of @ref UART_Hardware_Flow_Control */uint32_t OverSampling;              /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8).This parameter can be a value of @ref UART_Over_Sampling */
} UART_InitTypeDef;

BaudRate: 为串口波特率,用来确定串口通信的速率 。
WordLength: 为字长,可以设置8位字长或者9位字长。我们设置为 8 位字长数据格式 UART_WORDLENGTH_8B。
StopBits: 为停止位,可以设置为1个停止位或者2个停止位。我们设置为1个停止位 UART_STOPBITS_1。
Parity: 为是否需要奇偶校验,我们设定为无奇偶校 UART_PARITY_NONE。
Mode: 为串口模式,可以设置为只收模式、只发模式或者收发模式。我们设置为全双工收发模式 UART_MODE_TX_RX。
HwFlowCtl: 为是否支持硬件流控制,我们设置为无硬件流控制 UART_HWCONTROL_NONE。
pTxBuffPtr, TxXferSize 和 TxXferCount 三个变量分别用来设置串口发送的数据缓存指针,发送的数据量和还剩余的要发送的数据量。
pRxBuffPtr, RxXferSize 和RxXferCount 三个变量则是用来设置接收的数据缓存指针,接收的最大数据量以及还剩余的要接收的数据量。
hdmatx 和 hdmarx 是串口 DMA 相关的变量,指向 DMA 句柄。

函数 HAL_UART_Init 使用的一般格式为:

UART_HandleTypeDef UART1_Handler; //UART 句柄
UART1_Handler.Instance=USART1; //USART1
UART1_Handler.Init.BaudRate=115200; //波特率
UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为 8 位格式
UART1_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能 UART1

需要说明的是,函数HAL_UART_Init内部会调用串口使能函数使能相应串口,所以调用了该函数之后我们就不需要重复使能串口了。当然,HAL库也提供了具体的串口使能和失能的方法,具体使用方法如下:

__HAL_UART_ENABLE(handler); //使能句柄 handler 指定的串口
__HAL_UART_DISABLE(handler); //关闭句柄 handler 指定的串口

这里还需要注意,串口作为一个重要的外设,在调用的初始化函数HAL_UART_Init内部,会先调用MSP初始化回调函数进行MCU相关的初始化,函数为:

void HAL_UART_MspInit(UART_HandleTypeDef *huart);

我们的程序中,只需要重写该函数即可。一般情况下,该函数内部用来编写IO初始化,时钟使能以及NVIC配置。

2、使能串口和GPIO时钟

我们要使用串口,所以我们必须使能串口时钟和使用到的GPIO口的时钟。具体方法:

__HAL_RCC_USART1_CLK_ENABLE(); //使能 USART1 时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能 GPIOA 时钟

3、GPIO口初始化设置,以及复位映射配置

参看:STM32F4 HAL库开发 – GPIO

4、开启串口相关中断,配置串口中断优先级

__HAL_UART_ENABLE_IT 使能串口中断的标识符。
示例:

__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE); //开启接收完成中断

第一个参数:为串口句柄,类型为UART_HandleTypeDef 结构体类型。
第二个参数:为我们要开启的中断类型值。

#define UART_IT_PE                       ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_PEIE))
#define UART_IT_TXE                      ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TXEIE))
#define UART_IT_TC                       ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TCIE))
#define UART_IT_RXNE                     ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE))
#define UART_IT_IDLE                     ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE))

有开启中断就有关闭中断,操作方法为:

__HAL_UART_DISABLE_IT(huart,UART_IT_RXNE); //关闭接收完成中断

对于中断优先级配置,参考方法为:

HAL_NVIC_EnableIRQ(USART1_IRQn); //使能 USART1 中断通道
HAL_NVIC_SetPriority(USART1_IRQn,3,3); //抢占优先级 3,子优先级 3

5、编写中断服务函数

串口1中断服务函数为:

void USART1_IRQHandler(void) ;

当发生中断的时候,程序就会执行中断服务函数。然后我们在中断服务函数中编写相应的逻辑代码即可。

6、串口数据接收和发送

HAL 库操作 USART_DR 寄存器发送数据的函数是:

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size, uint32_t Timeout);

通过该函数向串口寄存器 USART_DR 写入一个数据。

HAL 库操作 USART_DR 寄存器读取串口接收到的数据的函数是:

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size, uint32_t Timeout);

通过该函数可以读取串口接受到的数据。

7、DMA配置

参看:STM32F4 HAL库开发 – DMA

三、STM32CubeMX 配置串口

1、配置

打开 Pinout选项卡界面,左侧依次进入 Categories->Connectivity->USART1 配置栏。

配置栏有2个选项
**Mode:**用来设置串口的模式或者关闭串口

Asynchronous:异步
Synchronous:同步
Single Wire(Half-Duplex):单线(半双工)
Multiprocessor Communication:多处理器通信

这里我们要开启串口的异步模式,选择Mode值为 Asynchronous。

Hardware Flow Control(RS232): 用来开启/关闭串口的硬件控制流。
该选项只有在Mode选项值为 Asynchronous(异步通信)模式的前提下才有效。

选择收发引脚:

在GPIO->USART里就可以看到新添加的USART1_TX和USART1_RX。

配置栏有一下几个选项:
GPIO mode:
Altemate Fuction Push Pull (复用推挽)
GPIO Pull-up/Pull-down:
Pull-up (上拉)
Maximum output speed:
Very High(速度)

再次打开进入 Categories->Connectivity->USART1 配置栏

下半部分可以看到:
Parameter Settings:
包含波特率、数据位、奇偶校验位、停止位、使能收发模式、过采样等设置。
我们将 USART1 配置为:波特率 115200, 8 位字长模式,无奇偶校验位, 1 个停止位,发送/接收均开启。

DMA settings:
可以点击Add,添加USART1_RX 和 USART1_TX。
可以选择,Priority 优先级。
在 DMA Request Settings,也可以进行设置。

NVIC Settings:
配置完DMA后,在打开NVIC Settings,就可以看到 DMA的使能是选中的。
这里我们勾选 USART1 global interrupt 的中断使能。

2、生成源码

MX_USART1_UART_Init 函数

void MX_USART1_UART_Init(void)
{huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}}

HAL_UART_MspInit 函数

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**USART1 GPIO ConfigurationPB6     ------> USART1_TXPB7     ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF7_USART1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* USART1 DMA Init *//* USART1_RX Init */hdma_usart1_rx.Instance = DMA2_Stream2;hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_rx.Init.Mode = DMA_NORMAL;hdma_usart1_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);/* USART1_TX Init */hdma_usart1_tx.Instance = DMA2_Stream7;hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_tx.Init.Mode = DMA_NORMAL;hdma_usart1_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}}

HAL_UART_MspDeInit 函数

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPB6     ------> USART1_TXPB7     ------> USART1_RX*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);/* USART1 DMA DeInit */HAL_DMA_DeInit(uartHandle->hdmarx);HAL_DMA_DeInit(uartHandle->hdmatx);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}

DMA中断:

void DMA2_Stream2_IRQHandler(void)
{/* USER CODE BEGIN DMA2_Stream2_IRQn 0 *//* USER CODE END DMA2_Stream2_IRQn 0 */HAL_DMA_IRQHandler(&hdma_usart1_rx);/* USER CODE BEGIN DMA2_Stream2_IRQn 1 *//* USER CODE END DMA2_Stream2_IRQn 1 */
}void DMA2_Stream7_IRQHandler(void)
{/* USER CODE BEGIN DMA2_Stream7_IRQn 0 *//* USER CODE END DMA2_Stream7_IRQn 0 */HAL_DMA_IRQHandler(&hdma_usart1_tx);/* USER CODE BEGIN DMA2_Stream7_IRQn 1 *//* USER CODE END DMA2_Stream7_IRQn 1 */
}

中断和接收数据处理:

void USART1_IRQHandler(void)
{THC_LiquidCooled_Handler();
}void THC_LiquidCooled_Handler (void)
{HAL_UART_IRQHandler(&DEF_UART_LIQUID);if(RESET != __HAL_UART_GET_FLAG(&DEF_UART_LIQUID, UART_FLAG_IDLE)){__HAL_UART_CLEAR_IDLEFLAG(&DEF_UART_LIQUID);  //清除标志位HAL_UART_DMAStop(&DEF_UART_LIQUID);METERComm.Rbuf_CNT =  LIQUID_BUF_RXD_SIZE - __HAL_DMA_GET_COUNTER(&DEF_HDMA_LIQUID_RX);HAL_UART_Receive_DMA(&DEF_UART_LIQUID,RLIQUIDBuf,LIQUID_BUF_RXD_SIZE);}
}void CheckLIQUID_RBuf_Fun(void)
{if(LIQUIDComm.Rbuf_CNT != 0){//判断帧头、帧尾、BCC校验u16 LenBuf;u16 onePackageLen = 0;u16 onePackageBodyLen = 0;int16_t onePackageBodyCrc = 0;LenBuf = (LIQUIDComm.Rbuf_CNT & (LIQUID_BUF_RXD_SIZE - 1));if ((RLIQUIDBuf[0] == 0x01) &&  (RLIQUIDBuf[1] == 0x03)){onePackageBodyLen = RLIQUIDBuf[2];onePackageLen = onePackageBodyLen + 5; //包含 子机地址、功能码、读取字节数、CRC码if( onePackageLen <= LenBuf ){onePackageBodyCrc=RLIQUIDBuf[onePackageLen-2] + ((RLIQUIDBuf[onePackageLen-1]<<8)&0xff00); //校验码反着的if( onePackageBodyCrc == Check_CRC16(RLIQUIDBuf, onePackageBodyLen+3) ){THC_LIQUID_Receive(RLIQUIDBuf+3, onePackageBodyLen);memset(RLIQUIDBuf,'\0', LIQUID_BUF_RXD_SIZE); //收到一帧以后,清空bufLIQUIDComm.Rbuf_CNT = 0;}}}}
}

四、485通讯

485通讯还需要有一个cs引脚配置。

// RS485 发送
#define LIQUID_RS485_T   (HAL_GPIO_WritePin(LIQUIDCOOLED_GPIO_Port, LIQUIDCOOLED_485CK_Pin, GPIO_PIN_SET))
//RS485 接收
#define LIQUID_RS485_R   (HAL_GPIO_WritePin(LIQUIDCOOLED_GPIO_Port, LIQUIDCOOLED_485CK_Pin, GPIO_PIN_RESET))

发送数据:

void LIQUID_RS485_Send_Data(u8 *pdata,u32 data_size)
{LIQUID_RS485_T;//RS485 发送HAL_UART_Transmit(&DEF_UART_LIQUID,pdata,data_size,1000);LIQUID_RS485_R;//RS485 接收
}

五、使能

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);     //uart使能idle中断
HAL_UART_Receive_DMA(&huart1,USART_RX_BUF1,USART_REC_LEN);//打开DMA接收,数据存入rx_buffer数组中。

六、接线

RS485:

RS485通信的时候,必须A接A,B接B,否则通信不正常。

RS232:

RS232通信的时候,Rx接Tx,Tx接Rx。

STM32F4 HAL库开发 -- 串口相关推荐

  1. STM32F4 HAL库开发 -- 工程模板解读

    一.关键文件介绍 1.HAL库关键文件 stm32f4xx_hal_ppp.c/.h 基本外设的操作API,ppp代表任意外设.其中stm32f4xx_hal_cortex.c/.h比较特殊,它是一些 ...

  2. STM32F4 HAL库开发 -- 温度传感器(DS18B20)

    参看:<嵌入式-STM32开发指南>第三部分 外设篇 - 第2章 温度传感器DS18B20 这篇文章讲的非常详细了. 一.简介 1.概述 DS18B20 是 DALLAS 最新单线数字温度 ...

  3. STM32F4 HAL库开发 -- 独立看门狗(IWDG)

    之前讲过看门狗,参看:STM32开发 – 看门狗详解 一.HAL库配置独立看门狗步骤 1.取消寄存器写保护,设置看门狗预分频系数和重装载值. 首先我们必须取消 IWDG_PR和 IWDG_RLR寄存器 ...

  4. STM32F4 HAL库开发 -- DMA

    一.DMA简介 DMA之前有讲过,参看:STM32开发 – DMA详解 DMA,全称为Direct Memory Access,即直接存储器访问.DMA传输方式无需CPU直接控制传输,也没有中断处理方 ...

  5. STM32F4 HAL库开发 --时钟使能和配置

    在STM32F4的HAL库中,外设时钟使能操作都是在RCC相关固件库文件头文件stm32f4xx_hal_rcc.h 定义的.外设时钟使能在HAL库中都是通过宏定义标识符来实现.首先,我们来看看GPI ...

  6. STM32F4 HAL库开发 -- GPIO

    这种外设都之前都讲过了,专栏:stm32库开发实战指南. 但是使用STM32CubeMX该配置配置呢??接下来看一下. 一.GPIO简介 STM32F4 的 IO 可以由软件配置成如下 8 种模式中的 ...

  7. STM32F4 HAL库开发 -- STM32CubeMX

    一.STM32CubeMX 简介 STM32CubeMX 是 ST 意法半导体近几年来大力推荐的 STM32 芯片图形化配置工具, 允许用户使用图形化向导生成 C 初始化代码,可以大大减轻开发工作,时 ...

  8. STM32F4 HAL库开发 -- 再识

    之前开发都是基于STM32F105 和 STM32F429,使用的是标准库,操作系统是UCOSII操作系统的. 新入职公司,使用的是STM32F407 和 STM32F429,使用的是HAL库的,国产 ...

  9. STM32F4 HAL库开发 -- 新建基于 HAL 库的工程模板

    一.STM32CubeF4 固件包下载 下载:STM32CubeF4 MCU Firmware Package 二.新建基于 HAL 库的工程模板 1.新建文件夹 建立一个文件夹为 Template. ...

最新文章

  1. sqlserver中如何实现时间按月,日,小时分组查询
  2. 句柄(Handle)
  3. apache属于什么类型的软件
  4. 电脑销售技巧_汝州市,如何查询楼盘详细销售数据?官方公布,精确到房间
  5. 浅析Java各种变量线程安全问题
  6. CentOS 7 安装MySQL 5.6遇到问题及解决方案
  7. 双子座|双子座性格分析
  8. 【机器学习】NMF(非负矩阵分解)
  9. Mac鼠标增强软件Bettertouchtool
  10. Swap file “*.swp“ already exists!的解决方法
  11. Android 中定义图片的资源文件
  12. 数据可视化8_数据分析的一般流程
  13. canva五角星空html,使用canvas绘制一个五角星
  14. PHP接口API文档转换SDK【神器】
  15. java中Scanner类用法的详解
  16. win10打开telnet客户端
  17. vue计算属性与监视属性
  18. Matlab矩阵论矩阵分析计算实现(四)求史密斯标准型和约当标准型
  19. Codex Network经济模型篇 (PoA、PoV、CPoA)
  20. python gui 三维 pyqt5_【PyQt5-Qt Designer】在GUI中使用pyqtgraph绘图库

热门文章

  1. Oracle建立约束、删除约束
  2. 完美解决idea继承maven后,构建项目慢的问题
  3. 简单json语句转化为map保存
  4. 珍惜那些爱你的人,不要令他们失望,加油吧,我们。
  5. 虚成员(virtual)
  6. shfflenetv2代码解读
  7. IEEE conference 中出现的PDF字体嵌入的问题
  8. mysql约束sex_MySQL笔记--约束
  9. 【Matlab】你想知道在图表标题中显示变量的一切
  10. 1.2传值、引用、常量引用