STM32 OLED屏的使用

//-----------------OLED端口预定义----------------

#define OLED_SCL_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_0)   //CLK SCL   置0
#define OLED_SCL_Set() GPIO_SetBits(GPIOA,GPIO_Pin_0)

#define OLED_SDA_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_1)   //MOSI SDA   置0
#define OLED_SDA_Set() GPIO_SetBits(GPIOA,GPIO_Pin_1)

#define OLED_RES_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_2)   //RES 复位   置0        
#define OLED_RES_Set() GPIO_SetBits(GPIOA,GPIO_Pin_2)

#define OLED_DC_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_3)    //DC 数据/命令选择  置0
#define OLED_DC_Set() GPIO_SetBits(GPIOA,GPIO_Pin_3)

#define OLED_CS_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_4)     //CS  片选  置0
#define OLED_CS_Set() GPIO_SetBits(GPIOA,GPIO_Pin_4)

//使用STM32 的PA0、PA1、PA2、PA3、PA4的IO口

//OLED模块只支持向模块写数据不能读数据,所以只需要写SPI发送 MOSI SDA即可

#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据

//***  自定义的 24*24 ASICII字库  ******************************************************

 const unsigned char asc2_2412[ ][36]={   

{0x00,0x00,0x80,0xC0,0x60,0x20,0x20,0x60,0xC0,0x80,0x00,0x00,0x00,0xFE,0xFF,0x01,0x00,0x00,0x00,

0x00,0x01,0xFF,0xFE,0x00,0x00,0x01,0x07,0x0E,0x18,0x10,0x10,0x18,0x0E,0x07,0x01,0x00},// "0"  0 
{0x00,0x00,0x80,0x80,0x80,0xC0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x1F,0x1F,0x10,0x10,0x10,0x00,0x00},// "1"   1
{0x00,0x80,0x40,0x20,0x20,0x20,0x20,0x60,0xC0,0x80,0x00,0x00,0x00,0x03,0x03,0x00,0x80,0x40,0x20,

0x38,0x1F,0x07,0x00,0x00,0x00,0x1C,0x1A,0x19,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00},//"2"   2

{0x00,0x00,0x00,0x00,0x80,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x7C,0x43,0x40,0x47,

0x7F,0xF8,0x80,0x00,0x00,0x10,0x18,0x1F,0x10,0x00,0x00,0x00,0x00,0x13,0x1F,0x1C,0x10}, //"A" 4
{0x20,0xE0,0xE0,0x20,0x20,0x20,0x20,0x60,0xC0,0x80,0x00,0x00,0x00,0xFF,0xFF,0x10,0x10,0x10,0x10,

0x18,0x2F,0xE7,0x80,0x00,0x10,0x1F,0x1F,0x10,0x10,0x10,0x10,0x10,0x18,0x0F,0x07,0x00},//"B"   5 
{0x00,0x00,0x80,0xC0,0x40,0x20,0x20,0x20,0x20,0x60,0xE0,0x00,0x00,0xFC,0xFF,0x01,0x00,0x00,0x00,

0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x07,0x0E,0x18,0x10,0x10,0x10,0x08,0x04,0x03,0x00},//"C"  6

                                                              }

//****  自定义的汉字库Hzk [ ][32]  *****************************

//字库代码用取模软件  PCtoLCD等生成字母、汉字、图片等生成。

const unsigned char Hzk [ ][32] = {

{0x00,0x80,0x60,0xF8,0x07,0x40,0x20,0x18,0x0F,0x08,0xC8,0x08,0x08,0x28,0x18,0x00,0x01,0x00,0x00,

0xFF,0x00,0x10,0x0C,0x03,0x40,0x80,0x7F,0x00,0x01,0x06,0x18,0x00}, //"你"   0
{0x10,0x10,0xF0,0x1F,0x10,0xF0,0x00,0x80,0x82,0x82,0xE2,0x92,0x8A,0x86,0x80,0x00,0x40,0x22,0x15,

0x08,0x16,0x61,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00}, //"好"    1 

                                                     }

//***************************************************************************************************

//*** OLED的初始化 *****************************************************************************
void OLED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); //使能A端口时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                            //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                           //速度50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);                                                      //初始化GPIOA
GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_15);
                                                                                                                       //初始IO置1
OLED_RES_Clr();                                //复位拉低
delay_ms(200);                                     //延时
OLED_RES_Set();                                //复位结束拉高

OLED_WR_Byte(0xAE,OLED_CMD);  //亮屏灭屏指令 OFF/ON: AE/AF)
OLED_WR_Byte(0x00,OLED_CMD);  //设起始列地址指令,用8位中低4位
OLED_WR_Byte(0x10,OLED_CMD);  //设起始列地址指令,用8位中高4位
OLED_WR_Byte(0x40,OLED_CMD);  //设起始行地址指令 

OLED_WR_Byte(0x81,OLED_CMD);  // 81对比度设置指令,接着发送一个值来设置
OLED_WR_Byte(0xCF,OLED_CMD);  // 屏幕对比度值(0X00--0XFF),FF最大
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(0xA8,OLED_CMD);  //设置驱动路数指令 (1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD);   // 默认0X3F(1/64) duty
OLED_WR_Byte(0xD3,OLED_CMD);  //设置显示偏移指令 (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);  //-00 不偏移
OLED_WR_Byte(0xd5,OLED_CMD);  //设置时钟分频因子,震荡频率指令
OLED_WR_Byte(0x80,OLED_CMD);  //[3:0],分频因子;[7:4],震荡频率t Clock as 100 Frames/Sec
OLED_WR_Byte(0xD9,OLED_CMD);  //设置预充电周期指令,下面跟值
OLED_WR_Byte(0xF1,OLED_CMD);  //预充15时钟/放电1时钟 [3:0],PHASE 1;[7:4],PHASE 2;
OLED_WR_Byte(0xDA,OLED_CMD);  //设置COM硬件引脚配置 下面跟值
OLED_WR_Byte(0x12,OLED_CMD);  //[5:4]配置
OLED_WR_Byte(0xDB,OLED_CMD);  //设置VCOMH 电压倍率指令,下面跟值
OLED_WR_Byte(0x40,OLED_CMD);  //40 Deselect Level,[6:4] 000,0.65*vcc;001,011,0.83*vcc;
OLED_WR_Byte(0x20,OLED_CMD);  //设置内存地址模式 (0x00/0x01/0x02) 下面跟值
OLED_WR_Byte(0x02,OLED_CMD);  //[1:0],00/列地址模式,01/行地址模式,10/页地址模式,默认10;
OLED_WR_Byte(0x8D,OLED_CMD);  //电荷泵的指令,下面跟值
OLED_WR_Byte(0x14,OLED_CMD);  //bit2,开启/关闭(0为关闭,1为开启)(0x10) disable
OLED_WR_Byte(0xA4,OLED_CMD);  //全局显示开启,bit0: 1/开启,0/关闭;(白屏/黑屏) (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD); //设置正常显示方式;bit0:0/A6,全屏黑底蓝字;反相显示bit0:1/A7,黑字蓝底
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD);// 亮屏
}

//*****  写字节函数  ****************************************************************************

void OLED_WR_Byte(u8 dat,u8 cmd)     // 数据/命令标志, 0表示命令,1表示数据
{
u8 i;
if(cmd)                                                      //如果cmd=1,是命令
     OLED_DC_Set();                                 //DC置1
else
     OLED_DC_Clr();                                  //cmd=0,是数据DC置0
OLED_CS_Clr();                                       //CS置0 芯片使能
for(i=0;i<8;i++)                                          //8位数据循环移位 
      {
       OLED_SCL_Clr();                              //SCL置0
       if(dat&0x80)                                       //数据和0x80与,判断数据最高位是否=1 
            OLED_SDA_Set();                       //最高位=1,MOSI SDA输出1
       else
            OLED_SDA_Clr();                        //最高位=0,MOSI SDA 输出0
       OLED_SCL_Set(); //CLK置1
       dat<<=1;                                           //最高移位移走,次高位顶上
       }
OLED_CS_Set();                                     //发送完毕,片选置1 失能
OLED_DC_Set();                                     //命令数据选择重置1
}

//***  更新OLED显存 (1屏126*64点)  ************************************************
void OLED_Refresh(void)
{
  u8 i,n;
  for(i=0;i<8;i++) //i为屏映射数组的行/页,上下共8页,每行/页8位*128位/列
{
  OLED_WR_Byte(0xb0+i,OLED_CMD);                      //设置行起始地址,实际用该字节低3位 0-8页就够了
  OLED_WR_Byte(0x00,OLED_CMD);                         //设置低8位,实际用该字节低4位 列起始地址
  OLED_WR_Byte(0x10,OLED_CMD);                         //设置高8位,实际用该字节高4位 0-127列就够了
   for(n=0;n<128;n++)                                                     //n为屏映射数组的列,左右共128列,1行1列是8位
   // for(n=0;n<130;n++)                                                  //屏边框亮条可修改此值
  OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);   //OLED_DATA预定义为1/数据
}                                                       //用i页n列取屏映射数组GRAM内对应的数据,该数据刷OLED对应的点
}                                                       //OLED收到数据刷新屏幕对应点后,按设置的刷新模式(页地址模式),
                                                        //OLED行不动列地址自动加1,等待再次接收数据。
 

//*** 清屏函数 ****************************************************************************************************
void OLED_Clear(void)
{
  u8 i,n;
  for(i=0;i<8;i++)
      {
       for(n=0;n<128;n++)
             {
              OLED_GRAM[n][i]=0;           //清除所有数据数组
              }
       }
 OLED_Refresh();                              //空数组刷新显示
 }

//***  画点  *********************************************************
//x:0~127  y:0~63  t:1填充 /0清空
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
  u8 i,m,n;
  i=y/8;           //输入的Y坐标要除以8,以定位到要改变的那个点的相应字节,因为是以字节形式来写入的
  m=y%8;                                                          // 该点在该字节中的位置                
  n=1<<m;                                                         //屏坐标和数组是上下相反,要把该点y坐标左移写入n
  if(t)

       {OLED_GRAM[x][i]|=n;}                            //t=1,就把该点写1 
  else
     {
       OLED_GRAM[x][i]=~OLED_GRAM[x][i];
       OLED_GRAM[x][i]|=n;
       OLED_GRAM[x][i]=~OLED_GRAM[x][i];
     }
 }

//*** 在指定位置显示一个字符,包括部分字符 ***********************************************
//x:0~127
//y:0~63
//size1:选择字体 6x8/6x12/8x16/12x24
//mode:0,反色显示;1,正常显示
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode)
{
u8 i,m,temp,size2,chr1;
u8 x0=x,y0=y;
if(size1==8)size2=6;
else size2=(size1/8+((size1%8)?1:0))*(size1/2);   //得到字体一个字符对应点阵集所占的字节数
chr1=chr-' ';                                                            //计算偏移后的值
for(i=0;i<size2;i++)
{
if(size1==8)
     {temp=asc2_0806[chr1][i];} //调用0806字体
else if(size1==12)
    {temp=asc2_1206[chr1][i];} //调用1206字体
else if(size1==16)
    {temp=asc2_1608[chr1][i];} //调用1608字体
else if(size1==24)
    {temp=asc2_2412[chr1][i];} //调用2412字体
else return;
for(m=0;m<8;m++)
   {
    if(temp&0x01)OLED_DrawPoint(x,y,mode);
    else OLED_DrawPoint(x,y,!mode);
    temp>>=1;
    y++;
   }
x++;
if((size1!=8)&&((x-x0)==size1/2))
    { x=x0;y0=y0+8;}
      y=y0;
    }
}

猜你喜欢

转载自www.cnblogs.com/beiyhs/p/12421434.html