ss1306 OLED 初始化流程

 

参考博客:https://blog.csdn.net/qq_42992084/article/details/89977888

 IIC学习:  https://blog.csdn.net/u010261063/article/details/114300238

SSD1306 IIC读写时序

1、 第一个字节(Slave Address )发送的是地址 和 读写属性(一般只会写数据);SA0(D/C引脚就是SA0)决定了从机的地址; 0x78

2、第二个字节(control byte )决定了第三个字节是命令还是数据

        a) Co = 0 代表后边全是数据

        b) D/C = 0 代表后边是数据(0x00);D/C = 0 代表后边是命令;(0x40)

//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
	I2C_Start();
	Send_Byte(0x78);//发送地址和写指令
	I2C_WaitAck();
	if(mode)
        {
            Send_Byte(0x40);//发命令
        }
        else
        {
            Send_Byte(0x00);//发数据
        }
	I2C_WaitAck();
	Send_Byte(dat);
	I2C_WaitAck();
	I2C_Stop();
}

第一次初始化流程

第二个初始化流程

1、地址设置命令(0x00-0x0F),高4位强制为0
(1)页地址模式下设置列起始地址低4位

(2)页地址模式下设置列起始地址高4位(0x10-ox1F),高4位强制为1

(3)设置内存地址寻址模式(Set Memory Addressing Mode)(20h)

       带有参数:02 表示页寻址模式

通常在页地址模式下访问GDDRAM, 需要如下步骤来定义起始RAM访问指针指向:

  • 通过命令(B0h-B7h)设置目标显示位置页起始地址
  • 通过命令(00h-0Fh)设置列起始地址低位
  • 通过命令(10h-1Fh)设置列起始地址高位

void OLED_Init(void)
{
    OLED_Config();

    OLED_SCK(HIGH); // 空闲态时,SCLK处于高电平
    OLED_CS(HIGH);  // 关闭选择输入

    /* 从上电到下面开始初始化要有足够的时间,即等待 RC复位完毕 */
    OLED_RST(LOW); // 复位(低电平有效)
    OLED_Delay_ms(100);
    OLED_RST(HIGH);
    OLED_Delay_ms(30);

    /*

    //官方的驱动流程
    OLED_Write_Cmd(0xA8); // 设置多路传输比率 -- set multiplex ratio (16 to 63)
    OLED_Write_Cmd(0x3F); // \ 1 / 64 duty

    OLED_Write_Cmd(0xD3); // 设置显示偏移 -- set display offset (0x00~0x3F)
    OLED_Write_Cmd(0x00); // \ not offset 偏移值是 0

    OLED_Write_Cmd(0x40); // 设置设置屏幕(GDDRAM)起始行 -- Set Display Start Line (0x40~0x7F)
    
    /配置显示方向
    OLED_Write_Cmd(0xA1); // 设置段重映射 -- Set SEG / Column Mapping     0xA0左右反置(复位值) 0xA1正常(重映射值)
    OLED_Write_Cmd(0xC8); // 设置行输出扫描方向 -- Set COM / Row Scan Direction   0xc0上下反置(复位值) 0xC8正常(重映射值)

    OLED_Write_Cmd(0xDA); // 设置列引脚硬件配置 -- set com pins hardware configuration
    OLED_Write_Cmd(0x12); // \ Sequential COM pin configuration,Enable COM Left/Right remap

    OLED_Write_Cmd(0x81); // 设置对比度 -- set contrast control register (0x00~0x100)
    OLED_Write_Cmd(0xCF); // \ Set SEG Output Current Brightness

    //根据RAM 内容显示
    OLED_Write_Cmd(0xA4); //  全局显示开启(黑屏/亮屏)  (0xA4 根据RAM 内容显示 / 0xA5 每个oled都点亮 全部显示)
                          //正常显示方式(不是反现)
    OLED_Write_Cmd(0xA6); // 设置显示方式(正常/反显) -- set normal display (0xA6 / 0xA7)

    //设置显示时钟分频因子/振荡器频率
    OLED_Write_Cmd(0xD5); // 设置显示时钟分频因子/振荡器频率 -- set display clock divide ratio/oscillator frequency
    OLED_Write_Cmd(0x80); // A[3:0] 分频因子, A[7:4] 震荡频率设置 Set Clock as 100 Frames/Sec

    OLED_Write_Cmd(0x8D); // 电荷泵设置 -- set Charge Pump enable / disable (0x14 / 0x10)
    OLED_Write_Cmd(0x14); // \ 启用电荷泵 Enable charge pump during display on

    OLED_Write_Cmd(0xAF); // 打开OLED -- turn on oled panel : OXAE 关闭OLED 休眠模式 0xaf 打开oled
    //官方的驱动流程

    */

    OLED_Write_Cmd(0xAE); // 关闭OLED -- turn off oled panel

    OLED_Write_Cmd(0xD5); // 设置显示时钟分频因子/振荡器频率 -- set display clock divide ratio/oscillator frequency
    OLED_Write_Cmd(0x80); // A[3:0] 分频因子, A[7:4] 震荡频率设置 Set Clock as 100 Frames/Sec

    OLED_Write_Cmd(0x20); // 设置内存寻址模式 -- Set Memory Addressing Mode (0x00 / 0x01 / 0x02)
    OLED_Write_Cmd(0x02); // \ Page Addressing 设置为页寻址模式

    OLED_Write_Cmd(0xA8); // 设置多路传输比率 -- set multiplex ratio (16 to 63)
    OLED_Write_Cmd(0x3F); // \ 1 / 64 duty

    OLED_Write_Cmd(0xDA); // 设置列引脚硬件配置 -- set com pins hardware configuration
    OLED_Write_Cmd(0x12); // \ Sequential COM pin configuration,Enable COM Left/Right remap

    /* ----- 方向显示配置 ----- */
    OLED_Write_Cmd(0xA1); // 设置段重映射 -- Set SEG / Column Mapping     0xA0左右反置(复位值) 0xA1正常(重映射值)
    OLED_Write_Cmd(0xC8); // 设置行输出扫描方向 -- Set COM / Row Scan Direction   0xc0上下反置(复位值) 0xC8正常(重映射值)
    /* ----- END ----- */

    OLED_Write_Cmd(0x40); // 设置设置屏幕(GDDRAM)起始行 -- Set Display Start Line (0x40~0x7F)

    OLED_Write_Cmd(0xD3); // 设置显示偏移 -- set display offset (0x00~0x3F)
    OLED_Write_Cmd(0x00); // \ not offset 偏移值是 0

    OLED_Write_Cmd(0x81); // 设置对比度 -- set contrast control register (0x00~0x100)
    OLED_Write_Cmd(0xCF); // \ Set SEG Output Current Brightness

    OLED_Write_Cmd(0xD9); // 设置预充电期间的持续时间 -- set pre-charge period
    OLED_Write_Cmd(0xF1); // \ Set Pre-Charge as 15 Clocks & Discharge as 1 Clock

    OLED_Write_Cmd(0xDB); // 调整VCOMH调节器的输出 -- set vcomh (0x00 / 0x20 / 0x30)
    OLED_Write_Cmd(0x20); // \ Set VCOM Deselect Level

    OLED_Write_Cmd(0x8D); // 电荷泵设置 -- set Charge Pump enable / disable (0x14 / 0x10)
    OLED_Write_Cmd(0x14); // \ 启用电荷泵 Enable charge pump during display on

    OLED_Write_Cmd(0xA4); //  全局显示开启(黑屏/亮屏)  (0xA4 根据RAM 内容显示 / 0xA5 每个oled都点亮 全部显示)

    OLED_Write_Cmd(0xA6); // 设置显示方式(正常/反显) -- set normal display (0xA6 / 0xA7)

    OLED_Write_Cmd(0xAF); // 打开OLED -- turn on oled panel : OXAE 关闭OLED 休眠模式 0xaf 打开oled
    OLED_Fill(0x00);      // 初始清屏
    OLED_Coord(0, 0);     // 设置原点坐标(0, 0)
}

代码

/************************************************************************************
*  Copyright (c), 2014, HelTec Automatic Technology co.,LTD.
*            All rights reserved.
*
* Http:    www.heltec.cn
* Email:   [email protected]
* WebShop: heltec.taobao.com
*
* File name: OLED_I2C.c
* Project  : HelTec.uvprij
* Processor: STM32F103C8T6
* Compiler : MDK fo ARM
* 
* Author : 小林
* Version: 1.00
* Date   : 2014.4.8
* Email  : [email protected]
* Modification: none
* 
* Description:128*64点阵的OLED显示屏驱动文件,仅适用于惠特自动化(heltec.taobao.com)的SD1306驱动IIC通信方式显示屏
*
* Others: none;
*
* Function List:
*	1. void I2C_Configuration(void) -- 配置CPU的硬件I2C
* 2. void I2C_WriteByte(uint8_t addr,uint8_t data) -- 向寄存器地址写一个byte的数据
* 3. void WriteCmd(unsigned char I2C_Command) -- 写命令
* 4. void WriteDat(unsigned char I2C_Data) -- 写数据
* 5. void OLED_Init(void) -- OLED屏初始化
* 6. void OLED_SetPos(unsigned char x, unsigned char y) -- 设置起始点坐标
* 7. void OLED_Fill(unsigned char fill_Data) -- 全屏填充
* 8. void OLED_CLS(void) -- 清屏
* 9. void OLED_ON(void) -- 唤醒
* 10. void OLED_OFF(void) -- 睡眠
* 11. void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize) -- 显示字符串(字体大小有6*8和8*16两种)
* 12. void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N) -- 显示中文(中文需要先取模,然后放到codetab.h中)
* 13. void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]) -- BMP图片
*
* History: none;
*
*************************************************************************************/

#include "OLED_I2C.h"
#include "delay.h"
#include "codetab.h"

void I2C_Configuration(void)
{
	I2C_InitTypeDef  I2C_InitStructure;
	GPIO_InitTypeDef  GPIO_InitStructure; 

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

	/*STM32F103C8T6芯片的硬件I2C: PB6 -- SCL; PB7 -- SDA */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//I2C必须开漏输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	I2C_DeInit(I2C1);//使用I2C1
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机的I2C地址,随便写的
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_ClockSpeed = 400000;//400K

	I2C_Cmd(I2C1, ENABLE);
	I2C_Init(I2C1, &I2C_InitStructure);
}

void I2C_WriteByte(uint8_t addr,uint8_t data)
{
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
	
	I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/

	I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 默认0x78
	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);//关闭I2C1总线
}

void WriteCmd(unsigned char I2C_Command)//写命令
{
	I2C_WriteByte(0x00, I2C_Command);
}

void WriteDat(unsigned char I2C_Data)//写数据
{
	I2C_WriteByte(0x40, I2C_Data);
}

void OLED_Init(void)
{
	DelayMs(100); //这里的延时很重要
	
	WriteCmd(0xAE); //display off

	WriteCmd(0x20);	//Set Memory Addressing Mode	
	WriteCmd(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
	
	WriteCmd(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7

	WriteCmd(0xc8);	//Set COM Output Scan Direction

	WriteCmd(0x00); //---set low column address
	WriteCmd(0x10); //---set high column address

	WriteCmd(0x40); //--set start line address

	WriteCmd(0x81); //--set contrast control register
	WriteCmd(0xff); //亮度调节 0x00~0xff

	WriteCmd(0xa1); //--set segment re-map 0 to 127
	WriteCmd(0xa6); //--set normal display
	WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
	WriteCmd(0x3F); //

	WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content

	WriteCmd(0xd3); //-set display offset
	WriteCmd(0x00); //-not offset

	WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
	WriteCmd(0xf0); //--set divide ratio

	WriteCmd(0xd9); //--set pre-charge period
	WriteCmd(0x22); //

	WriteCmd(0xda); //--set com pins hardware configuration
	WriteCmd(0x12);

	WriteCmd(0xdb); //--set vcomh
	WriteCmd(0x20); //0x20,0.77xVcc

	WriteCmd(0x8d); //--set DC-DC enable
	WriteCmd(0x14); //

	WriteCmd(0xaf); //--turn on oled panel
}

void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{ 
	WriteCmd(0xb0+y);
	WriteCmd(((x&0xf0)>>4)|0x10);
	WriteCmd((x&0x0f)|0x01);
}

void OLED_Fill(unsigned char fill_Data)//全屏填充
{
	unsigned char m,n;
	for(m=0;m<8;m++)
	{
		WriteCmd(0xb0+m);		//page0-page1
		WriteCmd(0x00);		//low column start address 列地址的低4位
		WriteCmd(0x10);		//high column start address 列地址的高4位
		for(n=0;n<128;n++)
			{
				WriteDat(fill_Data);
			}
	}
}

void OLED_CLS(void)//清屏
{
	OLED_Fill(0x00);
}

//--------------------------------------------------------------
// Prototype      : void OLED_ON(void)
// Calls          : 
// Parameters     : none
// Description    : 将OLED从休眠中唤醒
//--------------------------------------------------------------
void OLED_ON(void)
{
	WriteCmd(0X8D);  //设置电荷泵
	WriteCmd(0X14);  //开启电荷泵
	WriteCmd(0XAF);  //OLED唤醒
}

//--------------------------------------------------------------
// Prototype      : void OLED_OFF(void)
// Calls          : 
// Parameters     : none
// Description    : 让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
//--------------------------------------------------------------
void OLED_OFF(void)
{
	WriteCmd(0X8D);  //设置电荷泵
	WriteCmd(0X10);  //关闭电荷泵
	WriteCmd(0XAE);  //OLED休眠
}

//--------------------------------------------------------------
/*
Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
Calls          : 
Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7);
ch[] -- 要显示的字符串; 
TextSize -- 字符大小(1:6*8 ; 2:8*16)
Description    : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
//--------------------------------------------------------------
*/
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)
	{
		case 1:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 126)
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<6;i++)
					WriteDat(F6x8[c][i]);
				x += 6;
				j++;
			}
		}break;
		case 2:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i]);
				OLED_SetPos(x,y+1);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}

//--------------------------------------------------------------
// Prototype      : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls          : 
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引
// Description    : 显示codetab.h中的汉字,16*16点阵
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
	unsigned char wm=0;
	unsigned int  adder=32*N;
	OLED_SetPos(x , y);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
	OLED_SetPos(x,y + 1);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
}

//--------------------------------------------------------------
// Prototype      : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Calls          : 
// Parameters     : x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); 
// 					x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
// Description    : 显示BMP位图
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
	unsigned int j=0;
	unsigned char x,y;

  if(y1%8==0)
		y = y1/8;
  else
		y = y1/8 + 1;
	for(y=y0;y<y1;y++)
	{
		OLED_SetPos(x0,y);
    for(x=x0;x<x1;x++)
		{
			WriteDat(BMP[j++]);
		}
	}
}
#ifndef __OLED_I2C_H
#define	__OLED_I2C_H

#include "stm32f10x.h"

#define OLED_ADDRESS	0x78 //通过调整0R电阻,屏可以0x78和0x7A两个地址 -- 默认0x78

void I2C_Configuration(void);
void I2C_WriteByte(uint8_t addr,uint8_t data);
void WriteCmd(unsigned char I2C_Command);
void WriteDat(unsigned char I2C_Data);
void OLED_Init(void);
void OLED_SetPos(unsigned char x, unsigned char y);
void OLED_Fill(unsigned char fill_Data);
void OLED_CLS(void);
void OLED_ON(void);
void OLED_OFF(void);
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize);
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N);
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);

#endif

Guess you like

Origin blog.csdn.net/u010261063/article/details/119282317