找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 3085|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

STM32 OLED 屏幕 驅(qū)動芯片SSD1306 IIC代碼

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:788840 發(fā)表于 2020-6-28 08:44 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"           
#include "delay.h"
#include "usart.h"

//SSD1306 OLED 驅(qū)動IC驅(qū)動代碼
//驅(qū)動方式: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);    //設(shè)置頁地址(0~7)
                OLED_WR_Byte (0x00,OLED_CMD);      //設(shè)置顯示位置—列低地址
                OLED_WR_Byte (0x10,OLED_CMD);      //設(shè)置顯示位置—列高地址   
                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總線,準備發(fā)送或者接收數(shù)據(jù)
}
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;//發(fā)送I2C總線結(jié)束信號       
  delay_us(4);
}

//等待應(yīng)答信號到來
//返回值: 1,接收應(yīng)答失敗,停止IIC總線
// 0,接收應(yīng)答成功
//單片機作為主設(shè)備等待從設(shè)備的應(yīng)答信號
u8 OLED_IIC_WAITACK(void)
{
  u8 timer=0;

  OLED_SDIN=1;delay_us(1);//和開發(fā)教程IIC順序不同
  OLED_SCLK=1;delay_us(1);
  SDA_IN();      //SDA設(shè)置為輸入和開發(fā)教程IIC順序不同
  while(OLED_SDIN_IN)
        {
                timer++;
                if(timer++>250)
                {
                        OLED_IIC_STOP();
                        return 1;
                }
        }
       
        OLED_SCLK=0;//時鐘輸出0           
        return 0;
}

//IIC發(fā)送一個字節(jié)
void MCU_Send_Byte(u8 txd)
{                        
    u8 t;   
        SDA_OUT();             
    OLED_SCLK=0;//拉低時鐘開始數(shù)據(jù)傳輸
    for(t=0;t<8;t++)
    {              
        OLED_SDIN=(txd&0x80)>>7;
        txd<<=1;           
                delay_us(4);   //8位二進制依次發(fā)送出去
                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);//發(fā)送器件地址0X78, R/W# = 0 寫模式         
    if(OLED_IIC_WAITACK())
        return 1;
    MCU_Send_Byte(0X00);//0x00代表寫命令  0x40帶表寫數(shù)據(jù)
        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);//發(fā)送器件地址0X78, R/W# = 0 寫模式         
    OLED_IIC_WAITACK();
    MCU_Send_Byte(0X40);//0x00代表寫命令  0x40帶表寫數(shù)據(jù)
        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
}
//關(guān)閉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
}                                            
//清屏函數(shù),清完屏,整個屏幕是黑色的!和沒點亮一樣!!!          
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 填充區(qū)域的對角坐標
//確保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);                //得到字體一個字符對應(yīng)點陣集所占的字節(jié)數(shù)
        chr=chr-' ';//得到偏移后的值                 
    for(t=0;t<csize;t++)
    {   
                if(size==12)temp=asc2_1206[chr][t];                  //調(diào)用1206字體
                else if(size==16)temp=asc2_1608[chr][t];        //調(diào)用1608字體
                else if(size==24)temp=asc2_2412[chr][t];        //調(diào)用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函數(shù)
u32 mypow(u8 m,u8 n)
{
        u32 result=1;         
        while(n--)result*=m;   
        return result;
}               
//顯示2個數(shù)字
//x,y :起點坐標         
//len :數(shù)字的位數(shù)
//size:字體大小
//mode:模式        0,填充模式;1,疊加模式
//num:數(shù)值(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的整數(shù)部分
   temp_float=(num-temp_int)*100;//temp_float保存num的小數(shù)部分2位

   OLED_ShowNum(x,y,temp_int,4,size);//顯示4位整數(shù)部分數(shù)字
   OLED_ShowString(2*size+x,y,".",size);//顯示.
   OLED_ShowSmallNum((2*size+size/2)+x,y,temp_float,2,size);//顯示小數(shù)部分
}
//顯示字符串
//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 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表