zoukankan      html  css  js  c++  java
  • 一个OLED的采坑之旅

    最近在做某项目,拿到的一块oled屏幕 128*64

    mcu 是 f103RC 512kb 的核

    本来显彩色的 LCD 是直接 画对应的 像素点就行了

    可是这个 OLED 屏幕的 设置却是下边的样子

    1             OLED_DrawBMP(0,0,128,8, BMP3y);
    2 
    3             OLED_ShowChar(10,1,( unsigned char *)"HelTecAutomation",1);
    4 
    5             OLED_ShowChar(10,2,( unsigned char *)"HOLLEWORLD",1);
    6             OLED_ShowChar(10,4,( unsigned char *)"Voltage:",1);
    7             OLED_ShowChar(64,4,( unsigned char *)"20V ",1);
    8             OLED_ShowChar(34,6,( unsigned char *)"2020-09-08",1);

    这就给我们设置带来了很多问题

    图片总是偏移了几个像素

    直到我自己画图

     转换 下边的设置很重要 不然图形显示是乱的

     最后 发现 还是有一条亮边,真奇怪

    只能修改 总宽度 感觉是没刷新这列导致的。于是

    大功告成,显示完美

    下边是代码,感觉还是不完美,比如我想自己画条线,但是画的是   | | | | 这种。很奇怪

    #ifndef __OLED_H__
    #define __OLED_H__
    #include "stdint.h"
    
    
    #define OLED_CS PBout(6)
    #define OLED_DC PBout(7)
    
    #define    Brightness    0xCF
    #define X_WIDTH           129 // 132 //0.96(SSD1306) is 128 ,1.30(SH1106) is 132
    #define Y_WIDTH         64
    #define        Page            32
    
    #define IIC_SPI_TYPE         1    //1 is the spi,0 is the i2c
    
    #define CHIP_IS_SSD1306     0   //1 - SSD1306; 0 -- SH1106
    
    //#define INCH                0  // 0 is 0.96 inch & 0.91 inch & 1.3 inch & 1.54 inch,1 is 0.49 inch  (This Macro definition is for IIC with SSD1306)
    
    void OLED_WrDat(uint8_t dat);
    void OLED_WrCmd(uint8_t cmd);
    void OLED_SetPos(unsigned char x, unsigned char y);
    void OLED_Fill(unsigned char bmp_dat);
    void OLED_CLS(void);
    void OLED_ON(void);
    void OLED_OFF(void);
    void OLED_Init(void);
    //void OLED_DrawPoint(unsigned char x,unsigned char y,unsigned char t);
    //void OLED_Char(unsigned char x, unsigned char y, unsigned char ch);
    void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize);
    void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N);
    void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
    
    void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t BMPx[]);
    void OLED_Set_Pos(uint8_t x, uint8_t y);     //汉字显示,设置显示坐标
    void OLED_DrawLine(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t mode);
    void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t);
    void OLED_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
    //      OLED_Fill(0xFF);//屏幕全亮
    void OLED_Refresh(void);
    
    /*
                for(i=0; i<8; i++)
                {
                    OLED_ShowCN(i*16,0,i);    //行,列,第几个汉字
                    OLED_ShowCN(i*16,2,i+8);
                }
    */
    
    
    #endif
    View Code
    #include "spi.h"
    #include "OLED.h"
    #include "codetab.h"
    #include "delay.h"
    #include "sys.h"
    #include "delay.h"
    
    
    uint8_t OLED_GRAM[144][8];
    
    void OLED_WrCmd(uint8_t cmd)
    {
        OLED_DC = 0;
        SPI3_ReadWriteByte(cmd);
    }
    void OLED_WrDat(uint8_t dat)
    {
        OLED_DC = 1;
        SPI3_ReadWriteByte(dat);
    }
    
    
    void OLED_SetPos(unsigned char x, unsigned char y)
    { 
        OLED_WrCmd(0xb0+y);
        OLED_WrCmd(((x&0xf0)>>4)|0x10);
        OLED_WrCmd((x&0x0f)|0x01); 
    }
    
    
    void OLED_Fill(unsigned char bmp_dat) 
    {
        unsigned char y,x;
        for(y=0;y<Page;y++)
        {
            OLED_WrCmd(0xb0+y);
            OLED_WrCmd(0x01);
            OLED_WrCmd(0x10);
            for(x=0;x<X_WIDTH;x++)
            OLED_WrDat(bmp_dat);
        }
    }
    
    
    void OLED_CLS(void)
    {
        OLED_Fill(0x00);
    }
    
    
    void OLED_ON(void)
    {
        OLED_WrCmd(0X8D);
        OLED_WrCmd(0X14);
        OLED_WrCmd(0XAF);
    }
    
    
    void OLED_Init(void)
    {
          GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;                 //
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
        GPIO_Init(GPIOB, &GPIO_InitStructure);                       //配置
        GPIO_SetBits(GPIOB,GPIO_Pin_6 | GPIO_Pin_7);
        SPI3_Init();
        OLED_CS = 0;
        delay_ms(100);
        
    #if CHIP_IS_SSD1306
        
        OLED_WrCmd(0xae);//--turn off oled panel
        OLED_WrCmd(0x00);//---set low column address
        OLED_WrCmd(0x10);//---set high column address
        OLED_WrCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
        OLED_WrCmd(0x81);//--set contrast control register
        OLED_WrCmd(Brightness); // Set SEG Output Current Brightness
        OLED_WrCmd(0xa1);//--Set SEG/Column Mapping
        OLED_WrCmd(0xc8);//Set COM/Row Scan Direction
        OLED_WrCmd(0xa6);//--set normal display
        OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
        OLED_WrCmd(0x3f);//--1/64 duty
        OLED_WrCmd(0xd3);//-set display offset    Shift Mapping RAM Counter (0x00~0x3F)
        OLED_WrCmd(0x00);//-not offset
        OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
        OLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
        OLED_WrCmd(0xd9);//--set pre-charge period
        OLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
        OLED_WrCmd(0xda);//--set com pins hardware configuration
        OLED_WrCmd(0x12);
        OLED_WrCmd(0xdb);//--set vcomh
        OLED_WrCmd(0x40);//Set VCOM Deselect Level
        OLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
        OLED_WrCmd(0x02);//
        OLED_WrCmd(0x8d);//--set Charge Pump enable/disable
        OLED_WrCmd(0x14);//--set(0x10) disable
        OLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
        OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7) 
        OLED_WrCmd(0xaf);//--turn on oled panel
        
    #else //1106
        
        OLED_WrCmd(0xAE);    /*display off*/
        OLED_WrCmd(0x02);    /*set lower column address*/
        OLED_WrCmd(0x10);    /*set higher column address*/
        OLED_WrCmd(0x40);    /*set display start line*/
        OLED_WrCmd(0xB0);    /*set page address*/
        OLED_WrCmd(0x81);    /*contract control*/
        OLED_WrCmd(Brightness);    /*128*/
        OLED_WrCmd(0xA1);    /*set segment remap*/
        OLED_WrCmd(0xA6);    /*normal / reverse*/
        OLED_WrCmd(0xA8);    /*multiplex ratio*/
        OLED_WrCmd(0x3F);    /*duty = 1/32*/
        OLED_WrCmd(0xad);    /*set charge pump enable*/
        OLED_WrCmd(0x8b);    /*    0x8a    ??VCC   */
        OLED_WrCmd(0x30);    /*0X30---0X33  set VPP   9V liangdu!!!!*/
        OLED_WrCmd(0xC8);    /*Com scan direction*/
        OLED_WrCmd(0xD3);    /*set display offset*/
        OLED_WrCmd(0x00);    /*   0x20  */
        OLED_WrCmd(0xD5);    /*set osc division*/
        OLED_WrCmd(0x80);    
        OLED_WrCmd(0xD9);    /*set pre-charge period*/
        OLED_WrCmd(0x1f);    /*0x22*/
        OLED_WrCmd(0xDA);    /*set COM pins*/
        OLED_WrCmd(0x12);         //0x02 -- duanhang xianshi,0x12 -- lianxuhang xianshi!!!!!!!!!
        OLED_WrCmd(0xdb);    /*set vcomh*/
        OLED_WrCmd(0x40);     
        OLED_WrCmd(0xAF);    /*display ON*/
        
    #endif
        
        OLED_Fill(0x00);
        OLED_SetPos(0,0);     
    } 
    
    //显示英文字符,
    void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
    {
        unsigned char c = 0,i = 0,j = 0;
        switch(TextSize)
        {
            case 1:
            {
                while(ch[j] != '')
                {
                    c = ch[j] - 32;
                    if(x > 126)
                    {
                        x = 0;
                        y++;
                    }
                    OLED_SetPos(x,y);
                    for(i=0;i<6;i++)
                        OLED_WrDat(F6x8[c][i]);
                    x += 6;
                    j++;
                }
            }break;
            case 2:
            {
                while(ch[j] != '')
                {
                    c = ch[j] - 32;
                    if(x > 120)
                    {
                        x = 0;
                        y++;
                    }
                    OLED_SetPos(x,y);
                    for(i=0;i<8;i++)
                        OLED_WrDat(F8X16[c*16+i]);
                    OLED_SetPos(x,y+1);
                    for(i=0;i<8;i++)
                        OLED_WrDat(F8X16[c*16+i+8]);
                    x += 8;
                    j++;
                }
            }break;
        }
    }
    
    
    void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
    {
        unsigned char wm=0;
        unsigned int  adder=32*N;
        OLED_SetPos(x , y);
        for(wm = 0;wm < 16;wm++)
        {
            OLED_WrDat(F16x16[adder]);
            adder += 1;
        }
        OLED_SetPos(x,y + 1);
        for(wm = 0;wm < 16;wm++)
        {
            OLED_WrDat(F16x16[adder]);
            adder += 1;
        }
    }
    
    
    
    
    
    
    
    //void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
    //{
    //    unsigned int j=0;
    //    unsigned char x,y;
    
    //  if(y1%8==0)
    //        y = y1/8;
    //  else
    //        y = y1/8 + 1;
    //    for(y=y0;y<y1;y++)
    //    {
    //        OLED_SetPos(x0,y);
    //    for(x=x0;x<x1;x++)
    //        {
    //            OLED_WrDat(BMP[j++]);
    //        }
    //    }
    //}
    
    
    //显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7
    void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t BMPx[])
    {
        u16 j = 0;
        uint8_t x, y;
    
    //    if(y1 % 8 == 0) y = y1 / 8;
    //    else y = y1 / 8 + 1;
    //    for(y = y0; y < y1; y++)
    //    {
    //        OLED_SetPos(x0, y);
    //        for(x = x0; x < x1; x++)
    //        {
    //            OLED_WrDat(BMPx[j++]);
    //        }
    //    }
    //        
         if(y1 % Page == 0) y = y1 / Page;
        else y = y1 / Page + 1;
        for(y = y0; y < y1; y++)
        {
            OLED_SetPos(x0, y);
            for(x = x0; x < x1; x++)
            {
                OLED_WrDat(BMPx[j++]);
            }
        }
        
            
    }
    
    //更新显存到OLED    
    void OLED_Refresh(void)
    {
    //       for(y = 0; y < sizeof( OLED_GRAM[0]); y++)
    //    {
    //        OLED_SetPos(x0, y);
    //        for(x = x0; x < x1; x++)
    //        {
    //            OLED_WrDat(OLED_GRAM[x,y]);
    //        }
    //    }
        //OLED_DrawBMP(0,0,127,7,OLED_GRAM);
    //    u8 i,n;
    //    for(i=0;i<8;i++)
    //    {
    //       OLED_WrDat(0xb0+i,OLED_CMD); //设置行起始地址
    //       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);
    //  }
    }
    
    //画点 
    //x:0~127
    //y:0~63
    //t:1 填充 0,清空    
    void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t)
    {
        uint8_t i,m,n;
        i=y/8;
        m=y%8;
        n=1<<m;
        if(t){
    
        OLED_GRAM[x][i]|=n;
             OLED_SetPos(x, y);
           OLED_WrDat(0xff);
        
        }
        else
        {
            OLED_GRAM[x][i]=~OLED_GRAM[x][i];
            OLED_GRAM[x][i]|=n;
            OLED_GRAM[x][i]=~OLED_GRAM[x][i];
        }
    }
    
    //画线
    //x1,y1:起点坐标
    //x2,y2:结束坐标
    void OLED_DrawLine(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t mode)
    {
        u16 t; 
        int xerr=0,yerr=0,delta_x,delta_y,distance;
        int incx,incy,uRow,uCol;
        delta_x=x2-x1; //计算坐标增量 
        delta_y=y2-y1;
        uRow=x1;//画线起点坐标
        uCol=y1;
        if(delta_x>0)incx=1; //设置单步方向 
        else if (delta_x==0)incx=0;//垂直线 
        else {incx=-1;delta_x=-delta_x;}
        if(delta_y>0)incy=1;
        else if (delta_y==0)incy=0;//水平线 
        else {incy=-1;delta_y=-delta_x;}
        if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
        else distance=delta_y;
        for(t=0;t<distance+1;t++)
        {
            OLED_DrawPoint(uRow,uCol,mode);//画点
    
            xerr+=delta_x;
            yerr+=delta_y;
            if(xerr>distance)
            {
                xerr-=distance;
                uRow+=incx;
            }
            if(yerr>distance)
            {
                yerr-=distance;
                uCol+=incy;
            }
        }
    }
    void OLED_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
    {
        OLED_DrawLine(x1,y1,x2,y1,0);
        OLED_DrawLine(x1,y1,x1,y2,0);
        OLED_DrawLine(x1,y2,x2,y2,1);
        OLED_DrawLine(x2,y1,x2,y2,1);
    }
    
    void OLED_Set_Pos(uint8_t x, uint8_t y)     //汉字显示,设置显示坐标
    {
    //    OLED_WriteCmd(0xb0 + y);
    //    OLED_WriteCmd(((x & 0xf0) >> 4) | 0x10);
    //    OLED_WriteCmd((x & 0x0f) | 0x01);
    }
    
    
    void OLED_WriteData(uint8_t dat)        //写一字节数据
    {
    //    uint8_t i = 8;
    //    OLED_DC = 1;
    //    OLED_SCL = 0;
    //    for(i = 0; i < 8; i++)
    //    {
    //        if(dat & 0x80)
    //            OLED_SDA = 1;
    //        else
    //            OLED_SDA = 0;
    //        OLED_SCL = 1;
    //        OLED_SCL = 0;
    //        dat <<= 1;
    //    }
    }
    View Code

    下面文章貌似解决了这个问题

    https://blog.csdn.net/lagran/article/details/98893270

    https://blog.csdn.net/qq_39492932/article/details/87097988

  • 相关阅读:
    详解Javascript匿名函数的使用 转载自IT EYE Blog
    漂亮、免费和响应式HTML5网站模板 转
    Truth, Equality and JavaScript
    Ember.js 示例
    UX Pin 一款在线界面设计网站
    关于工资的三个秘密
    Semantic Versioning 如何进行版本管理
    CSSS CSS幻灯片
    oracle 导入数据报600错误
    Android 初步Android文件目录介绍
  • 原文地址:https://www.cnblogs.com/mrguoguo/p/13637362.html
Copyright © 2011-2022 走看看