简介:利用STM32F103C8T6芯片,0.96寸液晶屏显示与MPL3115A模块对大气压,海拔和温度的读取。
利用STM32作为主控对MPL3115A模块进行读取,并将显示的大气压值,温度值显示到液晶屏上面。
MPL3115A模块介绍:
20bit压力测量(Pascal);20bit高度测量(米);12bit温度测量;
绝对压力测量范围:20至110 kPa
相对测量精度: - + 0.05 kPa
有效分辨率:1.5Pa / 0.3m
工作温度范围:-40至85摄氏度;
I2C数字输出接口;
内置32个FIFO采样缓冲区;
软件代码流程如下:
/*配置SDA的IO口模式信息*/ void GPIO_Output_I2C_Configuration(GPIO_TypeDef* SDA, u16 GPIO_Pin) { GPIO_InitTypeDef GPIO_Initstructure; GPIO_Initstructure.GPIO_Pin = GPIO_Pin; GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SDA, &GPIO_Initstructure); } /*配置SCL的IO口模式信息*/ void GPIO_Input_I2C_Configuration(GPIO_TypeDef* SDA, u16 GPIO_Pin) { GPIO_InitTypeDef GPIO_Initstructure; GPIO_Initstructure.GPIO_Pin = GPIO_Pin; GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(SDA, &GPIO_Initstructure); } /*IIC总线启动*/ void I2C_Start ()//I2C开始 { GPIO_Output_I2C_Configuration(SCL.GPIOx, SCL.GPIO_Pin); //SCL置输出 GPIO_Output_I2C_Configuration(SDA.GPIOx, SDA.GPIO_Pin); //SDA置输出 GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=1; delay_us(50); //此处延时50us GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=1; delay_us(50); //此处延时50us GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=0; delay_us(50); //此处延时50us GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0; delay_us(50); //此处延时50us } /*IIC总线结束*/ void I2C_Stop () //I2C结束 { GPIO_Output_I2C_Configuration(SDA.GPIOx, SDA.GPIO_Pin); //SDA置输出 GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=0; delay_us(50); //此处延时50us GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=1; delay_us(50); //此处延时50us GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=1; delay_us(50); //此处延时50us } /*主机检查从机的响应信号*/ int I2C_Slave_ACK(void) // 检查从机应答信号,返回0有ACK,返回1无ACK { int ACK; u8 s1; GPIO_Input_I2C_Configuration(SDA.GPIOx, SDA.GPIO_Pin); //SDA置输入 GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=1; delay_us(50); //此处延时50us s1 = GPIO_ReadInputDataBit(SDA.GPIOx, SDA.GPIO_Pin); if (s1) //判断返回的数据类型,确定是否正常 { ACK = 1; } else { ACK = 0; } GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0; delay_us(50); //此处延时50us return(ACK); //返回应答信号 } /*主机发送IIC总线上一个字节数据*/ void I2C_SendByte(u8 data) //发送一个字节 { u8 i; //发送8位 GPIO_Output_I2C_Configuration(SDA.GPIOx, SDA.GPIO_Pin); //SDA置输出 for(i = 0; i < 8; i++) { if((data & 0x80) == 0x80) { GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin); } //SDA=1,写 1 else { GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin); } //SDA=0,写 0 GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=1; delay_us(50); //在时钟大于4u秒期间写数据 GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0; delay_us(50); //此处延时50us data = data << 1; //将返回的数据进行移位处理 } } /*主机接收IIC总线上一个字节数据*/ u8 I2C_ReciveByte(void) //接受一个字节 { u8 s1 = 0, temp1 = 0; u8 i; GPIO_Input_I2C_Configuration(SDA.GPIOx, SDA.GPIO_Pin); //SDA置输入 for(i = 0; i < 8; i++) { temp1 = temp1 << 1; GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=1; delay_us(50); //在时钟大于4u秒期间读数据 s1 = GPIO_ReadInputDataBit(SDA.GPIOx, SDA.GPIO_Pin); if(s1) //读 1 { temp1 = temp1 | 0x01; } else //读 0 { temp1 = temp1 & 0xfe; } GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0; delay_us(50); //此处延时50us } return(temp1); } /*主机向IC总线发送连续读信号*/ void I2C_ack(void) // 发送连续读信号 { GPIO_Output_I2C_Configuration(SDA.GPIOx, SDA.GPIO_Pin); //SDA置输出; GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=0; delay_us(50); //此处延时50us GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=1; delay_us(50); //此处延时50us GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0; } /*主机向IC总线发送不连续读信号*/ void I2C_nack(void) // 发送不连续读信号 { GPIO_Output_I2C_Configuration(SDA.GPIOx, SDA.GPIO_Pin); //SDA置输出 ; GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=1; delay_us(50); //此处延时50us GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=1; delay_us(50); //此处延时50us GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0; delay_us(50); //此处延时50us } void Write_MPL3115A2(u8 Address, u8 Dat) { I2C_Start(); //启动IIC时序 I2C_SendByte(MPL3115A2Wcmd);//主机发送MPL3115A2W的发送字节命令 I2C_Slave_ACK(); //主机等待模块返回应答指令 I2C_SendByte(Address);//主机发送MPL3115A2W的地址 I2C_Slave_ACK(); //主机等待模块返回应答指令 I2C_SendByte(Dat); //主机发送MPL3115A2W的数据 I2C_Slave_ACK(); //主机等待模块返回应答指令 I2C_Stop(); //停止IIC时序 } u8 MPL3115A2Read(u8 adrr) { char p; I2C_Start(); //启动IIC时序 I2C_SendByte(MPL3115A2Wcmd);//主机发送MPL3115A2W的发送字节命令 I2C_Slave_ACK(); //主机等待模块返回应答指令 I2C_SendByte(adrr); //主机发送MPL3115A2W的发送地址命令信息 I2C_Slave_ACK(); //主机等待模块返回应答指令 I2C_Start(); //启动IIC时序 I2C_SendByte(MPL3115A2Rcmd); I2C_Slave_ACK(); //主机等待模块返回应答指令 p = I2C_ReciveByte();//将模块返回 I2C_nack(); //确定IIC无应答 I2C_Stop(); //停止IIC时序 return p; } void MPL3115A2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); /************引脚设置******************/ SDA.GPIOx = GPIOB; SDA.GPIO_Pin = GPIO_Pin_13; SCL.GPIOx = GPIOB; SCL.GPIO_Pin = GPIO_Pin_12; /**************************************/ /* Set to Altimeter with an OSR = 1 */ Write_MPL3115A2(0x26, 0x80); /* Enable Data Flags in PT_DATA_CFG */ Write_MPL3115A2(0x13, 0x07); /* Set Active */ Write_MPL3115A2(0x26, 0xB9); } void MPL3115A2_Read(struct MPL3115A2 *p) { static u16 AData; static u8 BData, CData, DData; u16 pre; loat Alt_Integer,Alt_Fraction,Tmp_Integer,Tmp_Fraction,Pre_Integer,Pre_Fraction; //临时变量存放气压高度温度的小数和整数部分 /* Set to Altimeter with an OSR = 1 *///高度模式 Write_MPL3115A2(0x26, 0x80); /* Enable Data Flags in PT_DATA_CFG */ Write_MPL3115A2(0x13, 0x07); Write_MPL3115A2(0x26, 0xB9); /* Read STATUS Register */ while((MPL3115A2Read(0x00) & 0x08) == 0); AData = MPL3115A2Read(0x01) << 8 | MPL3115A2Read(0x02); BData = MPL3115A2Read(0x03); CData = MPL3115A2Read(0x04); DData = MPL3115A2Read(0x05); Alt_Integer = (s16)AData; Alt_Fraction=0; if (BData & 0x80) { Alt_Fraction += FRAC_2d1; } if (BData & 0x40) { Alt_Fraction += FRAC_2d2; } if (BData & 0x20) { Alt_Fraction += FRAC_2d3; } if (BData & 0x10) { Alt_Fraction += FRAC_2d4; } if(Alt_Integer>0) { p->Alt = Alt_Integer + Alt_Fraction/10000; } else { p->Alt = Alt_Integer - Alt_Fraction/10000; } Tmp_Integer = (s8)CData; Tmp_Fraction=0; if (DData & 0x80) { Tmp_Fraction += FRAC_2d1; } if (DData & 0x40) { Tmp_Fraction += FRAC_2d2; } if (DData & 0x20) { Tmp_Fraction += FRAC_2d3; } if (DData & 0x10) { Tmp_Fraction += FRAC_2d4; } if(Tmp_Integer>0) { p->Tmp = Tmp_Integer + Tmp_Fraction/10000; } else { p->Tmp = Tmp_Integer - Tmp_Fraction/10000; } /* Set to Altimeter with an OSR = 1 *///气压模式 /* Enable Data Flags in PT_DATA_CFG */ Write_MPL3115A2(0x26, 0x00); Write_MPL3115A2(0x13, 0x07); Write_MPL3115A2(0x26, 0x39); /* Read STATUS Register */ while((MPL3115A2Read(0x00) & 0x08) == 0); AData = MPL3115A2Read(0x01) << 8 | MPL3115A2Read(0x02); BData = MPL3115A2Read(0x03); CData = MPL3115A2Read(0x04); DData = MPL3115A2Read(0x05); pre=AData; pre=pre<<2; pre|=BData>>6; Pre_Integer=(float)pre; Pre_Fraction = 0; if (BData & 0x20)//第5位 { Pre_Fraction += FRAC_2d1; } if (BData & 0x10)//第4位 { Pre_Fraction += FRAC_2d2; } p->pre=(Pre_Integer+Pre_Fraction/10000)/100; }
模块使用心得:手册中提到读取气压的方式有轮询法和中断法。轮询法就是不使用中断的方法。我这里只是测试模块功能,对精度要求不是很高,所以就选择的该方式。只需要接SDA和SCI,而IN1 IN2只有在中断法中才会使用到,这里就不做过多的介绍。
MPL3115A2有3种工作模式。就绪模式、活动测高模式、活动测压模式。
步骤1:先进入就绪模式,CTRL_REG1寄存器(0x26)写入0x04,即就绪模式;
步骤2:再对该寄存器写入0xB9,进入活动测高模式;
步骤3:将PT_DATA_CDG寄存器(0x13)的值写为0x07。配置工作就完成了。
然后它就可以开始按照iic的工作时序开始工作了。我们需要的数据在0x01 0x02 0x03 这三个寄存器中。0x01和0x02都是以米做单位的,读出来就直接是海拔。
在大多数城市 0x01这个寄存器的值都是0,如果你在青藏高原就当我没说;
0x02的数据就是你城市的海拔,0x03的数据,就可以理解为小数点后的数值了。
2:OLED模块介绍:
2.1:OLED 简介:
OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。因为具备轻薄、省电等特性,因此从 2003 年开始,这种显示设备在 MP3 播放器上得到了广泛应用,而对于同属数码类产品的 DC 与手机,此前只是在一些展会上展示过采用 OLED 屏幕的工程样品。自 2007 年后,寿命得 到很大提高,具备了许多 LCD 不可比拟的优势。
GND:电源地 VCC:2.2V~5.5V SCL(D0):CLK 时钟 (高电平 2.2V~5.5V) SDA(D1):MOSI 数据(高电平 2.2V~5.5V) RST:复位(高电平 2.2V~5.5V) D/C:数据/命令(高电平 2.2V~5.5V) 兼容 3.3V 和 5V 控制芯片的 I/O 电平(无需任何设置,直接兼容)。
实物图片
2.2:汉字显示方法:
需要使用软件做自己的字库
//向SSD1106写入一个字节。 //dat:要写入的数据/命令 //cmd:数据/命令标志 0,表示命令;1,表示数据; void OLED_WR_Byte(u8 dat,u8 cmd) { u8 i; if(cmd) OLED_DC_Set(); else OLED_DC_Clr(); OLED_CS_Clr(); for(i=0;i<8;i++) { OLED_SCLK_Clr(); if(dat&0x80) OLED_SDIN_Set(); else OLED_SDIN_Clr(); OLED_SCLK_Set(); dat<<=1; } OLED_CS_Set(); OLED_DC_Set(); } void OLED_Set_Pos(u8 x, u8 y) { OLED_WR_Byte(0xb0+y,OLED_CMD); OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD); OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD); } //开启OLED显示 void OLED_Display_On(void) { OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令 OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON OLED_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 OFF OLED_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 (0x02,OLED_CMD); //设置显示位置—列低地址 OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); } //更新显示 } //在指定位置显示一个字符 调用OLED_ShowChar(48,6,16,t); //x0,y0显示起点坐标,x0(范围0~127),y0(范围0~7)*8 //size:选择字体 16/12 //chr:字符串ascii码 void OLED_ShowChar(u8 x, u8 y, u8 size, u8 chr) { u8 c=0,i=0; c=chr-' ';//得到偏移后的值 if(x>X_WIDTH-1){x=0;y=y+2;} if(size ==ASCII32x32) { OLED_Set_Pos(x,y); for(i=0;i<ASCII32x32/4;i++) OLED_WR_Byte(ASCII16x32[c*ASCII32x32+i],OLED_DATA); OLED_Set_Pos(x,y+1); for(i=0;i<ASCII32x32/4;i++) OLED_WR_Byte(ASCII16x32[c*ASCII32x32+i+ASCII32x32/4],OLED_DATA);//四列显示完 OLED_Set_Pos(x,y+2); for(i=0;i<ASCII32x32/4;i++) OLED_WR_Byte(ASCII16x32[c*ASCII32x32+i+2*ASCII32x32/4],OLED_DATA); OLED_Set_Pos(x,y+3); for(i=0;i<ASCII32x32/4;i++) OLED_WR_Byte(ASCII16x32[c*ASCII32x32+i+3*ASCII32x32/4],OLED_DATA); } else if(size ==ASCII24x24) { OLED_Set_Pos(x,y); for(i=0;i<ASCII24x24/3;i++) OLED_WR_Byte(ASCII12x24[c*ASCII24x24+i],OLED_DATA); OLED_Set_Pos(x,y+1); for(i=0;i<ASCII24x24/3;i++) OLED_WR_Byte(ASCII12x24[c*ASCII24x24+i+ASCII24x24/3],OLED_DATA);//三列显示完 OLED_Set_Pos(x,y+2); for(i=0;i<ASCII24x24/3;i++) OLED_WR_Byte(ASCII12x24[c*ASCII24x24+i+2*ASCII24x24/3],OLED_DATA); } else if(size ==ASCII16x16) { OLED_Set_Pos(x,y); for(i=0;i<ASCII16x16/2;i++) OLED_WR_Byte(ASCII8X16[c*ASCII16x16+i],OLED_DATA); OLED_Set_Pos(x,y+1); for(i=0;i<ASCII16x16/2;i++) OLED_WR_Byte(ASCII8X16[c*ASCII16x16+i+ASCII16x16/2],OLED_DATA);//两列显示完 } else if(size ==ASCII12x8) { OLED_Set_Pos(x,y); for(i=0;i<ASCII12x8;i++) OLED_WR_Byte(ASCII6x8[c*ASCII12x8+i],OLED_DATA); //一列显示完 } } //m^n函数 u32 oled_pow(u8 m,u8 n) { u32 result=1; while(n--)result*=m; return result; } //显示数字 调用OLED_ShowNum(103,6,t,3,16); //x0,y0显示起点坐标,x0(范围0~127),y0(范围0~7)*8 //len :数字的位数 //size:选择字体 16/12 //num:数值(0~65536); void OLED_ShowNum(u8 x,u8 y,u16 num,u8 len,u8 size) { 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+(size/2)*t,y,size,' '); continue; }else enshow=1; } OLED_ShowChar(x+(size/2)*t,y,size,temp+'0'); } } //显示一个字符号串 调用OLED_ShowString(30,0,"OLED TEST"); //x0,y0:显示起点坐标,x0(范围0~127),y0(范围0~7)*8 //size:选择字体 16/12 //char:字符串ascii码 void OLED_ShowString(u8 x,u8 y,u8 size,u8 *chr) { u8 j=0; while (chr[j]!='\0') { OLED_ShowChar(x,y,size,chr[j]); if(size==ASCII12x8) { x+=6;//单个ascii偏移量 } else if(size==ASCII16x16) { x+=ASCII16x16/2;//单个ascii偏移量 } else if(size==ASCII24x24) { x+=ASCII24x24/3;//单个ascii偏移量 } else if(size==ASCII32x32) { x+=ASCII32x32/4;//单个ascii偏移量 } if(x>X_WIDTH-size){x=0;y+=size/8;} j++; } } //显示显示BMP图片 调用OLED_DrawBMP(0,0,128,8,BMP1);最大图片 //x0,y0:显示起点坐标,x0(范围0~127),y0(范围0~7)*8 //x1,y1:显示图片长度和宽度,x1(范围0~127),y1(范围0~7)*8 //BMP[]:图片首地址 void OLED_DrawBMP(u8 x0, u8 y0,u8 x1, u8 y1,u8 BMP[]) { u16 j=0; u8 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); } } } //-----------------------------------显示中文------------------ u32 *getchinesecodepos(u16 ac) { u16 min,max,mid,midc; min=0; max=CHINESECHARNUMBER-1; while(1) { if(max-min<2) { if(ChineseCode[min]==ac) mid=min; else if(ChineseCode[max]==ac) mid=max; else mid=0; break; } mid=(max+min)/2; midc=ChineseCode[mid]; if(midc==ac) break; else if(midc>ac) max=mid-1; else min=mid+1; } return (u32*)(ChineseCharDot+mid*CHINESECHARDOTSIZE); } void Get_Code(u8* dis_buf,u32* address,u8 leng) { u8 i; for(i=0;i<leng/4;i++) //32为单片机4个字节 { *dis_buf=*address; dis_buf++; *dis_buf=*address>>8; dis_buf++; *dis_buf=*address>>16; dis_buf++; *dis_buf=*address>>24; dis_buf++; address++; } } void LCD_Char_CH(u8 x,u8 y,vu8 *str) { u8 i,buffer[CHINESECHARDOTSIZE]={0}; u16 chinese_ascii; u32 *p_address; chinese_ascii = *str; str++; chinese_ascii = chinese_ascii<<8|*str; //找到汉字内码 p_address=getchinesecodepos(chinese_ascii); Get_Code(buffer,p_address,32); // 取字模数据 OLED_Set_Pos(x,y); for(i=0;i<CHINESECHARSIZE;i++) OLED_WR_Byte(buffer[i],OLED_DATA); OLED_Set_Pos(x,y+1); for(i=0;i<CHINESECHARSIZE;i++) OLED_WR_Byte(buffer[i+CHINESECHARSIZE],OLED_DATA); } // * 函数名:LCD_Str_CH diao // * 描述 :在指定坐标处显示16*16大小汉字字符串 // * 输入 : - x: 显示位置横向坐标 // * - y: 显示位置纵向坐标 // * - str: 显示的中文字符串 // * 举例 : void LCD_Str_CHinese(u8 x,u8 y,vu8 *str) { while(*str != '\0') { LCD_Char_CH(x,y,str); str += 2 ; x += 16 ; } } //----------------------------------------------------------------------------- //初始化SSD1306 void OLED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能PD端口时钟 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOD3,6 GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); // DBGMCU->CR = DBGMCU->CR & ~((uint32_t)1<<5); // RCC->APB2ENR = 1 | (1<<3); /*AFIO/ GPIOB*/ // AFIO->MAPR = (AFIO->MAPR & ~((uint32_t)0x7 << 24)) | (2 << 24); /*释放 PA15 PB3 PB4*/ OLED_RST_Set(); delay_ms(100); OLED_RST_Clr(); delay_ms(100); OLED_RST_Set(); OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel OLED_WR_Byte(0x02,OLED_CMD);//---set low column address OLED_WR_Byte(0x10,OLED_CMD);//---set high column address OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64) OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty OLED_WR_Byte(0x81,OLED_CMD); //对比度设置 OLED_WR_Byte(0xfF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮) OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) OLED_WR_Byte(0x00,OLED_CMD);//-not offset OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration OLED_WR_Byte(0x12,OLED_CMD); OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02) OLED_WR_Byte(0x02,OLED_CMD);// OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5) OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ OLED_Clear(); OLED_Set_Pos(0,0); }
测试图片如下: