基于FPGA的OLED12864显示屏设计

一、概述

  本设计讨论以altera公司FPGA芯片为基础的OLED显示屏显示设计;

二、实验平台

  软件平台 :Quartus II 13.0 + Nios 13.0

  硬件平台 :

三、实验内容

  1、本设计的OLED采用的是4线SPI通信方式。包括:时钟 -->SCLK、数据 -->SDO、片选 -->CS、数据命令选择信号 -->DC;采用Nios软核定制方式,如下图

  定制软核的步骤不在复述,值得注意的是OLED的spi总线传输方式时钟极性和时钟相位都应当为1,

    CLOCK POLARITY --> 1

    CLOCK PHASE      --> 1

  2、软件设计

      1)初始化函数           

          void OLED_Init(void) //OLED设置初始化函数
          {
            int i = 0;
            const alt_u8 command[] = {
                            0x81, 0xff,          //设置最亮
                            0xd5, 0xf0,         //设置最高频率,最高刷新频率
                            0x20, 0x02,        //页寻址模式
                            0x40,              //起始线地址清零
                            0xa1,            //左右画面A1正常
                            0xc8,                            //上下画面C8正常
                            0xd3, 0x00,                  //显示偏移清零
                            0xd9, 0xf1,                   //充放电时间15:1
                            0xda, 0x12,                  //COM引脚默认配置
                            0xa4,                           //关闭满屏输出
                            0xa6,                           //正相正常显示
                            0xa8, 0x3f,                  //复用率复位64MUX
                            0xaf                            //开显示

                          };
            for(i=0; i<20; i++)
            {
              OLED_WriteByte(0, &command[i]);
            }
            OLED_CLR();
          }

      2)OLED写字节命令       

          void OLED_WriteByte(uchar cmd, const alt_u8 * data)  //OLED写字节函数
          {
            if(cmd)
            {
              IOWR(PIO_DC_BASE, 0, 0x1);           //OLED_DC=1
            }
            else
            {
              IOWR(PIO_DC_BASE, 0, 0x0);          //OLED_DC=0
            }
            alt_avalon_spi_command(SPI_BASE, 0, 1, data,0,NULL,1);
          }

      3)显示位置设定函数

        void OLED_SetPos(uchar x, uchar y)
        {
          const alt_u8 set[3] = {(0xb0+y), (((x&0xf0)>>4)|0x10), ((x&0x0f)|0x00)};
          OLED_WriteByte(0,&set[0]);
          OLED_WriteByte(0,&set[1]);
          OLED_WriteByte(0,&set[2]);
        }

      4)清屏函数      

        void OLED_CLR(void)
        {
          uchar i,j;
          const alt_u8 clear[4] = {0x00, 0xa5,0x81,0x0f};

          for(i=0;i<8;i++)
          {
            OLED_SetPos(0,i);
            for(j=0;j<128;j++)
            {
              OLED_WriteByte(1, &clear[0]);
            }
          }
        }

      5)显示函数 两页大小字体

        void OLED_ShowASCII(uchar x,uchar y,uchar len,uchar* AscChar) //向OLED中某两页组成的一行写入len长度的ASCII字符
        {
          uchar i,j,k,tmph,tmpl;

          /******将一般的8x16 ASCII码转换为OLED屏所用的ASCII码******/
          for(i=0;i<len;i++) //有几个字符处理几次
          {
            for(j=0;j<8;j++) //转换每个字符的16个字节
            {
              tmph=0;tmpl=0; //仅做临时变量
              for(k=0;k<8;k++)//一个结果字节的8位数据的处理
              {
                tmph>>=1;
                if(ASCII[(AscChar[i]*16)+k]&(0x80>>j)) //字库中ASCII码x16为此字符的起始字节,加k为从此字节开始1-8个字节的处理
                {
                  tmph=tmph|0x80; //高位是1就写临时变量的高位是1,否则不操作为0
                }
                tmpl>>=1;
                if(ASCII[(AscChar[i]*16)+k+8]&(0x80>>j))//字库中ASCII码x16为此字符的起始字节,加k+8为从此字节开始9-16个字节的处理
                {
                  tmpl=tmpl|0x80; //高位是1就写临时变量的高位是1,否则不操作为0
                }
              }
              ASCIITmp[i][j]=tmph;
              ASCIITmp[i][j+8]=tmpl; //传入临时显示数组
            }
          }

          /******开始向OLED写入数据******/
          for(i=0;i<2;i++)
          {
            OLED_SetPos(x,y+i);
            for(j=0;j<len;j++)
            {
              for(k=0;k<8;k++)
              {
                OLED_WriteByte(1,&ASCIITmp[j][k+(i*8)]);
              }
            }
          }
        }

      6)显示函数,一页字体大小

        void OLED_ShowASCII8(uchar x,uchar y,uchar len,uchar* AscChar) //向OLED中某两页组成的一行写入len长度的ASCII 8x8字符
        {
          uchar i,j,k,tmp;
          /******将一般的ASCII码8x8字符转换为OLED屏所用的ASCII码******/
          for(i=0;i<len;i++) //有几个字符处理几次
          {
            for(j=0;j<8;j++) //转换每个字符的8个8位数据
            {
              tmp=0;
              for(k=0;k<8;k++)//结果的8位数据的处理
              {
                tmp>>=1;
                if(ASCII8[(AscChar[i]*8)+k]&(0x80>>j))
                {
                  tmp=tmp|0x80;
                }
              }
              ASCIITmp[i][j]=tmp;
            }
          }

          /******开始向OLED写入数据******/
          OLED_SetPos(x,y);
          for(i=0;i<len;i++)
          {
            for(j=0;j<8;j++)
            {
              OLED_WriteByte(1,&ASCIITmp[i][j]);
            }
          }
        }

posted @ 2016-04-07 22:40  屋檐下的小麻雀  阅读(1468)  评论(0)    收藏  举报