找回密码
 立即注册
查看: 619|回复: 4

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

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:478
  • 最近打卡:2025-07-31 08:17:19

31

主题

366

回帖

3189

积分

荣誉版主

积分
3189
发表于 2025-7-21 17:03:46 | 显示全部楼层 |阅读模式
在用AiCube学习自动配置硬件I2CDMA之后点亮OLED12864之后,
感觉AiCube尝试
自动配置硬件SPIDMA也同样方便。
这里记录一下用AiCube自动配置硬件SPI和DMA点亮OLED的每一步过程。


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

1、配置 8H8K64U系列 单片机的硬件SPI
创建过硬件I2C之后,这个过程已经轻车熟路

1.1 在AiCube里创建一个 8H8K64U的项目
截图202507211419273261.jpg


1.2 在【图形化I/O口配置】里,选择一组硬件SPI的引脚
这次选择的是第一组 (P5.4, P1.3, P1.4, P1.5)。
为了信号稳定,将时钟引脚(P1.5)、发送数据引脚(P1.3)和片选引脚(P5.4)配置成推挽输出模式。
然后在左侧端口列表里,将P1和P5勾选上,这样对引脚工作模式的配置才会生效。
照例将左侧列表里的【时钟】和【USB】都勾选上,为的是得到比较准确的延时函数,还有USB下载的功能。
1.2配置AiCube_1.jpg


1.3 在SPI配置窗口,
【主/从模式】选择默认的“主机模式”;
【传输顺序】和【时钟相位】都是用默认配置;
【时钟分频】选项里,默认的对输入时钟进行4分频,对OLED屏幕来说比较通用,
如果使用的是SSD1306芯片的屏幕,在40MHz的频率下,2分频也可以顺利点亮屏幕。
截图202507211511477312.jpg

SPI中断和DMA的部分暂时暂时不启用。

硬件SPI的配置环节就完成了。

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

2、找一个模拟SPI的OLED驱动,添加进生成的工程里,然后用硬件SPI进行替换

2.1 先打开oled.h头文件
照例将AiCube框架里的系统配置文件 config.h 头文件添加到文件开头,这样就可以自由使用SPI的配置,以及数据类型缩写之类。

由于SPI的时钟和发送数据引脚,都由硬件SPI设备接管了,所以对于这两个引脚的定义部分可以注释掉。
(不注释掉也没关系,只是在程序中不再需要对这两个引脚进行手动操作)
只保留RES、D/C和CS的引脚定义就可以了。

截图202507211528309246.jpg


2.2 在oled.c文件里,找到发送数据的函数 OLED_WR_Byte。
在函数里,先通过配置D/C引脚的高低电平,来告诉屏幕接下来发送的是控制指令还是内容数据。
截图202507211536272058.jpg


然后使用AiCube的库函数里的SPI控制命令,对模拟SPI的语句进行替换。
截图202507211538425205.jpg
截图202507211543116736.jpg

瞬间清爽。

因为驱动程序里所有的功能函数,都是靠这个函数跟跟屏幕进行联系的,

所以改完这个函数,硬件SPI的替换过程也完成了。


2.3 在main.c文件里,添加OLED的头文件
最好是写在指定段落的 <BEGIN> 和 <END> 标记之间,这样在AiCube重新生成工程代码的时候就不会被清除掉。
截图202507211553096121.jpg


然后在main函数的代码指定位置中,添加屏幕初始化函数和显示函数,就可以正常使用OLED屏幕了。
截图202507211556098943.jpg 截图202507211557142658.jpg




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


3. 使用SPI的DMA外设点亮屏幕


3.1 在AiCube里打开刚才的配置文件,在硬件SPI的基础上添加DMA的配置部分。

AiCube_SPI_DMA.jpg

(1) 这次在SPI的配置窗口中,选择“使能SPI DMA”。

(2) 因为是驱动OLED屏幕,【DMA模式】一栏选择“只发送数据”就可以。

(3) 【发送字节数】这一项,因为STC8H单片机的DMA每次最多可以传输256个字节,所以这里改成最大值 256。

(4) 【自动控制SS脚】这一栏,如果选择“是”,DMA设备会自动控制CS引脚的状态,此时屏幕上的CS引脚必须连接在这组硬件SPI指定的管脚P5.4上面;
如果选择“否”,就需要在屏幕驱动程序里使用控制代码,由CPU来控制CS引脚的状态。这次先选择“否”。

(5) SPI的DMA中断,也选择打开。

(6) 优先级选择默认的最低。

(7) 最后给DMA的发送缓冲区起一个名称。

DMA部分的配置就添加完成了。


重新生成工程框架之后,之前的一些配置可能会清除掉。
这时可以打开AiCube的备份工程文件(工程名_bk1.uvopt),就可以继续使用前面配置好的东西了。
==================================================

4、创建DMA方式的控制函数

4.1 打开spi.c文件,查看一下变化。
可以看到多出了DMA发送缓冲区的数组的声明,数组大小就是设置的256个字节。

截图202507211618545950.jpg

这里需要手动添加一个表示DMA发送状态的标志位变量,比如 fSPIDMATxFlag。

当它等于1的时候表示数据正在发送过程中,等于0的时候表示数据发送完成。
在oled.h头文件里也声明一下这个变量。

然后还多了一个DMA发送的中断函数。

在DMA中断的函数里,每当DMA把数据发完之后,也将这个标志位变量清零。


在SPI初始化的函数里,AiCube也追加了关于DMA的配置代码。
可以直接使用。

截图202507211625181375.jpg


4.2 接下来就是创建用DMA发送数据的函数

在oled.c文件里,跟创建I2C发送函数的过程一样,
首先创建发送控制指令和内容数据的函数 DMA_Send_Command 和 DMA_Send_Data
截图202507211631229931.jpg


参数 cmd,表示要发送的指令的数组地址。
参数len,表示要发送的指令数量。

在函数中,先等待DMA空闲,防止打扰正在发送的数据。

等待结束之后,将DC引脚设置成对应的高低电平,告诉屏幕接下来发送的是控制指令还是内容数据。
片选使能引脚CS也保持低电平,确保OLED处于工作状态。
然后用memory copy命令,通过参数cmd和len,把要发送的控制指令,从CMD数组搬到DMA的发送缓冲区里,DMA发送字节数配置成len-1。
配置好之后就可以用触发SPI DMA的命令,把这些控制指令发送给屏幕了。
发送完成之后,将发送状态标志位手动置1,准备下一次的数据发送。


5. 有了这两个函数,就可以创建DMA的各种控制和显示的函数了。

因为有原先的那些函数,所以创建过程非常轻松。

5.1 用到控制指令的函数

比如屏幕初始化函数 OLED_Init,
只需要按照原本的代码结构,将控制指令部分变成一个数组,再用SendCommand函数一口气发送就可以了。
截图202507211640046791.jpg 截图202507211637369023.jpg


还有比较重要的  定位显示起始位置的函数 OLED_Set_Pos,
同样也是先将定位坐标值存入数组,再发送给屏幕。
截图202507211642424203.jpg 截图202507211643194589.jpg


5.2 有了定位函数,就可以创建各种显示函数了

比如清屏函数,比较通用的方法是,先创建一个有128个0的数组 DAT,
然后配合定位函数,分八次将数据发送到屏幕的八个行上。
(如果用的是AI8051U单片机,DMA每次最多可以发送65535个字节的数据,所以对于SSD1306之类支持水平地址模式的屏幕,可以一次性发送1024个0进行清屏)
截图202507211649281345.jpg


根据这个思路,也可以创建出简单的显示图片的函数,

先计算出图片占用屏幕多少行,然后从指定的起始位置开始,向每一行里分别发送图片的对应行里的数据。

截图202507211652046902.jpg

显示字符的函数也可以根据这个思路创建,只需要将原本的显示函数里的发送数据的部分,用DMA的方式进行替换就可以了。
代码可以在下方DMA的视频里看到。

截图202507211702367513.jpg 截图202507211703229197.jpg




最后,在oled.h头文件中把创建好的函数都声明一下,整个创建过程就完成了。


5.3 在main.c函数中,将之前的硬件SPI的显示函数,用DMA的函数替换,就可以用DMA的方式点亮OLED了。








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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:478
  • 最近打卡:2025-07-31 08:17:19

31

主题

366

回帖

3189

积分

荣誉版主

积分
3189
发表于 2025-7-21 17:26:51 | 显示全部楼层
有了硬件SPI和DMA点亮OLED12864屏幕的过程,再点亮其它SPI屏幕的时候,感觉也不是太麻烦。


比如SSD1327芯片的带16阶灰度的OLED
截图202507211710572734.jpg 截图202507211711319324.jpg 截图202507211712124514.jpg




、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

刚刚又试了下TFT彩屏用硬件SPI驱动,以及用DMA发送图片数据,也很顺利
截图202507211722386661.jpg 截图202507211725355023.jpg


AiCube图形化配置硬件SPIDMA点亮TFT彩屏@Ai8051U
大明哥 携 Ai8051U, 请大家吃瓜,看 DMA 直接刷 TFT彩屏,CPU吃瓜休息
DMA发送缓冲区设置成了5000字节,最后那张128×128像素的图片,
32768个数据分7次发完,显示得果然好快!
几乎看不出画面刷新的过程(主频40MHz,SPI速度是2分频)。








1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
能体会到发现一个不理解的现象然后找原因然后要么解决掉问题要么被问题解决掉的那种快乐是我的幸运
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-07-26 21:06:40

0

主题

2

回帖

114

积分

注册会员

积分
114
发表于 7 天前 | 显示全部楼层
希望楼主把代码直接贴上来给大家参考一下,有些细节我等小白还是不太明白

点评

随便找一个模拟SPI的OLED驱动,还有AiCube。然后跟着1楼贴子里的视频流程,就可以创建出硬件SPI+DMA的工程来了。 下面就是整个流程的三个阶段的工程文件,STC8H8K64版。(AI8051U的过程一样) 1、用AiCube创建一  详情 回复 发表于 4 天前
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:478
  • 最近打卡:2025-07-31 08:17:19

31

主题

366

回帖

3189

积分

荣誉版主

积分
3189
发表于 4 天前 | 显示全部楼层
hnsd*** 发表于 2025-7-24 20:48
希望楼主把代码直接贴上来给大家参考一下,有些细节我等小白还是不太明白 ...



随便找一个模拟SPI的OLED驱动,还有AiCube。然后跟着1楼贴子里的视频流程,就可以创建出硬件SPI+DMA的工程来了。

下面就是整个流程的三个阶段的工程文件,STC8H8K64版。(AI8051U的过程一样)

1、用AiCube创建一个硬件SPI的工程框架
01.OLED_SPI_Clean.rar (47.24 KB, 下载次数: 10)


2、把SPI协议的OLED驱动添加进工程里,然后把发送数据的函数OLED_WR_Byte();的内容替换成库文件里的硬件SPI的命令。
02.OLED_SPI_noDMA.rar (112.23 KB, 下载次数: 7)


3、AiCube添加DMA之后的工程,和DMA发送的代码。
03.OLED_SPI_DMA.rar (116.21 KB, 下载次数: 8)



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

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:119
  • 最近打卡:2025-07-31 09:12:45
已绑定手机

1

主题

37

回帖

259

积分

中级会员

积分
259
发表于 昨天 09:18 来自手机 | 显示全部楼层
有代码的讲解吗
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-7-31 18:09 , Processed in 1.384679 second(s), 82 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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