STM32利用库函数驱动OLED

使用的1.3寸OLED是I2C接口的对外有四个引脚,分别是VCC、GND、SCL、SDL。
首先看一下运行的效果图:
在这里插入图片描述
成功在小屏幕上显示“你好”。
首先,我们需要配置好STM32的I2C外设,和GPIO的模式。
PB6—>SCL
PB7—>SDA
GPIO口配置为开漏输出模式。

void GPIO_Config()
{
	GPIO_InitTypeDef GPIO_STRUCT;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	
	GPIO_STRUCT.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_STRUCT.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_STRUCT.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_STRUCT);	
}


void IIC_Config()
{
	I2C_InitTypeDef I2C_STRUCT;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	
	
	I2C_DeInit(I2C1);
	I2C_STRUCT.I2C_Mode = I2C_Mode_I2C;
	I2C_STRUCT.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_STRUCT.I2C_OwnAddress1 = 0x90;
	I2C_STRUCT.I2C_Ack = I2C_Ack_Enable;
	I2C_STRUCT.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_STRUCT.I2C_ClockSpeed =400000 ;
	
	I2C_Init(I2C1,&I2C_STRUCT);
	I2C_Cmd(I2C1,ENABLE);
	
}```
I2C的配置:
I2C_Mode:配置I2C的工作模式为I2C。
I2C_DutyCycle:配置时钟线的占空比,这里配置占空比为2:1.
I2C_OwnAddress1:peizhi STM32的I2C设备自己的地址。
I2C_Ack:接收应答,每接收到一个字节就返回一个应答。
I2C_AcknowledgedAddress:选择I2C的寻址模式,这个根据连接的设备来进行选择。
I2C_ClockSpeed:设置I2C的传输速率,最大不得高于400kHz。
配置好以后使能I2C外设。

配置完成以后我们就要使用I2C来驱动OLED进行显示了。
第一步我们需要构建一个发送的最小单元,什么意思呢?就是定义一个函数,这个函数主要用来进行命令和数据的发送。为什么要这个样子呢?因为I2C在通信时过程比较繁琐,如果每次发送数据或者命令都要来配置一下的话,代码量会大大增加,并且程序的结构性也会被破坏,不利于阅读。

void WriteByte(uint8_t addr,uint8_t data)
{
while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C1,ENABLE);

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1,0x78,I2C_Direction_Transmitter);

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

I2C_SendData(I2C1,addr);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1,data);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_GenerateSTOP(I2C1,ENABLE);

}’’’

这个就是发送的最小单元,在这里面接收两个参数,一个是地址,一个是数据。
内部实现的流程如下:
1、利用while循环判断I2C总线是否处于繁忙状态。
2、产生一个开始信号
3,、等待I2C_EVENT_MASTER_MODE_SELECT
4、发送目标设备的地址,也就是OLED屏幕的地址。
5,、等待事件I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
6、发送地址
7、等待事件I2C_EVENT_MASTER_BYTE_TRANSMITTED
8、发送数据
9、等待事件I2C_EVENT_MASTER_BYTE_TRANSMITTED
10、产生一个停止信号。

到此我们的最小发送单元配置完成。当我们再次发送命令和数据时不需要再这么复杂的敲写代码,直接调用该函数即可。
以下为发送命令和发送数据的封装函数:

void Write_Cmd(unsigned char command)
{
	WriteByte(0x00,command);
}

void Write_Dat(unsigned char data)
{
	WriteByte(0x40,data);
}

工欲善其事必先利其器,上面我们已经将如何发送数据写好了,下面我们就直接使用上面的函数来进行初始化等就可以了。
OLED屏幕的初始化:

void OLED_Init(void)
{
	int i = 10000;
	while(i--);//这个延时是必要的,没有使用定时器,就简单的写了个延时
	
	Write_Cmd(0xae);//开显示
	Write_Cmd(0x20);//设置内存寻址模式
	Write_Cmd(0x10);//00水平寻址01垂直10页面寻址
	Write_Cmd(0xb0);//为页面寻址模式设置页面开始地址0-7
	Write_Cmd(0xc8);//设置COM输出扫描方向
	Write_Cmd(0x00);//设置低列地址
	Write_Cmd(0x10);//设置高列地址
	Write_Cmd(0x40);//设置起始行地址
	Write_Cmd(0x81);//以下的使用的就去查找手册看一下吧!
	Write_Cmd(0xff);
	Write_Cmd(0xa1);
	Write_Cmd(0xa6);
	Write_Cmd(0xa8);
	Write_Cmd(0x3f);
	Write_Cmd(0xa4);
	Write_Cmd(0xd3);
	Write_Cmd(0x00);
	Write_Cmd(0xd5);
	Write_Cmd(0xf0);
	Write_Cmd(0xd9);
	Write_Cmd(0x22);
	Write_Cmd(0xda);
	Write_Cmd(0x12);
	Write_Cmd(0xdb);
	Write_Cmd(0x20);
	Write_Cmd(0x8d);
	Write_Cmd(0x14);
	Write_Cmd(0xaf);
}

初始完成,我们先来看一下OLED的屏幕的各个像素地址:
OLED的分别率是128x64.即是有128X64个像素点。所有的像素按照行分为8页,按列分为8段,每段里面有8行16列。
在这里插入图片描述
在这里插入图片描述
通常像素原点为左上角的(0,0)像素点,我们设置图像时,通常按照坐标来进行设置,但是我们设置的像素坐标需要转换为对应的地址。

void OLED_SetPos(unsigned char x,unsigned char y)
{
	Write_Cmd(0xb0+y);
	Write_Cmd(((x&0xf0)>>4)|0x10);
	Write_Cmd((x&0x0f)|0x01);
}

剩余的代码如下:

void OLED_Fill(unsigned char fill_data)
{
	unsigned char m,n;
	for(m = 0;m < 8;m++)
	{
		Write_Cmd(0xb0+m);
		Write_Cmd(0x00);
		Write_Cmd(0x10);
		for(n = 0;n < 130;n++)
		{
			Write_Dat(fill_data);
		}
				
	}
		
}

void OLED_CLS(void)
{
	OLED_Fill(0x00);
}


void OLED_ON(void)
{
	Write_Cmd(0x8d);
	Write_Cmd(0x14);
	Write_Cmd(0xaf);
}

void OLED_OFF(void)
{
	Write_Cmd(0x8d);
	Write_Cmd(0x10);
	Write_Cmd(0xae);
}

其中Write_Dat(0xf0);在屏幕上的像素分布如下:

0
0
0
0
1
1
1
1

所以在利用取模工具时,需要注意高低位的情况。

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
首先,你需要下载并安装STM32F4xx库函数,然后按照以下步骤进行操作: 1. 创建一个新工程,并在工程中添加OLED屏幕驱动所需的文件。 2. 在main.c文件中添加以下代码: ```c #include "stm32f4xx.h" #include "OLED.h" int main(void) { OLED_Init(); //初始化OLED屏幕 OLED_Clear(); //清屏 OLED_ShowString(0,0,"Hello World!"); //在屏幕上显示字符串 while (1); } ``` 3. 在OLED.c文件中添加以下代码: ```c #include "stm32f4xx.h" #include "OLED.h" //OLED屏幕初始化函数 void OLED_Init(void) { //将OLED屏幕的引脚设置为输出模式 GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); OLED_WriteCmd(0xAE); //display off OLED_WriteCmd(0x20); //Set Memory Addressing Mode OLED_WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid OLED_WriteCmd(0xB0); //Set Page Start Address for Page Addressing Mode,0-7 OLED_WriteCmd(0xC8); //Set COM Output Scan Direction OLED_WriteCmd(0x00); //---set low column address OLED_WriteCmd(0x10); //---set high column address OLED_WriteCmd(0x40); //--set start line address OLED_WriteCmd(0x81); //--set contrast control register OLED_WriteCmd(0xFF); OLED_WriteCmd(0xA1); //--set segment re-map 0 to 127 OLED_WriteCmd(0xA6); //--set normal display OLED_WriteCmd(0xA8); //--set multiplex ratio(1 to 64) OLED_WriteCmd(0x3F); // OLED_WriteCmd(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content OLED_WriteCmd(0xD3); //-set display offset OLED_WriteCmd(0x00); //-not offset OLED_WriteCmd(0xD5); //--set display clock divide ratio/oscillator frequency OLED_WriteCmd(0xF0); //--set divide ratio OLED_WriteCmd(0xD9); //--set pre-charge period OLED_WriteCmd(0x22); // OLED_WriteCmd(0xDA); //--set com pins hardware configuration OLED_WriteCmd(0x12); OLED_WriteCmd(0xDB); //--set vcomh OLED_WriteCmd(0x20); //0x20,0.77xVcc OLED_WriteCmd(0x8D); //--set DC-DC enable OLED_WriteCmd(0x14); // OLED_WriteCmd(0xAF); //--turn on oled panel } //向OLED屏幕写入命令 void OLED_WriteCmd(uint8_t cmd) { GPIO_ResetBits(GPIOA, GPIO_Pin_4); //RS=0,写命令 GPIO_ResetBits(GPIOA, GPIO_Pin_5); //RW=0,写入模式 GPIO_SetBits(GPIOA, GPIO_Pin_6); //E=1,允许写入 GPIOA->ODR &= 0xFF00; GPIOA->ODR |= cmd; //写入命令 GPIO_ResetBits(GPIOA, GPIO_Pin_6); //E=0,禁止写入 } //向OLED屏幕写入数据 void OLED_WriteData(uint8_t data) { GPIO_SetBits(GPIOA, GPIO_Pin_4); //RS=1,写数据 GPIO_ResetBits(GPIOA, GPIO_Pin_5); //RW=0,写入模式 GPIO_SetBits(GPIOA, GPIO_Pin_6); //E=1,允许写入 GPIOA->ODR &= 0xFF00; GPIOA->ODR |= data; //写入数据 GPIO_ResetBits(GPIOA, GPIO_Pin_6); //E=0,禁止写入 } //清屏 void OLED_Clear(void) { uint8_t i,j; for(i=0;i<8;i++) { OLED_WriteCmd(0xb0+i); //设置页地址 OLED_WriteCmd(0x00); //设置列地址低4位 OLED_WriteCmd(0x10); //设置列地址高4位 for(j=0;j<128;j++) { OLED_WriteData(0x00); //清空该页的所有列 } } } //在OLED屏幕上显示字符串 void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr) { uint8_t c=0,i=0,j=0; while (chr[c]!='\0') { j=chr[c]-32; if(x>120){x=0;y++;} OLED_SetPos(x,y); for(i=0;i<8;i++) { OLED_WriteData(F8X16[j*16+i]); } OLED_SetPos(x,y+1); for(i=0;i<8;i++) { OLED_WriteData(F8X16[j*16+i+8]); } x+=8; c++; } } //设置OLED屏幕某个像素的状态 void OLED_SetPixel(uint8_t x,uint8_t y,uint8_t color) { uint8_t page; uint8_t column; page=y/8; column=x; OLED_SetPos(column,page); if(color==1) { OLED_WriteData(0xff<<(y%8)); } else { OLED_WriteData(0x00<<(y%8)); } } //设置OLED屏幕显示位置 void OLED_SetPos(uint8_t x,uint8_t y) { OLED_WriteCmd(0xb0+y); OLED_WriteCmd(((x&0xf0)>>4)|0x10); OLED_WriteCmd(x&0x0f); } ``` 4. 在OLED.h文件中添加以下代码: ```c #ifndef __OLED_H #define __OLED_H #include "stm32f4xx.h" //OLED屏幕初始化函数 void OLED_Init(void); //向OLED屏幕写入命令 void OLED_WriteCmd(uint8_t cmd); //向OLED屏幕写入数据 void OLED_WriteData(uint8_t data); //清屏 void OLED_Clear(void); //在OLED屏幕上显示字符串 void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr); //设置OLED屏幕某个像素的状态 void OLED_SetPixel(uint8_t x,uint8_t y,uint8_t color); //设置OLED屏幕显示位置 void OLED_SetPos(uint8_t x,uint8_t y); #endif ``` 5. 编译并下载到STM32F407芯片中,即可看到OLED屏幕上显示“Hello World!”的字样。 需要注意的是,以上代码仅供参考,具体的代码实现可能会有所不同,具体实现方式需要根据所使用的OLED屏幕型号和具体的需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值