打开主菜单

谷雨文档中心 β

更改

NBDK-L4:基础实验教程

添加36,356字节2019年2月28日 (四) 15:52
无编辑摘要
[[文件:NBDK-SCH-UART-USB.png|边框|居中|无框|707x707像素]]
''<span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span>''
 
''<span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span>''这边给大家简单介绍一下STM32串口USART1和DMA的对应关系,从下面的图中我们可以看到USART1_TX对应DMA的CH4,USART1_RX对应DMA的CH5。
[[文件:NBDK-DS-USARTDMA.png|边框|居中|无框|707x707像素]]
''<span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span>''
 
=== 实验准备 ===
# 使用miniUSB线及10pin排线,通过Jlink仿真器连接PC端和开发板。
=== 实验验证 ===
下载完成后,我们打开miniUSB虚拟出的COM口,按下复位按键,会打印“Uart ISR DMA demo”。我们随意输入一些数据,可以看到STM32串口打印出相同的数据。[[文件:NBDK-XSHELL-UASRTISRUASRTDMA.png|边框|居中|无框|759x759像素]]
=== 源码详解 ===
==== gyu_usart_dma.c ====
串口初始化函数,初始化串口协议部分。<syntaxhighlight lang="c++" line="1" start="66">
void MX_USART1_UART_Init(void)
{
// 配置串口参数
huart1.Instance = USART1; // UART寄存器基础地址,定义为USART1的
huart1.Init.BaudRate = 115200; // 串口波特率为115200
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 串口数据位为8位
huart1.Init.StopBits = UART_STOPBITS_1; // 串口停止位为1位
huart1.Init.Parity = UART_PARITY_NONE; // 串口无校验位
huart1.Init.Mode = UART_MODE_TX_RX; // 串口模式,TX和RX作用
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 串口无流控制
huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 16位过采样
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; // 1位过采样禁能
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; // 没有串口高级功能初始化
// 串口初始化
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__); // 如果初始化失败,进入错误处理任务
}
}
</syntaxhighlight>串口DMA初始化函数,除了使能串口TX及RX引脚时钟,配置这两个引脚状态之外,最主要的还是配置这两个引脚的DMA功能,分别对应我们刚刚在DMA1中初始化的CH4和CH5。<syntaxhighlight lang="c++" line="1" start="95">
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
// 定义GPIO结构体
GPIO_InitTypeDef GPIO_InitStruct;
// 判断选择的是否为USART1
if(uartHandle->Instance==USART1)
{
// 使能GPIOA引脚时钟(因为选择的TX和RX分别为PA9和PA10)
__HAL_RCC_GPIOA_CLK_ENABLE();
// 使能USART1时钟
__HAL_RCC_USART1_CLK_ENABLE();
// GPIO配置
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; // 选择USART1的TX和RX引脚(TX:PA9,RX:PA10)
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 推挽输出
GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;// 引脚频率5-80MHz
GPIO_InitStruct.Alternate = GPIO_AF7_USART1; // 配置为USART1
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化引脚
}
// 配置DMA1 CH5
hdma_usart1_rx.Instance = DMA1_Channel5;
hdma_usart1_rx.Init.Request = DMA_REQUEST_2;
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_HALFWORD;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
// 关联DMA1 CH5 和 串口RX
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
// 配置DMA1 CH4
hdma_usart1_tx.Instance = DMA1_Channel4;
hdma_usart1_tx.Init.Request = DMA_REQUEST_2;
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_LOW;
if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
// 关联DMA1 CH4 和 串口TX
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
// 配置USART1中断
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
</syntaxhighlight>串口DMA初始化(用于在DMA模式下,接收数据)。<syntaxhighlight lang="c++" line="1" start="167">
void HAL_UARTDMA_Init(void)
{
HAL_UART_Receive_DMA(&huart1,UartDma_Init(uart_dma_send,USART1),RECE_BUF_MAX_LEN);
}
</syntaxhighlight><syntaxhighlight lang="c++" line="1" start="181">
void HAL_UART_Write(uint8_t*buf,uint16_t len)
{
UartDma_Write(buf,len);
}
</syntaxhighlight>
==== gyu_usart_dma_ex.c ====
== 实验13-TFT显示屏 ==
 
上一章中,已经给大家简单的展示了如何去配置一个串口,并且格式化输出数据。这一章给大家带来串口中断实验,顾名思义,此实验是使用中断的方式去接收和打印串口数据。
 
=== STM32L476 UART简介 ===
USART主要功能:
 
•全双工异步通信
 
•NRZ标准格式(标记/空格)
 
•可配置的过采样方法16或8,以提供速度和速度之间的灵活性
 
时钟容差
 
•通用可编程发送和接收波特率高达10 Mbit / s时
 
时钟频率为80 MHz,过采样为8
 
•双时钟域允许:
 
- USART功能和从停止模式唤醒
 
- 独立于PCLK重新编程的便捷波特率编程
 
•自动波特率检测
 
•可编程数据字长(7,8或9位)
 
•可编程数据顺序,具有MSB优先或LSB优先移位
 
•可配置的停止位(1或2个停止位)
 
•同步模式和时钟输出,用于同步通信
 
•单线半双工通信
 
•使用DMA进行持续通信
 
•使用集中式DMA将接收/发送的字节缓冲在保留的SRAM中
 
•发送器和接收器的独立使能位
 
•独立的信号极性控制,用于发送和接收
 
•可交换Tx / Rx引脚配置
 
•调制解调器和RS-485收发器的硬件流控制
 
•通信控制/错误检测标志
 
•奇偶校验控制:
 
- 传输奇偶校验位
 
- 检查接收数据字节的奇偶校验
 
•带有标志的14个中断源
 
•多处理器通信
 
如果地址不匹配,USART进入静音模式。
 
•从静音模式唤醒(通过空闲线路检测或地址标记检测)
 
''<span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span>''
=== 硬件设计 ===
选择STM32L4引脚PA9和PA10作为串口,当我们将拨码开关SW1拨到USB一端时,此串口通过CH340芯片转成USB接口,用于同PC端做一些串口数据通信。
[[文件:NBDK-SCH-UART-USB.png|边框|居中|无框|707x707像素]]
''<span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span>''
=== 实验准备 ===
# 使用miniUSB线及10pin排线,通过Jlink仿真器连接PC端和开发板。
# 使用miniUSB线,连接PC与开发板USB接口。
# 将SW1拨到USB端,SW2拨到MCU。
# 使用Keil打开基础实验的实验11-串口中断。
# 使用Xshell打开miniUSB虚拟出的COM口
# 下载程序,并完成功能测试。
 
=== 实验验证 ===
下载完成后,我们打开miniUSB虚拟出的COM口,按下复位按键,会打印“Uart ISR demo”。我们随意输入一些数据,可以看到STM32串口打印出相同的数据。
[[文件:NBDK-XSHELL-UASRTISR.png|边框|居中|无框|759x759像素]]
 
=== 源码详解 ===
本节中的源码说明,仅针对此例程中的重要功能,详细的源码介绍请大家参照代码后的注释。
 
==== stm32l4xx_hal_conf.h ====
此文件位于“实验10-串口打印\Inc”路径中,主要用途是选择使能此例程使用到的库文件。
 
此例程我们主要给大家展示STM32L4的串口功能,所以我们宏定义中打开UART相关的。
 
在这边大家也许会有疑问,我们这个实验不是串口中断吗,为什么要打开DMA宏定义,这个其实是stm32l4xx_hal_uart.c这个库文件的问题,在这个库文件中,它并有像我们用户使用串口那样去区分是使用串口中断还是DMA,所以只要我们使用到串口的宏定义,在不修改串口库文件的情况下,就必须打开DMA的宏定义,否则编译出错。<syntaxhighlight lang="c" line="1" start="103">
// 使能的宏
#define HAL_MODULE_ENABLED // 芯片
#define HAL_FLASH_MODULE_ENABLED // Flash
#define HAL_PWR_MODULE_ENABLED // 电源
#define HAL_RCC_MODULE_ENABLED // 时钟
#define HAL_CORTEX_MODULE_ENABLED // NVIC
 
#define HAL_GPIO_MODULE_ENABLED // GPIO
#define HAL_DMA_MODULE_ENABLED // DMA
#define HAL_UART_MODULE_ENABLED // UART
</syntaxhighlight>
 
==== main.c ====
main函数,我们的例程由此处开始执行,首先调用HAL_Init()函数初始化我们的模块,接着调用SystemClock_Config()函数初始化此例程用到的时钟,具体有哪些时钟被初始化,在gyu_util.c部分有详细说明。
 
接下来我们初始化串口,并且打印欢迎语"Uart ISR demo"。
 
在while()循环中,我们判断STM32L4是否接收到串口助手发送的串口数据,如果接收到数据,则回显打印到串口助手。
 
<syntaxhighlight lang="c++" line="1" start="38">
int main(void)
{
uint16_t msgLen = 0;
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
// 重置所有外设、flash界面以及系统时钟
HAL_Init();
 
// 配置系统时钟(包含振荡器、系统时钟、总线时钟等等)
SystemClock_Config();
// 初始化串口USART1
MX_USART1_UART_Init();
// 初始化USART1中断isrCfg结构
HAL_UARTISR_Init();
printf("Uart ISR demo"); // 展示printf函数
//
while (1)
{
// 轮训是否存在串口数据
if(HAL_UART_Poll())
{
msgLen = HAL_UART_RxBufLen(); // 读取当前接收缓存区中有效的数据长度
// 超过100字节长度的部分不读取
if(msgLen > APP_BUF_LEN)
{
msgLen = APP_BUF_LEN;
}
msgLen = HAL_UART_Read(app_buf,msgLen); // 读取缓冲区数据
HAL_UART_Write(app_buf,msgLen); // 通过串口TX打印显示
}
}
}
</syntaxhighlight>
==== gyu_util.c ====
请参照实验01中的介绍。
 
基础实验中的其他例程,大部分都是使用的相同的时钟配置函数,有特殊的时钟使用,将会在对应例程的源码详解中做针对性说明。
==== gyu_usart_isr.c ====
此文件中的函数,都是留给用户使用的(留给用户的串口API接口函数),函数名比较明朗,这边简单说一下各个函数的功能。
 
串口初始化函数,初始化串口协议波特率115200,数据位8位,停止位1位,无校验位、无流控制。<syntaxhighlight lang="c++" line="1" start="47">
void MX_USART1_UART_Init(void)
{
// 配置串口参数
huart1.Instance = USART1; // UART寄存器基础地址,定义为USART1的
huart1.Init.BaudRate = 115200; // 串口波特率为115200
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 串口数据位为8位
huart1.Init.StopBits = UART_STOPBITS_1; // 串口停止位为1位
huart1.Init.Parity = UART_PARITY_NONE; // 串口无校验位
huart1.Init.Mode = UART_MODE_TX_RX; // 串口模式,TX和RX作用
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 串口无流控制
huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 16位过采样
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; // 1位过采样禁能
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; // 没有串口高级功能初始化
// 串口初始化
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__); // 如果初始化失败,进入错误处理任务
}
}
</syntaxhighlight>串口初始化函数,初始化串口时钟及串口引脚所在的GPIOA时钟,配置串口引脚硬件功能,使能串口中断。<syntaxhighlight lang="c++" line="1" start="76">
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
// 定义GPIO结构体
GPIO_InitTypeDef GPIO_InitStruct;
// 判断选择的是否为USART1
if(uartHandle->Instance==USART1)
{
// 使能GPIOA引脚时钟(因为选择的TX和RX分别为PA9和PA10)
__HAL_RCC_GPIOA_CLK_ENABLE();
// 使能USART1时钟
__HAL_RCC_USART1_CLK_ENABLE();
// GPIO配置
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; // 选择USART1的TX和RX引脚(TX:PA9,RX:PA10)
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 推挽输出
GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;// 引脚频率5-80MHz
GPIO_InitStruct.Alternate = GPIO_AF7_USART1; // 配置为USART1
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化引脚
// 配置USART1中断优先级
HAL_NVIC_SetPriority(USART1_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
</syntaxhighlight>初始化串口数据isrCfg结构,并且开始串口数据接收。<syntaxhighlight lang="c++" line="1" start="112">
void HAL_UARTISR_Init(void)
{
UartIsr_Init(&huart1);
HAL_UART_StartRece();
}
</syntaxhighlight>串口打印函数,串口TX采样中断方式打印数据。<syntaxhighlight lang="c++" line="1" start="127">
void HAL_UART_Write(uint8_t *pData,uint16_t size)
{
if(size == 0)
{
return;
}
if(pData == 0)
{
return;
}
HAL_UART_Transmit_IT(&huart1,pData,size);
}
</syntaxhighlight>启动串口接收的函数,串口RX采用中断方式接收数据。<syntaxhighlight lang="c++" line="1" start="148">
void HAL_UART_StartRece(void)
{
HAL_UART_Receive_IT(&huart1,UartIsr_GetBuf(),RECE_BUF_MAX_LEN);
}
</syntaxhighlight>串口轮询函数,用于处理接收一包数据的超时时间。<syntaxhighlight lang="c++" line="1" start="161">
uint8_t HAL_UART_Poll(void)
{
return UartIsr_Poll();
}
</syntaxhighlight>读取串口数据的函数,并且返回读取到的数据的长度。<syntaxhighlight lang="c++" line="1" start="175">
uint16_t HAL_UART_Read(uint8_t *buf,uint16_t size)
{
return UartIsr_Read(buf,size);
}
</syntaxhighlight>返回当前串口RX缓冲区中的数据长度。<syntaxhighlight lang="c++" line="1" start="188">
uint16_t HAL_UART_RxBufLen(void)
{
return UartIsr_Avail();
}
</syntaxhighlight>串口接收中断的回调函数,在这个回调函数中,我们需要开启串口接收中断,用于接收下一包的串口数据。<syntaxhighlight lang="c++" line="1" start="199">
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_StartRece();
}
</syntaxhighlight>
 
==== gyu_uasrt_isr_ex.c ====
此文件是gyu_uasrt_usr.c中函数的底层处理函数,为了方便大家使用,我们将其从中分离出来。这部分大家根据自己实际情况选择看或者不看,熟悉ti芯片的朋友,可以看出这部分的串口数据处理是copy的ti CC25XX芯片的。
 
首先是有关串口中断的结构体定义,并且根据结构体参数的具体功能,分别RX缓冲区数据长度。<syntaxhighlight lang="c++" line="1" start="30">
// 串口RX缓冲区数据长度
#define HAL_UART_ISR_RX_AVAIL() \
(isrCfg.rxTail >= isrCfg.rxHead) ? \
(isrCfg.rxTail - isrCfg.rxHead) : \
(RECE_BUF_MAX_LEN - isrCfg.rxHead + isrCfg.rxTail)
 
static uartISRCfg_t isrCfg;
</syntaxhighlight>初始化串口中断结构体的isrCfg。<syntaxhighlight lang="c++" line="1" start="47">
void UartIsr_Init(UART_HandleTypeDef*huart)
{
isrCfg.rxHead = 0;
isrCfg.rxTail = 0;
isrCfg.rxTick = 0;
isrCfg.rxShdw = 0;
hUart = huart;
}
</syntaxhighlight>获取串口RX缓冲区中的数据,由gyu_usart_isr.c的HAL_UART_StartRece()函数中调用,并指向RX缓冲区。<syntaxhighlight lang="c++" line="1" start="64">
uint8_t* UartIsr_GetBuf(void)
{
return isrCfg.rxBuf; // 指向串口RX缓冲区
}
</syntaxhighlight>读取串口RX缓冲区中的数据的函数。<syntaxhighlight lang="c++" line="1" start="78">
uint16_t UartIsr_Read(uint8_t *buf, uint16_t len)
{
uint16_t cnt = 0;
while ((isrCfg.rxHead != isrCfg.rxTail) && (cnt < len))
{
*buf++ = isrCfg.rxBuf[isrCfg.rxHead++];
if (isrCfg.rxHead >= RECE_BUF_MAX_LEN)
{
isrCfg.rxHead = 0;
}
cnt++;
}
 
return cnt;
}
</syntaxhighlight>串口RX缓冲区数据长度获取函数。<syntaxhighlight lang="c++" line="1" start="103">
uint16_t UartIsr_Avail(void)
{
return HAL_UART_ISR_RX_AVAIL();
}
</syntaxhighlight>串口轮询函数,主要目的是检测串口RX缓冲区数据,一个是是否超过了设置的缓冲区大小,另一个是是否超时了。<syntaxhighlight lang="c++" line="1" start="116">
uint8_t UartIsr_Poll(void)
{
uint8_t evt = 0;
uint16_t cnt = 0;
volatile uint16_t tail = RECE_BUF_MAX_LEN - hUart->RxXferCount;
if(isrCfg.rxHead != tail)
{
if(tail != isrCfg.rxTail)
{
isrCfg.rxTail = tail;
if(isrCfg.rxTick == 0)
{
isrCfg.rxShdw = HAL_GetTick();
}
isrCfg.rxTick = HAL_UART_ISR_IDLE;
}
else if(isrCfg.rxTick)
{
uint32_t Tick = HAL_GetTick();
uint32_t delta = Tick >= isrCfg.rxShdw ?
(Tick - isrCfg.rxShdw ):
(Tick + (UINT32_MAX - isrCfg.rxShdw));
 
if (isrCfg.rxTick > delta)
{
isrCfg.rxTick -= delta;
}
else
{
isrCfg.rxTick = 0;
}
}
cnt = UartIsr_Avail();
}
else
{
isrCfg.rxTick = 0;
}
if (cnt >= HAL_UART_ISR_FULL)
{
evt = HAL_UART_RX_FULL;
}
else if (cnt && !isrCfg.rxTick)
{
evt = HAL_UART_RX_TIMEOUT;
}
return evt;
}
 
</syntaxhighlight>
== 实验14-二维码显示 ==
510
个编辑