基于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]);
}
}
}