打开主菜单

谷雨文档中心 β

更改

NBDK-L4:基础实验教程

删除7,043字节2019年3月1日 (五) 11:47
实验14-二维码显示
== 实验13-TFT显示屏 ==
TFT显示屏实验,给大家展示了TFT显示屏实验,给大家展示了显示屏的驱动实现,主要是针对显示屏打印英文、汉字、数字以及图片。
=== STM32L476 UART简介 SPI简介 ===USART主要功能:SPI接口说明:
•全双工异步通信SPI接口可用于使用SPI协议与外部设备通信。SPI模式可由软件选择。 器件复位后,默认选择SPI Motorola模式。
•NRZ标准格式(标记/空格)串行外设接口(SPI)协议支持与外部设备的半双工,全双工和单工同步串行通信。 接口可以配置为主设备,在这种情况下,它为外部从设备提供通信时钟(SCK)。 该接口还能够在多主机配置中运行。
•可配置的过采样方法16或8,以提供速度和速度之间的灵活性SPI主要功能:
时钟容差•主或从操作
•通用可编程发送和接收波特率高达10 Mbit / s时•三条线路上的全双工同步传输
时钟频率为80 MHz,过采样为8•两条线路上的半双工同步传输(带双向数据线)
•双时钟域允许:•两条线上的单工同步传输(带有单向数据线)
- USART功能和从停止模式唤醒•4位至16位数据大小选择
- 独立于PCLK重新编程的便捷波特率编程•多主机模式功能
•自动波特率检测•8个主模式波特率预分频器,最高可达fPCLK / 2。
•可编程数据字长(7,8或9位)•从机模式频率高达fPCLK / 2。
•可编程数据顺序,具有MSB优先或LSB优先移位•主机和从机的硬件或软件的NSS管理:动态变化
•可配置的停止位(1或2个停止位)主/从操作
•同步模式和时钟输出,用于同步通信•可编程时钟极性和相位
•单线半双工通信 •使用DMA进行持续通信 •使用集中式DMA将接收/发送的字节缓冲在保留的SRAM中 •发送器和接收器的独立使能位 •独立的信号极性控制,用于发送和接收•可编程数据顺序,具有MSB优先或LSB优先移位
•可交换Tx / Rx引脚配置•具有中断功能的专用传输和接收标志
•调制解调器和RS-485收发器的硬件流控制•SPI总线忙状态标志
•通信控制/错误检测标志•SPI Motorola支持
•奇偶校验控制:•硬件CRC功能,可靠通信:
- 传输奇偶校验位 CRC值可以在Tx模式下作为最后一个字节发送
- 检查接收数据字节的奇偶校验自动CRC错误检查最后接收的字节
•带有标志的14个中断源•主模式故障,具有中断功能的溢出标志
•多处理器通信•CRC错误标志
如果地址不匹配,USART进入静音模式。•两个具有DMA功能的32位嵌入式Rx和Tx FIFO
•从静音模式唤醒(通过空闲线路检测或地址标记检测)•SPI TI模式支持
==== TFT简介 ====
暂缺,有需要开发驱动的朋友,可以参照我们的源码和TFT使用手册。
''<span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span><span class="tlid-translation-gender-indicator translation-gender-indicator"></span>''
=== 硬件设计 ===
}
}
}
</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_exgui.c 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) TFT驱动文件,请大家查看[http: \ (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_isrdoc.c的HAL_UART_StartRece()函数中调用,并指向RX缓冲区。<syntaxhighlight lang="c++" line="1" start="64">uint8_t* UartIsr_GetBuf(void){ return isrCfgiotxx.rxBuf; // 指向串口RX缓冲区}<com/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++%E8%B0%B7%E9%9B%A8%E6%98%BE%E7%A4%BA%E6%8E%A5%E5%8F%A3%E5%8E%9F%E7%90%86%E8%AF%B4%E6%98%8E 谷雨显示接口原理说明]; 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
个编辑