这代码是上课的时候写出来的,太忙了还没有验证到底对不对,但是和江科大的对比了一下,除了自己改的那一部分,基本一模一样。所有应该是没有问题的。
后面就是填充一些写汉字,写字符,画图形的函数了,最后再研究一下指令都有啥用,那些玩意看数据手册看不懂,还是得实际操作一下。
void SetPlace(uint8_t X, uint8_t Page)//设置RAM中的地址
{
OLED_W_Command(0xB0|Page);//设置页地址
OLED_W_Command(0x00|(X&0x0F));//设置列地址低位
OLED_W_Command(0x10|((X&0xF0)>>4));//设置列地址高位
}
void OLED_UpDate(void)
{
uint8_t i;
for (i=0;i<8;i++)
{
SetPlace(0,i);
OLED_W_Data(OLED_DisplayBuf[i],128);
}
}
//目前,如果更新区域Y轴只包含部分页,则同一页的剩余部分会跟随一起更新
void OLED_UpDateArea(uint8_t X,uint8_t Y,uint8_t Width, uint8_t Height)
{
uint8_t i;
uint8_t Page,Page_End;
Page=Y/8;
Page_End=(Y + Height - 1) / 8 + 1;//通过两Page确定出更新数据所占的页数,(Y + Height - 1) / 8 + 1的目的是(Y + Height) / 8并向上取整
for (i=Page;i<Page_End;i++)
{
if (i >= 0 && i <= 7)//超出屏幕范围的不显示
{
SetPlace(X,i);
//由于页寻址模式下,当128列都寻址完成时,继续寻址会返回该页的第一列从头寻址。并且,我们的W_Data函数并没有超出屏幕的判断
//因此,我们再次加入是否超出屏幕的判断,改变Width值,使超出屏幕的不显示
if((X+Width)<=127)
{
OLED_W_Data(&OLED_DisplayBuf[i][X],Width);
}
else
{
Width=(127-X);
OLED_W_Data(&OLED_DisplayBuf[i][X],Width);
}
}
}
}
void OLED_Clear(void)
{
uint8_t i,j;
for (i=0;i<8;i++)
{
for (j=0;i<128;j++)
{
OLED_DisplayBuf[i][j]=0x00;
}
}
}
//ClearArea与Show_Image对缓存数组的改变方式不同,需要注意,但是目测两种方式能够相互替换
void OLED_ClearArea(uint8_t X,uint8_t Y,uint8_t Width, uint8_t Height)
{
uint8_t i,j;
for (j=Y;j<Height;j++)
{
for (i=X;i<Width;i++)
{
if (i >= 0 && i <= 127 && j >=0 && j <= 63)
{
OLED_DisplayBuf[j/8][i]&=~(0x01<<(j%8));
}
}
}
}
void OLED_Show_Image(uint8_t X,uint8_t Y,uint8_t *Data,uint8_t Width, uint8_t Height)
{
uint8_t i,j;
uint8_t Page,Shift;
OLED_ClearArea(X,Y,Width,Height);//将这一部分清空是必须的,后面对缓存数组的改变使用的是|,因此,如果原来的数据未清除,则会导致最后的图像是前后两种叠加的样子
for (j=0;j<(((Height-1)/8)+1);j++)//(Height - 1) / 8 + 1的目的是Height / 8并向上取整,这种向上取整的方式在上方也有使用
{
for (i=0;i<Width;i++)
{
if (X+i>=0&&X+i<=127)
{
Page=Y/8;
Shift=Y%8;
if ((Page+j)>=0&&(Page+j)<=7)
{
OLED_DisplayBuf[(Page)+j][X+i]|=(Data[i+j*Width]<<(Shift));
}
if ((Page+j+1)>=0&&(Page+j+1)<=7)
{
OLED_DisplayBuf[((Page)+1+j)][X+i]|=(Data[i+j*Width]>>(8-(Shift)));
}
}
}
}
}