这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 用AiCube配置硬件SPI和DMA点亮OLED12864,8H8K64U、Ai

共2条 1/1 1 跳转至

用AiCube配置硬件SPI和DMA点亮OLED12864,8H8K64U、Ai8051U

助工
2025-07-22 10:43:14     打赏

在用AiCube学习自动配置硬件I2CDMA之后点亮OLED12864之后,
感觉AiCube尝试
自动配置硬件SPIDMA也同样方便。
这里记录一下用AiCube自动配置硬件SPI和DMA点亮OLED的每一步过程。


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

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

1.1 在AiCube里创建一个 8H8K64U的项目



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



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


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

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

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

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

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

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




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



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



瞬间清爽。

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

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


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



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

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


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


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

(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个字节。



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

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

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

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


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




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

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



参数 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函数一口气发送就可以了。
 


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


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

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



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

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



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

 




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


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




关键词: AiCube;     OLED12864;     8H8K64    

助工
2025-07-22 10:44:19     打赏
2楼

有了硬件SPI和DMA点亮OLED12864屏幕的过程,再点亮其它SPI屏幕的时候,感觉也不是太麻烦。


比如SSD1327芯片的带16阶灰度的OLED
  

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

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

DMA发送缓冲区设置成了5000字节,最后那张128×128像素的图片,32768个数据分7次发完,显示得果然好快!几乎看不出画面刷新的过程(主频40MHz,SPI速度是2分频)。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]