全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 接口/总线/驱动 >

基于STC15W408AS单片机IIC驱动OLED

时间:2023-06-23 11:37

人气:

作者:admin

标签: STC15W408AS  OLED  单片机  IIC   

导读:基于STC15W408AS单片机IIC驱动OLED-STC15W408AS单片机并没有提供IIC总线的接口,但是我们可以通过模拟IIC的方式实现。关于IIC总线的只是大家可以自行上网搜索。这里以驱动SSD1306芯片的0.96寸的...

一、OLED显示屏

STC15W408AS单片机并没有提供IIC总线的接口,但是我们可以通过模拟IIC的方式实现。关于IIC总线的只是大家可以自行上网搜索。这里以驱动SSD1306芯片的0.96寸的128*64的OLED显示屏为例。

二、SSD1306芯片的IIC时序图

image.png

图片

这里我们需要看清楚START信号和STOP信号。关于时间,芯片的数据手册也有说明。

图片

IIC数据传输格式

图片

这个是芯片的数据传输格式。

  1. The slave address is following the start condition for recognition use. For the SSD1306, the slave address is either “b0111100” or “b0111101” by changing the SA0 to LOW or HIGH (D/C pin acts as SA0).

手册中的这句话和上图右下角的,也说明了芯片的器件地址是0x78或者0x79。至于我们用的OLED液晶是哪一个,需要我们用这两个地址测试,我没找到哪个手册有说明,具体是哪一个。

关于芯片的寄存器,手册上面有很多,这里不做说明,自己查阅手册即可。

三、测试程序

1.IIC.h文件

#ifndef __IIC_H_
#define __IIC_H_
#define u16 unsigned int 
#define u8  unsigned char


void IIC_Start();
void IIC_Stop();
void IIC_Write_Byte(u8 byte);
void IIC_Wait_Ack();
void IIC_Write_Command(u8 cmd);
void IIC_Write_Data(u8 dat);
#endif

2.IIC.c文件

#include "stc15.h"
#include "iic.h"
#define IIC_SCL   P10   // 时钟
#define IIC_SDA   P11   // 数据
// IIC 开始信号
void IIC_Start()
{
  IIC_SCL = 1 ;
  IIC_SDA = 1;
  IIC_SDA = 0;
  IIC_SCL = 0;
}
// IIC 停止信号
void IIC_Stop()
{
  IIC_SCL = 1 ;
//  IIC_SCL = 0;
  IIC_SDA = 0;
  IIC_SDA = 1; 
}
// IIC 应答信号
void IIC_Wait_Ack()
{
  IIC_SCL = 1 ;
  IIC_SCL = 0;
}
// IIC 写一字节数据
void IIC_Write_Byte(u8 IIC_Byte)
{
  u8 i;
  u8 m,da;
  da = IIC_Byte;
  IIC_SCL = 0;
  for(i = 0;i < 8;i++)     
  {
    m = da;
    //  IIC_SCL = 0;
    m = m&0x80;
    if(m==0x80)
    {
      IIC_SDA = 1;
    }
    else IIC_SDA = 0;
      da = da< < 1;
    IIC_SCL = 1;
    IIC_SCL = 0;
  }
}

3.OLED.h文件

#ifndef __OLED_H_
#define __OLED_H_
#define u16 unsigned int 
#define u8  unsigned char


#define OLED_CMD  0  // 写命令
#define OLED_DATA 1  // 写数据
#define OLED_MODE 0 // 显示模式
//OLED模式设置
//0:4线串行模式
//1:并行8080模式
#define OLED_Address 0x78
#define OLED_Cmd  0x00
#define OLED_Data 0x40
#define SIZE 16
#define XLevelL    0x02
#define XLevelH    0x10
#define Max_Column  128
#define Max_Row    64
#define  Brightness  0xFF 
#define X_WIDTH   128
#define Y_WIDTH   64    
//OLED控制用函数
void OLED_WR_Byte(u8 dat,u8 cmd);   
void OLED_Display_On(void);
void OLED_Display_Off(void);                               
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size);
void OLED_ShowNum(u8 x,u8 y,u16 num,u8 len,u8 size2);
void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size);    
void OLED_Set_Pos(u8 x, u8 y);
void OLED_ShowCHinese(u8 x,u8 y,u8 no);
void OLED_DrawBMP(u8 x0, u8 y0,u8 x1, u8 y1,u8 BMP[]);
void fill_picture(u8 fill_Data);
void Picture();
#endif

4.OLED.c文件

#include "oled.h"
#include "iic.h"
#include "oledfont.h"     
// IIC 写命令
void IIC_Write_Command(u8 IIC_Command)
{
  IIC_Start();
  IIC_Write_Byte(OLED_Address);           
  IIC_Wait_Ack();   
  IIC_Write_Byte(OLED_Cmd);       
  IIC_Wait_Ack();   
  IIC_Write_Byte(IIC_Command);  
  IIC_Wait_Ack();   
  IIC_Stop();
}
// IIC 写数据
void IIC_Write_Date(u8 IIC_Data)
{
  IIC_Start();
  IIC_Write_Byte(OLED_Address);     
  IIC_Wait_Ack();   
  IIC_Write_Byte(OLED_Data);   
  IIC_Wait_Ack();   
  IIC_Write_Byte(IIC_Data);
  IIC_Wait_Ack();   
  IIC_Stop();
}
// 往OLED写一字节数据
void OLED_WR_Byte(u8 dat,u8 cmd)
{
  if(cmd)
  {
    IIC_Write_Date(dat);
  }
  else {
   IIC_Write_Command(dat);   
  }
}
/********************************************
// fill_Picture
********************************************/
void fill_picture(u8 fill_Data)
{
  u8 m,n;
  for(m=0;m< 8;m++)
  {
    OLED_WR_Byte(0xb0+m,0);    //page0-page1
    OLED_WR_Byte(0x00,0);    //low column start address
    OLED_WR_Byte(0x10,0);    //high column start address
    for(n=0;n< 128;n++)
    {
      OLED_WR_Byte(fill_Data,1);
    }
  }
}
//坐标设置
void OLED_Set_Pos(u8 x, u8 y)  
{    
  OLED_WR_Byte(0xb0+y,OLED_CMD);
  OLED_WR_Byte(((x&0xf0) > >4)|0x10,OLED_CMD);
  OLED_WR_Byte((x&0x0f),OLED_CMD);  
}        
//开启OLED显示    
void OLED_Display_On(void)
{
  OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
  OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
  OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
  OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}               
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!    
void OLED_Clear(void)   
{   
  u8 i,n;         
  for(i=0;i< 8;i++)   
  {   
    OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
    OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
    OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
    for(n=0;n< 128;n++)OLED_WR_Byte(0,OLED_DATA);  
  } //更新显示
}
void OLED_On(void)   
{   
  u8 i,n;         
  for(i=0;i< 8;i++)   
  {   
    OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
    OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
    OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
    for(n=0;n< 128;n++)OLED_WR_Byte(1,OLED_DATA);  
  } //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示         
//size:选择字体 16/12 
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{         
  u8 c=0,i=0;   
  c=chr-' ';//得到偏移后的值      
  if(x >Max_Column-1){x=0;y=y+2;}
  if(Char_Size ==16)
  {
    OLED_Set_Pos(x,y);   
    for(i=0;i< 8;i++)
    OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
    OLED_Set_Pos(x,y+1);
    for(i=0;i< 8;i++)
    OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
  }
  else {   
    OLED_Set_Pos(x,y);
    for(i=0;i< 6;i++)
    OLED_WR_Byte(F6x8[c][i],OLED_DATA);
  }
}
//m^n函数
u16 oled_pow(u8 m,u8 n)
{
  u16 result=1;    
  while(n--)result*=m;     
  return result;
}           
//显示2个数字
//x,y :起点坐标   
//len :数字的位数
//size:字体大小
//mode:模式  0,填充模式;1,叠加模式
//num:数值(0~4294967295);         
void OLED_ShowNum(u8 x,u8 y,u16 num,u8 len,u8 size2)
{            
  u8 t,temp;
  u8 enshow=0;                
  for(t=0;t< len;t++)
  {
    temp=(num/oled_pow(10,len-t-1))%10;
    if(enshow==0&&t< (len-1))
    {
      if(temp==0)
      {
        OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
        continue;
      }else enshow=1;  


    }
     OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);  
  }
}  
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
  u8 j=0;
  while (chr[j]!='\\0')
  {     
    OLED_ShowChar(x,y,chr[j],Char_Size);
    x+=8;
    if(x >120){x=0;y+=2;}
    j++;
  }
}
//显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{                 
  u8 t;
  OLED_Set_Pos(x,y);   
  for(t=0;t< 16;t++)
  {
    OLED_WR_Byte(Hzk[no][t],OLED_DATA);
  }   
  OLED_Set_Pos(x,y+1);   
  for(t=0;t< 16;t++)
  {   
    OLED_WR_Byte(Hzk[no][t+16],OLED_DATA);
  }           
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(u8 x0, u8 y0,u8 x1, u8 y1,u8 BMP[])
{    
  u16 j=0;
  u8 x,y;
  if(y1%8==0) y=y1/8;       
  else y=y1/8+1;
  for(y=y0;y< y1;y++)
  {
    OLED_Set_Pos(x0,y);
    for(x=x0;x< x1;x++)
    {       
      OLED_WR_Byte(BMP[j++],OLED_DATA);         
    }
  }
}  
//初始化SSD1306              
void OLED_Init(void)
{    
  OLED_WR_Byte(0xAE,OLED_CMD);//Set Display ON/OFF 关闭显示
  OLED_WR_Byte(0x40,OLED_CMD);//Set Display Start Line
  OLED_WR_Byte(0xB0,OLED_CMD);//Set Page Start Address for Page Addressing Mode
  OLED_WR_Byte(0xC8,OLED_CMD);//重映射模式
  OLED_WR_Byte(0x81,OLED_CMD);//设置对比度
  OLED_WR_Byte(0xFF,OLED_CMD);
  OLED_WR_Byte(0xA1,OLED_CMD);//垂直寻址方式
  OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
  OLED_WR_Byte(0xA8,OLED_CMD);//设置驱动路数
  OLED_WR_Byte(0x1F,OLED_CMD);
  OLED_WR_Byte(0xD3,OLED_CMD);//Set Display Offset 设置垂直移位0d~63d
  OLED_WR_Byte(0x00,OLED_CMD);
  OLED_WR_Byte(0xD5,OLED_CMD);//Set Display Clock Divide Ratio/ Oscillator Frequency
  OLED_WR_Byte(0xF0,OLED_CMD);
  OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-charge Period
  OLED_WR_Byte(0x22,OLED_CMD);//Set Page Address
  OLED_WR_Byte(0xDA,OLED_CMD);//设置COM引脚硬件配置
  OLED_WR_Byte(0x02,OLED_CMD);
  OLED_WR_Byte(0xDB,OLED_CMD);//调整VCOMH调节器输出
  OLED_WR_Byte(0x49,OLED_CMD);
  OLED_WR_Byte(0x8D,OLED_CMD);
  OLED_WR_Byte(0x14,OLED_CMD);
  OLED_WR_Byte(0xAF,OLED_CMD);//Set Display ON/OFF 打开显示
  OLED_Clear();
}

关于字体文件和图片数据文件这里不贴代码了。关于其他的显示代码也不写了,网上很多。

5.main.c文件

#include "stc15.h"
#include "delay.h"
#include "oled.h"
#include "bmp.h"
int main(void)
{  
  OLED_Init();//初始化OLED  
  OLED_Clear() ;   
  while(1)  
  {     
    OLED_ShowCHinese(0,0,0);//小
    OLED_ShowCHinese(18,0,1);//猿
    OLED_ShowCHinese(36,0,2);//猪 
    OLED_ShowCHinese(54,0,3);//哥  
    }      
}
温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信