声明:本专题主要针对训练营的同学开设的,因为了解到大家对于一些常用模块还是不会使用,因此开设次专栏去给大家讲解,如何在项目中来快速入门一些模块,转载请注明出处。
作者:渣渣鑫

目录

  • 专题:OLED的使用说明
    • OLED介绍
    • 硬件配置
    • 软件配置(IIC协议层)
    • oled配置代码(这个大家直接移植就行)
    • 简单讲一下字模软件的使用吧(没有的找我要)
    • 总结
    • 点赞+再看是对我最大的鼓励!!!

专题:OLED的使用说明

OLED介绍

OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。

OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,并且能够节省电能,从2003年开始这种显示设备在MP3播放器上得到了应用。

LCD都需要背光,而OLED不需要,因为它是自发光的。这样同样的显示,OLED效果要来得好一些。以目前的技术,OLED的尺寸还难以大型化,但是分辨率确可以做到很高。

硬件配置

主要使用的IIC总线上的SDA数据线和SCL时钟线,这里接上拉电阻的目的是当iic总线处于空闲状态的时候,能够处于高电平状态。从图中我们可以看出来iic总线是支持多设备的。

软件配置(IIC协议层)

在配置IIC总线之前,我们需要先把相应的GPIO端口控制线打开

/***********************************  重写IIC时序  *****************************************************/
//初始化GPIO
/*SDA输出模式 PA3*/
void OLED_SDA_OUT(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_OLED_SDA, ENABLE);  /* 打开GPIO时钟 */GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   /* 开漏输出 */GPIO_Init(OLED_SDA_PORT, &GPIO_InitStructure);
}/*SDA输入模式 PA3*/
void OLED_SDA_IN(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_OLED_SDA, ENABLE);  /* 打开GPIO时钟 */GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    /* // 浮空输入 */GPIO_Init(OLED_SDA_PORT, &GPIO_InitStructure);
}

先要简单了解SDA与SCL的作用:当SCL处于高电平的时候,SDA上面的数据必须保持稳定。只有当SCL为低电平的时候,才允许SDA线的数据发生变化。

时序图必须要能看懂!

1、启动信号配置:SCL高电平期间,SDA电平由高到低跳变,我们代码就是去模拟这个过程。

/*i2c 起始信号*/
void OLED_Start(void)
{OLED_SDA_OUT(); //sda线输出OLED_SCL_HIGH;OLED_SDA_HIGH;i2c_delay();/*当CLK为高时,SDA由高变为低*/OLED_SDA_L0W;i2c_delay();/*将SCL电位拉低,钳住SCL线,准备发送地址数据*/OLED_SCL_L0W;
}

2、停止信号:当SCL为高电平期间,SDA由低电平变为高电平

/*i2c 停止信号*/
void OLED_Stop(void)
{OLED_SDA_OUT(); //sda线输出/*scl为高电平时,SDA由低电平变为高电平*/OLED_SDA_L0W;OLED_SCL_L0W;i2c_delay();OLED_SCL_HIGH;OLED_SDA_HIGH;i2c_delay();
}

3、空闲状态:当IIC总线的数据线SDA和时钟线SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

4、应答信号:发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位NACK),一般表示接收器接收该字节没有成功。

检测应答:

  • SCL为高电平的时候可以读取SDA的状态,因此可以将SDA模式切换为输入模式,读取SDA引脚状态,0位应答,1位非应答

  • SCL为低电平允许数据发生变化

  • SDA:为高电平的时候可以占用总线,此时将SDA拉低,开始通信。当为低电平的时候,SDA已经被占用。
    SCL: SCL为高电平的时候要求数据稳定 SCL为低电平的时候允许数据改变

等待应答的作用就是来判断SDA传给的是低电平还是高电平。


/*等待应答信号到来 (有效应答:从机第9个 SCL=0 时 SDA 被从机拉低,并且 SCL = 1时 SDA依然为低)
返回值: 1,接收应答失败0,接收应答成功*/uint8_t OLED_WaitAck(void)
{uint8_t ucErrTime=0;OLED_SDA_IN(); //SDA设置为输入模式  (从机给一个低电平做为应答) OLED_SDA_HIGH;i2c_delay();     OLED_SCL_HIGH;i2c_delay();   //读取SDA的电平状态 while(OLED_SDA_Read){ucErrTime++;if(ucErrTime>250){OLED_Stop();return 1;//接收应答失败}}OLED_SCL_L0W; //时钟输出0      return 0;  //接收应答成功
}

有效应答和无效应答:

void OLED_Ack(void)
{OLED_SCL_L0W;OLED_SDA_OUT();OLED_SDA_L0W;i2c_delay();  OLED_SCL_HIGH;i2c_delay();  OLED_SCL_L0W;
}void OLED_NAck(void)
{OLED_SCL_L0W;OLED_SDA_OUT();OLED_SDA_HIGH;i2c_delay(); OLED_SCL_HIGH;i2c_delay();  OLED_SCL_L0W;
}       

5、字节格式:
SDA数据线上的每个字节必须是8位,每次传输的字节数量没有限制。每个字节后必须跟一个响应位(ACK)。首先传输的数据是最高位(MSB),SDA上的数据必须在SCL高电平周期时保持稳定,数据的高低电平翻转变化发生在SCL低电平时期。

  • 每一个字节后面跟着一个ACK,有ACK就可以继续写或读。NACK,就停止

  • ACK:主机释放总线,传输完字节最后1位后的SCL的高电处,从机拉低电平。

  • NACK:主机释放总线,传输完字节最后1位后的SCL的高电处,从机无响应,总线为高电平。

发送数据:

/******************************************************************************
*函  数:void IIC_SendByte(uint8_t txd)
*功  能:IIC发送一个字节
*参  数:data 要写的数据
*返回值:无
*备  注:主机往从机发
*******************************************************************************/
void OLED_SendByte(uint8_t data)
{                        uint8_t t;   OLED_SDA_OUT();       OLED_SCL_L0W; //拉低时钟开始数据传输for(t=0;t<8;t++){              if((data&0x80)>>7)//0x80=1000 0000OLED_SDA_HIGH;elseOLED_SDA_L0W;data<<=1;i2c_delay();         OLED_SCL_HIGH;i2c_delay();  OLED_SCL_L0W;   i2c_delay();    }
}

读取数据:

uint8_t OLED_ReadByte(uint8_t ack)
{uint8_t i,receive=0;OLED_SDA_IN(); //SDA设置为输入模式 等待接收从机返回数据for(i=0;i<8;i++ ){OLED_SCL_L; i2c_delay();OLED_SCL_H;receive<<=1;if(OLED_SDA_Read)receive++; //从机发送的电平i2c_delay();}                   if(ack)OLED_Ack(); //发送ACK elseOLED_NAck(); //发送nACK  return receive;
}

总结:最难的时序部分代码完成后,就可以使用模拟的iic代码来完成oled屏幕代码的初始化了

oled配置代码(这个大家直接移植就行)

//初始化SSD1306
// 端口用PA5,PA6
void OLED_Init(void)
{   GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能A端口时钟GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN|OLED_SDA_PIN;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);      //初始化GPIO_SetBits(GPIOA,OLED_SCL_PIN|OLED_SDA_PIN);delay_ms(800);OLED_WR_Byte(0xAE,OLED_CMD);//--display offOLED_WR_Byte(0x00,OLED_CMD);//---set low column addressOLED_WR_Byte(0x10,OLED_CMD);//---set high column addressOLED_WR_Byte(0x40,OLED_CMD);//--set start line address  OLED_WR_Byte(0xB0,OLED_CMD);//--set page addressOLED_WR_Byte(0x81,OLED_CMD); // contract controlOLED_WR_Byte(0xFF,OLED_CMD);//--128   OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverseOLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 dutyOLED_WR_Byte(0xC8,OLED_CMD);//Com scan directionOLED_WR_Byte(0xD3,OLED_CMD);//-set display offsetOLED_WR_Byte(0x00,OLED_CMD);//OLED_WR_Byte(0xD5,OLED_CMD);//set osc divisionOLED_WR_Byte(0x80,OLED_CMD);//OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode offOLED_WR_Byte(0x05,OLED_CMD);//OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge PeriodOLED_WR_Byte(0xF1,OLED_CMD);//OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartionOLED_WR_Byte(0x12,OLED_CMD);//OLED_WR_Byte(0xDB,OLED_CMD);//set VcomhOLED_WR_Byte(0x30,OLED_CMD);//OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enableOLED_WR_Byte(0x14,OLED_CMD);//OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}  /********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{unsigned char m,n;for(m=0;m<8;m++){OLED_WR_Byte(0xb0+m,0);      //page0-page1OLED_WR_Byte(0x00,0);      //low column start addressOLED_WR_Byte(0x10,0);     //high column start addressfor(n=0;n<128;n++){OLED_WR_Byte(fill_Data,1);}}
}/***********************Delay****************************************/
void Delay_50ms(unsigned int Del_50ms)
{unsigned int m;for(;Del_50ms>0;Del_50ms--)for(m=6245;m>0;m--);
}void Delay_1ms(unsigned int Del_1ms)
{unsigned char j;while(Del_1ms--){  for(j=0;j<123;j++);}
}//坐标设置void OLED_Set_Pos(unsigned char x, unsigned char y)
{ OLED_WR_Byte(0xb0+y,OLED_CMD);OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);OLED_WR_Byte((x&0x0f),OLED_CMD);
}
//开启OLED显示
void OLED_Display_On(void)
{OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ONOLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFFOLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{  u8 i,n;          for(i=0;i<8;i++)  {  OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); } //更新显示
}
void OLED_On(void)
{  u8 i,n;          for(i=0;i<8;i++)  {  OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); } //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{       unsigned char c=0,i=0;    c=chr-' ';//得到偏移后的值          if(x>Max_Column-1){x=0;y=y+2;}if(Char_Size ==16){OLED_Set_Pos(x,y); for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);OLED_Set_Pos(x,y+1);for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);}else {   OLED_Set_Pos(x,y);for(i=0;i<6;i++)OLED_WR_Byte(F6x8[c][i],OLED_DATA);}
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{u32 result=1;  while(n--)result*=m;    return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式   0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{           u8 t,temp;u8 enshow=0;                        for(t=0;t<len;t++){temp=(num/oled_pow(10,len-t-1))%10;if(enshow==0&&t<(len-1)){if(temp==0){OLED_ShowChar(x+(size2/2)*t,y,' ',size2);continue;}else enshow=1; }OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); }
} void OLED_Float(unsigned char Y,unsigned char X,double real,unsigned char N)
{unsigned char   i_Count=1;unsigned char   n[12]={0};long   j=1;  int    real_int=0;double decimal=0;unsigned int   real_decimal=0;if(real<0){real_int=(int)(-real);}else{real_int=(int)real;}decimal=real-real_int;real_decimal=decimal*1e4;while(real_int/10/j!=0){j=j*10;i_Count++;  } n[0]=(real_int/10000)%10; n[1]=(real_int/1000)%10;n[2]=(real_int/100)%10;n[3]=(real_int/10)%10;n[4]=(real_int/1)%10; n[5]='.';n[6]=(real_decimal/1000)%10;n[7]=(real_decimal/100)%10;n[8]=(real_decimal/10)%10;n[9]=real_decimal%10;n[6+N]='\0'; for(j=0;j<10;j++) n[j]=n[j]+16+32;if(real<0) {       i_Count+=1;n[5-i_Count]='-';}n[5]='.';n[6+N]='\0';   OLED_ShowString(X,Y,&n[5-i_Count],12);
}//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{unsigned char j=0;while (chr[j]!='\0'){        OLED_ShowChar(x,y,chr[j],Char_Size);x+=8;if(x>120){x=0;y+=2;}j++;}
}
//显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{                   u8 t,adder=0;OLED_Set_Pos(x,y);    for(t=0;t<16;t++){OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);adder+=1;}   OLED_Set_Pos(x,y+1);   for(t=0;t<16;t++){    OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);adder+=1;}
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
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_Set_Pos(x0,y);for(x=x0;x<x1;x++){      OLED_WR_Byte(BMP[j++],OLED_DATA);          }}
}

这里会用到一个子模库:

简单讲一下字模软件的使用吧(没有的找我要)

配置要正确

最后我把完整的工程代码给大家!如果前面都看不懂的,就按我这个配置来!

#include "./OLED/oled.h"
#include "oledfont.h"
#include "./systick/bsp_systick.h"
#include "stdlib.h"    /*因为oled与6050的I2C引脚相同,所以oled要单独模拟I2C来用SCL----PA4SDA----PA5*//*宏定义*/
/*********************************************************************************/
#define RCC_OLED_SCL         RCC_APB2Periph_GPIOA  //端口时钟
#define OLED_SCL_PORT        GPIOA
#define OLED_SCL_PIN         GPIO_Pin_4#define RCC_OLED_SDA         RCC_APB2Periph_GPIOA  //端口时钟
#define OLED_SDA_PORT        GPIOA
#define OLED_SDA_PIN         GPIO_Pin_5/*********************************************************************************/
/*操作IO口*/
/*********************************************************************************/
#define OLED_SCL_L0W          (OLED_SCL_PORT->BRR = OLED_SCL_PIN)
#define OLED_SCL_HIGH         (OLED_SCL_PORT->BSRR = OLED_SCL_PIN)#define OLED_SDA_L0W          (OLED_SDA_PORT->BRR = OLED_SDA_PIN)
#define OLED_SDA_HIGH         (OLED_SDA_PORT->BSRR = OLED_SDA_PIN)
/*读取电平状态,低电平返回0,高电平返回非0*/
#define OLED_SDA_Read         ((OLED_SDA_PORT->IDR &OLED_SDA_PIN) != 0)
/*********************************************************************************//*********************************************************************************/
/*简单的延时函数*/
static void i2c_delay(void)
{delay_us(4);
}
/*********************************************************************************//*********************************************************************************/
/*先将SDA,SCL配置成开漏输出模式,再配置SDA的输入输出模式*/
/*i2c端口模式初始化SDA---->PA3SCL---->PA2
*/
//void i2c_MoniConfig(void)
//{//  GPIO_InitTypeDef GPIO_InitStructure;
//  RCC_APB2PeriphClockCmd(RCC_OLED_SCL, ENABLE);   /* 打开GPIO时钟 */
//  GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN ;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   /* 开漏输出 */
//  GPIO_Init(OLED_SCL_PORT, &GPIO_InitStructure);
//  OLED_SCL_HIGH;
//
//  RCC_APB2PeriphClockCmd(RCC_OLED_SDA, ENABLE);   /* 打开GPIO时钟 */
//  GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   /* 开漏输出 */
//  GPIO_Init(OLED_SDA_PORT, &GPIO_InitStructure);
//  OLED_SDA_HIGH;
//}/*SDA输出模式 PA3*/
void OLED_SDA_OUT(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_OLED_SDA, ENABLE);  /* 打开GPIO时钟 */GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   /* 开漏输出 */GPIO_Init(OLED_SDA_PORT, &GPIO_InitStructure);
}/*SDA输入模式 PA3*/
void OLED_SDA_IN(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_OLED_SDA, ENABLE);  /* 打开GPIO时钟 */GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    /* // 浮空输入 */GPIO_Init(OLED_SDA_PORT, &GPIO_InitStructure);
}
/*********************************************************************************//*i2c 起始信号*/
void OLED_Start(void)
{OLED_SDA_OUT(); //sda线输出OLED_SCL_HIGH;OLED_SDA_HIGH;i2c_delay();/*当CLK为高时,SDA由高变为低*/OLED_SDA_L0W;i2c_delay();/*将SCL电位拉低,钳住SCL线,准备发送地址数据*/OLED_SCL_L0W;
}/*i2c 停止信号*/
void OLED_Stop(void)
{OLED_SDA_OUT(); //sda线输出/*scl为高电平时,SDA由低电平变为高电平*/OLED_SDA_L0W;OLED_SCL_L0W;i2c_delay();OLED_SCL_HIGH;OLED_SDA_HIGH;i2c_delay();
}/*等待应答信号到来 (有效应答:从机第9个 SCL=0 时 SDA 被从机拉低,并且 SCL = 1时 SDA依然为低)
返回值: 1,接收应答失败0,接收应答成功*/uint8_t OLED_WaitAck(void)
{uint8_t ucErrTime=0;OLED_SDA_IN(); //SDA设置为输入  (从机给一个低电平做为应答) OLED_SDA_HIGH;i2c_delay();       OLED_SCL_HIGH;i2c_delay();    while(OLED_SDA_Read){ucErrTime++;if(ucErrTime>250){OLED_Stop();return 1;}}OLED_SCL_L0W; //时钟输出0      return 0;
} void OLED_Ack(void)
{OLED_SCL_L0W;OLED_SDA_OUT();OLED_SDA_L0W;i2c_delay();  OLED_SCL_HIGH;i2c_delay();  OLED_SCL_L0W;
}void OLED_NAck(void)
{OLED_SCL_L0W;OLED_SDA_OUT();OLED_SDA_HIGH;i2c_delay(); OLED_SCL_HIGH;i2c_delay();  OLED_SCL_L0W;
}       /******************************************************************************
*函  数:void IIC_SendByte(uint8_t txd)
*功  能:IIC发送一个字节
*参  数:data 要写的数据
*返回值:无
*备  注:主机往从机发
*******************************************************************************/
void OLED_SendByte(uint8_t data)
{                        uint8_t t;   OLED_SDA_OUT();       OLED_SCL_L0W; //拉低时钟开始数据传输for(t=0;t<8;t++){              if((data&0x80)>>7)OLED_SDA_HIGH;elseOLED_SDA_L0W;data<<=1;i2c_delay();          OLED_SCL_HIGH;i2c_delay();  OLED_SCL_L0W;   i2c_delay();    }
}    #define OLED_SCL_L   OLED_SCL_L0W
#define OLED_SCL_H   OLED_SCL_HIGH/******************************************************************************
*函  数:uint8_t IIC_ReadByte(uint8_t ack)
*功  能:IIC读取一个字节
*参  数:ack=1 时,主机数据还没接收完 ack=0 时主机数据已全部接收完成
*返回值:无
*备  注:从机往主机发
*******************************************************************************/
uint8_t OLED_ReadByte(uint8_t ack)
{uint8_t i,receive=0;OLED_SDA_IN(); //SDA设置为输入模式 等待接收从机返回数据for(i=0;i<8;i++ ){OLED_SCL_L; i2c_delay();OLED_SCL_H;receive<<=1;if(OLED_SDA_Read)receive++; //从机发送的电平i2c_delay();}                   if(ack)OLED_Ack(); //发送ACK elseOLED_NAck(); //发送nACK  return receive;
}void Write_IIC_Command(unsigned char IIC_Command)
{OLED_Start();OLED_SendByte(0x78);            //Slave address,SA0=0OLED_WaitAck(); OLED_SendByte(0x00);            //write commandOLED_WaitAck();  OLED_SendByte(IIC_Command); OLED_WaitAck(); OLED_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{OLED_Start();OLED_SendByte(0x78);          //D/C#=0; R/W#=0OLED_WaitAck();   OLED_SendByte(0x40);            //write dataOLED_WaitAck(); OLED_SendByte(IIC_Data);OLED_WaitAck(); OLED_Stop();
}
/*******************************************************************************************************************/void OLED_WR_Byte(unsigned dat,unsigned cmd)
{if(cmd){Write_IIC_Data(dat);}else {Write_IIC_Command(dat);}
}//初始化SSD1306
// 端口用PA5,PA6
void OLED_Init(void)
{   GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能A端口时钟GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN|OLED_SDA_PIN;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);      //初始化GPIO_SetBits(GPIOA,OLED_SCL_PIN|OLED_SDA_PIN);delay_ms(800);OLED_WR_Byte(0xAE,OLED_CMD);//--display offOLED_WR_Byte(0x00,OLED_CMD);//---set low column addressOLED_WR_Byte(0x10,OLED_CMD);//---set high column addressOLED_WR_Byte(0x40,OLED_CMD);//--set start line address  OLED_WR_Byte(0xB0,OLED_CMD);//--set page addressOLED_WR_Byte(0x81,OLED_CMD); // contract controlOLED_WR_Byte(0xFF,OLED_CMD);//--128   OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverseOLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 dutyOLED_WR_Byte(0xC8,OLED_CMD);//Com scan directionOLED_WR_Byte(0xD3,OLED_CMD);//-set display offsetOLED_WR_Byte(0x00,OLED_CMD);//OLED_WR_Byte(0xD5,OLED_CMD);//set osc divisionOLED_WR_Byte(0x80,OLED_CMD);//OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode offOLED_WR_Byte(0x05,OLED_CMD);//OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge PeriodOLED_WR_Byte(0xF1,OLED_CMD);//OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartionOLED_WR_Byte(0x12,OLED_CMD);//OLED_WR_Byte(0xDB,OLED_CMD);//set VcomhOLED_WR_Byte(0x30,OLED_CMD);//OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enableOLED_WR_Byte(0x14,OLED_CMD);//OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}  /********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{unsigned char m,n;for(m=0;m<8;m++){OLED_WR_Byte(0xb0+m,0);      //page0-page1OLED_WR_Byte(0x00,0);      //low column start addressOLED_WR_Byte(0x10,0);     //high column start addressfor(n=0;n<128;n++){OLED_WR_Byte(fill_Data,1);}}
}/***********************Delay****************************************/
void Delay_50ms(unsigned int Del_50ms)
{unsigned int m;for(;Del_50ms>0;Del_50ms--)for(m=6245;m>0;m--);
}void Delay_1ms(unsigned int Del_1ms)
{unsigned char j;while(Del_1ms--){  for(j=0;j<123;j++);}
}//坐标设置void OLED_Set_Pos(unsigned char x, unsigned char y)
{ OLED_WR_Byte(0xb0+y,OLED_CMD);OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);OLED_WR_Byte((x&0x0f),OLED_CMD);
}
//开启OLED显示
void OLED_Display_On(void)
{OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ONOLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFFOLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{  u8 i,n;          for(i=0;i<8;i++)  {  OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); } //更新显示
}
void OLED_On(void)
{  u8 i,n;          for(i=0;i<8;i++)  {  OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); } //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{       unsigned char c=0,i=0;    c=chr-' ';//得到偏移后的值          if(x>Max_Column-1){x=0;y=y+2;}if(Char_Size ==16){OLED_Set_Pos(x,y); for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);OLED_Set_Pos(x,y+1);for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);}else {   OLED_Set_Pos(x,y);for(i=0;i<6;i++)OLED_WR_Byte(F6x8[c][i],OLED_DATA);}
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{u32 result=1;  while(n--)result*=m;    return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式   0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{           u8 t,temp;u8 enshow=0;                        for(t=0;t<len;t++){temp=(num/oled_pow(10,len-t-1))%10;if(enshow==0&&t<(len-1)){if(temp==0){OLED_ShowChar(x+(size2/2)*t,y,' ',size2);continue;}else enshow=1; }OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); }
} void OLED_Float(unsigned char Y,unsigned char X,double real,unsigned char N)
{unsigned char   i_Count=1;unsigned char   n[12]={0};long   j=1;  int    real_int=0;double decimal=0;unsigned int   real_decimal=0;if(real<0){real_int=(int)(-real);}else{real_int=(int)real;}decimal=real-real_int;real_decimal=decimal*1e4;while(real_int/10/j!=0){j=j*10;i_Count++;  } n[0]=(real_int/10000)%10; n[1]=(real_int/1000)%10;n[2]=(real_int/100)%10;n[3]=(real_int/10)%10;n[4]=(real_int/1)%10; n[5]='.';n[6]=(real_decimal/1000)%10;n[7]=(real_decimal/100)%10;n[8]=(real_decimal/10)%10;n[9]=real_decimal%10;n[6+N]='\0'; for(j=0;j<10;j++) n[j]=n[j]+16+32;if(real<0) {       i_Count+=1;n[5-i_Count]='-';}n[5]='.';n[6+N]='\0';   OLED_ShowString(X,Y,&n[5-i_Count],12);
}//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{unsigned char j=0;while (chr[j]!='\0'){        OLED_ShowChar(x,y,chr[j],Char_Size);x+=8;if(x>120){x=0;y+=2;}j++;}
}
//显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{                   u8 t,adder=0;OLED_Set_Pos(x,y);    for(t=0;t<16;t++){OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);adder+=1;}   OLED_Set_Pos(x,y+1);   for(t=0;t<16;t++){    OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);adder+=1;}
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
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_Set_Pos(x0,y);for(x=x0;x<x1;x++){      OLED_WR_Byte(BMP[j++],OLED_DATA);          }}
} 

总结

以上就是oled屏幕和iic时序的全部讲解啦!
我想对训练营的同学说一下,态度决定成败!我为大家付出这么多,希望各位不要辜负我的努力。希望大家都能够将我安排的任务认真完成。

点赞+再看是对我最大的鼓励!!!

想学习更多知识可以加入我的公众号哈!

有想加入训练营的小伙伴可以私聊我哦!

项目训练营模块学习---Oled屏幕相关推荐

  1. OLED模块以及OLED屏幕上显示

    一.OLED简介 OLED(Organic Light Emitting Diode):有机发光二极管 OLED显示屏:性能优异的新型显示屏,具有功耗低.相应速度快.宽视角.轻薄柔韧等特点 0.96寸 ...

  2. stm32单片机屏幕一直闪_基于STM32单片机实现屏幕休眠后OLED屏幕滚动效果

    这次做项目时需要实现OLED屏幕上字符滚动的功能,从网上找到一个参考:https://blog.csdn.net/tbmmagic/article/details/111999673 int main ...

  3. STM32(基于HAL库)驱动0.96寸OLED屏幕(六脚)

    STM32驱动0.96寸OLED屏幕(六脚) 1 序言 2 如何利用STM32单片机驱动12864液晶屏 2.1*基本配置* 2.2 *0.96寸OLED端口含义* 2.3 *0.96寸OLED液晶屏 ...

  4. STM32固件库(标准外设库)入门学习 第四章OLED屏幕使用

    STM32固件库(标准外设库)入门学习 第四章OLED屏幕使用 本学习教程,参考B站江科大自化协STM32视频,型号为STM32F103C8T6. 文章目录 STM32固件库(标准外设库)入门学习 第 ...

  5. 物联网国赛LORA模块开发基础教程(通用库)—OLED屏幕

    LORA模块开发基础教程目录 物联网国赛LORA模块开发基础教程-开发环境配置 物联网国赛LORA模块开发基础教程-输出(LED) 物联网国赛LORA模块开发基础教程-输入(按键) 物联网国赛LORA ...

  6. OLED模块学习指南

    前言 OLED模块是一种通用型外设,可以被各种型号的微控制芯片操控.在此编者以TI公司生产的TMS320F28027芯片为例,根据自己使用该模块的经验,自定义了一系列使用方便的操作函数,并对整个模块的 ...

  7. 快速上手Arduino -- 打印超声波模块测距信息到OLED屏幕上

    文章目录 快速上手Arduino -- 打印超声波模块测距信息到OLED屏幕上 实现效果: 模块说明: 引脚接线方法: 程序源码 附录 快速上手Arduino – 打印超声波模块测距信息到OLED屏幕 ...

  8. ⑥ESP8266 开发学习笔记_By_GYC 【ESP8266 驱动 OLED屏幕】

    ⑥ESP8266 开发学习笔记_By_GYC [ESP8266 驱动 OLED屏幕] 目录 ⑥ESP8266 开发学习笔记_By_GYC [ESP8266 驱动 OLED屏幕] 适用范围 user_c ...

  9. 【PWM】从stm32到pwm到OLED屏幕调光到晚上不要玩手机

    一.前言 最近做项目,配置了单片机中PWM波形输出,配置单片机中的一个引脚输出PWM波,示波器查看这个波形,做了实践操作,有一些感想,将一些了解过的知识和常识结合,包括pwm.stm32单片机.引脚. ...

最新文章

  1. Qlik收购Idevio,为客户带来先进的地理信息分析功能
  2. 4.QPixmap,QTransform,绘图函数的使用
  3. myeclipse hbm2java_myeclipse试用小记----Hibernate多对一双向关联(2)
  4. java.lang.String小测试
  5. 650c公路车推荐_2020最具性价比的中高端公路整车盘点
  6. Android 内存数据库
  7. 有关深度学习领域的几点想法
  8. Spring事务(Transaction)
  9. 金融科技赋能 互融云手机回租系统 实现资产全流程在线运营管理
  10. eclipse Failed to create the part's controls 解决方法
  11. Surfacebook电池1充不上电解决办法亲测有效
  12. ps-ef命令linux,【Linux】- ps -ef |grep 命令
  13. python interpreter 中没有torch_python自动化办公之 Python 解析 PDF
  14. MetaQ安装部署文档
  15. 关于QC样本的制备与分析
  16. C++多线程学习06 利用RAII
  17. c#编写activeX控件详细教程,底部附有下载地址
  18. 盛迈坤电商:拼多多店铺怎么样推广
  19. Android响应式编程(一)RxJava前篇[入门基础]
  20. CSDN2018博客之星评选——期待各位大佬的投票!哈哈

热门文章

  1. PWM脉冲宽度调制,实现呼吸灯_领航者开发板
  2. [2013百度软件研发笔试题] 求字符串中连续出现同样字符的最大值
  3. 基于JAVA黑白图片和上色处理系统(Springboot框架+AI人工智能) 开题报告
  4. cf全屏下面桌面任务栏_还有玩CF时,下面会有任务栏。也就是说不能全屏!请问怎么回事...
  5. UTF8与GBK字符编码转换
  6. 一份超详细的IBM公司JAVA基础面试题附答案以及解析(题库)
  7. 项目开发遇到前端传递时间问题处理
  8. 对数函数 (logarithmic function)
  9. python中import string是什么意思_python string是什么
  10. Linux valgrind java_linux下利用valgrind工具进行内存泄露检测和性能分析