这次的任务是驱动手上的ssd1306OLED显示器显示内容。
要使得显示器显示数据,我们首先要给它数据和命令,告诉他要干什么,是去刷新显存还是清屏还是显示文字,是显示字母还是显示数字等等。那么要实现这个功能,我们就得了解SPIO总线,从底层去理解这样一个模块是如何运行的。
如何给OLED模块发送指令?首先我们需要看懂下面这张图:

好,我们只需要看懂上面的这个Table 8-4就行,这是什么意思呢?啊,但凡有个高中文化水平都能知道,第一行是代表了写入命令时需要做的动作,第二行是写入数据时要执行的操作。
再仔细来看,前两项都是一样的,我们着重看后面,首先要执行写入操作,都要把片选电压拉低;接着D / C#位确定下一个数据字节充当命令或数据,如果给D/C一个低电平, 设置为逻辑“0”,则将以下数据字节定义为命令。 如果给D/C一个高电平, 设置为逻辑“1”,则它将以下数据字节定义为数据。每次数据写入后,RAM中地址指针将自动增加1。 最后再结束的时候再拉高D0。
整个流程如下图:

好,在大概了解了数据的传递方式以后我们来康康官方给出的库函数。
[zhedie]
void OLED_WR_Byte(u8 dat,u8 cmd)
{
u8 i;
if(cmd)//如果传进来的是数据,那么拉高D/C
OLED_DC_Set();
else
OLED_DC_Clr();//若不是则拉低
OLED_CS_Clr();//拉低片选端
for(i=0;i<8;i++)
{
OLED_SCL_Clr();//D0拉低
if(dat&0x80)//如果dat与上0x80,即判断是否输入结束
OLED_SDA_Set();//上拉D1开始输入
else
OLED_SDA_Clr();//拉低D1结束输入
OLED_SCL_Set();//D0拉高
dat<<=1;//dat左移一位
}//for循环结束,数据输入完成
OLED_CS_Set();//拉高片选
OLED_DC_Set();//拉高D/C
}
//下面是一些预编写好的命令
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_Clear();
OLED_WR_Byte(0xAF,OLED_CMD);
//此外库函数还给出了很多已经编写好的函数以供调用
void OLED_ClearPoint(u8 x,u8 y);
void OLED_ColorTurn(u8 i);
void OLED_DisplayTurn(u8 i);
void OLED_WR_Byte(u8 dat,u8 mode);
void OLED_DisPlay_On(void);
void OLED_DisPlay_Off(void);
void OLED_Refresh(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode);
void OLED_DrawCircle(u8 x,u8 y,u8 r);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode);
void OLED_ShowChar6x8(u8 x,u8 y,u8 chr,u8 mode);
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode);
void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode);
void OLED_ScrollDisplay(u8 num,u8 space,u8 mode);
void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode);
void OLED_ShowGif(u8 BMP[],int time);
void OLED_Init(void);
[/zhedie]
在有了上面这些函数后,我们开始编写程序。
要实现目标有两个,一个是开机的画面,第二个是显示按下的矩阵键盘的键位。
第一个开机画面,我想的是要放一个诺基亚的开机画面上去,然后发现给定的库函数中并没有显示GIF的功能,只有一个显示图片的功能,于是就想到去给GIF抽帧,然后连续播放去实现一个动画的效果。先对原始的开机动画进行了抽帧处理,得到了下面的这个GIF:

Comments | NOTHING
Warning: Undefined variable $return_smiles in /www/wwwroot/blog/wp-content/themes/sakura-3.4.0/functions.php on line 1096