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

我会带着你远行 2023-07-03 07:27 70阅读 0赞

前期回顾:

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

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

0.**前言(文末有福利)**

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

  1. ![2020020414584513.png][]

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

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

1. 关于OLED显示屏的介绍

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

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

  1. ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNreWRheQ_size_16_color_FFFFFF_t_70 1][]

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

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

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

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

  1. 连头文件都没给,写的比较烂,不过能跑起来。
  2. ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNreWRheQ_size_16_color_FFFFFF_t_70 2][]

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

  1. 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个初始化命令。

  1. **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.65vcc;001,0.77vcc;011,0.83*vcc;

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

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

       0xAF,//开启显示    

};

 

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

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

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

  1. ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNreWRheQ_size_16_color_FFFFFF_t_70 3][]

(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个初始化命令。

  1. **OLED\_init****(****void****)--** **OLED\_send\_cmd****(****OLED\_init\_cmd****\[i\])****。**

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

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

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

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

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

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

  1. 填充屏幕写入的数据为:data=0xFF
  2. 清除屏幕写入数据为: data=0x00

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

  1. ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNreWRheQ_size_16_color_FFFFFF_t_70 4][]

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

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

3.1 Nordic I2C接口

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

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

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

  1. 具体的Nordic I2C实战应用,在前一篇SHT3x温湿度的文章有单独介绍过,
  2. /**
  3. * 描 述 : 向OLED写入1字节命令或数据
  4. * 入 参 : dat:数据;mode:=0:写入命令,=1:写入数据
  5. * 返回值 : 无
  6. **/
  7. void OLED_Write_Command(uint8_t command)
  8. {
  9. ret_code_t err_code;
  10. uint8_t command_send[2] = { 0x00,command};
  11. uint8_t retry_num = 50;
  12. do{
  13. err_code = nrf_drv_twi_tx(&m_twi, OLED096_ADDRESS, command_send, 2, false);
  14. retry_num--;
  15. //等待TWI总线应答
  16. //UNUSED_VARIABLE(err_code);
  17. }
  18. while((NRF_SUCCESS != err_code) && (0 < retry_num));
  19. }
  20. //oled write data
  21. void OLED_Write_Data(unsigned char o_data)
  22. {
  23. ret_code_t err_code;
  24. uint8_t dta_send[2] = { 0x40,o_data};
  25. uint8_t retry_num = 50;
  26. do{
  27. err_code = nrf_drv_twi_tx(&m_twi, OLED096_ADDRESS, dta_send, 2, false);
  28. retry_num--;
  29. }
  30. while ((NRF_SUCCESS != err_code) && (0 < retry_num));
  31. }
  32. /**
  33. * @brief Writes an byte to the display data ram or the command register
  34. *
  35. * @param [in] chData Data to be writen to the display data ram or the command register
  36. * @param [in] chCmd 0: Writes to the command register
  37. * 1: Writes to the display data ram
  38. * @return None
  39. */
  40. void OLED_Write_byte(uint8_t chData, uint8_t chCmd)
  41. {
  42. if(chCmd){ //write data
  43. OLED_Write_Data(chData);
  44. }
  45. else{ //write command
  46. OLED_Write_Command(chCmd);
  47. }
  48. }

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

  1. /**
  2. * @brief Brief
  3. * chMod:0,反白显示;1,正常显示。 size:选择字体16/12
  4. * @param [in] chXpos Specifies the X position ,0-127
  5. * @param [in] chYpos Specifies the Y position ,0-63
  6. * @param [in] chChr a character
  7. * @param [in] chSize character of size
  8. * @param [in] chMode character of mode
  9. * @retval None
  10. */
  11. void OLED_display_char(uint8_t chXpos, uint8_t chYpos, uint8_t chChr, uint8_t chSize, uint8_t chMode)
  12. {
  13. uint8_t i, j;
  14. uint8_t chTemp, chYpos0 = chYpos;
  15. chChr = chChr - ' '; //得到偏移后的值
  16. for (i = 0; i < chSize; i ++)
  17. {
  18. if (chSize == 12) //调用1206字体
  19. {
  20. if (chMode)
  21. {
  22. chTemp = c_chFont1206[chChr][i];
  23. }
  24. else
  25. {
  26. chTemp = ~c_chFont1206[chChr][i];
  27. }
  28. }
  29. else//调用1608字体
  30. {
  31. if (chMode)
  32. {
  33. chTemp = c_chFont1608[chChr][i];
  34. }
  35. else
  36. {
  37. chTemp = ~c_chFont1608[chChr][i];
  38. }
  39. }
  40. for (j = 0; j < 8; j ++)
  41. {
  42. if (chTemp & 0x80)
  43. {
  44. OLED_draw_point(chXpos, chYpos, 1);
  45. }
  46. else
  47. {
  48. OLED_draw_point(chXpos, chYpos, 0);
  49. }
  50. chTemp <<= 1;
  51. chYpos ++;
  52. if ((chYpos - chYpos0) == chSize)
  53. {
  54. chYpos = chYpos0;
  55. chXpos ++;
  56. break;
  57. }
  58. }
  59. }
  60. }
  61. /**
  62. * @brief Brief
  63. * 显示2个数字
  64. * @param [in] chXpos Parameter_Description
  65. * @param [in] chYpos Parameter_Description
  66. * @param [in] chNum Parameter_Description,数值
  67. * @param [in] chLen Parameter_Description,数字的位数
  68. * @param [in] chSize Parameter_Description,字体大小
  69. * @return Return_Description
  70. *
  71. * @details Details
  72. */
  73. void OLED_display_num(uint8_t chXpos, uint8_t chYpos, uint32_t chNum, uint8_t chLen, uint8_t chSize)
  74. {
  75. uint8_t i;
  76. uint8_t chTemp, chShow = 0;
  77. for(i = 0; i < chLen; i ++)
  78. {
  79. chTemp = (chNum / OLED_pow(10, chLen - i - 1)) % 10;
  80. if(chShow == 0 && i < (chLen - 1))
  81. {
  82. if(chTemp == 0)
  83. {
  84. OLED_display_char(chXpos + (chSize / 2) * i, chYpos, ' ', chSize, 1);
  85. continue;
  86. }
  87. else
  88. {
  89. chShow = 1;
  90. }
  91. }
  92. OLED_display_char(chXpos + (chSize / 2) * i, chYpos, chTemp + '0', chSize, 1);
  93. }
  94. }
  95. /**
  96. * @brief Displays a string on the screen
  97. * 显示字符串,*p:字符串起始地址
  98. * @param [in] chXpos Specifies the X position
  99. * @param [in] chYpos Specifies the Y position
  100. * @param [in] pchString Pointer to a string to display on the screen
  101. * @param [in] chSize
  102. * @param [in] chMode
  103. * @return None
  104. */
  105. void OLED_display_string(uint8_t chXpos, uint8_t chYpos, const uint8_t *pchString, uint8_t chSize, uint8_t chMode)
  106. {
  107. while (*pchString != '\0')
  108. {
  109. if (chXpos > (X_WIDTH - chSize / 2))
  110. {
  111. chXpos = 0;
  112. chYpos += chSize;
  113. if (chYpos > (Y_HEIGHT - chSize))
  114. {
  115. chYpos = chXpos = 0;
  116. OLED_clear_screen(0x00);
  117. }
  118. }
  119. OLED_display_char(chXpos, chYpos, *pchString, chSize, chMode);
  120. chXpos += chSize / 2;
  121. pchString ++;
  122. }
  123. }

4、结果展示

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

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

  1. ![20200204150147195.png][]

白浪介绍:

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

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

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

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

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

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

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

发表评论

表情:
评论列表 (有 0 条评论,70人围观)

还没有评论,来说两句吧...

相关阅读