Nordic蓝牙芯片上开发 4pin的0.96寸 OLED I2C屏幕

 前期回顾:

   Nordic 蓝牙芯片上开发 SHT3x系列温湿度传感器

   I2C详解学习 - nRF52832蓝牙芯片 TWI-I2C学习详解笔记

0.前言(文末有福利)

nRF52832蓝牙芯片上用4pin的I2C OLED屏幕显示温湿度:

                                     

 

淘宝买的屏幕模块,给的资料如下:

                                 

 

    给的参考代码包含Arduino、C51、STM平台,但是对于Nordic蓝牙芯片,并没有。根据之前的文章,我们可知,Nordic蓝牙芯片的I2C驱动官方已经写好,我们只需要调用接口就可以实现I2C功能,如SHT3x温湿度传感器等。

 

1. 关于OLED显示屏的介绍

通常我们所用的OLED屏有白色、蓝色、黄蓝双色等几种;屏的大小为0.96寸,像素点为128*64,所以我们也称之为0.96OLED屏或者12864屏。

内部驱动IC为SSD1306;通信方式一般为SPI或者I2C。如下图所示,配置哪种模式主要是根据BS0、BS1和BS2这三个管脚的电平逻辑来的。

                                   

 

如手册上关于I2C地址的描述,根据DC引脚电平的不同,地址为,0111100和0111101两种,通常我们设置DC引脚接地,所以作为I2C从机的七位地址为0111100;又因为我们与驱动IC交互时,都是主机发送命令或者数据到IC,也就是只有写数据,没有读数据,所以从机地址为0x78。

通信方式如上图所示:先发送从机地址,再发送命令字节,接着发送数据字节。注意每次主机要等待从机的应答。下图为写命令和写数据的代码示例。

2. 通过分析参考代码了解OLED屏幕

2.1先从STM32平台的参考code入手

    连头文件都没给,写的比较烂,不过能跑起来。

                                     

 

2.2 Main函数入手了解OLED工作方式:

    Main函数中:IO初始化—OLED初始化—OLED填充—图片轮流显示

int main()

{

  //point= &picture_tab[0];

  point = &word_show_1[0];

  IO_init();

 

  OLED_init();

  OLED_full();

  delay_ms(1000);

  //OLED_clear();

  

  while(1)

  {

    Picture_display(point);

    delay_ms(200);

   

    Picture_ReverseDisplay(point);

    delay_ms(200);

   

  }

}

 

(1)IO初始化没什么讲的,主要是配置IO口等。

(2)OLED屏幕初始化函数如下,主要是向屏幕模组写入25个初始化命令。

       OLED_init(void)-- OLED_send_cmd(OLED_init_cmd[i])

(3)发送每个初始化命令执行的步骤:I2C开始—写入0x00—写入命令—I2C结束。

(4)初始化屏幕的命令有25个。每个命令8bit,具体每个命令的作用在代码中有详细的中文介绍。

//oled初始化

void OLED_init(void)

  {

    unsigned char i;

    for(i=0;i<25;i++)

      {

        OLED_send_cmd(OLED_init_cmd[i]);

      }

  }

//oled 发送命令

void OLED_send_cmd(unsigned char o_command)

  {

   

    IIC_start();

    IIC_write(0x00);

    IIC_write(o_command);

    IIC_stop();

   

  }

const unsigned char  OLED_init_cmd[25]=

{

  /*0xae,0X00,0X10,0x40,0X81,0XCF,0xff,0xa1,0xa4,

  0xA6,0xc8,0xa8,0x3F,0xd5,0x80,0xd3,0x00,0XDA,0X12,

  0x8d,0x14,0xdb,0x40,0X20,0X02,0xd9,0xf1,0xAF*/

       0xAE,//关闭显示

       0xD5,//设置时钟分频因子,震荡频率

       0x80//[3:0],分频因子;[7:4],震荡频率

 

       0xA8,//设置驱动路数

       0X3F,//默认0X3F(1/64)

       0xD3,//设置显示偏移

       0X00,//默认为0

       0x40,//设置显示开始行 [5:0],行数.                             

       0x8D,//电荷泵设置

       0x14,//bit2,开启/关闭

       0x20,//设置内存地址模式

       0x02,//[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;

       0xA1,//段重定义设置,bit0:0,0->0;1,0->127;

       0xC8,//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数

       0xDA,//设置COM硬件引脚配置

       0x12,//[5:4]配置           

       0x81,//对比度设置

       0xEF,//1~255;默认0X7F (亮度设置,越大越亮)

       0xD9,//设置预充电周期

       0xf1,//[3:0],PHASE 1;[7:4],PHASE 2;

       0xDB,//设置VCOMH 电压倍率

       0x30,//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

       0xA4,//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)

       0xA6,//设置显示方式;bit0:1,反相显示;0,正常显示       

       0xAF,//开启显示    

};

 

 

(5)屏幕初始化后,可以选择清除屏幕或者填充屏幕。

    填充屏幕,主要是让屏幕全部点亮。通过代码,我们知道有两个步骤,填充page(页)数,和Column(列)数。

OLED屏幕像素为128*64,每一页page有8行,一共8页。124列。

                                        

 

(6)向屏幕写入数据:I2C开始—写入0x40—写入数据—I2C结束。

填充屏幕写入的数据为:data=0xFF

清除屏幕写入数据为:  data=0x00

/oled 屏幕填充

void OLED_full(void)

  {

    unsigned char page,column;

    for(page=0;page<8;page++)             //page loop

      {

        Page_set(page);

        Column_set(0);   

  for(column=0;column<128;column++) //column loop

          {

            OLED_send_data(0xff);

          }

      }

  }

// oled 发送数据

void OLED_send_data(unsigned char o_data)

  {

    IIC_start();

    IIC_write(0x40);

    IIC_write(o_data);

    IIC_stop();

   }

 

//设置行数

void Column_set(unsigned char column)

  {

    OLED_send_cmd(0x10|(column>>4));    //设置列地址高位

    OLED_send_cmd(0x00|(column&0x0f));   //设置列地址低位 

      

  }

//设置页数

void Page_set(unsigned char page)

  {

    OLED_send_cmd(0xb0+page);

  }

 

 

2.2 OLED屏幕工作总结:

(1)Main函数中:IO初始化—OLED初始化—OLED填充—图片轮流显示

(2)OLED屏幕初始化函数如下,主要是向屏幕模组写入25个初始化命令。

       OLED_init(void)-- OLED_send_cmd(OLED_init_cmd[i])

(3)向屏幕写入命令:I2C开始—写入0x00—写入命令(Command)—I2C结束。

(4)初始化屏幕的命令有25个。每个命令8bit,具体每个命令的作用在代码中有详细的中文介绍。

(5)屏幕初始化后,可以选择清除屏幕或者填充屏幕。

    填充屏幕,主要是让屏幕全部点亮。通过代码,我们知道有两个步骤,填充page(页)数,和Column(列)数。

OLED屏幕像素为128*64,每一页page有8行,一共8页。124列。

(6)向屏幕写入数据:I2C开始—写入0x40—写入数据(data)—I2C结束。

          填充屏幕写入的数据为:data=0xFF

         清除屏幕写入数据为:  data=0x00

(7)要屏幕显示其他内容,如数字,字符等,可以用字模提取软件进行转换,将特定特定汉字图片转换成16进制的data数据。下图是部分的1206字符大小的data数据,有专门的C文件可以可以直接用,这个不用担心。

                                    

 

至此OLED工作流程基本ok。接下来就是移植到Nordic蓝牙芯片上。

 

3. nRF52832蓝牙芯片上开发I2C的OLED屏幕

3.1 Nordic I2C接口

关于Noridc蓝牙芯片的I2C接口,之前的文章有单独详细介绍,请自行翻阅查看。

移植的困难点主要在重构 向OLED屏幕写入命令和写入数据这两个函数上。

通过多次调试,确定了一下代码最适用。

    具体的Nordic I2C实战应用,在前一篇SHT3x温湿度的文章有单独介绍过,

/**

 * 描  述 : 向OLED写入1字节命令或数据

 * 入  参 : dat:数据;mode:=0:写入命令,=1:写入数据

 * 返回值 : 无

 **/

void OLED_Write_Command(uint8_t command)    

{

        ret_code_t err_code;

        uint8_t command_send[2] = { 0x00,command};

        uint8_t retry_num = 50;     

        do{

            err_code = nrf_drv_twi_tx(&m_twi, OLED096_ADDRESS, command_send, 2, false);

            retry_num--;

            //等待TWI总线应答

            //UNUSED_VARIABLE(err_code);

        }

        while((NRF_SUCCESS != err_code) && (0 < retry_num));

}   



//oled write data

void OLED_Write_Data(unsigned char o_data)

  {

    ret_code_t err_code;

        uint8_t dta_send[2] = { 0x40,o_data};

        uint8_t retry_num = 50; 

        do{

            err_code = nrf_drv_twi_tx(&m_twi, OLED096_ADDRESS, dta_send, 2, false);

            retry_num--;

        }

        while ((NRF_SUCCESS != err_code) && (0 < retry_num));

 

}

/**

  * @brief Writes an byte to the display data ram or the command register

  * 

  * @param [in] chData Data to be writen to the display data ram or the command register

  * @param [in] chCmd   0: Writes to the command register

  *                     1: Writes to the display data ram

  * @return None

  */

void OLED_Write_byte(uint8_t chData, uint8_t chCmd)

{

    if(chCmd){  //write data

        OLED_Write_Data(chData);

    }

    else{   //write command

        OLED_Write_Command(chCmd);

    }



}

 

3.2 OLED显示字符和数字等函数

 

/**

  * @brief Brief

    * chMod:0,反白显示;1,正常显示。 size:选择字体16/12

  * @param [in] chXpos Specifies the X position ,0-127

  * @param [in] chYpos Specifies the Y position ,0-63

  * @param [in] chChr  a character

  * @param [in] chSize character of size

  * @param [in] chMode character of mode

  * @retval None

  */

void OLED_display_char(uint8_t chXpos, uint8_t chYpos, uint8_t chChr, uint8_t chSize, uint8_t chMode)

{

    uint8_t i, j;

    uint8_t chTemp, chYpos0 = chYpos;



    chChr = chChr - ' '; //得到偏移后的值

    for (i = 0; i < chSize; i ++)

    {

        if (chSize == 12)  //调用1206字体

        {

            if (chMode)

            {

                chTemp = c_chFont1206[chChr][i];

            }

            else

            {

                chTemp = ~c_chFont1206[chChr][i];

            }

        }

        else//调用1608字体

        {

            if (chMode)

            {

                chTemp = c_chFont1608[chChr][i]; 

            }

            else

            {

                chTemp = ~c_chFont1608[chChr][i];

            }

        }



        for (j = 0; j < 8; j ++)

        {

            if (chTemp & 0x80)

            {

                OLED_draw_point(chXpos, chYpos, 1);

            }

            else

            {

                OLED_draw_point(chXpos, chYpos, 0);

            }

            chTemp <<= 1;

            chYpos ++;



            if ((chYpos - chYpos0) == chSize)

            {

                chYpos = chYpos0;

                chXpos ++;

                break;

            }

        }

    }

}

/**

  * @brief Brief

  *  显示2个数字

  * @param [in] chXpos Parameter_Description

  * @param [in] chYpos Parameter_Description

  * @param [in] chNum  Parameter_Description,数值

  * @param [in] chLen  Parameter_Description,数字的位数

  * @param [in] chSize Parameter_Description,字体大小

  * @return Return_Description

  *

  * @details Details

  */

void OLED_display_num(uint8_t chXpos, uint8_t chYpos, uint32_t chNum, uint8_t chLen, uint8_t chSize)

{

    uint8_t i;

    uint8_t chTemp, chShow = 0;



    for(i = 0; i < chLen; i ++)

    {

        chTemp = (chNum / OLED_pow(10, chLen - i - 1)) % 10;

        if(chShow == 0 && i < (chLen - 1))

        {

            if(chTemp == 0)

            {

                OLED_display_char(chXpos + (chSize / 2) * i, chYpos, ' ', chSize, 1);

                continue;

            }

            else

            {

                chShow = 1;

            }

        }

        OLED_display_char(chXpos + (chSize / 2) * i, chYpos, chTemp + '0', chSize, 1);

    }

}

/**

  * @brief Displays a string on the screen

    * 显示字符串,*p:字符串起始地址

  * @param [in] chXpos    Specifies the X position

  * @param [in] chYpos    Specifies the Y position

  * @param [in] pchString Pointer to a string to display on the screen

  * @param [in] chSize   

  * @param [in] chMode   

  * @return None

  */

void OLED_display_string(uint8_t chXpos, uint8_t chYpos, const uint8_t *pchString, uint8_t chSize, uint8_t chMode)

{

    while (*pchString != '\0')

    {

        if (chXpos > (X_WIDTH - chSize / 2))

        {

            chXpos = 0;

            chYpos += chSize;

            if (chYpos > (Y_HEIGHT - chSize))

            {

                chYpos = chXpos = 0;

                OLED_clear_screen(0x00);

            }

        }



        OLED_display_char(chXpos, chYpos, *pchString, chSize, chMode);

        chXpos += chSize / 2;

        pchString ++;

    }

}

 

4、结果展示

nRF52832蓝牙芯片上用4pin的I2C OLED屏幕显示温湿度:

更多的项目代码资源可以关注公众号,或在公众号内加客服微信,获取项目帮助。

 

                               

白浪介绍:

(1)关于射频、微波、天线、无线通信、智能硬件、软件编程、渗透安全、人工智能、区块链,Java、Android、C/C++、python等综合能力的培养提升。

(2)各种学习资料、学习软件分享。

1.扫码关注公众号(Geekxiaobai)

                                      

2. 在后台发送“Python高级编程”“Python Graphics”或者“2003”,即可免费获得电子书籍。仅供学习之用。

3. 扫码关注后,查看往期内容,会有更多资料惊喜等着你来拿哦  

  想要更多相关学习资料,可以在文章后面留言哦。

========******=========******========******=========******==========

发布了42 篇原创文章 · 获赞 13 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/sunskyday/article/details/104169828