查看: 3769|回复: 2

小实验-基于stm32的OLED屏

[复制链接]
  • TA的每日心情
    开心
    2014-2-20 10:23
  • 签到天数: 45 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2017-7-31 09:22:06 | 显示全部楼层 |阅读模式
    分享到:
    OLED屏的特点:
    1.  模块有单色和双色可选,单色为纯蓝色,双色为黄蓝双色(本人选用双色);
        2.  显示尺寸为0.96寸
        3.  分辨率为128*64
        4.  多种接口方式,该模块提供了总共 5 种接口包括: 6800、 8080 两种并行接口方式、 3线或4线的SPI接口,IIC接口方式
        5.  不需要高压,直接接3.3V就可以工作;(可以与stm32的引脚直接相接)

    OLED图片:
    1015113-20161022220518342-2137724607.png

    1015113-20161022220532310-1996380875.png

    OLED引脚介绍:
        CS:OLED片选信号
        RST:OLED复位端口
        DC: 命令/数据选择端口(0:读写命令, 1: 读写数据)
        SCLK(D0):串口时钟线
        SDIN(D1): 串口数据线  
    4线SPI写操作时序图:
    1015113-20161022220343951-1342443939.png

    OLED的常用命令:
    1015113-20161022224907670-1419429774.png

    设置OLED显示内存的寻址方式:
    设置的命令:
    1015113-20161022233151763-1420300329.png

    0x00: 表示水平寻址方式
    1015113-20161022233516013-1817057104.png
      0x01: 表示垂直寻址方式
    1015113-20161022233541217-1750407964.png
      0x10: 表示页寻址方式(默认方式)
    1015113-20161022233602967-415313014.png
     stm32与OLED屏接口的引脚介绍:
          CS————GPIOD3;
          RST————GPIOD4;
          DC—————GPIOD5;
          D0——————GPIOD6;
          D1——————GPIOD7;

      程序代码:
          1.   相关宏定义
    1. #define OLED_CS(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_3):GPIO_ResetBits(GPIOD, GPIO_Pin_3)    //X为1时对应GPIO端口输出高电平,X为0时对应GPIO端口输出低电平

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

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

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

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


    6. #define OLED_Order 0     //定义写命令
    7. #define OLED_Data  1     //定义写数据
    复制代码
    2.  GPIO初始化代码:
    1. void OLED_GPIO_Init(void)
    2. {
    3.     GPIO_InitTypeDef GPIO_InitStruct;
    4.    
    5.     //开启GPIOD的时钟
    6.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
    7.     //设置GPIO的基本参数
    8.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    9.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出
    10.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    //输出速度50MHz
    11.    
    12.     GPIO_Init(GPIOD, &GPIO_InitStruct);
    13.    
    14.     GPIO_SetBits(GPIOD, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
    15. }
    复制代码
     3. SPI 写数据/命令
    1. /*        SPI写数据/命令
    2. *    Mode :O:写命令   1:写数据
    3. *    data :数据/命令
    4. *
    5. */
    6. void SPI_Write(char data, int Mode)
    7. {   
    8.     int i = 0;
    9.     if(Mode)
    10.     {
    11.         OLED_DC(1);        //DC引脚输入高,表示写数据
    12.     }
    13.     else
    14.     {
    15.         OLED_DC(0);        //DC引脚输入低,表示写命令
    16.     }
    17.     OLED_CS(0);            //CS引脚输入低,片选使能
    18.     for(i = 0; i < 8; i++)
    19.     {
    20.         OLED_D0(0);        //D0引脚输入低
    21.         if(data & 0x80)    //判断传输的数据最高位为1还是0
    22.         {
    23.             OLED_D1(1);    //D1引脚输入高
    24.         }
    25.         else
    26.         {
    27.             OLED_D1(0);    //D1引脚输入低
    28.         }
    29.         OLED_D0(1);        //D1引脚输入高
    30.         data <<= 1;        //将数据左移一位
    31.     }
    32.     OLED_DC(0);            //DC引脚输入低
    33.     OLED_CS(1);            //CS引脚输入高,片选失能
    34. }
    复制代码
    4. 设置OLED屏的显示坐标:
    1015113-20161022222221154-963719401.png

      例如:设置页地址为0xB2; 列地址的低4位为0x03,列地址的高4位为0x00;则显示的位置如下图:
    1015113-20161022234045763-1886402266.png

    代码:
    1. /*        设置OLED屏的显示坐标
    2. *      X : 表示OLED的水平坐标(0—127)
    3. *      Y : 表示OLED的页(0—7)
    4. *        
    5. */
    6. void OLED_Coord(unsigned char x, unsigned char y)
    7. {
    8.     SPI_Write((0xb0+(y & 0x0f)), OLED_Order);        //设置OLED显示的页   
    9.     SPI_Write((((x & 0xf0)>>4) | 0x10), OLED_Order);//设置OLED水平坐标的高4位
    10.     SPI_Write((x & 0x0f)|0x01, OLED_Order);                //设置OLED水平坐标的低4位
    11. }
    复制代码
      清除OLED的显示代码:
    1. /*
    2. *        清除OLED的显示
    3. *
    4. *
    5. */
    6. void OLED_Clear(void)
    7. {
    8.     int i = 0, j = 0;
    9.     for(i = 0; i < 8; i++)
    10.     {
    11.         OLED_Coord(0, i);
    12.         for(j = 0; j < 128; j++)
    13.         {
    14.             SPI_Write(0x00, OLED_Data);
    15.         }
    16.     }
    17. }
    复制代码
     关闭OLED显示代码:
    1. /*        关闭OLED显示
    2. *
    3. *
    4. */
    5. void OLED_Display_Off(void)
    6. {
    7.     //电荷泵设置(初始化时必须打开,否则看不到显示)
    8.     SPI_Write(0x8D, OLED_Order);
    9.     SPI_Write(0x10, OLED_Order);//bit2   0:关闭        1:打开
    10.     SPI_Write(0xAE, OLED_Order);//0xAE:关闭显示
    11. }
    复制代码
     开启OLED显示代码:
    1. /*
    2. *        开启OLED显示
    3. *
    4. */
    5. void OLED_Display_On(void)
    6. {
    7.     //电荷泵设置(初始化时必须打开,否则看不到显示)
    8.     SPI_Write(0x8D, OLED_Order);
    9.     SPI_Write(0x14, OLED_Order);//bit2   0:关闭        1:打开
    10.     SPI_Write(0xAF, OLED_Order);//0xAF:开显示   
    11. }
    复制代码
    OLED显示的参数的初始化:
          1. 在设置OLED的参数时,并不需要把所有的参数都设置一次;有些参数是默认的(可以不进行设置),只是需要设置一写必要的参数;
            (如:0xAF: 开显示, 0x8D:电荷泵设置(初始化是必须打开,否则看不到显示))
          2.代码(初始化代码中,介绍了大部分命令):
    1. /*        OLED显示参数的初始化
    2. *
    3. *
    4. *
    5. */
    6. void OLED_Init(void)
    7. {
    8.     OLED_GPIO_Init();
    9.    
    10.     OLED_RST(1);
    11.     delay_ms(100);
    12.     OLED_RST(0);
    13.     delay_ms(100);
    14.     OLED_RST(1);
    15.    
    16.     SPI_Write(0xAE, OLED_Order);//0xAE:关显示   
    17.    
    18.     SPI_Write(0x00, OLED_Order);//设置低列地址
    19.     SPI_Write(0x10, OLED_Order);//设置高列地址
    20.    
    21.     //设置行显示的开始地址(0-63)
    22.     //40-47: (01xxxxx)
    23.     SPI_Write(0x40, OLED_Order);
    24.    
    25.     //设置对比度
    26.     SPI_Write(0x81, OLED_Order);
    27.     SPI_Write(0xff, OLED_Order);//这个值越大,屏幕越亮(和上条指令一起使用)(0x00-0xff)
    28.    
    29.     SPI_Write(0xA1, OLED_Order);//0xA1: 左右反置,  0xA0: 正常显示(默认0xA0)
    30.     SPI_Write(0xC8, OLED_Order);//0xC8: 上下反置,  0xC0: 正常显示(默认0xC0)
    31.    
    32.     //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
    33.     //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
    34.     SPI_Write(0xA6, OLED_Order);
    35.    
    36.     SPI_Write(0xA8, OLED_Order);//设置多路复用率(1-64)
    37.     SPI_Write(0x3F, OLED_Order);//(0x01-0x3f)(默认为3f)
    38.    
    39.    
    40.     //设置显示抵消移位映射内存计数器
    41.     SPI_Write(0xD3, OLED_Order);
    42.     SPI_Write(0x00, OLED_Order);//(0x00-0x3f)(默认为0x00)
    43.    
    44.     //设置显示时钟分频因子/振荡器频率
    45.     SPI_Write(0xD5, OLED_Order);
    46.     //低4位定义显示时钟(屏幕的刷新时间)(默认:0000)分频因子= [3:0]+1
    47.     //高4位定义振荡器频率(默认:1000)
    48.     SPI_Write(0x80, OLED_Order);//
    49.    
    50.     //时钟预充电周期
    51.     SPI_Write(0xD9, OLED_Order);
    52.     SPI_Write(0xF1, OLED_Order);//[3:0],PHASE 1;   [7:4] PHASE 2
    53.    
    54.     //设置COM硬件应脚配置
    55.     SPI_Write(0xDA, OLED_Order);
    56.     SPI_Write(0x12, OLED_Order);//[5:4]  默认:01
    57.    
    58.     SPI_Write(0xDB, OLED_Order);//
    59.     SPI_Write(0x40, OLED_Order);//
    60.    
    61.     //设置内存寻址方式
    62.     SPI_Write(0x20, OLED_Order);
    63.     //00: 表示水平寻址方式
    64.     //01: 表示垂直寻址方式
    65.     //10: 表示页寻址方式(默认方式)
    66.     SPI_Write(0x02, OLED_Order);//   
    67.    
    68.     //电荷泵设置(初始化时必须打开,否则看不到显示)
    69.     SPI_Write(0x8D, OLED_Order);
    70.     SPI_Write(0x14, OLED_Order);//bit2   0:关闭        1:打开
    71.    
    72.     //设置是否全部显示 0xA4: 禁止全部显示
    73.     SPI_Write(0xA4, OLED_Order);

    74.     //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
    75.     //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
    76.     SPI_Write(0xA6, OLED_Order);//
    77.    
    78.     SPI_Write(0xAF, OLED_Order);//0xAF:开显示
    79.    
    80.     SPI_Write(0xAF, OLED_Order);//0xAF:开显示
    81.    
    82.     OLED_Clear();
    83. }
    复制代码
    显示16*16的汉字函数代码:
    1. /*        显示汉字
    2. *        x:表示显示的水平坐标
    3. *        y: 表示显示的垂直坐标
    4. *        *p: 表示要显示汉字模组的首地址
    5. */
    6. void OLED_ShowChinese(int x, int y, const unsigned char *p)
    7. {
    8.     int i = 0;
    9.     OLED_Coord(x, y);
    10.     for(i = 0; i < 32; i+=2)
    11.     {
    12.         SPI_Write(p[i], OLED_Data);
    13.     }
    14.     OLED_Coord(x, y+1);
    15.     for(i = 1; i < 32; i+=2)
    16.     {
    17.         SPI_Write(p[i], OLED_Data);
    18.     }
    19. }
    复制代码
    显示ASCII码的函数代码:
    1. /*        显示ASCII
    2. *        x:表示显示的水平坐标
    3. *        y: 表示显示的垂直坐标
    4. *        *p: 表示要显示汉字模组的首地址
    5. */
    6. void OLED_ShowChar(int x, int y, const unsigned char *p)
    7. {
    8.     int i = 0;
    9.     OLED_Coord(x, y);
    10.     for(i = 0; i < 16; i+=2)
    11.     {
    12.         SPI_Write(p[i], OLED_Data);
    13.     }
    14.     OLED_Coord(x, y+1);
    15.     for(i = 1; i < 16; i+=2)
    16.     {
    17.         SPI_Write(p[i], OLED_Data);
    18.     }
    19. }
    复制代码
    注意1:在使用PCtoLCD2002完美版进行取模时,如果取模的字高大于8时一定要注意;
          如果字高16;取模的顺序是:从第一列开始,前8个点为第一个字节,后8个点为第二个字节
         然后第二列取模,前8个点为第三个字节,后8个点为第四个字节,以此类推,而OLED屏的内存
        寻址方式为0x10: 表示页寻址方式(默认方式)时,那么显示时将会乱码;因为是按页来显示的,
         那么第一个字节显示在第一列,而第二个字节本应该显示在第二页的第一列,而被错误的显示在第一页的第二列,以此类推,导致显示乱码;
          (这就是为什么OLED_ShowChar()函数和OLED_ShowChinese()函数中, 前面先显示数组下标为偶数的数组, 后面显示数组下标为奇数的数组)
    1015113-20161022232939232-226759742.png

    OLED显示的main函数代码:
    1. int main(void)
    2. {
    3.     SysTick_Init();
    4.     OLED_Init();
    5.    
    6.     OLED_ShowChinese(0, 0, xing);//‘姓’   
    7.     OLED_ShowChinese(18, 0, ming);//‘名’
    8.     OLED_ShowChar(36, 0, ASCII_Colon);//‘:’
    9.     OLED_ShowChinese(0, 2, xue);//‘学’   
    10.     OLED_ShowChinese(18, 2, hao);//‘号’
    11.     OLED_ShowChar(36, 2, ASCII_Colon);//‘:’   
    12. //    SPI_Write(0x2F, OLED_Order);    //0x2F:激活滚动        0x2E:关闭滚动
    13. //    //设置滚动方式:
    14. //    //        0x26/0x27        :水平滚动(右向/左向)
    15. //    //        0x29/0x2A        :水平和垂直滚动(右向/左向)
    16. //    //        0xA3            :垂直滚动
    17. //    SPI_Write(0x27, OLED_Order);   
    18. //    SPI_Write(0x00, OLED_Order);
    19. //    SPI_Write(0x00, OLED_Order);
    20. //    SPI_Write(0x00, OLED_Order);
    21. //    SPI_Write(0x03, OLED_Order);
    22. //    SPI_Write(0x30, OLED_Order);   
    23.     while(1);
    复制代码
      注意:在使用滚动命令时,一定要先写入0x2F, 激活滚动
        取模数组:
    1. const unsigned char xing[]=
    2. {    0x10,0x40,0x10,0x22,0xF0,0x15,0x1F,0x08,
    3.     0x10,0x16,0xF0,0x21,0x40,0x40,0x3C,0x42,
    4.     0x10,0x42,0x10,0x42,0xFF,0x7F,0x10,0x42,
    5.     0x10,0x42,0x10,0x42,0x00,0x40,0x00,0x00};/*"姓",0*/
    6. const unsigned char A[]=
    7. {    0x00,0x20,0x00,0x3C,0xC0,0x23,0x38,0x02,
    8.     0xE0,0x02,0x00,0x27,0x00,0x38,0x00,0x20};/*"A",0*/
    9. const unsigned char ming[]=
    10. {    0x00,0x04,0x20,0x04,0x20,0x04,0x10,0x02,
    11.     0x08,0xFE,0x14,0x43,0x67,0x43,0x84,0x42,
    12.     0x44,0x42,0x24,0x42,0x14,0x42,0x0C,0x42,
    13.     0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00};/*"名",0*/
    14. const unsigned char ASCII_Colon[]=
    15. {    0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,
    16.     0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00};/*":",0*/   
    17. const unsigned char xue[]=
    18. {    0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,
    19.     0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
    20.     0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,
    21.     0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00};/*"学",0*/
    22. const unsigned char hao[]=
    23. {    0x80,0x00,0x80,0x00,0x80,0x00,0xBE,0x06,
    24.     0xA2,0x05,0xA2,0x04,0xA2,0x04,0xA2,0x04,
    25.     0xA2,0x44,0xA2,0x84,0xA2,0x44,0xBE,0x3C,
    26.     0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00};/*"号",0*/
    复制代码
          OLED的命令基本上已经在上面介绍,还有一些屏幕显示滚动的命令;本人没有进行一一实验;
       实验现象:

    1015113-20161023081706951-1616757005.png

    转自网络


    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2017-8-3 10:07
  • 签到天数: 3 天

    连续签到: 3 天

    [LV.2]偶尔看看I

    发表于 2017-8-2 18:54:08 | 显示全部楼层
    正在学习32~~~~~~~~~~~~~~~~~~~赞一个
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2021-2-27 22:16
  • 签到天数: 1568 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    发表于 2017-12-24 14:47:44 | 显示全部楼层
    赞的,小实验不错
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-11-25 00:05 , Processed in 0.150329 second(s), 22 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.