发帖
10 0 0

【外设移植】0.96寸IIC单色屏Ai-M61开发板

沈夜
论坛元老

62

主题

176

回帖

7382

积分

论坛元老

积分
7382
Ai-M61-Kit外设移植教程 3250 10 2023-12-30 22:51:21
本帖最后由 沈夜 于 2024-1-2 18:52 编辑

(1)外设介绍

0.96寸OLED显示屏(驱动芯片:SSD1306 / SSD1315)
[color=rgba(0, 0, 0, 0.87)]0.96寸OLED显示屏是一种小尺寸的有机发光二极管(OLED)显示屏,具有许多优点和特点。以下是对0.96寸OLED显示屏的介绍:
  • 尺寸:0.96寸指的是显示屏的对角线尺寸,通常为0.96英寸(约24.4毫米),适合小型设备和紧凑空间。
  • 分辨率:通常具有128x64像素的分辨率,可以显示清晰的图像和文本。
  • 技术:采用OLED技术,每个像素都是自发光的,不需要背光,因此具有更高的对比度和更广的视角。
  • 高亮度:OLED显示屏具有较高的亮度,即使在室外或明亮的环境下也能清晰可见。
  • 低功耗:相比传统的液晶显示屏,OLED显示屏具有较低的功耗,可以延长电池寿命。
  • 快速响应:OLED显示屏具有快速的响应时间,可以实现流畅的图像和动画效果。
  • 色彩鲜艳:OLED显示屏可以呈现鲜艳、饱满的颜色,使图像更加生动逼真。
  • 视角广:OLED显示屏具有广阔的视角,即使从不同的角度观看,图像仍然清晰可见。
  • 薄型轻便:OLED显示屏采用薄型设计,重量轻,适合应用于便携式设备和可穿戴设备。
  • 灵活性:某些OLED显示屏采用柔性基板制造,具有弯曲和弯折的能力,适用于柔性显示应用。
  • 高对比度:OLED显示屏具有高对比度,黑色显示非常深黑,白色显示非常亮白,使图像更加清晰。
  • 高刷新率:OLED显示屏具有高刷新率,可以实现流畅的视频播放和动态图像效果。



0001.jpg

(2)外设规格参数
工作电压:3.3V
工作电流:9MA
模块尺寸:27.3 x 27.8 MM
像素大小:128(H) x 64(V)RGB
驱动芯片:SSD1306
通信协议:IIC
管脚数量:4 Pin(2.54mm间距排针)

(3)移植过程(资料介绍、移植至工程、引脚选择)
上传的附件: 0.96寸OLED产品规格书.pdf (984.84 KB, 下载次数: 35)
上传的附件: 0.96寸OLED模块原理图-4针脚I2C接口.pdf (71.72 KB, 下载次数: 28)
上传的附件: 驱动芯片SSD1306数据手册.pdf (1.35 MB, 下载次数: 27)

keil stm32 项目移植。
00002.jpg

man.c 事例代码移植
  1. #include "stm32f10x.h"                  // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"



  4. int main(void)
  5. {
  6.         /*OLED初始化*/
  7.         OLED_Init();
  8.         
  9.         /*在(0, 0)位置显示字符'A',字体大小为8*16点阵*/
  10.         OLED_ShowChar(0, 0, 'A', OLED_8X16);
  11.         
  12.         /*在(16, 0)位置显示字符串"Hello World!",字体大小为8*16点阵*/
  13.         OLED_ShowString(16, 0, "Hello World!", OLED_8X16);
  14.         
  15.         /*在(0, 18)位置显示字符'A',字体大小为6*8点阵*/
  16.         OLED_ShowChar(0, 18, 'A', OLED_6X8);
  17.         
  18.         /*在(16, 18)位置显示字符串"Hello World!",字体大小为6*8点阵*/
  19.         OLED_ShowString(16, 18, "Hello World!", OLED_6X8);
  20.         
  21.         /*在(0, 28)位置显示数字12345,长度为5,字体大小为6*8点阵*/
  22.         OLED_ShowNum(0, 28, 12345, 5, OLED_6X8);
  23.         
  24.         /*在(40, 28)位置显示有符号数字-66,长度为2,字体大小为6*8点阵*/
  25.         OLED_ShowSignedNum(40, 28, -66, 2, OLED_6X8);
  26.         
  27.         /*在(70, 28)位置显示十六进制数字0xA5A5,长度为4,字体大小为6*8点阵*/
  28.         OLED_ShowHexNum(70, 28, 0xA5A5, 4, OLED_6X8);
  29.         
  30.         /*在(0, 38)位置显示二进制数字0xA5,长度为8,字体大小为6*8点阵*/
  31.         OLED_ShowBinNum(0, 38, 0xA5, 8, OLED_6X8);
  32.         
  33.         /*在(60, 38)位置显示浮点数字123.45,整数部分长度为3,小数部分长度为2,字体大小为6*8点阵*/
  34.         OLED_ShowFloatNum(60, 38, 123.45, 3, 2, OLED_6X8);
  35.         
  36.         /*在(0, 48)位置显示汉字串"你好,世界。",字体大小为固定的16*16点阵*/
  37.         OLED_ShowChinese(0, 48, "你好,世界。");
  38.         
  39.         /*在(96, 48)位置显示图像,宽16像素,高16像素,图像数据为Diode数组*/
  40.         OLED_ShowImage(96, 48, 16, 16, Diode);
  41.         
  42.         /*在(96, 18)位置打印格式化字符串,字体大小为6*8点阵,格式化字符串为"[%02d]"*/
  43.         OLED_Printf(96, 18, OLED_6X8, "[%02d]", 6);
  44.         
  45.         /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
  46.         OLED_Update();
  47.         
  48.         /*延时3000ms,观察现象*/
  49.         Delay_ms(3000);
  50.         
  51.         /*清空OLED显存数组*/
  52.         OLED_Clear();
  53.         
  54.         /*在(5, 8)位置画点*/
  55.         OLED_DrawPoint(5, 8);
  56.         
  57.         /*获取(5, 8)位置的点*/
  58.         if (OLED_GetPoint(5, 8))
  59.         {
  60.                 /*如果指定点点亮,则在(10, 4)位置显示字符串"YES",字体大小为6*8点阵*/
  61.                 OLED_ShowString(10, 4, "YES", OLED_6X8);
  62.         }
  63.         else
  64.         {
  65.                 /*如果指定点未点亮,则在(10, 4)位置显示字符串"NO ",字体大小为6*8点阵*/
  66.                 OLED_ShowString(10, 4, "NO ", OLED_6X8);
  67.         }
  68.         
  69.         /*在(40, 0)和(127, 15)位置之间画直线*/
  70.         OLED_DrawLine(40, 0, 127, 15);
  71.         
  72.         /*在(40, 15)和(127, 0)位置之间画直线*/
  73.         OLED_DrawLine(40, 15, 127, 0);
  74.         
  75.         /*在(0, 20)位置画矩形,宽12像素,高15像素,未填充*/
  76.         OLED_DrawRectangle(0, 20, 12, 15, OLED_UNFILLED);
  77.         
  78.         /*在(0, 40)位置画矩形,宽12像素,高15像素,填充*/
  79.         OLED_DrawRectangle(0, 40, 12, 15, OLED_FILLED);
  80.         
  81.         /*在(20, 20)、(40, 25)和(30, 35)位置之间画三角形,未填充*/
  82.         OLED_DrawTriangle(20, 20, 40, 25, 30, 35, OLED_UNFILLED);
  83.         
  84.         /*在(20, 40)、(40, 45)和(30, 55)位置之间画三角形,填充*/
  85.         OLED_DrawTriangle(20, 40, 40, 45, 30, 55, OLED_FILLED);
  86.         
  87.         /*在(55, 27)位置画圆,半径8像素,未填充*/
  88.         OLED_DrawCircle(55, 27, 8, OLED_UNFILLED);
  89.         
  90.         /*在(55, 47)位置画圆,半径8像素,填充*/
  91.         OLED_DrawCircle(55, 47, 8, OLED_FILLED);
  92.         
  93.         /*在(82, 27)位置画椭圆,横向半轴12像素,纵向半轴8像素,未填充*/
  94.         OLED_DrawEllipse(82, 27, 12, 8, OLED_UNFILLED);
  95.         
  96.         /*在(82, 47)位置画椭圆,横向半轴12像素,纵向半轴8像素,填充*/
  97.         OLED_DrawEllipse(82, 47, 12, 8, OLED_FILLED);
  98.         
  99.         /*在(110, 18)位置画圆弧,半径15像素,起始角度25度,终止角度125度,未填充*/
  100.         OLED_DrawArc(110, 18, 15, 25, 125, OLED_UNFILLED);
  101.         
  102.         /*在(110, 38)位置画圆弧,半径15像素,起始角度25度,终止角度125度,填充*/
  103.         OLED_DrawArc(110, 38, 15, 25, 125, OLED_FILLED);
  104.         
  105.         /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
  106.         OLED_Update();
  107.         
  108.         /*延时3000ms,观察现象*/
  109.         Delay_ms(3000);
  110.         
  111.         while (1)
  112.         {
  113.                 for (uint8_t i = 0; i < 4; i ++)
  114.                 {
  115.                         /*将OLED显存数组部分数据取反,从(0, i * 16)位置开始,宽128像素,高16像素*/
  116.                         OLED_ReverseArea(0, i * 16, 128, 16);
  117.                         
  118.                         /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
  119.                         OLED_Update();
  120.                         
  121.                         /*延时1000ms,观察现象*/
  122.                         Delay_ms(1000);
  123.                         
  124.                         /*把取反的内容翻转回来*/
  125.                         OLED_ReverseArea(0, i * 16, 128, 16);
  126.                 }
  127.                
  128.                 /*将OLED显存数组全部数据取反*/
  129.                 OLED_Reverse();
  130.                
  131.                 /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
  132.                 OLED_Update();
  133.                
  134.                 /*延时1000ms,观察现象*/
  135.                 Delay_ms(1000);
  136.         }
  137. }
复制代码
删除 不用的代码。
#include "stm32f10x.h" // Device header
#include "Delay.h"

确少一个 延时,你以为我要写一个一样的函数?
功能一样直接调用博流的库,可以 手动替换成bflb_mtimer_delay_ms
但是可以根据c语法,[color=rgba(0, 0, 0, 0.87)]在您的代码中添加以下宏定义:
#define Delay_ms(ms) bflb_mtimer_delay_ms(ms)

则无需修改任何代码。
oled.c i2c 移植

可见需要 修改的地方
OLED引脚初始化>>OLED_GPIO_Init
I2C发送一个字节>>OLED_I2C_SendByte
iOLED写命令>>OLED_WriteCommand
OLED写数据>>OLED_WriteData
修改方法。直接复制 sdk里面的i2c代码即可
  1. /**
  2.   * 函    数:OLED引脚初始化
  3.   * 参    数:无
  4.   * 返 回 值:无
  5.   * 说    明:当上层函数需要初始化时,此函数会被调用
  6.   *           用户需要将SCL和SDA引脚初始化为开漏模式,并释放引脚
  7.   */
  8. void OLED_GPIO_Init(void)
  9. {
  10.     struct bflb_device_s* gpio;
  11.     board_init();
  12.     //board_i2c0_gpio_init();
  13.    

  14.     gpio = bflb_device_get_by_name("gpio");
  15.     /* I2C0_SCL */
  16.     bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
  17.     /* I2C0_SDA */
  18.    bflb_gpio_init(gpio, GPIO_PIN_1, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
  19.     i2c0 = bflb_device_get_by_name("i2c0");

  20.     bflb_i2c_init(i2c0, 400000);
  21.     //oled_write(OLED_CMD, OLED_init_cmd, sizeof(OLED_init_cmd) / sizeof(unsigned char));
  22.     printf("OLED_Init over\r\n");
  23. }
复制代码

经过分析。原先工程用的是软件模拟i2c,本次使用的硬件库的。
I2C发送一个字节>>OLED_I2C_SendByte 这个不用移植,直接删掉。


iOLED写命令>>OLED_WriteCommand
OLED写数据>>OLED_WriteData

  1. /**
  2.   * 函    数:OLED写命令
  3.   * 参    数:Command 要写入的命令值,范围:0x00~0xFF
  4.   * 返 回 值:无
  5.   */
  6. void OLED_WriteCommand(uint8_t Command)
  7. {
  8.         OLED_I2C_Start();                                //I2C起始
  9.         OLED_I2C_SendByte(0x78);                //发送OLED的I2C从机地址
  10.         OLED_I2C_SendByte(0x00);                //控制字节,给0x00,表示即将写命令
  11.         OLED_I2C_SendByte(Command);                //写入指定的命令
  12.         OLED_I2C_Stop();                                //I2C终止
  13. }
复制代码
分析得来 就是发送从机地址,和命令。

里面的函数都用不到,直接删除。
OLED_I2C_Start(); I2C起始

OLED_I2C_SendByte(0x78);

OLED_I2C_Stop(); //I2C终止

  1. /**
  2.   * 函    数:OLED写命令
  3.   * 参    数:Command 要写入的命令值,范围:0x00~0xFF
  4.   * 返 回 值:无
  5.   */
  6. void OLED_WriteCommand(uint8_t Command)
  7. {


  8.         oled_writea(0x00, &Command, 1);

  9. }

  10. /**
  11.   * 函    数:OLED写数据
  12.   * 参    数:Data 要写入数据的起始地址
  13.   * 参    数:Count 要写入数据的数量
  14.   * 返 回 值:无
  15.   */
  16. void OLED_WriteData(uint8_t *Data, uint8_t Count)
  17. {
  18.         uint8_t i;
  19.         
  20.         /*循环Count次,进行连续的数据写入*/
  21.         for (i = 0; i < Count; i ++)
  22.         {
  23.                 //OLED_I2C_SendByte(Data[i]);        //依次发送Data的每一个数据
  24.                 oled_writea(0x40, &Data[i], 1);
  25.         }
  26.         //OLED_I2C_Stop();                                //I2C终止
  27. }
复制代码


(4)移植验证


功能齐全 - 支持字符、数字、汉字、图像及各种绘图图形显示
优化大量代码,专业用 功能实现即可。
即使小白也能 简单学习就能使用。带注释。
PS:代码非原创,只是移植到了Ai-M61
代码无任何报错。
01.jpg



快速使用:
解压 修改 Makefile 文件
BL_SDK_BASE ?= D:\test\boliu\bouffalo_sdk/

为自己的sdk路径即可
#include "OLED.h"

    /*OLED初始化*/
    OLED_Init();
   
    /*在(0, 0)位置显示字符'A',字体大小为8*16点阵*/
    OLED_ShowChar(0, 0, 'A', OLED_8X16);

    /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
    OLED_Update();

02.jpg




只需要引用一个,就能方便调用了。
高级设置:
OLED.c
OLED_GPIO_Init 函    数:OLED引脚初始化


只需要替换
GPIO_PIN_0
GPIO_PIN_1
接可以修改自定义引脚
04.jpg

OLED_Data.c
03.jpg
添加没有的中文字库。
添加图像 都在此。
demo里面有详细的调用过程都非常简单。
取模教程
一:配置软件,点设置然后按照如下设置。
z01.jpg
二:生成字模
z04.jpg
三:安装他的格式 调整一下就行,删掉多余的,
复制没有的 即可。

z02.jpg

z05.jpg
效果如下。
z10.jpg

上传的附件: PCtoLCD2002.zip (886.22 KB, 下载次数: 19)

上传的附件: 0.96oled.zip (17.69 KB, 下载次数: 25)

(5)常见问题汇总


通过本次移植,复习了很多c语言的知识,真正解决问题。
感谢园长的这次活动
大家也可以看到,移植纯c代码 需要改的地方 并不多,
我甚至原封不动的 复制过来的 man文件,仅仅是添加了文件头
  5.1文件找不到
打开CMakeLists.txt
添加文件包含,格式空格 一个文件名
target_sources(app PRIVATE oled.c OLED_Data.c)
5.2 编译器找不到路径
修改 Makefile 文件
BL_SDK_BASE ?= D:\test\boliu\bouffalo_sdk/

也可以 直接修改为sdk的绝对路径,这样你项目的目录 可以随便放在任何地方。
5.3 数据类型找不到。
引入c语言 库

能解决90%
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdarg.h>



──── 0人觉得很赞 ────
z06.jpg

使用道具 举报

2023-12-30 23:11:54
沙发
2023-12-30 23:41:52
学习
2023-12-31 07:43:06
速度快呀
2023-12-31 09:06:56
2023-12-31 10:45:18
要是都能够统一放到一个仓库就好了,测试完成都pr一下
2023-12-31 21:05:58
厉害
2023-12-31 23:10:07
真好
2024-1-1 19:29:44
End 发表于 2023-12-31 10:45
要是都能够统一放到一个仓库就好了,测试完成都pr一下

这得问问园长了。
2024-1-2 08:51:27
End 发表于 2023-12-31 10:45
要是都能够统一放到一个仓库就好了,测试完成都pr一下

我问问技术,看下怎么实现!
您需要登录后才可以回帖 立即登录
高级模式
12下一页
统计信息
  • 会员数: 28273 个
  • 话题数: 40244 篇