项目训练营模块学习---Oled屏幕
声明:本专题主要针对训练营的同学开设的,因为了解到大家对于一些常用模块还是不会使用,因此开设次专栏去给大家讲解,如何在项目中来快速入门一些模块,转载请注明出处。
作者:渣渣鑫
目录
- 专题: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屏幕相关推荐
- OLED模块以及OLED屏幕上显示
一.OLED简介 OLED(Organic Light Emitting Diode):有机发光二极管 OLED显示屏:性能优异的新型显示屏,具有功耗低.相应速度快.宽视角.轻薄柔韧等特点 0.96寸 ...
- stm32单片机屏幕一直闪_基于STM32单片机实现屏幕休眠后OLED屏幕滚动效果
这次做项目时需要实现OLED屏幕上字符滚动的功能,从网上找到一个参考:https://blog.csdn.net/tbmmagic/article/details/111999673 int main ...
- 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液晶屏 ...
- STM32固件库(标准外设库)入门学习 第四章OLED屏幕使用
STM32固件库(标准外设库)入门学习 第四章OLED屏幕使用 本学习教程,参考B站江科大自化协STM32视频,型号为STM32F103C8T6. 文章目录 STM32固件库(标准外设库)入门学习 第 ...
- 物联网国赛LORA模块开发基础教程(通用库)—OLED屏幕
LORA模块开发基础教程目录 物联网国赛LORA模块开发基础教程-开发环境配置 物联网国赛LORA模块开发基础教程-输出(LED) 物联网国赛LORA模块开发基础教程-输入(按键) 物联网国赛LORA ...
- OLED模块学习指南
前言 OLED模块是一种通用型外设,可以被各种型号的微控制芯片操控.在此编者以TI公司生产的TMS320F28027芯片为例,根据自己使用该模块的经验,自定义了一系列使用方便的操作函数,并对整个模块的 ...
- 快速上手Arduino -- 打印超声波模块测距信息到OLED屏幕上
文章目录 快速上手Arduino -- 打印超声波模块测距信息到OLED屏幕上 实现效果: 模块说明: 引脚接线方法: 程序源码 附录 快速上手Arduino – 打印超声波模块测距信息到OLED屏幕 ...
- ⑥ESP8266 开发学习笔记_By_GYC 【ESP8266 驱动 OLED屏幕】
⑥ESP8266 开发学习笔记_By_GYC [ESP8266 驱动 OLED屏幕] 目录 ⑥ESP8266 开发学习笔记_By_GYC [ESP8266 驱动 OLED屏幕] 适用范围 user_c ...
- 【PWM】从stm32到pwm到OLED屏幕调光到晚上不要玩手机
一.前言 最近做项目,配置了单片机中PWM波形输出,配置单片机中的一个引脚输出PWM波,示波器查看这个波形,做了实践操作,有一些感想,将一些了解过的知识和常识结合,包括pwm.stm32单片机.引脚. ...
最新文章
- Qlik收购Idevio,为客户带来先进的地理信息分析功能
- 4.QPixmap,QTransform,绘图函数的使用
- myeclipse hbm2java_myeclipse试用小记----Hibernate多对一双向关联(2)
- java.lang.String小测试
- 650c公路车推荐_2020最具性价比的中高端公路整车盘点
- Android 内存数据库
- 有关深度学习领域的几点想法
- Spring事务(Transaction)
- 金融科技赋能 互融云手机回租系统 实现资产全流程在线运营管理
- eclipse Failed to create the part's controls 解决方法
- Surfacebook电池1充不上电解决办法亲测有效
- ps-ef命令linux,【Linux】- ps -ef |grep 命令
- python interpreter 中没有torch_python自动化办公之 Python 解析 PDF
- MetaQ安装部署文档
- 关于QC样本的制备与分析
- C++多线程学习06 利用RAII
- c#编写activeX控件详细教程,底部附有下载地址
- 盛迈坤电商:拼多多店铺怎么样推广
- Android响应式编程(一)RxJava前篇[入门基础]
- CSDN2018博客之星评选——期待各位大佬的投票!哈哈
热门文章
- PWM脉冲宽度调制,实现呼吸灯_领航者开发板
- [2013百度软件研发笔试题] 求字符串中连续出现同样字符的最大值
- 基于JAVA黑白图片和上色处理系统(Springboot框架+AI人工智能) 开题报告
- cf全屏下面桌面任务栏_还有玩CF时,下面会有任务栏。也就是说不能全屏!请问怎么回事...
- UTF8与GBK字符编码转换
- 一份超详细的IBM公司JAVA基础面试题附答案以及解析(题库)
- 项目开发遇到前端传递时间问题处理
- 对数函数 (logarithmic function)
- python中import string是什么意思_python string是什么
- Linux valgrind java_linux下利用valgrind工具进行内存泄露检测和性能分析