| 
 
| 本帖最后由 沈夜 于 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显示屏具有高刷新率,可以实现流畅的视频播放和动态图像效果。
 
 
 
   
 (2)外设规格参数
 工作电压:3.3V
 工作电流:9MA
 模块尺寸:27.3 x 27.8 MM
 像素大小:128(H) x 64(V)RGB
 驱动芯片:SSD1306
 通信协议:IIC
 管脚数量:4 Pin(2.54mm间距排针)
 
 (3)移植过程(资料介绍、移植至工程、引脚选择)
 
 keil stm32 项目移植。
 
   
 man.c 事例代码移植
 
 删除 不用的代码。复制代码#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
int main(void)
{
        /*OLED初始化*/
        OLED_Init();
        
        /*在(0, 0)位置显示字符'A',字体大小为8*16点阵*/
        OLED_ShowChar(0, 0, 'A', OLED_8X16);
        
        /*在(16, 0)位置显示字符串"Hello World!",字体大小为8*16点阵*/
        OLED_ShowString(16, 0, "Hello World!", OLED_8X16);
        
        /*在(0, 18)位置显示字符'A',字体大小为6*8点阵*/
        OLED_ShowChar(0, 18, 'A', OLED_6X8);
        
        /*在(16, 18)位置显示字符串"Hello World!",字体大小为6*8点阵*/
        OLED_ShowString(16, 18, "Hello World!", OLED_6X8);
        
        /*在(0, 28)位置显示数字12345,长度为5,字体大小为6*8点阵*/
        OLED_ShowNum(0, 28, 12345, 5, OLED_6X8);
        
        /*在(40, 28)位置显示有符号数字-66,长度为2,字体大小为6*8点阵*/
        OLED_ShowSignedNum(40, 28, -66, 2, OLED_6X8);
        
        /*在(70, 28)位置显示十六进制数字0xA5A5,长度为4,字体大小为6*8点阵*/
        OLED_ShowHexNum(70, 28, 0xA5A5, 4, OLED_6X8);
        
        /*在(0, 38)位置显示二进制数字0xA5,长度为8,字体大小为6*8点阵*/
        OLED_ShowBinNum(0, 38, 0xA5, 8, OLED_6X8);
        
        /*在(60, 38)位置显示浮点数字123.45,整数部分长度为3,小数部分长度为2,字体大小为6*8点阵*/
        OLED_ShowFloatNum(60, 38, 123.45, 3, 2, OLED_6X8);
        
        /*在(0, 48)位置显示汉字串"你好,世界。",字体大小为固定的16*16点阵*/
        OLED_ShowChinese(0, 48, "你好,世界。");
        
        /*在(96, 48)位置显示图像,宽16像素,高16像素,图像数据为Diode数组*/
        OLED_ShowImage(96, 48, 16, 16, Diode);
        
        /*在(96, 18)位置打印格式化字符串,字体大小为6*8点阵,格式化字符串为"[%02d]"*/
        OLED_Printf(96, 18, OLED_6X8, "[%02d]", 6);
        
        /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
        OLED_Update();
        
        /*延时3000ms,观察现象*/
        Delay_ms(3000);
        
        /*清空OLED显存数组*/
        OLED_Clear();
        
        /*在(5, 8)位置画点*/
        OLED_DrawPoint(5, 8);
        
        /*获取(5, 8)位置的点*/
        if (OLED_GetPoint(5, 8))
        {
                /*如果指定点点亮,则在(10, 4)位置显示字符串"YES",字体大小为6*8点阵*/
                OLED_ShowString(10, 4, "YES", OLED_6X8);
        }
        else
        {
                /*如果指定点未点亮,则在(10, 4)位置显示字符串"NO ",字体大小为6*8点阵*/
                OLED_ShowString(10, 4, "NO ", OLED_6X8);
        }
        
        /*在(40, 0)和(127, 15)位置之间画直线*/
        OLED_DrawLine(40, 0, 127, 15);
        
        /*在(40, 15)和(127, 0)位置之间画直线*/
        OLED_DrawLine(40, 15, 127, 0);
        
        /*在(0, 20)位置画矩形,宽12像素,高15像素,未填充*/
        OLED_DrawRectangle(0, 20, 12, 15, OLED_UNFILLED);
        
        /*在(0, 40)位置画矩形,宽12像素,高15像素,填充*/
        OLED_DrawRectangle(0, 40, 12, 15, OLED_FILLED);
        
        /*在(20, 20)、(40, 25)和(30, 35)位置之间画三角形,未填充*/
        OLED_DrawTriangle(20, 20, 40, 25, 30, 35, OLED_UNFILLED);
        
        /*在(20, 40)、(40, 45)和(30, 55)位置之间画三角形,填充*/
        OLED_DrawTriangle(20, 40, 40, 45, 30, 55, OLED_FILLED);
        
        /*在(55, 27)位置画圆,半径8像素,未填充*/
        OLED_DrawCircle(55, 27, 8, OLED_UNFILLED);
        
        /*在(55, 47)位置画圆,半径8像素,填充*/
        OLED_DrawCircle(55, 47, 8, OLED_FILLED);
        
        /*在(82, 27)位置画椭圆,横向半轴12像素,纵向半轴8像素,未填充*/
        OLED_DrawEllipse(82, 27, 12, 8, OLED_UNFILLED);
        
        /*在(82, 47)位置画椭圆,横向半轴12像素,纵向半轴8像素,填充*/
        OLED_DrawEllipse(82, 47, 12, 8, OLED_FILLED);
        
        /*在(110, 18)位置画圆弧,半径15像素,起始角度25度,终止角度125度,未填充*/
        OLED_DrawArc(110, 18, 15, 25, 125, OLED_UNFILLED);
        
        /*在(110, 38)位置画圆弧,半径15像素,起始角度25度,终止角度125度,填充*/
        OLED_DrawArc(110, 38, 15, 25, 125, OLED_FILLED);
        
        /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
        OLED_Update();
        
        /*延时3000ms,观察现象*/
        Delay_ms(3000);
        
        while (1)
        {
                for (uint8_t i = 0; i < 4; i ++)
                {
                        /*将OLED显存数组部分数据取反,从(0, i * 16)位置开始,宽128像素,高16像素*/
                        OLED_ReverseArea(0, i * 16, 128, 16);
                        
                        /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
                        OLED_Update();
                        
                        /*延时1000ms,观察现象*/
                        Delay_ms(1000);
                        
                        /*把取反的内容翻转回来*/
                        OLED_ReverseArea(0, i * 16, 128, 16);
                }
                
                /*将OLED显存数组全部数据取反*/
                OLED_Reverse();
                
                /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
                OLED_Update();
                
                /*延时1000ms,观察现象*/
                Delay_ms(1000);
        }
}
#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代码即可
 
 复制代码/**
  * 函    数:OLED引脚初始化
  * 参    数:无
  * 返 回 值:无
  * 说    明:当上层函数需要初始化时,此函数会被调用
  *           用户需要将SCL和SDA引脚初始化为开漏模式,并释放引脚
  */
void OLED_GPIO_Init(void)
{
    struct bflb_device_s* gpio;
    board_init();
    //board_i2c0_gpio_init();
    
    gpio = bflb_device_get_by_name("gpio");
    /* I2C0_SCL */
    bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    /* I2C0_SDA */
   bflb_gpio_init(gpio, GPIO_PIN_1, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    i2c0 = bflb_device_get_by_name("i2c0");
    bflb_i2c_init(i2c0, 400000);
    //oled_write(OLED_CMD, OLED_init_cmd, sizeof(OLED_init_cmd) / sizeof(unsigned char));
    printf("OLED_Init over\r\n");
}
经过分析。原先工程用的是软件模拟i2c,本次使用的硬件库的。
 I2C发送一个字节>>OLED_I2C_SendByte 这个不用移植,直接删掉。
 
 
 iOLED写命令>>OLED_WriteCommand
 OLED写数据>>OLED_WriteData
 
 
 分析得来 就是发送从机地址,和命令。复制代码/**
  * 函    数:OLED写命令
  * 参    数:Command 要写入的命令值,范围:0x00~0xFF
  * 返 回 值:无
  */
void OLED_WriteCommand(uint8_t Command)
{
        OLED_I2C_Start();                                //I2C起始
        OLED_I2C_SendByte(0x78);                //发送OLED的I2C从机地址
        OLED_I2C_SendByte(0x00);                //控制字节,给0x00,表示即将写命令
        OLED_I2C_SendByte(Command);                //写入指定的命令
        OLED_I2C_Stop();                                //I2C终止
}
 里面的函数都用不到,直接删除。
 OLED_I2C_Start(); I2C起始
 
 OLED_I2C_SendByte(0x78);
 
 OLED_I2C_Stop(); //I2C终止
 
 
 复制代码/**
  * 函    数:OLED写命令
  * 参    数:Command 要写入的命令值,范围:0x00~0xFF
  * 返 回 值:无
  */
void OLED_WriteCommand(uint8_t Command)
{
        oled_writea(0x00, &Command, 1);
}
/**
  * 函    数:OLED写数据
  * 参    数:Data 要写入数据的起始地址
  * 参    数:Count 要写入数据的数量
  * 返 回 值:无
  */
void OLED_WriteData(uint8_t *Data, uint8_t Count)
{
        uint8_t i;
        
        /*循环Count次,进行连续的数据写入*/
        for (i = 0; i < Count; i ++)
        {
                //OLED_I2C_SendByte(Data[i]);        //依次发送Data的每一个数据
                oled_writea(0x40, &Data[i], 1);
        }
        //OLED_I2C_Stop();                                //I2C终止
}
 (4)移植验证
 
 
 
 功能齐全 - 支持字符、数字、汉字、图像及各种绘图图形显示 优化大量代码,专业用 功能实现即可。 即使小白也能 简单学习就能使用。带注释。 PS:代码非原创,只是移植到了Ai-M61 代码无任何报错。   
 
 
 
 快速使用: 解压 修改 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();
 
 
   
 
 
 只需要引用一个,就能方便调用了。 高级设置: OLED.c
 OLED_GPIO_Init 函    数:OLED引脚初始化
 
 
 只需要替换 
GPIO_PIN_0
GPIO_PIN_1接可以修改自定义引脚
 
   
 OLED_Data.c
   
 添加没有的中文字库。 添加图像 都在此。 demo里面有详细的调用过程都非常简单。 取模教程
 一:配置软件,点设置然后按照如下设置。
 二:生成字模
 三:安装他的格式 调整一下就行,删掉多余的,复制没有的 即可。
 
 
 
 效果如下。 
 
 (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>
 
 
 
 
 | 
 |