• oled的一套stm32实验1


    详细的oled介绍:http://blog.sina.com.cn/s/blog_57ad1bd20102wtq8.html

    整理自:https://www.cnblogs.com/wp2312139418/p/5988713.html

    应该可以直接运行了。

    stm32与OLED屏接口的引脚介绍:

          CS————GPIOD3;

          RST————GPIOD4;

          DC—————GPIOD5;

          D0——————GPIOD6;

          D1——————GPIOD7;

      OLED引脚介绍:

        CS:OLED片选信号

        RST:OLED复位端口

        DC: 命令/数据选择端口(0:读写命令, 1: 读写数据)

        SCLK(D0):串口时钟线

        SDIN(D1): 串口数据线

     

    估计电荷泵的作用是为了得到更好的显示效果。

    相关宏定义:

    #define OLED_CS(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_3):GPIO_ResetBits(GPIOD, GPIO_Pin_3)    //X为1时对应GPIO端口输出高电平,X为0时对应GPIO端口输出低电平

    #define OLED_RST(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_4):GPIO_ResetBits(GPIOD, GPIO_Pin_4)    

    #define OLED_DC(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_5):GPIO_ResetBits(GPIOD, GPIO_Pin_5)

    #define OLED_D0(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_6):GPIO_ResetBits(GPIOD, GPIO_Pin_6)    

    #define OLED_D1(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_7):GPIO_ResetBits(GPIOD, GPIO_Pin_7)    


    #define OLED_Order 0     //定义写命令
    #define OLED_Data  1     //定义写数据

    gpio的初始化:

    void OLED_GPIO_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStruct;
        
        //开启GPIOD的时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
        //设置GPIO的基本参数
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  //这里就是连接oled的几个引脚
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    //输出速度50MHz
        
        GPIO_Init(GPIOD, &GPIO_InitStruct);
        
        GPIO_SetBits(GPIOD, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
    }

    spi的构造

    /*        SPI写数据/命令
     *    Mode :O:写命令   1:写数据
     *    data :数据/命令
     *
    */
    void SPI_Write(char data, int Mode)
    {    
        int i = 0;
        if(Mode)
        {
            OLED_DC(1);        //DC引脚输入高,表示写数据
        }
        else
        {
            OLED_DC(0);        //DC引脚输入低,表示写命令
        }
        OLED_CS(0);            //CS引脚输入低,片选使能
        for(i = 0; i < 8; i++)
        {
            OLED_D0(0);        //D0引脚输入低
            if(data & 0x80)    //判断传输的数据最高位为1还是0
            {
                OLED_D1(1);    //D1引脚输入高
            }
            else
            {
                OLED_D1(0);    //D1引脚输入低
            }
            OLED_D0(1);        //D1引脚输入高
            data <<= 1;        //将数据左移一位
        }
        OLED_DC(0);            //DC引脚输入低
        OLED_CS(1);            //CS引脚输入高,片选失能
    }

     

    /*        设置OLED屏的显示坐标
     *      X : 表示OLED的水平坐标(0—127) ,横着走
     *      Y : 表示OLED的页(0—7)                ,竖着走
     *        
    */
    void OLED_Coord(unsigned char x, unsigned char y)
    {
        SPI_Write((0xb0+(y & 0x0f)), OLED_Order);        //设置OLED显示的页                 
        SPI_Write((((x & 0xf0)>>4) | 0x10), OLED_Order);//设置OLED水平坐标的高4位    根据上面那张图分析,这是取x的高四位,
        SPI_Write((x & 0x0f)|0x01, OLED_Order);                //设置OLED水平坐标的低4位  至于为什么要|0x01,可能是为了防止太靠边。
    }

    /*
     *        清除OLED的显示
     *          //从代码上来看,似乎是给每一个像素点都写一个0,,,一共写了 128*8次。,显然,y的值是8但是,应该是8*8=64个像素

    *           //也就是在写0x00 的时候是给纵向的8个像素点写了0,即上图中天蓝色的8个格子
     *
    */
    void OLED_Clear(void)
    {
        int i = 0, j = 0;
        for(i = 0; i < 8; i++)
        {
            OLED_Coord(0, i);               
            for(j = 0; j < 128; j++)
            {
                SPI_Write(0x00, OLED_Data);
            }
        }
    }

    /*        关闭OLED显示
     *
     *
    */
    void OLED_Display_Off(void)
    {
        //电荷泵设置(初始化时必须打开,否则看不到显示)
        SPI_Write(0x8D, OLED_Order);
        SPI_Write(0x10, OLED_Order);//bit2   0:关闭        1:打开
        SPI_Write(0xAE, OLED_Order);//0xAE:关闭显示
    }

    /*
     *        开启OLED显示
     *
    */
    void OLED_Display_On(void)
    {
        //电荷泵设置(初始化时必须打开,否则看不到显示)
        SPI_Write(0x8D, OLED_Order);
        SPI_Write(0x14, OLED_Order);//bit2   0:关闭        1:打开
        SPI_Write(0xAF, OLED_Order);//0xAF:开显示    
    }

        OLED显示的参数的初始化:

          1. 在设置OLED的参数时,并不需要把所有的参数都设置一次;有些参数是默认的(可以不进行设置),只是需要设置一写必要的参数;

            (如:0xAF: 开显示, 0x8D:电荷泵设置(初始化是必须打开,否则看不到显示))

           2.代码(初始化代码中,介绍了大部分命令):

    屏幕的大部分初始化厂家都会提供的。

    /*        OLED显示参数的初始化
     *
     *
     *
    */
    void OLED_Init(void)
    {
        OLED_GPIO_Init();
        
        OLED_RST(1);
        delay_ms(100);
        OLED_RST(0);
        delay_ms(100);
        OLED_RST(1);
        
        SPI_Write(0xAE, OLED_Order);//0xAE:关显示   
        
        SPI_Write(0x00, OLED_Order);//设置低列地址
        SPI_Write(0x10, OLED_Order);//设置高列地址
        
        //设置行显示的开始地址(0-63)
        //40-47: (01xxxxx)
        SPI_Write(0x40, OLED_Order);
        
        //设置对比度
        SPI_Write(0x81, OLED_Order);
        SPI_Write(0xff, OLED_Order);//这个值越大,屏幕越亮(和上条指令一起使用)(0x00-0xff)
        
        SPI_Write(0xA1, OLED_Order);//0xA1: 左右反置,  0xA0: 正常显示(默认0xA0)
        SPI_Write(0xC8, OLED_Order);//0xC8: 上下反置,  0xC0: 正常显示(默认0xC0)
        
        //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
        //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
        SPI_Write(0xA6, OLED_Order);
        
        SPI_Write(0xA8, OLED_Order);//设置多路复用率(1-64)
        SPI_Write(0x3F, OLED_Order);//(0x01-0x3f)(默认为3f)
        
        
        //设置显示抵消移位映射内存计数器
        SPI_Write(0xD3, OLED_Order);
        SPI_Write(0x00, OLED_Order);//(0x00-0x3f)(默认为0x00)
        
        //设置显示时钟分频因子/振荡器频率
        SPI_Write(0xD5, OLED_Order);
        //低4位定义显示时钟(屏幕的刷新时间)(默认:0000)分频因子= [3:0]+1
        //高4位定义振荡器频率(默认:1000)
        SPI_Write(0x80, OLED_Order);//
        
        //时钟预充电周期
        SPI_Write(0xD9, OLED_Order);
        SPI_Write(0xF1, OLED_Order);//[3:0],PHASE 1;   [7:4] PHASE 2
        
        //设置COM硬件应脚配置
        SPI_Write(0xDA, OLED_Order);
        SPI_Write(0x12, OLED_Order);//[5:4]  默认:01
        
        SPI_Write(0xDB, OLED_Order);//
        SPI_Write(0x40, OLED_Order);//
        
        //设置内存寻址方式
        SPI_Write(0x20, OLED_Order);
        //00: 表示水平寻址方式
        //01: 表示垂直寻址方式
        //10: 表示页寻址方式(默认方式)
        SPI_Write(0x02, OLED_Order);//    
        
        //电荷泵设置(初始化时必须打开,否则看不到显示)
        SPI_Write(0x8D, OLED_Order);
        SPI_Write(0x14, OLED_Order);//bit2   0:关闭        1:打开
        
        //设置是否全部显示 0xA4: 禁止全部显示
        SPI_Write(0xA4, OLED_Order);

        //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
        //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
        SPI_Write(0xA6, OLED_Order);//
        
        SPI_Write(0xAF, OLED_Order);//0xAF:开显示
        
        SPI_Write(0xAF, OLED_Order);//0xAF:开显示
        
        OLED_Clear();
    }

    下面的显示汉字和显示ascii都需要结合取模方式的。

    /*        显示汉字
     *        x:表示显示的水平坐标
     *        y: 表示显示的垂直坐标
     *        *p: 表示要显示汉字模组的首地址
    */
    void OLED_ShowChinese(int x, int y, const unsigned char *p)
    {
        int i = 0;
        OLED_Coord(x, y);
        for(i = 0; i < 32; i+=2)
        {
            SPI_Write(p[i], OLED_Data);
        }
        OLED_Coord(x, y+1);
        for(i = 1; i < 32; i+=2)
        {
            SPI_Write(p[i], OLED_Data);
        }
    }

    /*        显示ASCII
     *        x:表示显示的水平坐标
     *        y: 表示显示的垂直坐标
     *        *p: 表示要显示汉字模组的首地址
    */
    void OLED_ShowChar(int x, int y, const unsigned char *p)
    {
        int i = 0;
        OLED_Coord(x, y);
        for(i = 0; i < 16; i+=2)
        {
            SPI_Write(p[i], OLED_Data);
        }
        OLED_Coord(x, y+1);
        for(i = 1; i < 16; i+=2)
        {
            SPI_Write(p[i], OLED_Data);
        }
    }

    int main(void)
    {
        SysTick_Init();
        OLED_Init();
        
        OLED_ShowChinese(0, 0, xing);//‘姓’    
        OLED_ShowChinese(18, 0, ming);//‘名’
        OLED_ShowChar(36, 0, ASCII_Colon);//‘:’
        OLED_ShowChinese(0, 2, xue);//‘学’    
        OLED_ShowChinese(18, 2, hao);//‘号’
        OLED_ShowChar(36, 2, ASCII_Colon);//‘:’    
    //    SPI_Write(0x2F, OLED_Order);    //0x2F:激活滚动(一定要有)        0x2E:关闭滚动
    //    //设置滚动方式:
    //    //        0x26/0x27        :水平滚动(右向/左向)
    //    //        0x29/0x2A        :水平和垂直滚动(右向/左向)
    //    //        0xA3            :垂直滚动
    //    SPI_Write(0x27, OLED_Order);    
    //    SPI_Write(0x00, OLED_Order);
    //    SPI_Write(0x00, OLED_Order);
    //    SPI_Write(0x00, OLED_Order);
    //    SPI_Write(0x03, OLED_Order);
    //    SPI_Write(0x30, OLED_Order);    
        while(1);

    }

    const unsigned char xing[]=
    {    0x10,0x40,0x10,0x22,0xF0,0x15,0x1F,0x08,
        0x10,0x16,0xF0,0x21,0x40,0x40,0x3C,0x42,
        0x10,0x42,0x10,0x42,0xFF,0x7F,0x10,0x42,
        0x10,0x42,0x10,0x42,0x00,0x40,0x00,0x00};/*"姓",0*/
    const unsigned char A[]=
    {    0x00,0x20,0x00,0x3C,0xC0,0x23,0x38,0x02,
        0xE0,0x02,0x00,0x27,0x00,0x38,0x00,0x20};/*"A",0*/
    const unsigned char ming[]=
    {    0x00,0x04,0x20,0x04,0x20,0x04,0x10,0x02,
        0x08,0xFE,0x14,0x43,0x67,0x43,0x84,0x42,
        0x44,0x42,0x24,0x42,0x14,0x42,0x0C,0x42,
        0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00};/*"名",0*/
    const unsigned char ASCII_Colon[]=
    {    0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,
        0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00};/*":",0*/    
    const unsigned char xue[]=
    {    0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,
        0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
        0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,
        0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00};/*"学",0*/
    const unsigned char hao[]=
    {    0x80,0x00,0x80,0x00,0x80,0x00,0xBE,0x06,
        0xA2,0x05,0xA2,0x04,0xA2,0x04,0xA2,0x04,
        0xA2,0x44,0xA2,0x84,0xA2,0x44,0xBE,0x3C,
        0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00};/*"号",0*/

    注意1:在使用PCtoLCD2002完美版进行取模时,如果取模的字高大于8时一定要注意;

          如果字高16;取模的顺序是:从第一列开始,前8个点为第一个字节,后8个点为第二个字节

         然后第二列取模,前8个点为第三个字节,后8个点为第四个字节,以此类推,而OLED屏的内存

         寻址方式为0x10: 表示页寻址方式(默认方式)时,那么显示时将会乱码;因为是按页来显示的,

         那么第一个字节显示在第一列,而第二个字节本应该显示在第二页的第一列,而被错误的显示在第一页的第二列,以此类推,导致显示乱码;

          (这就是为什么OLED_ShowChar()函数和OLED_ShowChinese()函数中, 前面先显示数组下标为偶数的数组, 后面显示数组下标为奇数的数组)

  • 相关阅读:
    .Net 控制台动态刷新使用
    VS 将!=转换成 ≠
    C# 自定义Html分页
    .NET MVC ModelBinder基本使用
    C# 重启电脑 程序自启动
    ASP.NET JsonResult返回日期格式及首字母大写解决
    java快速排序代码实现
    系统高可靠的设计需要考虑哪些方面
    sentinel源码学习--transport模块
    TiDB学习笔记分享--存储篇
  • 原文地址:https://www.cnblogs.com/chulin/p/9373088.html
Copyright © 2020-2023  润新知