打印

基于TI cc2541的I2C 的OLED应用,遇到一些问题

[复制链接]
5593|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
azq13158|  楼主 | 2015-9-28 13:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
azq13158|  楼主 | 2015-9-28 13:54 | 只看该作者
下面我贴上我软件i2c的代码,请各位指教。

#define STATE_MAX               0xFF
#define STATE_MIN               0x00
#define STATE_55                0x55
#define STATE_AA                0xAA
#define START_PAGE              0xB0
#define OLED_TOTAL_PAGE         2
//#define START_HIGH_BIT          0x12
//#define START_LOW_BIT           0x00
#define START_HIGH_BIT          0x10
#define START_LOW_BIT           0x00
#define FRAME_HIGH_ROW          0x01
#define FRAME_LOW_ROW           0x80

#define COLUMN_MIN              0
#define COLUMN_MAX              96
#define ROW_MAX                 16

// The address of SSD1306
#define        OLED_ADDR               0x78               
#define        OP_CMD                  0x00
#define        OP_DATA                 0x40


#define I2C_IO_ENABLE()       st( I2CWC =  0x83;)
#define I2C_SDA_HI()          st( I2CIO |= 0x01;)
#define I2C_SDA_LOW()         st( I2CIO &= ~(0x01);)
#define I2C_SDA_READ()        (I2CIO & 0x01)
#define I2C_SCL_HI()          st( I2CIO |= 0x02;)
#define I2C_SCL_LOW()         st( I2CIO &= ~(0x02);)
#define I2C_SCL_READ()        (I2CIO&0x02)




CONST uint8 num4x8[] =
{
   0x7C,0x82,0x82,0x7C,  // -- 0 --   num4x8[0]
   0x00,0x04,0xFE,0x00,  // -- 1 --   num4x8[4]
   0xCC,0xA2,0x92,0x8C,  // -- 2 --   num4x8[8]
   0x44,0x92,0x92,0x6C,  // -- 3 --   num4x8[12]
   0x78,0x44,0xFE,0x40,  // -- 4 --   num4x8[16]
   0x4E,0x8A,0x8A,0x72,  // -- 5 --   num4x8[20]
   0x7C,0x92,0x92,0x64,  // -- 6 --   num4x8[24]
   0x02,0xC2,0x32,0x0E,  // -- 7 --   num4x8[28]
   0x6C,0x92,0x92,0x6C,  // -- 8 --   num4x8[32]
   0x4C,0x92,0x92,0x7C,  // -- 9 --   num4x8[36]
   0xBC,0xC2,0x02,0xC2,0xBC, // -- O -- num4x8[40]
   0x3E,0x40,0x80,0x40,0x3E, // -- V -- num4x8[45]
};


static void Delay_I2C(void)
{
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
}

void Hal_HW_WaitUs(uint16 microSecs)
{
  while(microSecs--)
  {
    /* 32 NOPs == 1 usecs */
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop");
  }
}

static void Hal_IIC_Start(void)
{
   I2C_SDA_HI();
   I2C_SCL_HI();
   Delay_I2C();
   I2C_SDA_LOW();
   Delay_I2C();
   I2C_SCL_LOW();
}

static void Hal_IIC_Stop(void)
{
   I2C_SDA_LOW();
   Delay_I2C();
   I2C_SCL_HI();
   Delay_I2C();
   I2C_SDA_HI();
}

void IIC_Write_Data(uint8 Data)
{
    for(uint8 i = 0; i < 8; i++)               
    {
        if((Data<<i) & 0x80)
          I2C_SDA_HI();
        else
          I2C_SDA_LOW();

        Delay_I2C();
        I2C_SCL_HI();
        Delay_I2C();
        I2C_SCL_LOW();
    }
   
    I2C_SDA_HI(); //Release the I2C bus,and generates the signal of ack for master
    Delay_I2C();
    I2C_SCL_HI();
    Delay_I2C();
    I2C_SCL_LOW();       
}

void LCD_Write_Cmd(uint8 command)
{
   Hal_IIC_Start();
   IIC_Write_Data(OLED_ADDR);                // send the address of the OLED
   IIC_Write_Data(OP_CMD);                   // send the write command to the oled
   IIC_Write_Data(command);                  // send the command to the oled
   Hal_IIC_Stop();                          // stop the iic bus after send over
}

void LCD_Write_Dat_Start(void)
{
   Hal_IIC_Start();                        // Start-up the I2C bus
   IIC_Write_Data(OLED_ADDR);               // Send the Salve Adress
   IIC_Write_Data(OP_DATA);                 // Send the write command
}

static void OLED_Reset(void)
{
   OLED_NORMAL();
   Hal_HW_WaitUs(10000);
   OLED_RESET();
   Hal_HW_WaitUs(50000);
   OLED_NORMAL();
   Hal_HW_WaitUs(50000);
}

static void Init_OLED_IC()
{
   LCD_Write_Cmd(0xAE);       //Display OFF (sleep mode)
   LCD_Write_Cmd(0xD5);       //Set Display Clock Divide Ratio/Oscillator Frequency
   LCD_Write_Cmd(0xD0);       //0x71
   LCD_Write_Cmd(0xA8);       //Set Multiplex Ratio
   LCD_Write_Cmd(0x0F);       //32
   LCD_Write_Cmd(0xD3);       //Set Display Offset
   LCD_Write_Cmd(0x00);       //
   LCD_Write_Cmd(0x40);       //Set Display Start Line
   LCD_Write_Cmd(0x8D);       //Set Display Offset
   LCD_Write_Cmd(0x14);       //VCC Generated by Internal DC/DC circuit
   
   LCD_Write_Cmd(0xA1);              //¿ØÖÆSEGÏÔʾ×óÓÒ·­×ª         £¬A0H/A1H
   LCD_Write_Cmd(0xC8);              //¿ØÖÆcomÏÔʾÉÏÏ·­×ª         £¬C0H/C8H
   
   LCD_Write_Cmd(0xDA);       //Set COM Pins Hardware Configuration
   LCD_Write_Cmd(0x02);       //

   LCD_Write_Cmd(0x81);       //Set Contrast Control
   LCD_Write_Cmd(0x56);       //0x23

   LCD_Write_Cmd(0xD9);       //Set Pre-charge Period
   LCD_Write_Cmd(0xF1);       //VCC Generated by Internal DC/DC circuit
   LCD_Write_Cmd(0xDB);       //Set VCOMH Deselect Level
   LCD_Write_Cmd(0x20);       //0x3C
   LCD_Write_Cmd(0xA4);       //Output follows RAM content
   LCD_Write_Cmd(0xA6);       //Set Normal Display
   LCD_Write_Cmd(0xAF);       //Set Display ON
}

uint8 Display_Init(uint8 flip_set)
{
    if(flip_set)
    {       
      LCD_Write_Cmd(0xA0);            //控制SEG显示左右翻转         ,A0H/A1H
      LCD_Write_Cmd(0xC0);             //控制com显示上下翻转         ,C8H/C0H

    }
    else
    {
      //初始化时已经写过A0,C0
      LCD_Write_Cmd(0xA1);            //控制SEG显示左右翻转         ,A0H/A1H
      LCD_Write_Cmd(0xC8);            //控制com显示上下翻转         ,C8H/C0H
    }
   
    Clear_Screen(flip_set);
   
    return TRUE;
}

void HaloLedInit(void)
{
  
  OLED_RST_SEL &= ~OLED_RST_BIT;  // Config the reset pin
  OLED_RST_DDR |= OLED_RST_BIT;
  I2C_IO_ENABLE();               // Enable the pins of the I2C bus
  OLED_Reset();                  // Reset the oled
  Init_OLED_IC();                // initial the the register of the oled

}

void Clear_Screen(uint8 flip)
{  
   uint8 i,page_number,column_number;

   i = reversal_chk(flip);
   for(page_number=0;page_number<OLED_TOTAL_PAGE;page_number++)
   {
       LCD_Write_Cmd(START_PAGE+page_number);
       LCD_Write_Cmd(START_HIGH_BIT+i);
       LCD_Write_Cmd(START_LOW_BIT);
       LCD_Write_Dat_Start();
       for(column_number=COLUMN_MIN;column_number<COLUMN_MAX;column_number++)
       {
          IIC_Write_Data(STATE_MIN);
       }
           Hal_IIC_Stop();
   }
}

void Display_Number(uint8 flip,uint8 num,uint8 start_col,uint8 start_page,Num_Font_Def font)
{
    uint8 page_number,column_number,page_total,width_total;
    CONST uint8  *p;
    uint16 num_addr = 0;
    uint8 i = reversal_chk(flip);
    // select the type of the number
   
    switch(font)
    {
      // temporary needs is Font4x8
        case Font4x8 :
        {
            
            page_total = 1;
            if(num >= 10)
            {
               num_addr = 40 + (num-10)*5;
               p = &num4x8[num_addr];
               width_total = 5;
            }
            else if(num < 10)
            {
               width_total = 4;
               p = &num4x8[num*4];
            }
            
        }break;
        case Font8x16  :
        {
            page_total = 2;
            width_total = 8;
            if(num == 0)
              p = &num8x16[0];
            else if(num == 1)
            {
                p = &num8x16[16];
                width_total = 6;
            }
            else
            {
              num_addr = 28 + ((num-2)<<4);
               p = &num8x16[num_addr];
              if(num == WAT_UINT)
                width_total = 13;
            }

        }break;
      
        default: break;
    }
       
    // write the data to the OLED
    for(page_number=start_page;page_number<(start_page+page_total);page_number++)
    {
         LCD_Write_Cmd(START_PAGE+page_number);  // Set the page address
         LCD_Write_Cmd(START_HIGH_BIT + (start_col/15)+i);         // Set Higher Column Start Address for Page Addressing Mode
             LCD_Write_Cmd(START_LOW_BIT + (start_col%15));            // Set Lower Column Start Address for Page Addressing Mode
             LCD_Write_Dat_Start();                      // Start to write data

               
         for(column_number=0;column_number<width_total;column_number++)
         {
            IIC_Write_Data(*p++);
         }
        
    }
       
}


int main()
{
        Init_Pot();
        HaloLedInit();
        Display_Init(0);

        Clear_Screen(0);
        //不翻转  写入数字 1  在第0列,第0页开始写入  字体为Font4*8
        Display_Number(0,9,1,0,Font4x8);  
}

使用特权

评论回复
板凳
azq13158|  楼主 | 2015-9-28 13:56 | 只看该作者
最后是  不翻转 写入数字9,在第1列,第0页开始写。

为什么OLED连亮都没亮呢?

使用特权

评论回复
地板
dirtwillfly| | 2015-9-28 13:57 | 只看该作者
你用的OLED什么型号的?有时序图吗?
这个主要是慢慢调时序,多用示波器或者逻辑分析仪观察

使用特权

评论回复
5
dirtwillfly| | 2015-9-28 13:58 | 只看该作者
没有好办法。或者你找卖家要个例程

使用特权

评论回复
6
azq13158|  楼主 | 2015-9-28 14:36 | 只看该作者
dirtwillfly 发表于 2015-9-28 13:58
没有好办法。或者你找卖家要个例程

卖家一般只有51 或stm32的,没有cc2541的。我也是借鉴其他平台,然后移植过来的。

使用特权

评论回复
7
azq13158|  楼主 | 2015-9-28 14:38 | 只看该作者
dirtwillfly 发表于 2015-9-28 13:57
你用的OLED什么型号的?有时序图吗?
这个主要是慢慢调时序,多用示波器或者逻辑分析仪观察 ...

OLED是ssd1306的 ,时序顺序是对的,我是按照时序顺序来的,而且参考了其他平台的代码,也是这么写的。

使用特权

评论回复
8
azq13158|  楼主 | 2015-9-28 14:40 | 只看该作者
dirtwillfly 发表于 2015-9-28 13:57
你用的OLED什么型号的?有时序图吗?
这个主要是慢慢调时序,多用示波器或者逻辑分析仪观察 ...

这个和延迟有关系么,会不会是延迟时间不够,或者太长,造成时序错乱呢。(ps: 示波器的没有)

使用特权

评论回复
9
dirtwillfly| | 2015-9-28 14:53 | 只看该作者
azq13158 发表于 2015-9-28 14:40
这个和延迟有关系么,会不会是延迟时间不够,或者太长,造成时序错乱呢。(ps: 示波器的没有) ...

很有可能啊。
cc2541也是51的内核,你用51的代码稍微改一下就可以。
另外注意,你的cc2541运行频率和从网上找的代码是否一致。
即使代码完全一样,如果主频不同,也不能正常显示的。

使用特权

评论回复
10
azq13158|  楼主 | 2015-9-28 15:19 | 只看该作者
dirtwillfly 发表于 2015-9-28 14:53
很有可能啊。
cc2541也是51的内核,你用51的代码稍微改一下就可以。
另外注意,你的cc2541运行频率和从网 ...

主频不同,  延迟函数延迟的时间就不同。主要是这个不同是吧

使用特权

评论回复
11
dirtwillfly| | 2015-9-28 16:31 | 只看该作者
azq13158 发表于 2015-9-28 15:19
主频不同,  延迟函数延迟的时间就不同。主要是这个不同是吧

是啊

使用特权

评论回复
12
azq13158|  楼主 | 2015-9-28 17:04 | 只看该作者

#define I2C_IO_ENABLE()       st( I2CWC =  0x83;)
#define I2C_SDA_HI()          st( I2CIO |= 0x01;)
#define I2C_SDA_LOW()         st( I2CIO &= ~(0x01);)
#define I2C_SCL_HI()          st( I2CIO |= 0x02;)
#define I2C_SCL_LOW()         st( I2CIO &= ~(0x02);)

这是软件模拟的i2c,这样写是对的吗。  I2C_SDA_HI()    等价于 SDA = 1

使用特权

评论回复
13
huarana| | 2015-9-28 17:36 | 只看该作者
这个很容易就搞定的吧 - -

主要是看你哪个oled模块方式配置对吗

上面有几个跳线电阻,默认是跳到spi的  。

使用特权

评论回复
14
azq13158|  楼主 | 2015-9-28 17:45 | 只看该作者
huarana 发表于 2015-9-28 17:36
这个很容易就搞定的吧 - -

主要是看你哪个oled模块方式配置对吗


我i2c 部分反复确认,oled部分也反复确认了,不知道问题出在哪。不过oled部分的代码都是从文档里拷出来的。

还会默认跳到SPI的?  能具体讲下么

使用特权

评论回复
15
huarana| | 2015-9-29 14:38 | 只看该作者
azq13158 发表于 2015-9-28 17:45
我i2c 部分反复确认,oled部分也反复确认了,不知道问题出在哪。不过oled部分的代码都是从文档里拷出来 ...

买来的模块默认是spi

要用iic就要重新焊接那几个电阻

使用特权

评论回复
16
拉克丝| | 2015-9-29 19:44 | 只看该作者
涉及到通信就必须注意时钟和时序问题

使用特权

评论回复
17
cemaj| | 2015-9-29 22:49 | 只看该作者
光粘贴代码呢。

使用特权

评论回复
18
cemaj| | 2015-9-29 22:50 | 只看该作者
说现象呢。

使用特权

评论回复
19
feilusia| | 2015-9-30 09:37 | 只看该作者
我买的smart rf板子,是用SPI控制oled的。

使用特权

评论回复
20
azq13158|  楼主 | 2015-9-30 11:16 | 只看该作者

现象就是没有任何反应,OLED没有驱动起来

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

92

帖子

2

粉丝