[活动专区] 【AT-START-F423测评】11.使用I2C驱动OLED

[复制链接]
 楼主| yuyy1989 发表于 2023-11-7 19:44 | 显示全部楼层 |阅读模式
#申请原创# @21小跑堂  

这块0.96的OLED是I2C接口的,控制芯片是SSD1315
微信图片_20231107193320.jpg
卖家给的资料里有驱动的例程,接下来参考例程实现对这块屏幕的控制
首先定义一个设备的结构体,里面定义要用到的I2C控制指针和发送方法,这样做为的是方便移植用
  1. typedef struct
  2. {
  3.     void *iicx;
  4.     YUYY_IIC_MasterSendRegDatasFunc_Type iic_senddatas_func;
  5. }YUYY_OLED_SSD1315_DEV_Type;
实现发送命令和数据的方法,原例程中一次I2C通讯只发送2字节的数据,感觉有点浪费
QQ截图20231107193540.png
看一下SSD1315的手册,一次I2C通讯是可以发送2个字节以上的数据的
QQ截图20231106210520.png
看一下控制位的描述
QQ截图20231106210542.png
意思是co这位为0时控制字节后面就全是数据字节,这样就能得到下面的命令格式
发送命令数据:start addr+w 0x00 byte1 byte2 … byteN stop
发送显示数据:start addr+w 0x40 byte1 byte2 … byteN stop
按此实现发送方法
  1. uint8_t YUYY_OLED_SSD1315_SendCmds(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *cmds,uint8_t cmdlen)
  2. {
  3.     uint8_t cbyte = 0x00;
  4.     if(!oled_ssd1315_dev->iic_senddatas_func)
  5.         return 1;
  6.     if(oled_ssd1315_dev->iic_senddatas_func(oled_ssd1315_dev->iicx,YUYY_OLED_SSD1315_IIC_ADDR,0x00,1,cmds,cmdlen) > 0)
  7.         return 2;
  8.     return 0;
  9. }

  10. uint8_t YUYY_OLED_SSD1315_SendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *datas,uint8_t datalen)
  11. {
  12.     uint8_t cbyte = 0x40;
  13.     if(!oled_ssd1315_dev->iic_senddatas_func)
  14.         return 1;
  15.     if(oled_ssd1315_dev->iic_senddatas_func(oled_ssd1315_dev->iicx,YUYY_OLED_SSD1315_IIC_ADDR,0x40,1,datas,datalen) > 0)
  16.         return 2;
  17.     return 0;
  18. }
这样初始化时可以直接发送初始化的命令数组
  1. const uint8_t oled_ssd1315_init_cmd[25]=
  2. {
  3.        0xAE,//关闭显示
  4.        0xD5,//设置时钟分频因子,震荡频率
  5.        0x80,  //[3:0],分频因子;[7:4],震荡频率
  6.        0xA8,//设置驱动路数
  7.        0X3F,//默认0X3F(1/64)
  8.        0xD3,//设置显示偏移
  9.        0X00,//默认为0
  10.        0x40,//设置显示开始行 [5:0],行数.                              
  11.        0x8D,//电荷泵设置
  12.        0x14,//bit2,开启/关闭
  13.        0x20,//设置内存地址模式
  14.        0x02,//[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
  15.        0xA1,//段重定义设置,bit0:0,0->0;1,0->127;
  16.        0xC8,//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
  17.        0xDA,//设置COM硬件引脚配置
  18.        0x12,//[5:4]配置            
  19.        0x81,//对比度设置
  20.        0xEF,//1~255;默认0X7F (亮度设置,越大越亮)
  21.        0xD9,//设置预充电周期
  22.        0xF1,//[3:0],PHASE 1;[7:4],PHASE 2;
  23.        0xDB,//设置VCOMH 电压倍率
  24.        0x30,//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
  25.        0xA4,//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
  26.        0xA6,//设置显示方式;bit0:1,反相显示;0,正常显示        
  27.        0xAF,//开启显示     
  28. };
  29. uint8_t YUYY_OLED_SSD1315_Init(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev)
  30. {
  31.     uint8_t err = 0;
  32.     err = YUYY_OLED_SSD1315_SendCmds(oled_ssd1315_dev,oled_ssd1315_init_cmd,25);
  33.     return err;
  34. }
写入显示数据时一次写入一行
  1. uint8_t YUYY_OLED_SSD1315_SetPageCol(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t page,uint8_t col)
  2. {
  3.     uint8_t cmds[3];
  4.     if(page < 8 && col < 128)
  5.     {
  6.         cmds[0] = 0xB0+page;
  7.         cmds[1] = 0x10|(col>>4);
  8.         cmds[2] = 0x00|(col&0x0f);
  9.         return YUYY_OLED_SSD1315_SendCmds(oled_ssd1315_dev,cmds,3);
  10.     }
  11.     return 1;
  12. }

  13. uint8_t YUYY_OLED_SSD1315_ClearScreen(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev)
  14. {
  15.     uint8_t i=0,datas[128]={0};
  16.     while(i<8)
  17.     {
  18.         if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,i,0))
  19.             return 1;
  20.         if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,128))
  21.             return 1;
  22.         i += 1;
  23.     }
  24.     return 0;
  25. }

  26. uint8_t YUYY_OLED_SSD1315_TestScreen(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t d1,uint8_t d2)
  27. {
  28.     uint8_t i=0,datas[128]={0};
  29.     while (i < 128)
  30.     {
  31.         datas[i] = d1;
  32.         datas[i+1] = d2;
  33.         i += 2;
  34.     }
  35.     i = 0;
  36.     while(i<8)
  37.     {
  38.         if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,i,0))
  39.             return 1;
  40.         if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,128))
  41.             return 1;
  42.         i += 1;
  43.     }
  44.     return 0;
  45. }

  46. void YUYY_OLED_SSD1315_CopyDatas(uint8_t *dst,uint8_t *src,uint8_t len,uint8_t rev)
  47. {
  48.     uint8_t i = 0;
  49.     while (i < len)
  50.     {
  51.         if(rev)
  52.             dst[i] = ~src[i];
  53.         else
  54.             dst[i] = src[i];
  55.         i += 1;
  56.     }
  57. }

  58. void YUYY_OLED_SSD1315_DisplayString8x16(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,char *text)
  59. {
  60.     uint8_t i=0,j = 0,rev = option&YUYY_FONT_DATAS_REVERSE;
  61.     uint8_t datas1[128] = {0},datas2[128] = {0};
  62.    
  63.     while(text[i]>0x00 && j < 128)
  64.     {
  65.         if((text[i] > 0x1F)&&(text[i] < 0x7F))
  66.         {
  67.             YUYY_OLED_SSD1315_CopyDatas(&datas1[j],&YUYY_FONT_ASCII_TABLE_8x16[text[i]-0x20][0],8,rev);
  68.             YUYY_OLED_SSD1315_CopyDatas(&datas2[j],&YUYY_FONT_ASCII_TABLE_8x16[text[i]-0x20][8],8,rev);
  69.         }
  70.         j += 8;
  71.         i += 1;
  72.     }
  73.     if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page,column))
  74.         return;
  75.     if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas1,j))
  76.         return;
  77.     if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page+1,column))
  78.         return;
  79.     if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas2,j))
  80.         return;
  81. }

  82. void YUYY_OLED_SSD1315_DisplayString6x8(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,char *text)
  83. {
  84.     uint8_t i=0,j = 0,rev = option&YUYY_FONT_DATAS_REVERSE;
  85.     uint8_t datas[128] = {0};
  86.     while(text[i]>0x00 && j < 128)
  87.     {
  88.         if((text[i] > 0x1F)&&(text[i] < 0x7F))
  89.         {
  90.             if(j < 126)
  91.                 YUYY_OLED_SSD1315_CopyDatas(&datas[j],YUYY_FONT_ASCII_TABLE_6x8[text[i]-0x20],6,rev);
  92.             else
  93.                 YUYY_OLED_SSD1315_CopyDatas(&datas[j],YUYY_FONT_ASCII_TABLE_6x8[text[i]-0x20],2,rev);
  94.         }
  95.         j += 6;
  96.         i += 1;
  97.     }
  98.     if(j > 128)
  99.         j = 128;
  100.     if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page,column))
  101.         return;
  102.     if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,j))
  103.         return;
  104. }
先用软件I2C测试
  1. YUYY_OLED_SSD1315_DEV_Type oled_dev;
  2. void oled_init()
  3. {
  4.     oled_dev.iicx = &siic_dev;
  5.     oled_dev.iic_senddatas_func = (YUYY_IIC_MasterSendRegDatasFunc_Type)YUYY_SOFTIIC_MasterSendRegDatas;
  6.     YUYY_OLED_SSD1315_Init(&oled_dev);
  7.     YUYY_OLED_SSD1315_ClearScreen(&oled_dev);
  8.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,0,0," AT32F423 TEST");
  9.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,2,0,"    I2C OLED");
  10.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,6,0,"Code by yuyy1989");
  11. }

  12. uint8_t testnum = 0;
  13. void oled_test()
  14. {
  15.     char out[20];
  16.     sprintf(out,"  Test Num:%02X",testnum);
  17.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,out);
  18.     testnum += 1;
  19. }
效果
WeChat_20231107193957 00_00_00-00_00_30.gif
再用硬件I2C试试,只修改这里就行了
  1. //oled_dev.iicx = &siic_dev;
  2. //oled_dev.iic_senddatas_func = (YUYY_IIC_MasterSendRegDatasFunc_Type)YUYY_SOFTIIC_MasterSendRegDatas;
  3. oled_dev.iicx = I2C1;
  4. oled_dev.iic_senddatas_func = (YUYY_IIC_MasterSendRegDatasFunc_Type)YUYY_HARDIIC_MasterSendRegDatas;
  5. YUYY_OLED_SSD1315_Init(&oled_dev);
效果
WeChat_20231107194004 00_00_00-00_00_30.gif

ccwwbb76 发表于 2023-12-27 15:39 | 显示全部楼层
楼主能给一个完整的程序吗,这样看起来比较好一些!谢谢了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

161

主题

815

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部
认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

161

主题

815

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部