找回密码
 立即注册
楼主: 大明狐

用AiCube配置硬件SPI和DMA点亮OLED12864 | 跟帖问OLED12864程序给您全搞定

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:512
  • 最近打卡:2025-09-03 06:12:15

31

主题

411

回帖

3470

积分

荣誉版主

积分
3470
发表于 2025-8-25 08:30:35 | 显示全部楼层
Tui*** 发表于 2025-8-24 07:15
版主你好,我的OLED12864驱动芯片是ST7567,MCU为AI8051U,用P2端口。通过你的讲解,硬件SPI硬件驱动成功了 ...

不清楚你说的DMA移植不顺利集体是什么,就先忙猜一下是速度问题。
因为不同型号的控制芯片,时序之类其实都不太一样。比如,即便是驱动程序看起来通用的OLED,不同型号之间,对单片机的速度要求也不完全一样。所以,硬件SPI通过了而DMA没通过,就有可能是SPI的速度配置对了,DMA的速度没配置合适。
而ST7567是LCD液晶屏的驱动芯片,不是OLED的,而是跟TFT彩屏是一个系统的,它们对时序要求更高。

能体会到发现一个不理解的现象然后找原因然后要么解决掉问题要么被问题解决掉的那种快乐是我的幸运
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:572
  • 最近打卡:2025-09-02 10:34:06

25

主题

198

回帖

1724

积分

金牌会员

积分
1724
发表于 2025-8-25 15:34:10 | 显示全部楼层
大*** 发表于 2025-8-25 08:30
不清楚你说的DMA移植不顺利集体是什么,就先忙猜一下是速度问题。
因为不同型号的控制芯片,时序之类其实 ...

我可能描述不清楚,重新交流一下。
就是移植后,SPI硬件驱动(无DMA)屏幕能正常驱动显示。加了DMA后,显示不正常,只有第一行(程序中只能显示一行,即第6page,其它页都显示乱码,且显示不对应)显示正常,其它乱码,怎么修改都不得其法。现将截图和程序贴上,请版主指导!
IMG_20250825_152452.jpg

ai8051u_spi_dma.rar

428.69 KB, 下载次数: 9

点评

不知道没有DMA的成功代码是什么样。从照片上看,DFMA的这个是只刷新了屏幕的最上面一行。 手头也暂时没有这种屏幕,没法测试想法。 这个DMA的代码里,刷新全屏用的是一次性发送1024个数据。 但是找了下ST7567的资料  详情 回复 发表于 2025-8-25 16:50
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:512
  • 最近打卡:2025-09-03 06:12:15

31

主题

411

回帖

3470

积分

荣誉版主

积分
3470
发表于 2025-8-25 16:50:34 | 显示全部楼层
Tui*** 发表于 2025-8-25 15:34
我可能描述不清楚,重新交流一下。
就是移植后,SPI硬件驱动(无DMA)屏幕能正常驱动显示。加了DMA后,显 ...

不知道没有DMA的成功代码是什么样。从照片上看,用DMA的这个是只刷新了屏幕的最上面一行。
手头也暂时没有这种屏幕,没法测试想法。
这个DMA的代码里,刷新全屏用的是一次性发送1024个数据。
但是找了下ST7567的资料,控制芯片的结构是每个page有132列,只用到其中128列,类似SH1106的OLED屏幕,而且列地址只在指定行里自增和归零,相当于OLED屏幕的“页地址模式”。
这样的话,128×64的区域应该不能用这种方式填充数据,而是分成8行,每次发送128个数据才对。

把OLED_Refresh函数的一次性发送1024个数据,换成分8行发送,每次128个数据试试看?


能体会到发现一个不理解的现象然后找原因然后要么解决掉问题要么被问题解决掉的那种快乐是我的幸运
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:572
  • 最近打卡:2025-09-02 10:34:06

25

主题

198

回帖

1724

积分

金牌会员

积分
1724
发表于 2025-8-26 10:06:07 | 显示全部楼层
大*** 发表于 2025-8-25 16:50
不知道没有DMA的成功代码是什么样。从照片上看,用DMA的这个是只刷新了屏幕的最上面一行。
手头也暂时没有 ...

还是不行。未成功代码在12楼末尾
void OLED_Refresh(void)
{
    uint8_t cmd[3];
   
    cmd[0] = 0x40;                      //设置行起始地址
    cmd[1] = 0x00;                      //设置低列起始地址
    cmd[2] = 0x10;                      //设置高列起始地址
    OLED_WR_CMD(cmd, 3);  
//    OLED_WR_DAT(OledCache, 1024);       //写数据...
          OLED_WR_DAT(OledCache, 128);        
                OLED_WR_DAT(OledCache, 128);
                OLED_WR_DAT(OledCache, 128);
                OLED_WR_DAT(OledCache, 128);
                OLED_WR_DAT(OledCache, 128);
                OLED_WR_DAT(OledCache, 128);
                OLED_WR_DAT(OledCache, 128);
                OLED_WR_DAT(OledCache, 128);
        
}

点评

12楼末尾的代码看过了,上面的回复就是根据这个代码推测的。 关于OLED_Refresh函数的修改方法,结构可以参考显示图片的函数。 分成8行发送,就是分别定位每一行,然后发送对应的128个数据。 你的这个修改,依旧是在  详情 回复 发表于 2025-8-26 13:54
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:512
  • 最近打卡:2025-09-03 06:12:15

31

主题

411

回帖

3470

积分

荣誉版主

积分
3470
发表于 2025-8-26 13:54:39 | 显示全部楼层
Tui*** 发表于 2025-8-26 10:06
还是不行。未成功代码在12楼末尾
void OLED_Refresh(void)
{

12楼末尾的代码看过了,上面的回复就是根据这个代码推测的。

关于OLED_Refresh函数的修改方法,结构可以参考显示图片的函数。
分成8行发送,就是分别定位每一行,然后发送对应的128个数据。
你的这个修改,依旧是在第一行里反复发送缓存数组里的钱128个数据。可以借助一个变量,对行号进行递增,然后发送对应的128个数据。

根据芯片手册里关于设置页地址的指令表,是以0xB0为基础的(1011xxxx),低四位是行号,
截图202508261222486469.jpg

所以比如像这样写:


void OLED_Refresh(void)
{
    uint8_t page;
    uint8_t cmd[4];
   
    for( page=0; page<8; page++ )
    {
        cmd[0] = 0x40;                      //设置屏幕最顶上一行作为第0行
        cmd[1] = 0xB0+page;             //设置行起始地址
        cmd[2] = 0x10;                      //设置低列起始地址(高四位)
        cmd[3] = 0x00;                      //设置高列起始地址(低四位)
        OLED_WR_CMD( cmd, 4 );  

        OLED_WR_DAT( OledCache + page*128 , 128 );        
    }        
}


其中0x40也可以放到初始化函数里,就不用每次都发送了。
能体会到发现一个不理解的现象然后找原因然后要么解决掉问题要么被问题解决掉的那种快乐是我的幸运
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:572
  • 最近打卡:2025-09-02 10:34:06

25

主题

198

回帖

1724

积分

金牌会员

积分
1724
发表于 7 天前 | 显示全部楼层
大*** 发表于 2025-8-26 13:54
12楼末尾的代码看过了,上面的回复就是根据这个代码推测的。

关于OLED_Refresh函数的修改方法,结构可以 ...

按照版主老师的程序,显示有所改善:不花屏了,但显示不正常,无法定位显示,自己试着修改其它参数仍不能正常,奈何技术水平有限,再次与版主交流。具体描述如下:
程序里所有页都有内容时,显示如下:
第一种情况:
while (1)
    {
        //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
        // 在此添加主函数中用户主循环代码
         
        OLED_ClearScreen(0);
        OLED_SetFontHeight(16);
        OLED_DrawString(0, 0, "   OLED-12864   ", 0);
        OLED_DrawString(0, 2, "    文本模式    ", 0);
        OLED_SetFontHeight(8);
        OLED_DrawString(0, 4, "OLED Model : SSD1306", 0);
        OLED_DrawString(0, 5, "Target MCU : Ai8051U", 0);
        OLED_DrawString(0, 6, "Work Freq. : 40.0MHz", 1);

}有显示,但显示不全。而且重复显示。
***************************************************
第二种情况:
屏蔽掉
while (1)
    {
        //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
        // 在此添加主函数中用户主循环代码
         
        OLED_ClearScreen(0);
        OLED_SetFontHeight(16);
        OLED_DrawString(0, 0, "   OLED-12864   ", 0);
        OLED_DrawString(0, 2, "    文本模式    ", 0);
        OLED_SetFontHeight(8);
       // OLED_DrawString(0, 4, "OLED Model : SSD1306", 0);
        //OLED_DrawString(0, 5, "Target MCU : Ai8051U", 0);
        //OLED_DrawString(0, 6, "Work Freq. : 40.0MHz", 1);

}屏幕无显示。

*******************************************************
第三种情况:
屏蔽掉
while (1)
    {
        //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
        // 在此添加主函数中用户主循环代码
         
        OLED_ClearScreen(0);
       // OLED_SetFontHeight(16);
       // OLED_DrawString(0, 0, "   OLED-12864   ", 0);
       // OLED_DrawString(0, 2, "    文本模式    ", 0);
        OLED_SetFontHeight(8);
        OLED_DrawString(0, 4, "OLED Model : SSD1306", 0);
        OLED_DrawString(0, 5, "Target MCU : Ai8051U", 0);
        OLED_DrawString(0, 6, "Work Freq. : 40.0MHz", 1);

}只显示第6页。只要把第6页去掉,其它再多的内容都不显示了
只要保留第6页,刷屏只能显示偶数页(0、2、4、6页的内容),奇数页显示是偶数页的内容。
*************************************************
试着修改OLED_Refresh()其它参数,都不得要领。
如果想在第0行、0列开始显示内容,结果是空白。根本无法实现随心所欲在任何位置显示。感觉DMA好难理解






IMG_20250827_074646.jpg
IMG_20250827_075038.jpg
IMG_20250827_074901.jpg

点评

刚刚拿到了一块ST7567的屏幕,用你的程序试了一下,的确不是速度原因,而是DMA发送数据的问题。 然后发现,上个回复里的OLED_Refresh函数的修改建议里,发送数据的部分写错了 应该是: void OLED_Refresh(void)  详情 回复 发表于 6 天前
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:512
  • 最近打卡:2025-09-03 06:12:15

31

主题

411

回帖

3470

积分

荣誉版主

积分
3470
发表于 6 天前 | 显示全部楼层
Tui*** 发表于 2025-8-27 11:08
按照版主老师的程序,显示有所改善:不花屏了,但显示不正常,无法定位显示,自己试着修改其它参数仍不能 ...

刚刚拿到了一块ST7567的屏幕,用你的程序试了一下,的确不是速度原因,而是DMA发送数据的问题。
然后发现,上个回复里的OLED_Refresh函数的修改建议里,发送数据的部分写错了,应该是:
void OLED_Refresh(void)
{
    uint8_t page;
    uint8_t cmd[4];
   
    for( page=0; page<8; page++ )
    {
        cmd[0] = 0x40;                      //设置屏幕最顶上一行作为第0行
        cmd[1] = 0xB0+page;             //设置行起始地址
        cmd[2] = 0x10;                      //设置低列起始地址(高四位)
        cmd[3] = 0x00;                      //设置高列起始地址(低四位)
        OLED_WR_CMD( cmd, 4 );  

        OLED_WR_DAT( OledCache + page*128, 128 );
    }        
}

也可以写成
void OLED_Refresh(void)
{
    uint8_t page;
    uint8_t cmd[3];
   
    for( page=0; page<8; page++ )
    {
        cmd[0] = 0xB0+page;             //设置行起始地址
        cmd[1] = 0x10;                      //设置低列起始地址(高四位)
        cmd[2] = 0x00;                      //设置高列起始地址(低四位)
        OLED_WR_CMD( cmd, 3 );  


        OLED_WR_DAT( OledCache + page*128, 128 );
    }        
}

就是把 0x40 指令拿到初始化函数里

    static uint8_t code INIT_SEQU[] =
    {
        0xAE,                //关闭显示
        0x40,                //设置屏幕第一行为起始行
        0xA0,                //设置列扫描方向从左向右
        0xC8,                //设置行扫描方向从上向下
        0xB0,                //设置起始页地址
        0x10,0x00,        //设置起始列地址
        0xA6,                //A6-正常显示,A7-反色显示
        0xA4,                //A4-正常显示,A5-显示全部点阵
        0xA2,                //设置偏压比
        0x26,                //调节电阻比,0x20+[B2:B0]
        0x2F,                //打开电源,  0x28+[B2:B0]
        0x81,0x05,        //设置对比度(00h~3Fh)
        0xAD,                //AD-正常模式,AC-睡眠模式
        0xF8,0x00,        //设置升压倍数
        0xAF,                //开启显示
    };

这样每次就可以少发一个字节了。

======================================================

下面是用修改OLED_Refresh函数后的显示效果




能体会到发现一个不理解的现象然后找原因然后要么解决掉问题要么被问题解决掉的那种快乐是我的幸运
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:572
  • 最近打卡:2025-09-02 10:34:06

25

主题

198

回帖

1724

积分

金牌会员

积分
1724
发表于 6 天前 | 显示全部楼层
大*** 发表于 2025-8-28 12:25
刚刚拿到了一块ST7567的屏幕,用你的程序试了一下,的确不是速度原因,而是DMA发送数据的问题。
然后发现 ...

非常感谢版主,成功了!对于初学者或技术不硬来说,一点小细节可以让你想破脑袋。再次感谢版主辛苦付出!愿你工作越来越顺利!
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-9-3 12:49 , Processed in 0.528452 second(s), 95 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表