/**********************************************************************************************
Copyright 2008 - 2019 深圳市信盈达电子有限公司. All rights reserved.
描述 :
作者 : 何文宾
版本 : V1.0
修改 :
完成日期: 2019年2月17日
信盈达官网:http://www.edu118.com/
信盈达网校:http://www.edu118.cn/
信盈达技术论坛:http://bbs.edu118.com/
Notice :本程序只供学习使用,未经作者许可,不得用于其它任何用途。版权所有,盗版必究
***********************************************************************************************/
/**********************************************************************************************
* INCLUDES
*/
#include "oled.h"
#include "systick.h"
#include "font.h"
#include "rtc.h"
/**********************************************************************************************
* CONSTANTS
*/
/**********************************************************************************************
* TYPEDEFS
*/
/**********************************************************************************************
* LOCAL VARIABLES
*/
/**********************************************************************************************
* LOCAL FUNCTIONS DECLARE
*/
/**********************************************************************************************
* LOCAL FUNCTIONS
*/
/**********************************************************************************************
* PUBLIC FUNCTIONS
*/
/*******************************************************************
* 函数名: OLED_Init()
* 功能描述 : 初始化oled
* 作者: 何文宾
* 参数说明: 无
* 返回值说明: 无
* 修改记录:
* 其他:
*******************************************************************/
/**
SCK----PB13
MOSI---PB15
CS-----PA15
DC-----PA11
RES----PA12
*/
void OLED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;
/***********************管脚定义********************************************/
if(SPI_MODE)
{
/*************************硬件SPI*********************************************/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);//使能A&&B时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//SPI2时钟使能
/*CS-----PA15*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_CS_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(OLED_GPIO,&GPIO_InitStruct);
/*DC-----PA11*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_DC_PIN;
GPIO_Init(OLED_GPIO,&GPIO_InitStruct);
/*RES-----PA12*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_RES_PIN;
GPIO_Init(OLED_GPIO,&GPIO_InitStruct);
OLED_RES_H;
/*SCK----PB13*/ //复用推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_SCK_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(OLED_SPI_GPIO,&GPIO_InitStruct);
/*MOSI---PB15*/ //复用推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_MOSI_PIN;
GPIO_Init(OLED_SPI_GPIO,&GPIO_InitStruct);
/*MISO---PB14*/ //浮空输入
GPIO_InitStruct.GPIO_Pin = OLED_MISO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(OLED_SPI_GPIO,&GPIO_InitStruct);
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//波特率
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;//在时钟第二个电平发送数据
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;//时钟空闲状态为高电平
SPI_InitStruct.SPI_CRCPolynomial = DISABLE;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;//8位数据帧
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//双线双向模式
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;//先发高位
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;//主机模式
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;//软件从设备管理
SPI_Init(SPI2,&SPI_InitStruct);
SPI_Cmd(SPI2,ENABLE);
spi_read_write(0xff);
}
else
{
/*软件模拟SPI*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);//使能A&&B时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
/*SCK----PB13*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_SCK_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(OLED_SPI_GPIO,&GPIO_InitStruct);
/*MOSI---PB15*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_MOSI_PIN;
GPIO_Init(OLED_SPI_GPIO,&GPIO_InitStruct);
/*CS-----PA15*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_CS_PIN;
GPIO_Init(OLED_GPIO,&GPIO_InitStruct);
/*DC-----PA11*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_DC_PIN;
GPIO_Init(OLED_GPIO,&GPIO_InitStruct);
/*RES-----PA12*/ //推挽输出 50MHZ
GPIO_InitStruct.GPIO_Pin = OLED_RES_PIN;
GPIO_Init(OLED_GPIO,&GPIO_InitStruct);
OLED_RES_H;
}
/***********************初始化时序********************************************/
delay_ms(200);
Oled_Write_Cmd(0xAE); //关闭显示
Oled_Write_Cmd(0xD5); //设置时钟分频因子,震荡频率
Oled_Write_Cmd(80); //[3:0],分频因子;[7:4],震荡频率
Oled_Write_Cmd(0xA8); //设置驱动路数
Oled_Write_Cmd(0X3F); //默认0X3F(1/64)
Oled_Write_Cmd(0xD3); //设置显示偏移
Oled_Write_Cmd(0X00); //默认为0
Oled_Write_Cmd(0x40); //设置显示开始行 [5:0],行数.
Oled_Write_Cmd(0x8D); //电荷泵设置
Oled_Write_Cmd(0x14); //bit2,开启/关闭
Oled_Write_Cmd(0x20); //设置内存地址模式
Oled_Write_Cmd(0x02); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
Oled_Write_Cmd(0xA1); //段重定义设置,bit0:0,0->0;1,0->127;
Oled_Write_Cmd(0xC8); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
Oled_Write_Cmd(0xDA); //设置COM硬件引脚配置
Oled_Write_Cmd(0x12); //[5:4]配置
Oled_Write_Cmd(0x81); //对比度设置
Oled_Write_Cmd(0xEF); //1~255;默认0X7F (亮度设置,越大越亮)
Oled_Write_Cmd(0xD9); //设置预充电周期
Oled_Write_Cmd(0xf1); //[3:0],PHASE 1;[7:4],PHASE 2;
Oled_Write_Cmd(0xDB); //设置VCOMH 电压倍率
Oled_Write_Cmd(0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
Oled_Write_Cmd(0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
Oled_Write_Cmd(0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示
Oled_Write_Cmd(0xAF); //开启显示
OLED_Clear(0,128,0,8,0x00);
}
/*******************************************************************
* 函数名: spi_read_write()
* 功能描述 : SPI读写数据
* 作者: 何文宾
* 参数说明: 待发送的数据
* 返回值说明: 读取的值
* 修改记录:
* 其他:
*******************************************************************/
//SPI读写数据
u8 spi_read_write(u8 dat)
{
if (SPI_MODE)
{
while(!SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)); //等待发送缓冲为空
SPI_I2S_SendData(SPI2,dat);
while(!SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)); //等待接收缓冲不为空
return SPI_I2S_ReceiveData(SPI2); //返回收到的数据
}
else
{
u8 i;
OLED_CS_L;
for(i=0;i<8;i++)
{
OLED_SCK_L;
if((dat&0x80))
{
OLED_MOSI_H;
}
else OLED_MOSI_L;
OLED_SCK_H;
dat<<=1;
}
OLED_CS_H;
return dat;
}
}
/*******************************************************************
* 函数名: Oled_Write_Data()
* 功能描述 : OLED写数据
* 作者: 何文宾
* 参数说明: 待发送的指令
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void Oled_Write_Data(u8 dat)
{
OLED_DC_H;
OLED_CS_L;
spi_read_write(dat);
OLED_CS_H;
}
/*******************************************************************
* 函数名: Oled_Write_Cmd()
* 功能描述 : OLED写指令
* 作者: 何文宾
* 参数说明: 待发送的指令
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void Oled_Write_Cmd(u8 cmd)
{
OLED_DC_L;
OLED_CS_L;
spi_read_write(cmd);
OLED_CS_H;
}
/*******************************************************************
* 函数名: OLED_Setpos()
* 功能描述 : OLED设置位置
* 作者: 何文宾
* 参数说明: 待发送的指令
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_Setpos(u8 sx,u8 sy)
{
Oled_Write_Cmd(0xb0+sy); //哪一页
Oled_Write_Cmd(0x10+(sx>>4)); //高4位地址
Oled_Write_Cmd(0x00+(sx&0x0f));//低4位地址
}
/*******************************************************************
* 函数名: OLED_Clear()
* 功能描述 : OLED设置位置
* 作者: 何文宾
* 参数说明: 待发送的指令
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_Clear(u8 sx,u8 ex,u8 sy,u8 ey,u8 data)
{
u8 i,j;
for(i=sy;i<ey;i++) //页
{
Oled_Write_Cmd(0xb0+i); //哪一页
Oled_Write_Cmd(0x10+(sx>>4)); //高4位地址
Oled_Write_Cmd(0x00+(sx&0x0f));//低4位地址
for(j=0;j<(ex-sx);j++) //列
{
Oled_Write_Data(data);
}
}
}
/*******************************************************************
* 函数名: OLED_ShowChar()
* 功能描述 : 显示字符
* 作者: 何文宾
* 参数说明: x:X坐标,y:Y坐标,p:显示的字符,size:字符大小
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_ShowChar(u8 x,u8 y,u8 p,u8 size)
{
u8 i;
u8 ex,ey;
u8 res=p-' ';
ex=x;ey=y;
if(size==16)
{
OLED_Setpos(ex,ey);
for(i=0;i<16;i++)
{
if(((i%8)==0)&&(i!=0))
{
ex=x;
ey+=1;
OLED_Setpos(ex,ey);
}
Oled_Write_Data(char16X16[res][i]);
}
}
else if(size==12)
{
OLED_Setpos(ex,ey);
for(i=0;i<12;i++)
{
if(((i%6)==0)&&(i!=0))
{
ex=x;
ey+=1;
OLED_Setpos(ex,ey);
}
Oled_Write_Data(char12X12[res][i]);
}
}
else if(size==24)
{
OLED_Setpos(ex,ey);
for(i=0;i<36;i++)
{
if(((i%12)==0)&&(i!=0))
{
ex=x;
ey+=1;
OLED_Setpos(ex,ey);
}
Oled_Write_Data(char24X24[res][i]);
}
}
}
/*******************************************************************
* 函数名: OLED_ShowString()
* 功能描述 : 显示字符串
* 作者: 何文宾
* 参数说明: x:X坐标,y:Y坐标,p:显示的字符串,size:字符串大小
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_ShowString(u8 x,u8 y,u8 *p,u8 size)
{
while(*p!='\0')
{
OLED_ShowChar(x,y,*p,size);
p+=1;
x+=(size/2);
}
}
/*******************************************************************
* 函数名: OLED_ShowNum()
* 功能描述 : 显示数字
* 作者: 何文宾
* 参数说明: x:X坐标,y:Y坐标,num:显示的数字,size:数字大小,len:长度
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 size)
{
u8 cnum,cnum2;
u8 nn;
u8 i;
u8 length=0;
nn=1;
cnum=num;
cnum2=num;
if(num!=0)
{
while(num>0)
{
length+=1;
num/=10;
}
}
else
{
length=1;
}
while(length)
{
for(i=0;i<(length-1);i++)
{
nn=nn*10;
}
cnum=cnum/nn;
OLED_ShowChar(x,y,cnum+48,size);
x+=(size/2);
cnum=cnum2%nn;
nn=1;
length--;
}
}
/*******************************************************************
* 函数名: OLED_ShowTime()
* 功能描述 : 显示当前时间
* 作者: 何文宾
* 参数说明: x:X坐标,y:Y坐标,size:数字大小
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_ShowTime(u8 x,u8 y,u8 size)
{
u8 sx=x;
/*显示当前时间*/
RTC_Get_Time();
OLED_ShowNum(sx,y,my_time.hour,16);
sx+=size;
OLED_ShowChar(sx,y,':',16);
sx+=(size/2);
OLED_ShowNum(sx,y,my_time.min,16);
sx+=size;
OLED_ShowChar(sx,y,':',16);
sx+=(size/2);
OLED_ShowNum(sx,y,my_time.sec ,16);
}
/*******************************************************************
* 函数名: OLED_Showpic()
* 功能描述 : 显示图片
* 作者: 何文宾
* 参数说明:
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_Showpic(u8 sx,u8 sy,u8 ex,u8 ey,const unsigned char * p)
{
u8 i,j;
for(j=0;j<(ey-sy);j++)
{
OLED_Setpos(sx,sy+j);
for(i=0;i<(ex-sx);i++)
{
Oled_Write_Data(*p);
p++;
}
}
}
/*******************************************************************
* 函数名: OLED_Show_Font()
* 功能描述 : 显示单个汉字
* 作者: 何文宾
* 参数说明:
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_Show_Font(u8 x,u8 y,u8 size,u8 num)
{
u8 i;
u8 temp;
u8 ssize;
u8 x0=x;
u8 *zk;
ssize=size*(size/8+(size%8?1:0)); //计算不同字体大小所占用的字节数
switch(size)
{
case 12:
zk=(u8*)F12X12[num]; //得到汉字编号对应的点阵库
for(i=0;i<ssize;i++)
{
if(i==size)
{
x=x0;
y++;
}
temp=zk[i]; //得到点阵数据
OLED_Setpos(x,y);
Oled_Write_Data(temp);
x++;
}
break;
case 16:
zk=(u8*)F16X16[num]; //得到汉字编号对应的点阵库
for(i=0;i<ssize;i++)
{
if(i==size)
{
x=x0;
y++;
}
temp=zk[i]; //得到点阵数据
OLED_Setpos(x,y);
Oled_Write_Data(temp);
x++;
}
break;
case 24:
zk=(u8*)F24X24[num]; //得到汉字编号对应的点阵库
for(i=0;i<ssize;i++)
{
if(i==size)
{
x=x0;
y++;
}
temp=zk[i]; //得到点阵数据
OLED_Setpos(x,y);
Oled_Write_Data(temp);
x++;
}
break;
default:break;
}
}
/*******************************************************************
* 函数名: OLED_Show_Font()
* 功能描述 : 显示多个汉字
* 作者: 何文宾
* 参数说明:
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_ShowMultiple_Font(u8 x,u8 y,u8 size,u8 *p)
{
while(*p!=0)
{
OLED_Show_Font(x,y,size,*p);
p++;
x+=size;
}
}
/*******************************************************************
* 函数名: OLED_Show_gezi()
* 功能描述 : 显示下划线
* 作者: 何文宾
* 参数说明: mode:1 密码格子 0:时间格子
* 返回值说明:
* 修改记录:
* 其他:
*******************************************************************/
void OLED_Show_gezi(u8 sx,u8 sy,u8 ex,u8 ey)
{
u8 i;
for(i=0;i<6;i++)
{
OLED_Showpic(sx,sy,ex,ey,&gezi[0]);
sx+=15;
ex+=15;
}
}
void show_voice(u8 sx,u8 sy,u8 vol)
{
u8 i=0;
u8 x=sx;
OLED_Clear(sx,sx+80,sy,sy+1,0x00);
for(i=0;i<vol;i++)
{
OLED_Showpic(x,sy,x+8,sy+1,&voice[i][0]);
x+=10;
}
}
/***********************************************************************************************
***********************************************************************************************/
我想在此基础上添加切换屏幕的功能,并且屏幕显示请输入密码