avrydy 发表于 2014-10-19 15:59:16

写了一个简单的SSD1306 OLED测试代码

手上有个 SSD1306 的OLED屏,今天礼拜本来想玩一下,程序写好了调试了半天才发现屏裂了,现在没有屏了,不知道那个有屏的朋友可以测试一下代码是否正常,谢谢。

芯片:ATMEGA8

通信方式:I2C

SCLK -------- > PC0
DATA ------- > PC1

下面是代码:

#include "ATMEGA88PA.h"
#include <macros.h>

#define u8 unsigned char

#define I2C_SCLK   PC0
#define I2C_DATA        PC1

#define        I2C_DATA_0 PORTC &= ~BIT(I2C_DATA)
#define        I2C_DATA_1 PORTC |= BIT(I2C_DATA)

#define        I2C_SCLK_0 PORTC &= ~BIT(I2C_SCLK)
#define        I2C_SCLK_1 PORTC |= BIT(I2C_SCLK)

#define        I2C_DATA_IN DDRC &= ~BIT(I2C_DATA)
#define        I2C_DATA_OUT DDRC |= BIT(I2C_DATA)

#define I2C_Command 0x00
#define I2C_WData 0x40

/*-----------------------------------------

------------------------------------------*/
void PortInit(void)
{
   DDRC |= 0xff;
   PORTC |= 0xff;
}

/*--------------------------

----------------------------*/
void uDelay(u8 l)
{
        while(l--);
}

/*
;------------------开始-----------------------------
;                开始
;SDA -----\______
;SCL --------\_____
;---------------------------------------------------
*/
void I2C_Start(void)
        {
        I2C_DATA_1;
        I2C_SCLK_1;
        uDelay(2);
        I2C_DATA_0;
        uDelay(2);
        I2C_SCLK_0;
        uDelay(2);
        }
/*
;-------------------------------------------------------------
;                数据传送
;规则:SCL 为低的情况下,SDA 才能跳变
;首先传送的是数据的最高位
;搂据位       7    6    5    4    3    2    1    0   ACK(0)
;SDA _______[===][===][===][===][===][===][===][===]________
;SCL ________/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\______
;-------------------------------------------------------------
*/
void SendDATA(u8 Data)
        {
        u8 i;
       
        I2C_SCLK_0;
        for (i=8; i>0; i--)
                {
                uDelay(1);
                if(Data & 0x80)                //当前数据位是否是1
                        {
                        I2C_DATA_1;                //当前位是1,拉高数据端
                        }
                else                                                  
                        {
                        I2C_DATA_0;                //当前位是0,拉低数据端
                        }
                Data = Data << 1;
                uDelay(1);
                I2C_SCLK_1; //SCLK = 1;
                uDelay(1);
                I2C_SCLK_0;
                }
        }

/*
;---------------------------------------------
;                Send_ACK
;SDA _________________
;SCL ____/-----\______
;---------------------------------------------
*/

void Send_ACK(void)
        {
        I2C_DATA_0;
        uDelay(2);
        I2C_SCLK_1;               
        uDelay(2);
        I2C_SCLK_0;               
        uDelay(2);
        }


/*
;---------------------------------------------
;                Read_ACK
;SDA ___[=======]_____
;SCL ____/-----\______
;ack = 0
;nack = 1
;---------------------------------------------
*/

u8 I2C_ReadACK(void)
{
        u8 I2C_AckFlag;
        I2C_SCLK_0;                //确保时钟拉低状态
       
        I2C_DATA_IN;        //设为输入,准备读取ACK
        I2C_DATA_1;
       
        I2C_SCLK_1;                //拉高时钟口
        uDelay(1);
       
        if(I2C_DATA)
                {
                I2C_AckFlag = 0xff;
                }
        else
                {
                I2C_AckFlag = 0;
                }
       
        uDelay(1);
        I2C_SCLK_0;                //拉低时钟口
        uDelay(1);
        I2C_DATA_0;
        I2C_DATA_OUT;
        I2C_DATA_0;
        return I2C_AckFlag;
}

/*
;---------------------------------------------
;                STOP
;在数据口为低的情况下,拉高时钟 请求结束通信       
;结束条件建立时间大于4μs
;
;SDA _______/-----
;SCL ____/-----
;----------------------------------------------
*/
void I2C_Stop(void)
        {
        I2C_SCLK_1;
        uDelay(2);
        I2C_DATA_1;
        uDelay(2);
        }


void I2C_SendCD(u8 Control, u8 Data)
        {
        u8 NOack,SendCoutn;
        StratWrite:
        I2C_Start();
        SendCoutn++;
        if(SendCoutn >= 30)return;
       
        SendDATA(0x78);
        NOack = I2C_ReadACK();
        if(NOack)goto StratWrite;
        SendDATA(Control);
        NOack = I2C_ReadACK();
        if(NOack)goto StratWrite;
        SendDATA(Data);
        NOack = I2C_ReadACK();
        if(NOack)goto StratWrite;
        I2C_Stop();
}

void OledInit(void)
{
    int i;;
    for(i=0;i<1000;i++) //
    {
      uDelay(200);
    }

    I2C_SendCD(I2C_Command,0xAE);        //关闭显示
    I2C_SendCD(I2C_Command,0xD5);        //设置时钟分频因子,震荡频率
    I2C_SendCD(I2C_Command,0x80); //,分频因子;,震荡频率
        I2C_SendCD(I2C_Command,0xA8); //设置驱动路数
        I2C_SendCD(I2C_Command,0X3F); //默认0X3F(1/64)
    I2C_SendCD(I2C_Command,0x40); //设置显示开始行 ,行数.
    I2C_SendCD(I2C_Command,0xA1); // Remap
        I2C_SendCD(I2C_Command,0xC8); // Scan direction
    I2C_SendCD(I2C_Command,0xDA); //设置COM硬件引脚配置
        I2C_SendCD(I2C_Command,0x12); //配置
    I2C_SendCD(I2C_Command,0x81); //对比度设置
        I2C_SendCD(I2C_Command,0xEF); // 1~255;默认0X66(亮度设置,越大越亮)
        I2C_SendCD(I2C_Command,0xD9); //设置预充电周期
        I2C_SendCD(I2C_Command,0xF1); //,PHASE 1;,PHASE 2;
        I2C_SendCD(I2C_Command,0xDB); //设置VCOMH 电压倍率
        I2C_SendCD(I2C_Command,0x30); // 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
        I2C_SendCD(I2C_Command,0xB0);        // set page address
        I2C_SendCD(I2C_Command,0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
        I2C_SendCD(I2C_Command,0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示                                                            
        I2C_SendCD(I2C_Command,0xD3); //设置显示偏移
        I2C_SendCD(I2C_Command,0X00); //默认为0
    I2C_SendCD(I2C_Command,0x00); ////set lower column addres
        I2C_SendCD(I2C_Command,0x10); //set higher column address
        I2C_SendCD(I2C_Command,0x20); //设置内存地址模式
        I2C_SendCD(I2C_Command,0x02); //,00,列地址模式;01,行地址模式;10,页地址模式;默认10;
        I2C_SendCD(I2C_Command,0xA1); //段重定义设置,bit0:0,0->0;1,0->127;
        I2C_SendCD(I2C_Command,0x8d); //set charge pump enable
    I2C_SendCD(I2C_Command,0x14);
        I2C_SendCD(I2C_Command,0xAF); //开启显示       
}


void main(void)
{
    u8 i,n;
    PortInit();
    OledInit();       

       
    I2C_Start();
    I2C_SendCD(I2C_Command,0xA1);         // Remap
        for(i=0;i<8;i++)
                {
                I2C_SendCD (I2C_Command,0xb0+i);        //+(line-1)*2);//设置页地址(0~7)
                I2C_SendCD (I2C_Command,0x0);                //设置显示位置-列低地址,偏移了2列
                I2C_SendCD (I2C_Command,0x10);      //设置显示位置-列高地址
               
                for(n=0;n<128;n++)
                        {
              I2C_SendCD(I2C_WData,0xFF);                //
                        }
                }
        I2C_Stop();

}

江南雨絮 发表于 2014-10-19 16:57:45

最近也在搞oled呵呵

avrydy 发表于 2014-10-19 17:10:32

江南雨絮 发表于 2014-10-19 16:57
最近也在搞oled呵呵

你有屏吧,可以的话,顺便测试一下{:biggrin:}
页: [1]
查看完整版本: 写了一个简单的SSD1306 OLED测试代码