详细的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()函数中, 前面先显示数组下标为偶数的数组, 后面显示数组下标为奇数的数组)

oled的一套stm32实验1的更多相关文章

  1. oled的一套stm32实验2(自己的实验)

    stm32与OLED屏接口的引脚介绍: CS————GPIOD3: RST————GPIOD4: DC—————GPIOD5: D0——————GPIOD6: D1——————GPIOD7; 上是我参 ...

  2. STM32实验非正式报告之DMA

    前言 DMA即直接内存存取.我理解它就是一个“交通部长”抑或是一个“搬运工”,协助CPU存储或读取数据.既然它的主要工作就是“搬运”数据,服务对象自然就是内存(不太严格的说法吧,STM32中Flash ...

  3. 嵌入式02 STM32 实验01 端口复用和重映射

    内设与外设: 端口复用和端口重映射都需要了解内设和外设,那么什么是内设?什么是外设? 内设:单片机内部集成的功能一般包括:串口模块.SPI模块(Serial Peripheral Interface  ...

  4. 嵌入式02 STM32 实验04跑马灯

    开学STM32 跑马灯的实验主要就是了解GPIO口的配置及使用,我这里是使用库函数进行编程,主要需要设置以下两方面: 1.使能需要使用的IO口的时钟,一共有A.B.C.D.E.F.G七组IO口 2.初 ...

  5. 嵌入式02 STM32 实验11 NVIC和中断总结

    一.基础知识 1.cortex-m3支持256个中断,其中包含了16个内核中断,240个外部中断 2.STM32只有84个中断,包括16个内核中断和68个可屏蔽中断 3.STM32F103上只有60个 ...

  6. 嵌入式02 STM32 实验10 定时器中断

    优秀文章 https://blog.csdn.net/qq_38351824/article/details/82619734 一.STM32通用定时器(TIM2.TIM3.TIM4和TIM5共四个通 ...

  7. 嵌入式02 STM32 实验08 外部中断

    一.中断 由于某个事件的发生,CPU暂停当前正在执行的程序,转而执行处理事件的一个程序.该程序执行完成后,CPU接着执行被暂停的程序.这个过程称为中断.(我正在捉泥鳅,但是我妈喊我回家吃饭,我必须回家 ...

  8. 嵌入式02 STM32 实验07 串口通信

    STM32串口通信(F1系列包含3个USART和2个UART) 一.单片机与PC机串行通信研究目的和意义: 单片机自诞生以来以其性能稳定,价格低廉.功能强大.在智能仪器.工业装备以及日用电子消费产品中 ...

  9. 嵌入式02 STM32 实验06 按键

    按键实验和前面的跑马灯.蜂鸣器主要的区别就是这个是读取外部的输入信号,之前的实验都是对外部输出信号. 一.硬件设计 本实验的硬件为三个按键.两个lED(LED0.LED1).一个蜂鸣器(BEEP). ...

随机推荐

  1. Add Webhooks to Your API the Right Way

    Add Webhooks to Your API the Right Way Adam DuVander / December 15, 2016 In the last 10 years, APIs ...

  2. ArcGIS 空间查询一例

    ISpatialFilter spatialFilter = new SpatialFilterClass(); spatialFilter.Geometry = Polygon ;//设置用于筛选几 ...

  3. 11.2.0.1升级到11.2.0.4报错之中的一个:UtilSession failed: Patch 9413827

    UtilSession failed: Patch 9413827 requires component(s) that are not installed in OracleHome. These ...

  4. leetcode 链表 Partition List

    Partition List Total Accepted: 19761 Total Submissions: 73252My Submissions Given a linked list and ...

  5. SWTBOK測试实践系列(1) -- 測试在项眼下期的评审投入划算吗?

    測试策略:静态測试还是动态測试? [对话场景] 成功公布某个软件版本号之后,项目团队召开了项目的经验教训总结大会.在会议期间,项目经理小项和測试经理小測进行了例如以下的对话: 小项:"小測, ...

  6. php实现简单算法3

    php实现简单算法3 这篇文章主要介绍了PHP经典算法集锦,整理了各种常见的算法,包括排序.查找.遍历.运算等各种常见算法原理与实现技巧,需要的朋友可以参考下 1.首先来画个菱形玩玩,很多人学C时在书 ...

  7. 41.内存函数实现(memcpy,memset,memmove,memicmp,memchr.memccpy)

    memcpy #include <stdio.h> #include <stdlib.h> #include <memory.h> void * mymemcpy( ...

  8. janos.io

    http://janos.io/ https://developer.mozilla.org/en-US/Firefox_OS/Developing_Firefox_OS/Porting

  9. html页面中块级元素的居中

    第一:在页面中使用 margin: 0 auto;居中: <div> <p>夜屋</p> </div> div { width: 100%; posit ...

  10. 清除celery 任务队列

    celery 有密码的时候 清除任务 redis-cli -h host -p port -a password -n 11 ltrim transcode 0 196 没有密码的时候 redis-c ...