zoukankan      html  css  js  c++  java
  • OLED的使用-4线SPI驱动

    一 、OLED屏

    1.OLED屏(七针)

    2.OLED电路图

    3.0.96'OLED简介

    该模块特点:

    1、三色可选,模块有两种单色和黄蓝双色两种颜色可选,单色为纯白色和纯蓝色,双
    色为黄蓝双色;
    2、超小尺寸,显示尺寸为 0.96 寸,模块尺寸为 27mm(长)*26mm(宽)*4mm(高);
    3、高分辨率,分辨率为 128*64;
    4、接口模式,4 线串行 SPI 接口模式;
    5、带字库,可显示标准的国标简体(GB2312)汉字、8*16 点 ASCII 粗体字库、7*8
    点 ASCII 字库、5*7 点 ASCII 字库。

    6、兼容 3.3V~5V 电压。

    二、GPIO模拟SPI

    1.引脚定义

    GND                      地

    VCC                       电源,3.3V~5V

    D0                         4 线 ISP 接口模式:时钟线(CLK) PA4

    D1                         4 线 ISP 接口模式:串行数据线(MOSI)PA3

    RES                        4 线 ISP 接口模式:命令/数据标志位(RET复位)PA2

    DC                        命令/数据标志位 A1

    CS                        OLED 片选

    2.时序图

    模块只支持向模块写数据不能读数据

    所以只需要写SPI发送即可

    3.程序

    "SPI.h"

    
    
    #define OLED_CMD 0   //命令声明
    #define OLED_DATA 1 //数据声明
    
    #define OLED_CLK    PAout(4)    // CLK时钟    d0
    #define OLED_MOSI   PAout(3)    // MOSI     d1
    #define OLED_RST    PAout(2)    // RET复位    ret
    #define OLED_DC     PAout(1)    // 命令|数据    dc  (0表传输命令1表传输数据)
    
    void OLED_SPI_Init(void); //配置MCU的SPI
    void SPI_WriteByte(uint8_t addr,uint8_t data); //向寄存器地址写一个byte的数据
    void WriteCmd(unsigned char cmd); //写命令
    void WriteDat(unsigned char data); //写数据
    
    

    "SPI.c"

    /*************************************************************************/
    /*函数功能: GPIO模拟SPI端口初始化                                         */
    /*************************************************************************/
    void OLED_SPI_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);//使能PA端口时钟
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //端口配置
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz
        GPIO_Init(GPIOA,&GPIO_InitStructure);//根据设定参数初始化GPIOA
    }
    
    /*************************************************************************/
    /*函数功能: 通过SPIO软件模拟SPI通信协议,向模块(SSD1306)写入一个字节                                  */
    /*入口参数:                                                                                                                          */ 
    /*                      data:要写入的数据/命令                                                                       */             
    /*                      cmd :数据/命令标志 0,表示命令;1,表示数据;                   */
    /*************************************************************************/
    void SPI_WriteByte(unsigned char data,unsigned char cmd)
    {
        unsigned char i=0;
        OLED_DC =cmd;
        OLED_CLK=0;
        for(i=0;i<8;i++)
        {
            OLED_CLK=0;
            if(data&0x80)OLED_MOSI=1; //从高位到低位
            else OLED_MOSI=0;
            OLED_CLK=1;
            data<<=1;
        }
        OLED_CLK=1;
        OLED_DC=1;
    }
    /*************************************************************************/
    /*函数功能: 写命令                                                        */
    /*************************************************************************/
    void WriteCmd(unsigned char cmd)
    {
        SPI_WriteByte(cmd,OLED_CMD);
    }
    /*************************************************************************/
    /*函数功能: 写数据                                                        */
    /*************************************************************************/
    void WriteData(unsigned char data)
    {
        SPI_WriteByte(data,OLED_DATA);
    }

    4.SSD1306的命令

    1.SSD1306显存为128*64bit大小, SSD1306将全部显存分为8页,每页128字节

    2.ssd1306命令

    0:OLED设置对比度
         发送两个字节
         第一个字节为命令-0x81
         第二个字节为设置对比度值,值越大屏幕越亮(0X00-0XFF)
    
    1:关闭/开启OLED显示
         发送一个命令字节,高七位固定,最低位X0=0关闭显示,X0=1开启显示
         0xAE:关闭显示
         0xAF:开启显示
    
    2:关闭/开启电荷泵
         发送两个字节
         第一个字节为命令-0x8D
         第二个字节为设置电荷泵开关
              位0,1,4,5,6固定,位6位7随意,位2控制电荷泵开关
              A2=0关闭电荷泵
              A2=1开启电荷泵
         注意:在模块初始化时,必须开启,否则看不到屏幕显示
    
    3:0xB0-0xB7 设置页地址
         发送一个字节,高5位固定
         位0-位2 , X[2:0]共3位, 值范围0-7对应页0-7地址(共8页)
    
    4:0x00-0x0F设置列地址起始低四位
         高四位固定
         低四位设置列地址起始低四位
    
    5:0x10-0x1F设置列地址起始高四位
         高四位固定
         低四位设置列地址起始高四
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    "OLED.h"

    void OLED_Init(void);//初始化OLED
    void OLED_ON(void);//唤醒OLED
    void OLED_OFF(void);//OLED休眠
    void OLED_Refresh_Gram(void);//更新显存到OLED
    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 size,u8 mode);//显示字符
    void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);//显示2个数字
    void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size);//显示字符串

    "OLED.c"

    //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];   
    
    /*************************************************************************/
    /*函数功能: 软延时                                                        */
    /*************************************************************************/
    void OLED_DLY_ms(unsigned int ms)
    {                         
      unsigned int a;
      while(ms)
      {
        a=1335;
        while(a--);
        ms--;
      }
    }
    /*************************************************************************/
    /*函数功能: 初始化OLED模块                                                */
    /*************************************************************************/
    void OLED_Init(void)
    {
        OLED_SPI_Init();
        OLED_CLK = 1;
        OLED_RST = 0;
        OLED_DLY_ms(100);
        OLED_RST = 1;
    
        //从上电到下面开始初始化要有足够的时间,即等待RC复位完毕
        WriteCmd(0xAE);         // Display Off (0x00)
        WriteCmd(0xD5);
        WriteCmd(0x80);         // Set Clock as 100 Frames/Sec
        WriteCmd(0xA8);
        WriteCmd(0x3F);         // 1/64 Duty (0x0F~0x3F)
        WriteCmd(0xD3);
        WriteCmd(0x00);         // Shift Mapping RAM Counter (0x00~0x3F)
        WriteCmd(0x40 | 0x00);  // Set Mapping RAM Display Start Line (0x00~0x3F)
        WriteCmd(0x8D);
        WriteCmd(0x10 | 0x04);  // Enable Embedded DC/DC Converter (0x00/0x04)
        WriteCmd(0x20);
        WriteCmd(0x02);         // Set Page Addressing Mode (0x00/0x01/0x02)
        WriteCmd(0xA0 | 0x01);  // Set SEG/Column Mapping    
        WriteCmd(0xC0);  // Set COM/x Scan Direction   
        WriteCmd(0xDA);
        WriteCmd(0x02 | 0x10);  // Set Sequential Configuration (0x00/0x10)
        WriteCmd(0x81);
        WriteCmd(0xCF);         // Set SEG Output Current
        WriteCmd(0xD9);
        WriteCmd(0xF1);         // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
        WriteCmd(0xDB);
        WriteCmd(0x40);         // Set VCOM Deselect Level
        WriteCmd(0xA4 | 0x00);  // Disable Entire Display On (0x00/0x01)
        WriteCmd(0xA6 | 0x00);  // Disable Inverse Display On (0x00/0x01)
        WriteCmd(0xAE | 0x01);  // Display On (0x01)
    
        OLED_Clear();  //初始清屏   
    }
    /*************************************************************************/
    /*函数功能: 将OLED从休眠中唤醒                                            */
    /*************************************************************************/
    void OLED_ON(void)
    {
        WriteCmd(0X8D);  //设置电荷泵
        WriteCmd(0X14);  //开启电荷泵
        WriteCmd(0XAF);  //OLED唤醒
    }
    /*************************************************************************/
    /*函数功能: 将OLED休眠 -- 休眠模式下,OLED功耗不到10uA                      */
    /*************************************************************************/
    void OLED_OFF(void)
    {
        WriteCmd(0X8D);  //设置电荷泵
        WriteCmd(0X10);  //关闭电荷泵
        WriteCmd(0XAE);  //OLED休眠
    }
    
    /*************************************************************************/
    /*函数功能: 更新显存到OLED                                                 */
    /*************************************************************************/
    void OLED_Refresh_Gram(void)
    {
        u8 i,n;         
        for(i=0;i<8;i++)  
        {  
            WriteCmd(0xb0+i);   //设置页地址(0~7)
            WriteCmd(0x00);      //设置显示位置—列低地址
            WriteCmd(0x10);      //设置显示位置—列高地址   
            for(n=0;n<128;n++)WriteData(OLED_GRAM[n][i]); 
        }   
    }
    /*************************************************************************/
    /*函数功能: 清屏                                                          */
    /*************************************************************************/
    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                     */
    /*                      dot:0,清空;1,填充                                                                                */             
    /*************************************************************************/
    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~12                                                     */
    /*                      y:0~63                                                                      */
    /*                      mode:0,反白显示;1,正常显示                                                       */ 
    /*            size:选择字体 16/12                                        */
    /*************************************************************************/
    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); 
        }
    } 
    /*************************************************************************/
    /*函数功能: 显示字符串                                                                            */
    /*入口参数:                                                                                                                          */
    /*                      x,y:起点坐标                                                */
    /*                      size:字体大小                                                          */
    /*                      *p:字符串起始地址                                                               */ 
    /*************************************************************************/
    void OLED_ShowString(u8 x,u8 y,const u8 *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++;
        }  
    
    }   
  • 相关阅读:
    如何在Power BI Desktop中呈现D3.js自定义图表
    在Power BI中动态嵌入网页
    Querying SQL Server Agent Job Information
    shell 切换当前路径到脚本所在路径
    洛谷 P1220 关路灯
    P7077 函数调用(CSP-S2020 T3)
    P7075 儒略日(2020CSP-S T1)
    2020CSP-S 复赛总结
    洛谷 P1886 滑动窗口 /【模板】单调队列
    洛谷P5656 【模板】二元一次不定方程(exgcd)
  • 原文地址:https://www.cnblogs.com/godven/p/10776511.html
Copyright © 2011-2022 走看看