找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2768|回复: 0
打印 上一主题 下一主题
收起左侧

STM32 OLED 屏幕 驱动芯片SSD1306 IIC代码

[复制链接]
跳转到指定楼层
楼主
ID:788840 发表于 2020-6-28 08:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"           
#include "delay.h"
#include "usart.h"

//SSD1306 OLED 驱动IC驱动代码
//驱动方式:IIC

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127       
//[1]0 1 2 3 ... 127       
//[2]0 1 2 3 ... 127       
//[3]0 1 2 3 ... 127       
//[4]0 1 2 3 ... 127       
//[5]0 1 2 3 ... 127       
//[6]0 1 2 3 ... 127       
//[7]0 1 2 3 ... 127                   
u8 OLED_GRAM[128][8];         

//更新显存到LCD                 
void OLED_Refresh_Gram(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(OLED_GRAM[n][i],OLED_DATA);
        }   
}

void OLED_IIC_START(void)
{
  SDA_OUT();   //SDA线输出
  OLED_SDIN=1;
  OLED_SCLK=1;  
  delay_us(4);
  OLED_SDIN=0;//START:when CLK is high,DATA change form high to low
  delay_us(4);
  OLED_SCLK=0;//钳住IIC总线,准备发送或者接收数据
}
void OLED_IIC_STOP(void)
{
  SDA_OUT();  //SDA线输出
  OLED_SCLK=0;
  OLED_SDIN=0;//STOP:when CLK is high DATA change form low to high
  delay_us(4);
  OLED_SCLK=1;
  OLED_SDIN=1;//发送I2C总线结束信号       
  delay_us(4);
}

//等待应答信号到来
//返回值: 1,接收应答失败,停止IIC总线
// 0,接收应答成功
//单片机作为主设备等待从设备的应答信号
u8 OLED_IIC_WAITACK(void)
{
  u8 timer=0;

  OLED_SDIN=1;delay_us(1);//和开发教程IIC顺序不同
  OLED_SCLK=1;delay_us(1);
  SDA_IN();      //SDA设置为输入和开发教程IIC顺序不同
  while(OLED_SDIN_IN)
        {
                timer++;
                if(timer++>250)
                {
                        OLED_IIC_STOP();
                        return 1;
                }
        }
       
        OLED_SCLK=0;//时钟输出0           
        return 0;
}

//IIC发送一个字节
void MCU_Send_Byte(u8 txd)
{                        
    u8 t;   
        SDA_OUT();             
    OLED_SCLK=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        OLED_SDIN=(txd&0x80)>>7;
        txd<<=1;           
                delay_us(4);   //8位二进制依次发送出去
                OLED_SCLK=1;
                delay_us(4);
                OLED_SCLK=0;       
                delay_us(4);
    }         
}


//oled中写命令
u8 OLED_WR_CMD(u8 cmd)//
{                                                                                                                                                                          
    OLED_IIC_START();  
        MCU_Send_Byte(0X78);//发送器件地址0X78, R/W# = 0 写模式         
    if(OLED_IIC_WAITACK())
        return 1;
    MCU_Send_Byte(0X00);//0x00代表写命令  0x40带表写数据
        if(OLED_IIC_WAITACK())
        return 2;
        MCU_Send_Byte(cmd);
        if(OLED_IIC_WAITACK())
        return 3;
        OLED_IIC_STOP();
    return 0;       
}

void OLED_WR_DAT(u8 dat)//
{                                                                                                                                                                          
    OLED_IIC_START();  
        MCU_Send_Byte(0X78);//发送器件地址0X78, R/W# = 0 写模式         
    OLED_IIC_WAITACK();
    MCU_Send_Byte(0X40);//0x00代表写命令  0x40带表写数据
        OLED_IIC_WAITACK();
        MCU_Send_Byte(dat);
        OLED_IIC_WAITACK();
        OLED_IIC_STOP();        //
}

void OLED_WR_Byte(u8 dat,u8 cmd)
{
  if(cmd) OLED_WR_DAT(dat);
  else OLED_WR_CMD(dat);
}

//开启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++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00;  
        OLED_Refresh_Gram();//更新显示
}
//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空                                  
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
        u8 pos,bx,temp=0;
        if(x>127||y>63)return;//超出范围了.
        pos=7-y/8;
        bx=y%8;
        temp=1<<(7-bx);
        if(t)OLED_GRAM[x][pos]|=temp;
        else OLED_GRAM[x][pos]&=~temp;            
}
//x1,y1,x2,y2 填充区域的对角坐标
//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63                  
//dot:0,清空;1,填充          
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)  
{  
        u8 x,y;  
        for(x=x1;x<=x2;x++)
        {
                for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);
        }                                                                                                            
        OLED_Refresh_Gram();//更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示                                 
//size:选择字体 12/16/24
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{                                  
        u8 temp,t,t1;
        u8 y0=y;
        u8 csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数
        chr=chr-' ';//得到偏移后的值                 
    for(t=0;t<csize;t++)
    {   
                if(size==12)temp=asc2_1206[chr][t];                  //调用1206字体
                else if(size==16)temp=asc2_1608[chr][t];        //调用1608字体
                else if(size==24)temp=asc2_2412[chr][t];        //调用2412字体
                else return;                                                                //没有的字库
        for(t1=0;t1<8;t1++)
                {
                        if(temp&0x80)OLED_DrawPoint(x,y,mode);
                        else OLED_DrawPoint(x,y,!mode);
                        temp<<=1;
                        y++;
                        if((y-y0)==size)
                        {
                                y=y0;
                                x++;
                                break;
                        }
                }           
    }         
}

//m^n函数
u32 mypow(u8 m,u8 n)
{
        u32 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,u32 num,u8 len,u8 size)
{                
        u8 t,temp;
        u8 enshow=0;                                                  
        for(t=0;t<len;t++)
        {
                temp=(num/mypow(10,len-t-1))%10;
                if(enshow==0&&t<(len-1))
                {
                        if(temp==0)
                        {
                                OLED_ShowChar(x+(size/2)*t,y,' ',size,1);
                                continue;
                        }else enshow=1;
                          
                }
                 OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);
        }
}

void OLED_ShowSmallNum(u8 x,u8 y,u32 num,u8 len,u8 size)
{                
        u8 t,temp;                                          
        for(t=0;t<len;t++)
        {
                temp=(num/mypow(10,len-t-1))%10;
                 OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);
        }
}


void OLED_ShowFloatNum(u8 x,u8 y,float num,u8 len,u8 size)
{
   u16 temp_int=0;
   u16 temp_float=0;

   temp_int=num;  //temp_int保存num的整数部分
   temp_float=(num-temp_int)*100;//temp_float保存num的小数部分2位

   OLED_ShowNum(x,y,temp_int,4,size);//显示4位整数部分数字
   OLED_ShowString(2*size+x,y,".",size);//显示.
   OLED_ShowSmallNum((2*size+size/2)+x,y,temp_float,2,size);//显示小数部分
}
//显示字符串
//x,y:起点坐标  
//size:字体大小
//*p:字符串起始地址
void OLED_ShowString(u8 x,u8 y,const char *p,u8 size)
{       
    while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
    {      
        if(x>(128-(size/2))){x=0;y+=size;}
        if(y>(64-size)){y=x=0;OLED_Clear();}
        OLED_ShowChar(x,y,*p,size,1);         
        x+=size/2;
        p++;
    }  
       
}
u8 OLED_Init(void)
{                                                                                      

        RCC->APB2ENR|=1<<4;    //使能PORTC时钟
        RCC->APB2ENR|=1<<8;    //使能PORTG时钟
       
    GPIOC->CRL&=0XFFFFFFF0; //PC0 OUT IIC模式
        GPIOC->CRL|=0X00000003;         //   
        GPIOC->ODR|=1<<0;        //
       
        GPIOG->CRH&=0X0FFFFFFF;        //RST          
        GPIOG->CRH|=0X30000000;         
        GPIOG->ODR|=1<<15;
       
        OLED_RST=0;
        delay_ms(100);
        OLED_RST=1;

    if(!OLED_WR_CMD(0XAE)) printf("1-ok\r\n");
    else printf("1-no\r\n");
    if(!OLED_WR_CMD(0Xd5)) printf("2-ok\r\n");
        else printf("2-no\r\n");
    if(!OLED_WR_CMD(80)) printf("3-ok\r\n");
        else printf("3-no\r\n");
    if(!OLED_WR_CMD(0XA8)) printf("4-ok\r\n");
        else printf("4-no\r\n");
    if(!OLED_WR_CMD(0X3F)) printf("5-ok\r\n");
        else printf("5-no\r\n");
    if(!OLED_WR_CMD(0XD3)) printf("6-ok\r\n");
        else printf("6-no\r\n");
    if(!OLED_WR_CMD(0X00)) printf("7-ok\r\n");
        else printf("7-no\r\n");
    if(!OLED_WR_CMD(0X40)) printf("8-ok\r\n");
        else printf("8-no\r\n");
        if(!OLED_WR_CMD(0X8D)) printf("9-ok\r\n");
        else printf("9-no\r\n");
        if(!OLED_WR_CMD(0X14)) printf("10-ok\r\n");
        else printf("10-no\r\n");
        if(!OLED_WR_CMD(0X20)) printf("11-ok\r\n");
        else printf("11-no\r\n");
        if(!OLED_WR_CMD(0X02)) printf("12-ok\r\n");
        else printf("12-no\r\n");
        if(!OLED_WR_CMD(0XA1)) printf("13-ok\r\n");
        else printf("13-no\r\n");
        if(!OLED_WR_CMD(0XC0)) printf("14-ok\r\n");
        else printf("14-no\r\n");
        if(!OLED_WR_CMD(0XDA)) printf("15-ok\r\n");
        else printf("15-no\r\n");
        if(!OLED_WR_CMD(0X12)) printf("16-ok\r\n");
        else printf("16-no\r\n");
        if(!OLED_WR_CMD(0X81)) printf("17-ok\r\n");
        else printf("17-no\r\n");
    if(!OLED_WR_CMD(0XEF)) printf("18-ok\r\n");
        else printf("18-no\r\n");
        if(!OLED_WR_CMD(0XD9)) printf("19-ok\r\n");
        else printf("19-no\r\n");
        if(!OLED_WR_CMD(0XF1)) printf("20-ok\r\n");
        else printf("20-no\r\n");
        if(!OLED_WR_CMD(0XDB)) printf("21-ok\r\n");
    else printf("21-no\r\n");       
        if(!OLED_WR_CMD(0X30)) printf("22-ok\r\n");
        else printf("22-no\r\n");
    if(!OLED_WR_CMD(0XA4)) printf("23-ok\r\n");
        else printf("23-no\r\n");
    if(!OLED_WR_CMD(0XA6)) printf("24-ok\r\n");
        else printf("24-no\r\n");
        if(!OLED_WR_CMD(0XAF)) printf("25-ok\r\n");
        else printf("25-no\r\n");
        OLED_Clear();
        return 0;
}  









分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表