IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 14.STC15W408AS单片机IIC驱动OLED -> 正文阅读

[嵌入式]14.STC15W408AS单片机IIC驱动OLED

一、OLED显示屏

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

? ? ? ?

图片

? ? ? ?

二、SSD1306芯片的IIC时序图

? ? ? ?

图片

? ? ? ?

图片

? ? ? ?

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

?

图片

? ? ?

IIC数据传输格式??

图片

? ? ? ? ?

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

2) 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);//哥  
    }      
}

四、显示效果

? ? ?

图片

?

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-21 15:38:02  更:2021-08-21 15:39:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 17:44:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计