基于STM32的OLED显示

本文详细介绍了如何使用STM32微控制器通过SPI接口驱动OLED显示屏,包括OLED的工作原理、SPI通信协议解析,以及在实际项目中显示学号姓名的步骤,从汉字点阵获取到代码修改、硬件连接和程序烧录全过程。
摘要由CSDN通过智能技术生成


一、什么是OLED

OLED (Organic Light-Emitting Diode)即有机发光二极管,在手机OLED上属于新型产品,被称誉为“梦幻显示器”。

OLED显示技术与传统的LCD显示方式不同,无需背光灯,采用非常薄的有机材料涂层和玻璃基板(或柔性有机基板),当有电流通过时,这些有机材料就会发光。而且OLED显示屏幕可以做得更轻更薄,可视角度更大,并且能够显著的节省耗电量。>

二、了解SPI

SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议,比如AT91RM9200。

SPI协议概括

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)。

(1)SDI –SerialDataIn,串行数据输入;
(2)SDO –SerialDataOut,串行数据输出;
(3)SCLK – Serial Clock,时钟信号,由主设备产生;
(4)CS – Chip Select,从设备使能信号,由主设备控制。>

SPI总线四种工作状态:
SPI总线四种工作状态
SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果CPOL=0,串行同步时钟的空闲状态为低电平;SPI主模块和与之通信的外设时钟相位和极性应该一致。SPI接口时序如图3、图4所示。
在这里插入图片描述

同步串行口

SPI总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。外围设置FLASHRAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。SPI总线系统可直接与各个厂家生产的多种标准外围器件直接接口,该接口一般使用4条线:串行时钟线(SCLK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线SS(有的SPI接口芯片带有中断信号线INT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。

(1)MOSI– SPI总线主机输出/ 从机输入(SPI Bus Master Output/Slave Input);
(2)MISO– SPI总线主机输入/ 从机输出(SPI Bus Master Input/Slave Output);
(3)SCLK –时钟信号,由主设备产生;
(4)CS – 从设备使能信号,由主设备控制(Chip select),有的IC此pin脚叫SS。>

三、学号姓名的显示

1.汉字点阵获取

下载一个小程序
请添加图片描述
点击设置

请添加图片描述
输入你想要的信息
请添加图片描述
请添加图片描述

代码修改

在 oledfont.h文件中插入你需要显示的汉字点阵信息

"任",0x08,0x10,0x08,0x78,0x0B,0xC0,0x10,0x40,0x10,0x40,0x30,0x40,0x30,0x40,0x5F,0xFE,
0x90,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x17,0xFC,0x10,0x00,/*"任",0*/
"智",0x20,0x00,0x3E,0x7C,0x48,0x44,0x08,0x44,0xFF,0x44,0x14,0x44,0x22
以下是基于STM32OLED显示屏的年月日显示代码: ```c #include "stm32f10x.h" #include "oled.h" #include "stdlib.h" #include "stdio.h" #include "delay.h" #include "iic.h" #define I2C_Speed 400000 #define I2C1_SLAVE_ADDRESS7 0x78 u8 year,month,day,week; u8 hour,minute,second; void RTC_Configuration(void); void I2C_Configuration(void); void TIM_Configuration(void); void NVIC_Configuration(void); void OLED_Init(void); void OLED_ShowStr(u8 x,u8 y, u8 ch[], u8 TextSize); void OLED_ShowNum(u8 x,u8 y, u32 num, u8 len, u8 TextSize); void OLED_ShowTime(u8 x,u8 y); void OLED_ShowDate(u8 x,u8 y); void OLED_ShowWeek(u8 x,u8 y); int main(void) { NVIC_Configuration(); TIM_Configuration(); OLED_Init(); RTC_Configuration(); I2C_Configuration(); while(1) { OLED_ShowTime(0,0); OLED_ShowDate(0,2); OLED_ShowWeek(0,4); } } void RTC_Configuration(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); RTC_WaitForSynchro(); RTC_WaitForLastTask(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_WaitForLastTask(); } void I2C_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); I2C_DeInit(I2C1); I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); } void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Period = 999; TIM_TimeBaseStructure.TIM_Prescaler = 7199; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_Cmd(TIM2, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); EXTI_ClearITPendingBit(EXTI_Line17); EXTI_InitStructure.EXTI_Line = EXTI_Line17; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); } void OLED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); OLED_InitGpio(); OLED_InitI2c(); OLED_InitDev(); OLED_Fill(0x00); OLED_Refresh_Gram(); } void OLED_ShowStr(u8 x,u8 y, u8 ch[], u8 TextSize) { u8 c = 0,i = 0,j = 0; switch(TextSize) { case 1: while (ch[j] != '\0') { c = ch[j] - 32; if(x>128-6) { x=0; y++; } OLED_ShowChar(x,y,c,TextSize); x+=6; j++; } break; case 2: while (ch[j] != '\0') { c = ch[j] - 32; if(x>128-12) { x=0; y++; } OLED_ShowChar(x,y,c,TextSize); x+=12; j++; } break; } } void OLED_ShowNum(u8 x,u8 y, u32 num, u8 len, u8 TextSize) { u8 t,temp; u8 enshow=0; for(t=0;t<len;t++) { temp=(num/10^(len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { OLED_ShowChar(x+(TextSize/2)*t,y,' ',TextSize); continue; } else enshow=1; } OLED_ShowChar(x+(TextSize/2)*t,y,temp+'0',TextSize); } } void OLED_ShowTime(u8 x,u8 y) { RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure); hour = RTC_TimeStructure.RTC_Hours; minute = RTC_TimeStructure.RTC_Minutes; second = RTC_TimeStructure.RTC_Seconds; OLED_ShowNum(x,y,hour,2,1); OLED_ShowChar(x+2*6,y,':',1); OLED_ShowNum(x+3*6,y,minute,2,1); OLED_ShowChar(x+5*6,y,':',1); OLED_ShowNum(x+6*6,y,second,2,1); } void OLED_ShowDate(u8 x,u8 y) { RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure); year = RTC_DateStructure.RTC_Year; month = RTC_DateStructure.RTC_Month; day = RTC_DateStructure.RTC_Date; OLED_ShowNum(x,y,year,4,1); OLED_ShowChar(x+4*6,y,'/',1); OLED_ShowNum(x+5*6,y,month,2,1); OLED_ShowChar(x+7*6,y,'/',1); OLED_ShowNum(x+8*6,y,day,2,1); } void OLED_ShowWeek(u8 x,u8 y) { RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure); week = RTC_DateStructure.RTC_WeekDay; switch(week) { case 1: OLED_ShowStr(x,y,"Monday",1); break; case 2: OLED_ShowStr(x,y,"Tuesday",1); break; case 3: OLED_ShowStr(x,y,"Wednesday",1); break; case 4: OLED_ShowStr(x,y,"Thursday",1); break; case 5: OLED_ShowStr(x,y,"Friday",1); break; case 6: OLED_ShowStr(x,y,"Saturday",1); break; case 7: OLED_ShowStr(x,y,"Sunday",1); break; } } ``` 请注意,这只是一个示例代码,实际使用时需要根据自己的硬件和软件环境进行适当的修改。同时需要注意的是,本代码仅提供参考,对于代码的正确性和安全性,需读者自行进行检验和验证。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值