STM32F103C8T6 使用 HAL 库驱动 OLED 显示屏(SPI 接口)
STM32F103C8T6 使用 HAL 库驱动 OLED 显示屏(SPI 接口)的报告
一、项目概述
本报告详细介绍了使用STM32F103C8T6微控制器结合STM32 HAL库,通过SPI接口驱动OLED显示屏的过程。OLED显示屏因其高对比度、宽视角和快速响应时间,在嵌入式系统中得到广泛应用。本项目通过STM32的SPI接口与OLED显示屏进行高速数据传输,实现文字、图像等信息的显示。
二、硬件环境
三、软件设计
1. 开发环境
2. SPI通信配置
HAL_SPI_Init
函数配置SPI接口,包括时钟极性(CPOL)、时钟相位(CPHA)、数据位数、波特率等。3. OLED驱动实现
4. 调试与优化
四、测试结果
五、结论
通过STM32F103C8T6微控制器结合HAL库,成功实现了通过SPI接口驱动OLED显示屏的功能。SPI通信的高效性和OLED显示屏的优质显示效果相结合,为嵌入式系统的显示应用提供了强有力的支持。整个项目过程中,HAL库简化了硬件操作,提高了开发效率,同时保证了系统的稳定性和可靠性。
六、未来展望
```c
#include "stm32f1xx_hal.h" // 引入STM32F1系列微控制器的HAL库头文件
#include "oled.h" // 引入OLED显示屏驱动库头文件
SPI_HandleTypeDef hspi1; // 定义SPI1句柄结构体变量
void SystemClock_Config(void); // 系统时钟配置函数声明
static void MX_GPIO_Init(void); // GPIO初始化函数声明
static void MX_SPI1_Init(void); // SPI1初始化函数声明
int main(void)
{
HAL_Init(); // 初始化HAL库
SystemClock_Config(); // 配置系统时钟
MX_GPIO_Init(); // 初始化GPIO
MX_SPI1_Init(); // 初始化SPI1
OLED_Init(&hspi1); // 初始化OLED显示屏,传入SPI1句柄
OLED_Clear(); // 清屏
OLED_ShowString(0, 0, "Hello, STM32!"); // 在OLED屏幕上显示字符串"Hello, STM32!"
OLED_Refresh(); // 刷新OLED屏幕显示内容
while (1)
{
HAL_Delay(1000); // 延时1秒
}
}
// 系统时钟配置函数实现
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 定义RCC振荡器初始化结构体变量
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 定义RCC时钟初始化结构体变量
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 设置振荡器类型为外部高速晶振
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 使能外部高速晶振
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // 使能PLL锁相环
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // 设置PLL输入源为外部高速晶振
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 设置PLL倍频系数为9
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) // 配置RCC振荡器
{
Error_Handler(); // 如果配置失败,调用错误处理函数
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; // 设置时钟类型
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 设置系统时钟源为PLL输出时钟
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟不分频
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1时钟分频系数为2
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2时钟不分频
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) // 配置RCC时钟
{
Error_Handler(); // 如果配置失败,调用错误处理函数
}
}
// SPI1初始化函数实现
static void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1; // 设置SPI1实例
hspi1.Init.Mode = SPI_MODE_MASTER; // 设置为主机模式
hspi1.Init.Direction = SPI_DIRECTION_2LINES; // 设置为双线模式
hspi1.Init.DataSize = SPI_DATASIZE_8BIT; // 数据大小为8位
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // 时钟极性为低
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // 时钟相位为第一个边沿
hspi1.Init.NSS = SPI_NSS_SOFT; // NSS信号由软件控制
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; // 波特率预分频系数为256
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; // 数据传输从最高位开始
hspi1.Init.TIMode = SPI_TIMODE_DISABLE; // 禁用TI模式
hspi1.Init.CRCPolynomial = 10; // CRC多项式为10
if (HAL_SPI_Init(&hspi1) != HAL_OK) // 初始化SPI1
{
Error_Handler(); // 如果初始化失败,调用错误处理函数
}
}
// GPIO初始化函数实现
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; // 定义GPIO初始化结构体变量
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_7; // 设置引脚为PA5和PA7
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 设置为复用推挽输出模式
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 设置为高速输出频率
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化GPIOA引脚
GPIO_InitStruct.Pin = GPIO_PIN_6; // 设置引脚为PA6
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 设置为输入模式
GPIO_InitStruct.Pull = GPIO_NOPULL; // 不使用上下拉电阻
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化GPIOA引脚
}
```
作者:科创工作室li