搜索
bottom↓
回复: 2

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

[复制链接]

出0入0汤圆

发表于 2014-10-19 15:59:16 | 显示全部楼层 |阅读模式
手上有个 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); //[3:0],分频因子;[7:4],震荡频率
        I2C_SendCD(I2C_Command,0xA8); //设置驱动路数
        I2C_SendCD(I2C_Command,0X3F); //默认0X3F(1/64)
    I2C_SendCD(I2C_Command,0x40); //设置显示开始行 [5:0],行数.
    I2C_SendCD(I2C_Command,0xA1); // Remap
        I2C_SendCD(I2C_Command,0xC8); // Scan direction
    I2C_SendCD(I2C_Command,0xDA); //设置COM硬件引脚配置
        I2C_SendCD(I2C_Command,0x12); //[5:4]配置
    I2C_SendCD(I2C_Command,0x81); //对比度设置
        I2C_SendCD(I2C_Command,0xEF); // 1~255;默认0X66(亮度设置,越大越亮)
        I2C_SendCD(I2C_Command,0xD9); //设置预充电周期
        I2C_SendCD(I2C_Command,0xF1); //[3:0],PHASE 1;[7:4],PHASE 2;
        I2C_SendCD(I2C_Command,0xDB); //设置VCOMH 电压倍率
        I2C_SendCD(I2C_Command,0x30); //[6:4] 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); //[1:0],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();
  
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2014-10-19 16:57:45 | 显示全部楼层
最近也在搞oled呵呵

出0入0汤圆

 楼主| 发表于 2014-10-19 17:10:32 | 显示全部楼层
江南雨絮 发表于 2014-10-19 16:57
最近也在搞oled呵呵

你有屏吧,可以的话,顺便测试一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 17:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表