0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于Apollo2 SDK上OLED屏幕的实现

润欣科技Fortune 2019-04-24 09:28 次阅读

上海润欣科技股份有限公司创研社


导读: 本文详细介绍了,如何在Apollo2 SDK-1.2.12平台上点亮并使用Heletc 1.3寸12864-OLED屏幕。本文将阐述,如何通过硬件SPI与模拟SPI模式,分别实现外设OLED屏的驱动代码和实现步骤。

1.SPI通信原理

SPI是串行外设接口(Serial Peripheral Interface)的缩写。是 Motorola 公司推出的一种同步串行接口技术,是一种高速的,全双工,同步的通信总线。

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入)、SDO(数据输出)、SCLK时钟)、CS(片选)。

1MOSI/SDI –SerialDataIn,串行数据输入;

2MISO/SDO –SerialDataOut,串行数据输出;

3SCLK – Serial Clock,时钟信号,由主设备产生;

4CS – Chip Select,从设备使能信号,由主设备控制。

其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。

接下来就负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCLK时钟线存在的原因,由SCLK提供时钟脉冲,SDISDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。因此,至少需要8次时钟信号的改变(上沿和下沿为一次),才能完成8位数据的传输。

pIYBAFyhiASAdzA5AABqZ1Wuw-o994.png

(图1SPI通信结构图

pIYBAFyhiCiATlakAAA0JfkmpHs135.jpg

(图2SPI常规读操作

o4YBAFyhiBCAUGx_AAA1WaY2pOA462.jpg

(图3SPI常规写操作

2.SPI的四种模式

根据SPI时钟极性(CPOL)和时钟相位(CPHA)配置的不同可分为4种模式。

时钟极性是指SPI通信设备处于空闲状态时(或SPI通信开始时,即SS为低电平时),SCK的电平信号CPOL=0时,SCK空闲状态为低电平,CPOL=1时则相反。

时钟相位是指数据采样的时刻,当CPHA=0时,MOSIMISO数据线会在时钟线第一个边沿开始采样(奇数边沿)。

CPHA=1时,MOSIMISO数据线会在时钟线第二个边沿开始采样(偶数边沿)。

详细如下:

1CPOL=0CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。

2CPOL=0CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。

3CPOL=1CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。

4CPOL=1CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。

o4YBAFyhiDiABdK1AABe59wDXw0595.jpg

(图4SPICPOLCPHA

3.硬件SPI与模拟SPI的区别

在模拟SPI的模式下,我们需要使用IO口去模拟SPI的时序,这个模拟的全部过程,都需要CPU全程负责,但在获取或者发送数据的时候,可能会使用软件延时,这个时间在数据交互量不大的情况下并明显,但是如果数据量大,可能会打乱SPI的时序。

对于硬件SPI来说,我们只需要开启相应的寄存器配置和对应的中断。数据的交互就不需要CPU参与。当传输中断产生的时候,CPU只需要从中断中搬运数据就好了,省下了软件模拟IO的存取时间。让CPU省下更多时间去运行其他代码。

4.硬件SPI的配置

首先我们需要确定OLED屏幕上面的引脚,如图:

(图5OLED硬件管脚图

GND - 接地 VCC – 3.3V

SCL – SCK5脚) SDA – MOSI7脚)

RST – 42脚(可修改)DC43脚(可修改)

作为Master模式下,提供有6IO口供用户选择,而作为Slave1组。在Master模式下,Apollo提供一个128-byte local RAM作为双向FIFO的传输容量。Apollo2的管脚复用具体如下:

(图6Apollo2全部引脚寄存器配置图

说明: C:\Users\xushanlin.FOVISIO\Desktop\1553678319(1).jpg

(图7Apollo2 引脚颜色比对图

第一步,我们选择Master 0 Signals 也就是相对于的 567引脚。

具体通过am_hal_gpio_pin_config()函数进行引脚配置

pIYBAFyhiN6AcDWsAAA5UPmCjrM652.jpg

pIYBAFyhiOSAU1xFAAAnxA4oV7I500.jpg

第二步,配置iom_config

o4YBAFyhiL-ABNI9AAAn-qu7KOo109.png

SPI_g_sIOMConfig里面配置的是IOM的一些常规参数:

pIYBAFyhiPWAdx-VAABWNyIJYRU523.jpg

模式我们选择为AM_HAL_IOM_SPIMODE 传输速率为 100KHZ,相位和极性都是0 。写数据的阈值是4bit,读取是60bit。这两个是生产中断的条件。

最后记得开启IO Master

pIYBAFyhiPyAYY00AAATXNECH8Y321.jpg

第三步,对屏幕进行复位操作,而复位操作主要是改变RST引脚的高低电平。

o4YBAFyhiNaAWGW4AAA5vRc6BO4504.png

通过Apollo2 SDK提供的API去修改IO口状态。

am_hal_gpio_out_bit_clear()置0 am_hal_gpio_out_bit_set()置1

pIYBAFyhiQmAexreAAAxER9t-j0172.jpg

第四步,通过SPI通信,将指令或者数据传输到OLED屏幕中。OLED屏幕判断指令还是数据,是通过DC引脚的高低电平实现的。所以需要有一个参数去控制 43引脚的状态。代码如下:

o4YBAFyhiOSAKa_TAAAxio8bQpc373.jpg

数据先传输进Buffer,通过判断cmd 控制DC_Set/ DC_Clr

然后通过am_hal_iom_spi_write()函数,将数据直接传输到外设。

am_hal_iom_spi_write(uint32_t ui32Module, uint32_t ui32ChipSelect,

uint32_t *pui32Data, uint32_t ui32NumBytes,

uint32_t ui32Options)

{

am_hal_iom_status_e ui32Status;

//

// Validate parameters

//

if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )

{

return AM_HAL_IOM_ERR_INVALID_MODULE;

}

// Reset the error status

ui32Status = g_iom_error_status[ui32Module] = AM_HAL_IOM_SUCCESS;

if (ui32NumBytes == 0)

{

g_iom_error_status[ui32Module] = ui32Status = AM_HAL_IOM_ERR_INVALID_PARAM;

return ui32Status;

}

//

// Check to see if queues have been enabled. If they are, we'll actually

// switch to the queued interface.

//

if ( g_psIOMQueue[ui32Module].pui8Data != NULL )

{

//

// If the queue is on, go ahead and add this transaction to the queue.

//

ui32Status = am_hal_iom_queue_spi_write(ui32Module, ui32ChipSelect, pui32Data,

ui32NumBytes, ui32Options, 0);

if (ui32Status == AM_HAL_IOM_SUCCESS)

{

//

// Wait until the transaction actually clears.

//

am_hal_iom_queue_flush(ui32Module);

// g_iom_error_status gets set in the isr handling

ui32Status = g_iom_error_status[ui32Module];

}

//

// At this point, we've completed the transaction, and we can return.

//

}

else

{

//

// Otherwise, we'll just do a polled transaction.

//

ui32Status = am_hal_iom_spi_write_nq(ui32Module, ui32ChipSelect, pui32Data,

ui32NumBytes, ui32Options);

}

return ui32Status;

}

该函数的几个参数定义分别如下:

1ui32Module – IOMMaster编号选择

2ui32ChipSelect – 外设编号选择

3pui32Data – 传输的数据

4ui32NumBytes –传输数据的大小

5ui32Options – 寄存器偏移量

这里可以根据实际情况去配置各个参数,从而达到传输数据的目的。至此,硬件SPI模式基本配置完成。

5.模拟SPI配置

模拟SPI基本与硬件SPI类似。使用任意两个IO口模拟通信,不需要使用指定的SPI接口,也不需要响应的SPI配置。

第一步,IO口的配置大概如下:

o4YBAFyhiOyAN52BAABttoH1cy4961.jpg

四个引脚如下:SCL – 8脚; SDA – 9脚;RES – 42脚;DC – 43 同样需要配置各个IO口的状态:

pIYBAFyhiR6AO1pXAAByGmjvE4o617.jpg

模拟SPI与硬件SPI的最主要区别是在写函数里面。使用一个引脚模拟时钟,另外一个引脚发送数据。

第二步,发送函数:

o4YBAFyhiPqAWo3eAABI-2jP_yo250.jpg

判断cmd的操作是必不可少的,接着判断(dat & 0x80) 判断高位是否为‘1’。dat 高位为‘1’,MOSI就输出‘1’;否则输出‘0’。然后移位,次高位变为最高位。就是把dat的数据从MOSI脚输出。

6.了解OLED屏幕

有机发光显示OLEDOrganicLight EmittingDisplay)是比液晶显示技术更为先进的新一代平板显示技术,是被业界公认为最具发展前景的下一代显示技术。

OLED12864128*64行点阵的OLED单色,字符,图形显示模块,模块内有64*64的显示数据RAM,其中的每位数据对应于OLED屏上的每一个点的亮,暗状态。

12864OLED的像素矩阵的划分是比较特殊的。 整个屏幕水平方向划分为8page, 垂直方向则是按像素划分为128 column. 每个page-column包含8个像素, 通过一个十六进制数(其实就是一个字节, 8bit)来控制, 每个bit控制一个像素。

(图8-1OLED屏幕像素矩阵

pIYBAFyhlP-AH9G_AADGdi9nqqI737.png

(图8-2OLED屏幕像素矩阵

7.OLED屏幕配置

与大部分12864 OLED屏幕一样,需要提前给屏幕输入特定的显示指令。代码如家,需要注意的是硬件SPI与模拟SPI选择自己响应的OLED_WR_Byte()即可。配置过程如下:

OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel

OLED_WR_Byte(0x00,OLED_CMD);//---set low column address

OLED_WR_Byte(0x10,OLED_CMD);//---set high column address

OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)

OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register

OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness

OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0×óÓÒ·´ÖÃ 0xa1Õý³£

OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0ÉÏÏ·´Öà 0xc8Õý³£

OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display

OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)

OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty

OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)

OLED_WR_Byte(0x00,OLED_CMD);//-not offset

OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency

OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec

OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period

OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock

OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration

OLED_WR_Byte(0x12,OLED_CMD);

OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh

OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level

OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)

OLED_WR_Byte(0x02,OLED_CMD);//

OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable

OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable

OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)

OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)

OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel

OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/

OLED_Clear();

OLED_Set_Pos(0,0);

将上述代码发送给OLED屏幕之后,屏幕的初始化也基本完成

8.OLED屏幕文字显示

下面是使用OLED显示中文汉字的范例。代码如下

o4YBAFyhlN6AcvDfAABdOi_kp1o383.png

OLED_Set_Pos()函数是用来定位文字在屏幕上显示的位置。文字的大小是16*16个像素点,所以for()循环里面的t16次。Hzk[ ][ ]数组里面存储的是通过取模软件,将文字转换成16进制的数据。

取模工具选用PCtolCD2002 完美版本,这里选择字符模式。输入文字的时候,可以点击生成字模,在下方就会显示出各个文字相对应的16进制数组。

pIYBAFyhlRGAfoPJAAEX-AX0Low747.jpg

(图9)文字取模

将各个数组分别添加到Hzk数组里面之后,就可以在主函数里面通过OLED_ShowCHinese()进行显示。

o4YBAFyhlO2AFAzlAABL_uiyq-c154.png

显示效果如下图:

(图10)文字显示效果

9.OLED屏幕图片显示

照片显示和文字显示原理相同,也是点亮相对应的像素点。

o4YBAFyhlPuAatDqAAA17R3Qps4844.jpg

该函数当中,x0 y0表示的是图片所显示的的起始坐标,x1 表示的是图片像素的x轴所占的像素,y1表示的是页数(0-7

将想要显示的图片,转换成BMP格式之后,通过PCtolCD2002的图片模式进行转换。设置如下:选择阴码,逆向,十六进制输出。

pIYBAFyhlS-AA1d_AABd10Rs1a0354.jpg

(图11)图片取模选项设置

o4YBAFyhlRKAF***qAAB-x_Z8Zq8735.jpg

(图12)图片取模界面

将所生成的十六进制数据进行,修改对齐后,装到BMP数组当中。在主函数当中就可以直接显示了,效果如下图。

(图13)图片显示效果

后记:

在调试当中遇到的一些需要注意的点:

1、 freeRTOS下,使用OLED屏幕的话,需要预先启用SPI相对于的IOM 口。

o4YBAFyhlR6AHS-BAABduemv8kQ836.jpg

需要用到函数am_hal_pwrctrl_periph_enable(uint32_t ui32Peripheral)进行相应的配置。同理在进行低功耗处理的时候,可以关闭SPI接口。

am_hal_pwrctrl_periph_enable(uint32_t ui32Peripheral)

{

am_hal_debug_assert_msg(ONE_BIT(ui32Peripheral),

"Cannot enable more than one peripheral at a time.");

//

// Begin critical section.

//

AM_CRITICAL_BEGIN_ASM

//

// Enable power control for the given device.

//

AM_REG(PWRCTRL, DEVICEEN) |= ui32Peripheral;

//

// End Critical Section.

//

AM_CRITICAL_END_ASM

//

// Wait for the power to stablize. Using a simple delay loop is more

// power efficient than a polling loop.

//

am_hal_flash_delay(AM_HAL_PWRCTRL_DEVICEEN_DELAYCYCLES / 3);

//

// Quick check to guarantee we're good (should never be more than 1 read).

//

POLL_PWRSTATUS(ui32Peripheral);

}

2、 OLED屏幕在进行Clear的时候,屏幕不干净

(图14)屏幕刷新有残留

原因是:写到寄存器第一列和第二列的数据被驱动芯片当做乱码并在 显示屏的最后一列显示出来。修改如下:

把程序中所有 X”轴的值改成 132,如下图定义的是 X 轴与 Y 轴。

o4YBAFyhlS6AL2_hAADTW0FjAqs611.png

同时,clear函数里面,循环发送数据的次数,也应该从n<128 改为 n<132

pIYBAFyhlk6AIVHzAABLylVIuYU329.png

3、 图片显示函数

void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1,

unsigned char y1,unsigned char BMP[])

{

unsigned int j=0;

unsigned char x,y;

if(y1%8==0) y=y1/8;

else y=y1/8+1;

for(y=y0;y

{

OLED_Set_Pos(x0,y);

for(x=x0;x

{

OLED_WR_Byte(BMP[j++],OLED_DATA);

}

}

}

在使用该函数的时候,首先要注意的是,y1表示的是页数(0-7)也就是前文指的page,而不是你所给照片取模的Y轴的像素。其次在照片取模当中,尽量控制为128*64的大小。如果图片大小无法满足,则在使用OLED_DrawBMP()的时候,xx1的数据差应该就是你图片的像素大小。

例如:

我的照片大小为 (92 X 60 ),如果选择屏幕显示的起始坐标点为(0,0

则函数为:OLED_DrawBMP(0,0,92,7,BMP);

但是当你想移动图片的位置,修改为OLED_DrawBMP(18,0,92,7,BMP);显示的结果会出现乱码。

正确的方式是改为OLED_DrawBMP(18,0,110,7,BMP);

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • OLED屏幕
    +关注

    关注

    3

    文章

    206

    浏览量

    27964
收藏 人收藏

    评论

    相关推荐

    【RA-Eco-RA2E1-48PIN-V1.0开发板试用】(第二篇)串口打印+SPI_OLED显示

    第一件事情 --实现回调函数 都完成后,就是写OLED的初始化、字符显示等功能了 最终hal_enty的代码内容就为下图 其中oled_demo()实现的效果就是,从
    发表于 11-09 01:30

    tft屏幕oled屏幕哪个更好一些

    TFT屏幕OLED屏幕各有其独特的优势和适用场景,难以一概而论哪个“更好”。 一、技术原理与结构 TFT屏幕 :TFT(Thin Film Transistor)
    的头像 发表于 10-21 16:48 820次阅读

    利用Sitara AM57x处理器的处理器SDK实现工业机器视觉的2D物体识别

    电子发烧友网站提供《利用Sitara AM57x处理器的处理器SDK实现工业机器视觉的2D物体识别.pdf》资料免费下载
    发表于 10-10 09:36 0次下载
    利用Sitara AM57x处理器<b class='flag-5'>上</b>的处理器<b class='flag-5'>SDK</b><b class='flag-5'>实现</b>工业机器视觉的<b class='flag-5'>2</b>D物体识别

    三星携手LG Display共研屏幕发声OLED技术

    9月26日,国际媒体报道称,科技巨头三星显示与LG显示正携手研发一项革命性的OLED屏幕技术,该技术赋予了屏幕直接发声的神奇能力,预示着未来可折叠智能手机可能摆脱传统扬声器束缚,实现
    的头像 发表于 09-26 17:04 847次阅读

    oled光源的光线发射方向是垂直于屏幕朝前

    OLED是一种先进的显示技术,它使用有机材料层来产生光。与传统的液晶显示(LCD)技术不同,OLED不需要背光源,因为每个像素都能够自发光。这种自发光特性使得OLED屏幕能够提供更高的
    的头像 发表于 09-20 14:56 251次阅读

    聚徽-OLED 屏幕和 LED 幕哪个适合户外

    OLED 屏幕和 LED 屏幕在户外使用上的适用性各有特点,但一般来说,LED 屏幕更适合户外使用。
    的头像 发表于 09-18 10:56 223次阅读

    聚徽-Oled 屏幕为什么会烧屏

    OLED 屏幕出现烧屏现象的原因主要归结于 OLED 材料的特性和使用习惯。以下是详细解释:
    的头像 发表于 09-06 09:37 881次阅读

    苹果iPhone全面拥抱OLED屏幕,夏普与JDI出局

    苹果公司宣布了一项重大变革,自2025年起,其全系iPhone将全面升级至OLED屏幕,这一决定标志着LCD屏幕时代的终结,也预示着智能手机显示技术的又一次飞跃。此次转型不仅覆盖了旗舰及高端机型,连传统
    的头像 发表于 09-04 15:46 314次阅读

    聚徽-OLED 屏幕应用场景有哪些

    OLED 屏幕的应用场景非常广泛,包括但不限于以下几个领域:
    的头像 发表于 08-15 09:27 329次阅读

    聚徽-OLED 屏幕与其他屏幕相比的主要优势

    OLED 屏幕与其他屏幕相比的主要优势体现在多个方面:
    的头像 发表于 08-06 09:27 501次阅读

    在OpenHarmony 3.1版本中,润和hispark hi3861智能家居套件I2C驱动OLED屏幕的驱动如何改写?

    目前找到的例程都是基于OpenHarmony1.0或者2.0的,目前使用OpenHarmony3.1.4 release版本的系统后,ssd1306 OLED屏幕的例程和代码已经调不通了,请问如何解
    发表于 07-11 16:45

    OLED屏幕、包装外壳机器视觉定位软硬件方案

    OLED屏幕、包装外壳视觉定位检测
    的头像 发表于 06-17 10:22 243次阅读
    <b class='flag-5'>OLED</b><b class='flag-5'>屏幕</b>、包装外壳机器视觉定位软硬件方案

    告别LCD,新款iPhone SE将搭载OLED屏幕

    电子发烧友网报道(文/吴子鹏)日前,有多家媒体报道称,苹果可能会在2025年推出新款iPhone SE系列,配备OLED显示屏。当前款式的iPhone SE则是目前唯一使用LCD屏幕的iPhone
    的头像 发表于 02-21 00:18 3036次阅读

    SF1 RISC-V Core 驱动OLED屏幕

    第1章 SF1 RISC-V Core 驱动OLED屏幕本次测评采用安路的SF1 RISC-V内核实现对SPI OLED屏幕的驱动,
    发表于 12-10 10:26

    树莓派Pico使用SSD1306 OLED屏幕

    SSD1306 OLED 屏幕模块配备 0.9 英寸迷你单色屏,128×32 分辨率,白光像素点。拥有极高的对比度,显示清晰极易辨识。OLED 仅使用树莓派的 I2C 和电源引脚,无需
    的头像 发表于 11-21 14:17 1806次阅读
    树莓派Pico<b class='flag-5'>上</b>使用SSD1306 <b class='flag-5'>OLED</b><b class='flag-5'>屏幕</b>