首页->【玩CortexM0】

238 4

实验十五 I2C接口与OLED驱显

最近为了实验只有4个输出IO口的开发板,专门买了一款I2C口的OLED。见照片F1。F1-I2COLED.jpg

I2C接口的OLED——不是假的OLED

因为采用mbed工程开发的LPC824编程比较简单,自然她成了首选。于是开始编程。

打开i2c.h,精简的代码实例如下:

 * I2C i2c(p28, p27);

 * int main() {

 *     int address = 0x62;

 *     char data[2];

 *     i2c.read(address, data, 2);

 * }

再查看PinNames.h,得知标准的I2C的IO口为P0_10,P0_11。于是按照编程方法直接开始。为了简单和功能模块化,先创建一个文件:oled.h,打开首先定义i2c对象:

#include "mbed.h"

//Define Object

I2C i2c(P0_10,P0_11);//SDA,SCL

由于OLED不带字库,因此需要自编点阵字库,为了字库占的小点,设计成为6X8点阵的,字库较大省了。定义一个延时函数,也省了。

定义i2c的速度函数:

//I2C speed

void i2cInit(void){i2c.frequency(200000);}//300K就不正常了

定义i2c写函数:

//Write qa byte to OLED

void i2cWri(int dat0){i2c.write(dat0);}

判断写入的是命令还是数据函数:

//?Command ?Data

void i2cCov(unsigned char dat,int com){

 i2c.start();

 if(com){//write data

  i2cWri(0x78);

  i2cWri(0x40);

  i2cWri(dat);

 }else{//write command

  i2cWri(0x78);//Slave address,SA0=0

  i2cWri(0x00);

  i2cWri(dat);

 }

 i2c.stop();

}

设置写入数据的X,Y坐标

//Set OLED X,Y

void setXy(unsigned char x,unsigned char y){ 

 i2cCov(0xb0+y,0);

 i2cCov(x&0x0f,0);

 i2cCov(0x10|((x&0xf0)>>4),0);

}

充满屏幕——实际上就是清除屏幕

//OLED Fill

void lcdClear(unsigned char vola){

 unsigned char y,x;

 for(y=0;y<8;y++){

  i2cCov(0xb0+y,0);

  i2cCov(0x01,0);

  i2cCov(0x10,0);

  for(x=0;x<128;x++)

   i2cCov(vola,1);

 }

}

写一个ASCII字符到OLED

//Send a word to OLED

void c2l(unsigned char x,unsigned char y,int cc){

 unsigned char line;

 setXy(x*6,y);

 for (line=0;line<6;line++)

  i2cCov(asc2[cc][line],1);

}

初始化OLED函数:

//12864_OLED Intial

void lcdInit(void){

 delay0(500000);//初始化之前的延时很重要!

 i2cCov(0xAE,0);//turn off oled panel

 i2cCov(0x00,0);//set low column address

 i2cCov(0x10,0);//set high column address

 i2cCov(0x40,0);//set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)

 i2cCov(0x81,0);//set contrast control register

 i2cCov(0xCF,0);// Set SEG Output Current Brightness

 i2cCov(0xA1,0);//Set SEG/Column Mapping     0xa0左右反置 0xa1正常

 i2cCov(0xC8,0);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常

 i2cCov(0xA6,0);//set normal display

 i2cCov(0xA8,0);//set multiplex ratio(1 to 64)

 i2cCov(0x3F,0);//1/64 duty

 i2cCov(0xD3,0);//set display offset Shift Mapping RAM Counter (0x00~0x3F)

 i2cCov(0x00,0);//not offset

 i2cCov(0xD5,0);//set display clock divide ratio/oscillator frequency

 i2cCov(0x80,0);//set divide ratio, Set Clock as 100 Frames/Sec

 i2cCov(0xD9,0);//set pre-charge period

 i2cCov(0xF1,0);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock

 i2cCov(0xDA,0);//set com pins hardware configuration

 i2cCov(0x12,0);

 i2cCov(0xDB,0);//set vcomh

 i2cCov(0x40,0);//Set VCOM Deselect Level

 i2cCov(0x20,0);//Set Page Addressing Mode (0x00/0x01/0x02)

 i2cCov(0x02,0);//

 i2cCov(0x8D,0);//set Charge Pump enable/disable

 i2cCov(0x14,0);//set(0x10) disable

 i2cCov(0xA4,0);//Disable Entire Display On (0xa4/0xa5)

 i2cCov(0xA6,0);//Disable Inverse A7 Normorn A6 

 i2cCov(0xAf,0);//turn on oled panel

 delay0(1000);

}

显示所有ASCII码函数:

//Display ASCiI Test

void dispAsc(void){

 int i,j,k=0;

 for(i=0;i<8;i++){

  for(j=0;j<20;j++){

   c2l(j,i,k);

   if(k<91){k++;}else{k=0;}

  }

 }

}

主函数:

#include "mbed.h"

#include "oled.h"

//DEFINE GPIO

DigitalOut led0(P0_15);

//MAIN Program

void main(void){

 i2cInit();

 lcdInit();

 lcdClear(0x00);

 while(true){

  led0 = !led0;

  dispAsc();

  wait(0.2f);

  lcdClear(0x00);

 }

}

下载运行,结果见照片F2。F2-驱显OLED.jpg

I2C接口的OLED驱显效果——ASCII码刷屏

注意一个问题,在PinNames.h中i2c的定义是:

    // I2C pins

    SCL = P0_10,

    SDA = P0_11,

    I2C_SCL = P0_10,

    I2C_SDA = P0_11,

实际上是反的:SCL为P0_11,SDA为P0_10.发现此问题是在程序完成下载后,总不显示。当输出减少到40K时,用示波器看波形是方波了,再看两个管脚才发现P0_11管脚的波形频率高于P0_10的,说明P0_11是CLK,而P0_10才是SDA,换过来后立马显示了。但是最快稳定的速率为200K,300K是就乱码出现了——示波器看波形已成了近似锯齿状。当然没有外接上拉电阻。

楼主可见

  1. zhjb1 4#
    @shwnyoo  

    哪家的开发板?

    NXP的Breakout,LPC824

  2. shwnyoo 3#

    哪家的开发板?

  3. zhjb1 2#
    @chchengyong  

    多些分享!!

    可以的。平时不多玩这些了。你可以提出要求来,我抽空实现。这次的I2C是因为为了一块只有4个IO口,还有1个是AD的小开发板,只能买了个I2C的OLED做这玩意的显示。为了测试好坏,拿LPC824做实验的结果。如果你有什么需要,提出来哦,在时间允许的情况下,会尽量满足的。

  4. chchengyong 1#

    多些分享!!