基于Zynq7000平台VxWorks6.9开发应用——OLED开发应用篇

 

目录

 

1、前言

2、OLED设计概述

2.1 Vivado OLED IP核设计与实现

2.2 SDK OLED驱动设计与实现

2.3 OLED初始化

2.4  OLED更新显存

3、VxWorks6.9开发驱动与应用

3.1 OLED驱动

3.2  OLED应用

3.3  OLED显示


1、前言

        本篇文章主要讲解在Xilinx ZedBoard上开发OLED显示功能,从OLED硬件平台设计、IP核设计、SDK驱动设计到应用VxWorks6.9开发OLED显示功能,力求讲述清楚开发流程,并配套完整的演示软件和相关代码进行验证。下面将从以下几个方面进行讲解。

  1. OLED设计概述
  2. Xilinx Vivado OLED IP核设计与实现
  3. OLED驱动设计与实现
  4. VxWorks6.9开发OLED驱动和应用。

开发工具说明:

  1. Xilinx Vivado2018.3
  2. Xilinx SDK2018.3
  3. WorkBench3.3

 

 

2、OLED设计概述

图1 OLED设计流程图

 

        Zedboard使用Inteltronic/Wisechip公司的OLED显示模组UG-2832HSWEG04,分辨率为128×32,是一款单色被动式显示屏幕,驱动电路采用SSD1306芯片,Zedboard具体的OLED接口电路如图2所示, UG-2832HSWEG04对应的引脚定义如表1所描述。

 图2 OLED接口原理图

UG-2832HSWEG04引脚定义表1

引脚定义

描述

OLED_VBAT

电源控制引脚,低电平有效。(注意,不直接对应OLED的VBAT引脚,在原理图上作为控制脚,为低的时候将VCC3V3送入OLED。)

OLED_VDD

同OLED_VBAT,低电平有效

OLED_RES

复位脚,上电的时候拉低,复位一段时间再拉高

OLED_DC

数据/命令选择引脚

OLED_SCLK

串行时钟引脚

OLED_SDIN

串行数据引脚

 

2.1 Vivado OLED IP核设计与实现

让OLED正确的显示数据,需要Znyq7000与其通信,参考SSD1306的控制时序,通信协议采用四线SPI协议,支持写模式,数据和命令均通过该协议传输,其时序如图3所示,SPI通信协议在时钟的下降沿改变数据,上升沿采样有效数据。因此,需要通过Vivado设计OLED的IP核,使其满足OLED对应的驱动时序。

         

                                                    图3 OLED SPI控制时序图

        图4为系统设计框图,标黄色部分为OLED IP核模块,其引脚OLED[5:0]分别对应图2原理图中的6个控制管脚。具体对应关系如下。

OLED[0]-OLED_DC

OLED[1]-OLED_RES

OLED[2]-OLED_SCK

OLED[3]-OLED_SDIN

OLED[4]-OLED_VBAT

OLED[5]-OLED_VDD

图4 系统设计框图

       OLED对应的IP核PL侧AXI地址空间分配如图5所示。访问OLED的地址为0x43C00000,分配的空间大小为64KB。

图5 OLED分配的PL侧地址空间

 

2.2 SDK OLED驱动设计与实现

       首先分析OLED UG-2832HSWEG04屏幕驱动芯片SSD1306工作原理。如图6所示,该OLED一共有四页,Page0-Page3,每页大小为128×8,该图没有重映射,为复位后默认映射。其初始化命令可以参考SSD1306的资料,为了快速开发OLED的驱动,可以基于Xilinx提供的SDK工具和BSP包快速进行开发。

图6 OLED显示方式

        本节主要在Vivado完成硬件平台PL设计之后,基于PS部分的驱动软件设计,实现对OLED的控制。

        由于ZedBoard开发板的OLED只支持写,不支持读,因此控制OLED就是在SCLK的时钟下,通过SDIN进行命令和数据的传输。OLED的初始化通过命令进行操作实现。

        对于SPI通信,需要通过PS操作AXI地址控制PL输出对应管脚的高低电平。本示例共有6个引脚,因此需要设置6个引脚的高低电平。代码如下:

#define OLED_BASE_ADDR 0X43c00000  //这里根据vivado中分配的地址来修改

 

#define OLED_DC         0

#define OLED_RES        1

#define OLED_SCLK       2

#define OLED_SDIN       3

#define OLED_VBAT       4

#define OLED_VDD        5

 

// DC

#define Set_OLED_DC  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)|(1<<OLED_DC)))

#define Clr_OLED_DC  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)&(~(1<<OLED_DC))))

// RES

#define Set_OLED_RES  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)|(1<<OLED_RES)))

#define Clr_OLED_RES  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)&(~(1<<OLED_RES))))

// SCLK

#define Set_OLED_SCLK  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)|(1<<OLED_SCLK)))

#define Clr_OLED_SCLK  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)&(~(1<<OLED_SCLK))))

// SDIN

#define Set_OLED_SDIN  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)|(1<<OLED_SDIN)))

#define Clr_OLED_SDIN  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)&(~(1<<OLED_SDIN))))

// OLED_VBAT

#define Set_OLED_VBAT  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)|(1<<OLED_VBAT)))

#define Clr_OLED_VBAT  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)&(~(1<<OLED_VBAT))))

// OLED_VDD

#define Set_OLED_VDD  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)|(1<<OLED_VDD)))

#define Clr_OLED_VDD  (Xil_Out32(OLED_BASE_ADDR,Xil_In32(OLED_BASE_ADDR)&(~(1<<OLED_VDD))))

 

//OLED控制用函数

void write_data(u8 data);

void write_cmd(u8 data);

void OLED_Display_On(void);

void OLED_Display_Off(void);

void OLED_Refresh_Gram(void);

void OLED_Init(void);

void OLED_Clear(void);

void OLED_DrawPoint(u8 x,u8 y,u8 t);

void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);

void OLED_ShowString(u8 x,u8 y,const u8 *p);

 

2.3 OLED初始化

       OLED初始化代码一般参考屏幕厂家推荐的配置,满足需求即可。根据SSD1306数据手册的初始化说明,其初始化流程如图7所示。

图7  SSD1306初始化流程

SSD1306初始化,首先需要实现最基本的SPI写命令和写数据函数。

//SSD1306写入一个字节的命令。

void write_cmd(u8 data)

{

    u8 i;

    Clr_OLED_DC;

 

    for(i=0;i<8;i++)

    {

        Clr_OLED_SCLK;

 

        if(data&0x80)

            Set_OLED_SDIN;

        else

            Clr_OLED_SDIN;

        Set_OLED_SCLK;

        data<<=1;

    }

}

 

//SSD1306写入一个字节的数据。

void write_data(u8 data)

{

    u8 i;

    Set_OLED_DC;

 

    for(i=0;i<8;i++)

    {

        Clr_OLED_SCLK;

 

        if(data&0x80)

            Set_OLED_SDIN;

        else

            Clr_OLED_SDIN;

        Set_OLED_SCLK;

        data<<=1;

    }

}

       利用写数据和写命令的函数来实现SSD1306的初始化,初始化前需要对OLED屏幕进行复位。具体实现代码如下:

//初始化SSD1306

void OLED_Init(void)

{

    Clr_OLED_VDD;

    usleep(300);        // 延时300us

    Clr_OLED_RES;

    usleep(30000);      // 延时30ms

    Set_OLED_RES;

    usleep(30000);      // 延时30ms

    Clr_OLED_VBAT;

 

    write_cmd(0xA8);

    write_cmd(0x3F);

    write_cmd(0xD3);

    write_cmd(0x00);

    write_cmd(0x40);

    write_cmd(0xA0);

    write_cmd(0xC8);

    write_cmd(0xDA);

    write_cmd(0x02);

    write_cmd(0x81);

    write_cmd(0x7F);

    write_cmd(0xA4);

    write_cmd(0xA6);

    write_cmd(0xD5);

    write_cmd(0x80);

    write_cmd(0x8D);

    write_cmd(0x14);

    write_cmd(0xAF);

}

2.4  OLED更新显存

显存数据写入SSD1306存储器,通过PS侧创建GRAM内存(共128个字节),在每次修改的时候,只修改PS的GRAM(映射OLED的SRAM),修改完后一次性把PS上的GRAM写入OLED的GRAM。

//OLED的显存

//存放格式如下.

//[0]0 1 2 3 ... 127

//[1]0 1 2 3 ... 127

//[2]0 1 2 3 ... 127

//[3]0 1 2 3 ... 127

//[4]0 1 2 3 ... 127

//[5]0 1 2 3 ... 127

//[6]0 1 2 3 ... 127

//[7]0 1 2 3 ... 127

u8 OLED_GRAM[128][8];

更新显存到OLED具体代码如下:

//更新显存到LCD

void OLED_Refresh_Gram(void)

{

    u8 i,n;

    for(i=0;i<8;i++)

    {

        write_cmd (0xb0+i);    //设置页地址(0~7

        write_cmd (0x02);      //设置显示位置列低地址,偏移了2

        write_cmd (0x10);      //设置显示位置列高地址

        for(n=0;n<128;n++)write_data(OLED_GRAM[n][i]);

    }

}

 

3、VxWorks6.9开发驱动与应用

3.1 OLED驱动

 VxWorks6.9开发OLED驱动可以参考Xilinx SDK OLED的驱动代码,快速移植到VxWorks6.9中。

1、首先在sysLib.c文件中映射OLED AXI基地址空间为VxWorks的虚拟地址空间。

{

    ZYNQ7K_OLED_BASE,   /* OLED */

    ZYNQ7K_OLED_BASE,

    SZ_64K,

    MMU_ATTR_VALID_MSK | MMU_ATTR_PROT_MSK | MMU_ATTR_DEVICE_SHARED_MSK,

    MMU_ATTR_VALID     | MMU_ATTR_SUP_RWX  | MMU_ATTR_DEVICE_SHARED          

},

 

 

2、在xlnx_zyn7k的BSP包中增加oled的目录,新建oled.h和oled.c文件,导入font.h字库文件,如图8所示。

图8 OLED BSP包目录

 

3、oled.c文件主要把之前Xilinx SDK访问OLED AXI地址宏定义进行VxWorks接口的适配即可。

图9 适配VxWorks6.9接口

4、把oled.c文件include加入到sysLib.c,只有这样编译器才会关联编译oled.c文件,否则不会对oled.c文件进行编译。

 

注意:如果出现WorkBench3.3采用“//”注释编译不能通过,可以通过配置编译器编译选项解决该问题。如图10所示,增加-std=gnu99选项或者-std=c99选项。

图10 编译器配置项

3.2  OLED应用

        在userAppInit.c文件中应用上面开发的BSP驱动接口。将在ZedBoard板卡上显示“Hi   VxWorks6.9”字样。

void usrAppInit (void)

{

#ifdef        USER_APPL_INIT

         USER_APPL_INIT;              /* for backwards compatibility */

#endif

 

    /* add application specific code here */

                   dosFsVolFormat("/ram0", 0, 0);

                  

#ifdef  FLASH_TFFS_FORMAT         /* 仅针对第一次格式化tffs文件系统生效  */

                   tffsDrv();

                   sysTffsFormat();               

                   usrTffsConfig(0, 0, "/tffs0");            

                   dosFsVolFormat("/tffs0", 0, 0);

#endif      

 

                   ifconfig("gem0 172.17.70.230 up");

                  

                   OLED_Init();

                   OLED_Clear();

                   OLED_ShowString(0,0,"Hi   VxWorks6.9");

                   OLED_Refresh_Gram();

}

3.3  OLED显示

        本示例提供oled.bit的FPGA文件和vxWorks烧写文件,为了调试方便,提供了支持网络启动VxWorks的BOOT.bin引导文件方便验证。本示例所有的软件均在Avnet发布的ZedBoard上验证通过。

操作命令如下:

1.加载FPGA bit文件

tftpboot 0x10000000 oled.bit

fpga loadb 0 0x10000000  ${filesize}

 

2.加载和运行vxWorks文件

tftpboot 0x10000000 vxWorks

bootelf 0x10000000

 

VxWorks6.9运行结果如图11所示,OLED显示效果如图12所示。

 

图11  VxWorks6.9运行图

图12  OLED显示图

 

 

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CPUOS2010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值