• 03 OLED显示屏实现


    前言

    这一章主要是上一节没有讲完的项目的一个编写,上一章我们说道单片机的输入和输出,包括四种单片机与外设之间的数据交换使用到的方式,这一章就利用前面说到的这几种方式来编写一个OLED显示屏的驱动。

    一、软件模拟IIC协议

    这使用的OLED屏幕是用的4引脚IIC协议的,在编写相关代码之前我们需要先了解一下什么是IIC协议,在单片机中,IIC通常指的是Inter-Integrated Circuit,也称为I2C(Inter-Integrated Circuit)总线,它是一种用于在集成电路之间进行通信的串行通信协议。

    I2C总线由飞利浦公司(现在的恩智浦半导体公司)开发,用于在数字集成电路之间进行通信。它通常用于连接微控制器和外部设备,如传感器、存储器、扩展模块等。

    I2C总线使用两根线进行通信:串行数据线(SDA)和串行时钟线(SCL)。通过这两根线,多个设备可以在同一总线上进行通信。每个设备都有一个唯一的地址,因此可以通过地址来选择要通信的特定设备。

    I2C总线采用主从结构,主设备负责发起通信并控制总线,而从设备则响应主设备的命令。这种通信协议简单而灵活,适用于连接多种类型的设备。

    简单来说IIC协议就是一种串行通讯协议,我们只需要对两根数据线进行操作就可以了,在32中有对应的IIC的函数库,我们可以直接调用来实现,但是那个内容我安排在后面了,我们实现先学习上一节用输入和输出来进行模拟的方式,学习完后我们才可以用一些传感器来观察效果并实现更高级的内容。

    1.开启IIC协议

    我们在使用IIC协议之前需要发送一个开始信号的,这个开始信号的时序图如下:

    3.png

    可以看到左边是起始条件,我们要开启IIC协议必须得先发送其实条件,这里的代码很容易就可以编写,这里我用了一下宏定义和位操作:

    void IIC_Start(void){
        GPIO_SetBits(GPIO, SDA);
        GPIO_SetBits(GPIO, SCL);
        GPIO_ResetBits(GPIO, SDA);
        GPIO_ResetBits(GPIO, SCL);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这个函数就可以让IIC协议开始,当开始后我们就可以参数数据和一些命令了。

    2.结束IIC协议

    当一条IIC协议传输完成后需要发送一条协议结束信号,这个信号的写法也很简单,代码如下:

    void IIC_Stop(void){
        GPIO_ResetBits(GPIO, SDA);
        GPIO_SetBits(GPIO, SCL);
        GPIO_SetBits(GPIO, SDA);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这样就可以结束上一次的IIC数据传输。

    3.传输数据

    这个的时序图也可以参考上面的时序图

    3.png

    看中间的位置,这个位置就是传输一位数据时的时序图,那么我们就可以根据这个图写出传输一个字节的数据了,这里需要注意一下,我们传输一条字节数据时是需要先传递高位数据,在SCL从高电平到低电平的时候才会将数据传递过去,代码如下:

    void IIC_WriteBit(u8 byte){
        u8 i;
        for (i = 0; i < 8; i++){
            if (byte & 0x80){
                GPIO_SetBits(GPIO, SDA);
            }
            else{
                GPIO_ResetBits(GPIO, SDA);
            }
            byte <<= 1;
            GPIO_SetBits(GPIO, SCL);
            GPIO_ResetBits(GPIO, SCL);
        }
        // 跳过一个ACK信号
        GPIO_SetBits(GPIO, SCL);
        GPIO_ResetBits(GPIO, SCL);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    这里就是向IIC传递一个字节数据的函数,最后这里写了一个跳过ACK响应,这个ACK响应是什么呢?

    我们可以看这个时序图:

    3.jpg

    可以看到WORD数据后有一个ACK信号,这个ACK信号是响应信号,就是当我们数据传递到IIC设备后,它如果接受到数据后就会发送一个接受信号,这个就是接受信号,我们不需要这个信号,所以直接忽略即可。

    好了,模拟IIC的操作就是这些了,下面我们就介绍一下OLED的操作了。

    二、OLED的操作

    1.传输数据的准备

    在用IIC协议向OLED传输数据前需要做的操作有下面这几步,我们只有操作好了才能正确的传输命令或者数据:

    1.开启IIC协议

    2.向OLED传入从地址

    3.传输是写入的是命令还是数据

    4.开始传输数据

    5.结束IIC协议

    在传输数据或者命令之前要先向OLED传入它的地址,相当于一个片选,当选中了才可以进行操作,每个OLED的地址都是固定的,都是为0x78,如果要更改需要联系厂家

    4.png

    这个就是时序图,在右边的SSD1306 Slave Address就是它的地址,我们就将这个先传入即可,在下面的写入命令会有这个代码。

    然后就是传入是数据还是命令,在words这个数据块中可以告诉你该如何传入,第一个Co不用管,默认0皆可,然后第二个是选择命令还是数据,1是数据,0是命令,所以就可以得到下面的内容,当我们要写命令的时候,传入完地址后再传入0x00。如果要写数据得到的时候,要传入0x40

    2.写入命令

    知道了上面的过程后我们就可以写写入命令的函数了:

    void write_command(u8 cmd){
        IIC_Start();        // 开启IIC协议
        IIC_Write(0x78);    // 传入地址
        IIC_Write(0x00);    // 传入0x00代表要传入命令
        IIC_Write(cmd);     // 传入命令
        IIC_Stop();         // 结束IIC协议
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这样就完成了一次写入命令。

    3.写入数据

    写入数据的函数和上面的函数一样,只不过就是传入地址后传入的内容不同:

    void write_data(u8 data){
        IIC_Start();
        IIC_Write(0x78);
        IIC_Write(0x40);
        IIC_Write(data);
        IIC_Stop();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这样就可以完成一次数据的传送。

    这些基础功能讲完了,后面的操作是需要结合命令列表来进行操作了。

    4.初始化函数

    首先我们要操作需要先进行初始化,这里初始化的功能不会全部说明,大家如果有问题可以查一下OLED的数据手册即可。

    初始化传入的命令步骤如下:

    1. 关闭显示屏

    2. 设置显示时钟分频比/振荡器频率

    3. 设置多路复用率

    4. 显示开始行

    5. 设置左右方向

    6. 设置上下方向

    7. 设置COM引脚硬件配置

    8. 设置对比度

    9. 设置预充电周期

    10. 设置VCOMH取消选择级别

    11. 设置整个显示打开/关闭

    12. 设置正常/倒转显示

    13. 设置充电泵

    14. 开启显示

    这个内容需要查看手册来慢慢写,我这里就不一个一个介绍了,我这写好了,你们可以直接复制和粘贴

    #define CMD 0x00
    #define DATA 0x40
    #define CLOSESHOW 0xAE
    #define SETCLS 0xD5
    #define RATE    0xA8
    #define OFFSET  0xD3
    #define START   0x40
    #define LEFTRIG 0xA1
    #define UPDOWN  0xC8
    #define HARD    0xDA
    #define RATION  0x81
    #define  CYCLE  0xD9
    #define VCOM    0xDB
    #define SHOWUP  0xA4
    #define BEN     0x8D
    #define SHOWOK  0xAF
    void OLED_Init(){
        write_command(CLOSESHOW);
        write_command(SETCLS);
        write_command(0x80);
        write_command(RATE);
        write_command(0x3F);
        write_command(OFFSET);
        write_command(0x00);
        write_command(START);
        write_command(LEFTRIG);
        write_command(UPDOWN);
        write_command(HARD);
        write_command(0x12);
        write_command(RATION);
        write_command(0xCF);
        write_command(CYCLE);
        write_command(0xF1);
        write_command(VCOM);
        write_command(0x30);
        write_command(SHOWUP);
        write_command(0xA6);
        write_command(BEN);
        write_command(0x14);
        write_command(SHOWOK);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    5.设置光标

    在屏幕中有一个光标,只不过我们在初始化的时候就把这个光标给隐藏了,但是你要有这个概念,设置光标也是需要使用命令来进行操作,这里也需要参考一下命令手册,但是,我这已经写好了,直接用就可以了:

    void set_currsor(u8 row, u8 col){
        write_command(0xB0 |row);
        write_command(0x10 | ((col & 0xF0) >> 4));
        write_command(0x00 | (col & 0x0F));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    row就是光标所在的行,col是光标所在的列。

    6.显示字符

    要让OLED显示字符需要使用到取摸3工具取出来,因为我们显示其实就是让那些液晶块亮,哪些不亮,所以需要取摸,这里我没找到Linux下的取摸工具,等后面我有时间后我写一个,然后下面是我之前取好的ASCII后32个字符对应的字摸,大家可以直接拿来用:

    static unsigned char ASCII1[][16] = {
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
    
    {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00},/*"!",0*/
    
    {0x00,0x10,0x0C,0x02,0x10,0x0C,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",1*/
    
    {0x00,0x40,0xC0,0x78,0x40,0xC0,0x78,0x00,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x00},/*"#",2*/
    
    {0x00,0x70,0x88,0x88,0xFC,0x08,0x30,0x00,0x00,0x18,0x20,0x20,0xFF,0x21,0x1E,0x00},/*"$",3*/
    
    {0xF0,0x08,0xF0,0x80,0x60,0x18,0x00,0x00,0x00,0x31,0x0C,0x03,0x1E,0x21,0x1E,0x00},/*"%",4*/
    
    {0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x2C,0x19,0x27,0x21,0x10},/*"&",5*/
    
    {0x00,0x12,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",6*/
    
    {0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},/*"(",7*/
    
    {0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},/*")",8*/
    
    {0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},/*"*",9*/
    
    {0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x0F,0x01,0x01,0x01},/*"+",10*/
    
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x70,0x00,0x00,0x00,0x00,0x00},/*",",11*/
    
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x00},/*"-",12*/
    
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},/*".",13*/
    
    {0x00,0x00,0x00,0x00,0xC0,0x38,0x04,0x00,0x00,0x60,0x18,0x07,0x00,0x00,0x00,0x00},/*"/",14*/
    
    {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",0*/
    
    {0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00},/*"1",1*/
    
    {0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",2*/
    
    {0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00},/*"3",3*/
    
    {0x00,0x00,0x80,0x40,0x30,0xF8,0x00,0x00,0x00,0x06,0x05,0x24,0x24,0x3F,0x24,0x24},/*"4",4*/
    
    {0x00,0xF8,0x88,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x20,0x20,0x20,0x11,0x0E,0x00},/*"5",5*/
    
    {0x00,0xE0,0x10,0x88,0x88,0x90,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x20,0x1F,0x00},/*"6",6*/
    
    {0x00,0x18,0x08,0x08,0x88,0x68,0x18,0x00,0x00,0x00,0x00,0x3E,0x01,0x00,0x00,0x00},/*"7",7*/
    
    {0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},/*"8",8*/
    
    {0x00,0xF0,0x08,0x08,0x08,0x10,0xE0,0x00,0x00,0x01,0x12,0x22,0x22,0x11,0x0F,0x00},/*"9",9*/
    
    {0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},/*":",0*/
    
    {0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00},/*";",1*/
    
    {0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00},/*"<",2*/
    
    {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x00},/*"=",3*/
    
    {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00},/*">",4*/
    
    {0x00,0x70,0x48,0x08,0x08,0x88,0x70,0x00,0x00,0x00,0x00,0x30,0x37,0x00,0x00,0x00},/*"?",5*/
    
    {0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x28,0x2F,0x28,0x17,0x00},/*"@",6*/
    
    {0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20},/*"A",0*/
    
    {0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},/*"B",1*/
    
    {0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},/*"C",2*/
    
    {0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},/*"D",3*/
    
    {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},/*"E",4*/
    
    {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},/*"F",5*/
    
    {0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},/*"G",6*/
    
    {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},/*"H",7*/
    
    {0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"I",8*/
    
    {0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},/*"J",9*/
    
    {0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},/*"K",10*/
    
    {0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},/*"L",11*/
    
    {0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x01,0x3E,0x01,0x3F,0x20,0x00},/*"M",12*/
    
    {0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},/*"N",13*/
    
    {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},/*"O",14*/
    
    {0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},/*"P",15*/
    
    {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x28,0x28,0x30,0x50,0x4F,0x00},/*"Q",16*/
    
    {0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},/*"R",17*/
    
    {0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},/*"S",18*/
    
    {0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"T",19*/
    
    {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"U",20*/
    
    {0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},/*"V",21*/
    
    {0x08,0xF8,0x00,0xF8,0x00,0xF8,0x08,0x00,0x00,0x03,0x3E,0x01,0x3E,0x03,0x00,0x00},/*"W",22*/
    
    {0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},/*"X",23*/
    
    {0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"Y",24*/
    
    {0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},/*"Z",25*/
    
    {0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00},/*"[",0*/
    
    {0x00,0x04,0x38,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00},/*"\",1*/
    
    {0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00},/*"]",2*/
    
    {0x00,0x00,0x04,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",3*/
    
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},/*"_",4*/
    
    {0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",5*/
    
    {0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x19,0x24,0x24,0x12,0x3F,0x20,0x00},/*"a",0*/
    
    {0x10,0xF0,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"b",1*/
    
    {0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},/*"c",2*/
    
    {0x00,0x00,0x80,0x80,0x80,0x90,0xF0,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},/*"d",3*/
    
    {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x24,0x24,0x24,0x24,0x17,0x00},/*"e",4*/
    
    {0x00,0x80,0x80,0xE0,0x90,0x90,0x20,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"f",5*/
    
    {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},/*"g",6*/
    
    {0x10,0xF0,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"h",7*/
    
    {0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"i",8*/
    
    {0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},/*"j",9*/
    
    {0x10,0xF0,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x06,0x29,0x30,0x20,0x00},/*"k",10*/
    
    {0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"l",11*/
    
    {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},/*"m",12*/
    
    {0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"n",13*/
    
    {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"o",14*/
    
    {0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0x91,0x20,0x20,0x11,0x0E,0x00},/*"p",15*/
    
    {0x00,0x00,0x00,0x80,0x80,0x00,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0x91,0xFF,0x80},/*"q",16*/
    
    {0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},/*"r",17*/
    
    {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},/*"s",18*/
    
    {0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x10,0x00},/*"t",19*/
    
    {0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},/*"u",20*/
    
    {0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x03,0x0C,0x30,0x0C,0x03,0x00,0x00},/*"v",21*/
    
    {0x80,0x80,0x00,0x80,0x80,0x00,0x80,0x80,0x01,0x0E,0x30,0x0C,0x07,0x38,0x06,0x01},/*"w",22*/
    
    {0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x20,0x31,0x0E,0x2E,0x31,0x20,0x00},/*"x",23*/
    
    {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x81,0x86,0x78,0x18,0x06,0x01,0x00},/*"y",24*/
    
    {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},/*"z",25*/
    };
    
    static unsigned char number1[][16] = {
    {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",0*/
    
    {0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00},/*"1",1*/
    
    {0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",2*/
    
    {0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00},/*"3",3*/
    
    {0x00,0x00,0x80,0x40,0x30,0xF8,0x00,0x00,0x00,0x06,0x05,0x24,0x24,0x3F,0x24,0x24},/*"4",4*/
    
    {0x00,0xF8,0x88,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x20,0x20,0x20,0x11,0x0E,0x00},/*"5",5*/
    
    {0x00,0xE0,0x10,0x88,0x88,0x90,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x20,0x1F,0x00},/*"6",6*/
    
    {0x00,0x18,0x08,0x08,0x88,0x68,0x18,0x00,0x00,0x00,0x00,0x3E,0x01,0x00,0x00,0x00},/*"7",7*/
    
    {0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},/*"8",8*/
    
    {0x00,0xF0,0x08,0x08,0x08,0x10,0xE0,0x00,0x00,0x01,0x12,0x22,0x22,0x11,0x0F,0x00},/*"9",9*/
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205

    然后根据这个字摸,我们可以显示字符了,这里写一个显示字符的函数:

    void show_char(u8 row, u8 col, u8 charr){
        u8 i;     // 遍历变量
        set_currsor(row, col + 8);    // 设置显示位置
        for (i = 0; i < 8; i++){
            IIC_Write(ASCII1[charr - 32][i]);
        }
        set_currsor(row + 1, col + 8);  // 设置下一行显示的位置
        for (i = 0; i < 8; i++){
            IIC_Write(ASCII1[charr - 32][i + 8]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    字摸的长度是16位,而我们显示的这个ASCII是8*8大小的,我们在第一次设置光标的时候要加上8是为了错过前面的一个字符,然后在显示字符的时候选择的是逐列式。

    也就是先将第一个字节的字摸先显示,然后转到下一列再显示第二个字摸,依次下去,这样如果只有一半,也就是只有4*8,还需要转到下一行补上那4行才可以变成8*8。

    在写这个函数的时候,我发现了一个好玩的,我这如果让列不跳过一个字符,而是跳过一位,那这个字符就会扭动,虽然没有什么用,但是感觉很有趣,代码如下,大家可以来试试:

    // 扭动字符显示
    // 只能显示一个,显示多个就不流畅了
    void show_Twistchar(u8 row, u8 col, u8 word){
        u8 i;
        set_currsor(row, col * 8);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i]);
        }
        set_currsor(row + 1, col * 8);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i + 8]);
        }
        // 下面这些可以删掉,然后在主函数调用的时候调用两遍,要一样的字符
        delay_us(5); 
        set_currsor(row, col * 8 + 1);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i]);
        }
        set_currsor(row + 1, col * 8 + 1);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i + 8]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    7.显示字符串

    这个就得看大家对于串操作的熟练程度了,就是用到对字符串的操作,但是呢,这个需要考虑到换行,代码如下:

    void show_string(u8 row, u8 col, u8* str){
        u8 i, j = 0;
        for (i = 0; str[i] != '\0'; i++, j++){
            if (j >= 16){
                row += 1;
                col = 0;
                j = 0;
            }
            show_char(row, col + j, str[i]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这里我用一个变量作为判断条件,因为一行有128个像素点,我们显示8*8的字符,那一行只能显示16个8*8的字符,所以当j变量到了16个字符,我们就让行换一行,列清零,这样就可以实现换行操作了。

    8.清屏

    这个操作很简单,就是将每一行和每一列的所有像素点全部变为0x00就可以了,代码如下:

    void clear(){
        u8 i, j;
        for (i = 0; i < 8; i++){
            set_currsor(i, 0);
            for (j = 0; j < 128; j++){
                write_data(0x00);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    9.显示汉字

    这个也是需要使用取摸得到,然后每个汉字是16*16的点阵,我们只需要显示即可:

    // 现实汉字
    void show_hz(u8 row, u8 col, u8 len){
        u8 i, j, x, y;
        y = row;
        x = col;
        for (j = 0; j < len * 2; j += 2, y+= 2){
            if ((x + y) * 8 >= 128){
                y = 0;
                row = 2;
            }
            set_currsor(row, (x + y) * 8);
            for (i = 0; i < 16; i++){
                write_data(hz[j][i]);
            }
            set_currsor(row + 1, (x + y) * 8);
            for (i = 0; i < 16; i++){
                write_data(hz[j + 1][i]);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这个也是可以自动换行的,但在使用前需要将字摸放入到hz这个数组中,这个数组的格式如下:

    static unsigned char hz[][16] = {
    	{0x20,0x24,0x24,0x24,0xFE,0x23,0x22,0x20,0x20,0xFF,0x20,0x22,0x2C,0xA0,0x20,0x00},
    	{0x00,0x08,0x48,0x84,0x7F,0x02,0x41,0x40,0x20,0x13,0x0C,0x14,0x22,0x41,0xF8,0x00},/*"我",0*/
    
    	{0x00,0x80,0x60,0xF8,0x07,0x00,0xF8,0x01,0x06,0x00,0x04,0x04,0x04,0xFC,0x00,0x00},
    	{0x01,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00},/*"们",1*/
    
    	{0x20,0x24,0x24,0xA4,0x7F,0x24,0x34,0x28,0x26,0x20,0xFE,0x02,0x22,0xDA,0x06,0x00},
    	{0x04,0x02,0xFF,0x49,0x49,0x49,0x49,0xFF,0x00,0x00,0xFF,0x08,0x10,0x08,0x07,0x00},/*"都",2*/
    
    	{0x04,0x04,0x04,0x84,0xE4,0x3C,0x27,0x24,0x24,0x24,0x24,0xE4,0x04,0x04,0x04,0x00},
    	{0x04,0x02,0x01,0x00,0xFF,0x09,0x09,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00,0x00},/*"有",3*/
    
    	{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00},
    	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"一",4*/
    
    	{0x80,0x80,0x40,0x20,0x10,0x08,0x04,0xC3,0x04,0x08,0x10,0x20,0x40,0x80,0x80,0x00},
    	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"个",5*/
    
    	{0x40,0x44,0x24,0x14,0x7F,0x94,0x24,0x00,0x24,0x14,0x7F,0x14,0x24,0x44,0x40,0x00},
    	{0x00,0x80,0x88,0x84,0x42,0x45,0x29,0x11,0x11,0x09,0x05,0x03,0x00,0x00,0x00,0x00},/*"梦",6*/
    
    	{0x00,0x08,0x88,0x68,0xFF,0x48,0x88,0x00,0xFE,0x52,0x52,0x52,0xFE,0x00,0x00,0x00},
    	{0x40,0x31,0x00,0x00,0x3B,0x40,0x40,0x44,0x5B,0x42,0x42,0x72,0x03,0x08,0x30,0x00},/*"想",7*/
    
    	{0x00,0x08,0x88,0x68,0xFF,0x48,0x88,0x00,0xFE,0x52,0x52,0x52,0xFE,0x00,0x00,0x00},
    	{0x40,0x31,0x00,0x00,0x3B,0x40,0x40,0x44,0x5B,0x42,0x42,0x72,0x03,0x08,0x30,0x00},/*"想",7*/
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    这里面有一些测试的汉字,大家可以测试一下。

    10.显示图片

    显示图片的代码我没有写,其实和显示字符和汉字一样,然后用取摸工具取出,然后看一下行有多少,列有多少,然后显示即可,这里我后面写完后会放入gitee上的,github的话因为我最近资金不足,所以没工具,懂得都懂。

    11.显示动图

    这个其实和GIF的原理一样,图片上覆盖图片,这样就会让图片动起来。

    三、完整代码

    我这个项目是分文件编写的,分为oled.c函数原型,oled.h函数声明和头文件引入,oledfont.h这个是字符库,sys.c是延时函数和系统操作,gpio.h是gpio口的初始化函数的声明

    // gpio.c
    #include "gpio.h"
    
    void MX_GPIOInit(){
        GPIO_InitTypeDef GPIO_InitStruct = {0};
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
        GPIO_InitStruct.GPIO_Pin = CLK;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIO, &GPIO_InitStruct);
    
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
        GPIO_InitStruct.GPIO_Pin = SDA;
        GPIO_Init(GPIO, &GPIO_InitStruct);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    // gpio.h
    #ifndef __GPIO_H
    #define __GPIO_H
    
    #include "stm32f10x.h"
    
    #define CLK GPIO_Pin_8
    #define SDA GPIO_Pin_9
    #define GPIO GPIOB
    
    void MX_GPIOInit();
    
    #endif
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // oled.c
    #include "oled.h"
    
    // I2C协议开始
    void IIC_Start(){
        GPIO_SetBits(GPIO, SDA);
        GPIO_SetBits(GPIO, CLK);
        GPIO_ResetBits(GPIO, SDA);
        GPIO_ResetBits(GPIO, CLK);
    }
    
    // IIC协议结束
    void IIC_Stop(){
        GPIO_ResetBits(GPIO, SDA);
        GPIO_SetBits(GPIO, CLK);
        GPIO_SetBits(GPIO, SDA);
    }
    
    // 通过IIC写入数据
    void IIC_Write(u8 data){
        u8 i;
        for (i = 0; i < 8; i++){
            
            if (data & 0x80){
                GPIO_SetBits(GPIO, SDA);
            }
            else{
                GPIO_ResetBits(GPIO, SDA);
            }
            GPIO_SetBits(GPIO, CLK);
            GPIO_ResetBits(GPIOB, CLK);
            data <<= 1;
            // GPIO_ResetBits(GPIO, CLK);
            // GPIO_SetBits(GPIO, CLK);
        }
        GPIO_SetBits(GPIO, CLK);
        GPIO_ResetBits(GPIO, CLK);
    }
    
    // 写入命令
    void write_command(u8 cmd){
        IIC_Start();
        IIC_Write(ADDR);
        IIC_Write(0x00);
        IIC_Write(cmd);
        IIC_Stop();
    }
    
    // 写入数据
    void write_data(u8 data){
        IIC_Start();
        IIC_Write(ADDR);
        IIC_Write(0x40);
        IIC_Write(data);
        IIC_Stop();
    }
    
    // 设置光标
    void set_currsor(u8 row, u8 col){
        write_command(0xB0 |row);
        write_command(0x10 | ((col & 0xF0) >> 4));
        write_command(0x00 | (col & 0x0F));
    }
    
    // 扭动字符显示
    // 只能显示一个,显示多个就不流畅了
    void show_Twistchar(u8 row, u8 col, u8 word){
        u8 i;
        set_currsor(row, col * 8);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i]);
        }
        set_currsor(row + 1, col * 8);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i + 8]);
        }
        delay_us(5);
        set_currsor(row, col * 8 + 1);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i]);
        }
        set_currsor(row + 1, col * 8 + 1);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i + 8]);
        }
    }
    
    // 显示一个字符
    void show_char(u8 row, u8 col, u8 word){
        u8 i;
        set_currsor(row * 2, col * 8);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i]);
        }
        set_currsor(row * 2 + 1, col * 8);
        for (i = 0; i < 8; i++){
            write_data(ASCII1[word - 32][i + 8]);
        }
    }
    
    // 显示字符串
    void show_string(u8 row, u8 col, u8* str){
        u8 i, j = 0;
        for (i = 0; str[i] != '\0'; i++, j++){
            if (j >= 16){
                row += 1;
                col = 0;
                j = 0;
            }
            show_char(row, col + j, str[i]);
        }
    }
    
    // 现实汉字
    void show_hz(u8 row, u8 col, u8 len){
        u8 i, j, x, y;
        y = row;
        x = col;
        for (j = 0; j < len * 2; j += 2, y+= 2){
            // x = (x + j) * 8;
            if ((x + y) * 8 >= 128){
                y = 0;
                row = 2;
            }
            set_currsor(row, (x + y) * 8);
            for (i = 0; i < 16; i++){
                write_data(hz[j][i]);
            }
            set_currsor(row + 1, (x + y) * 8);
            for (i = 0; i < 16; i++){
                write_data(hz[j + 1][i]);
            }
        }
    }
    
    // 清屏
    void clear(){
        u8 i, j;
        for (i = 0; i < 8; i++){
            set_currsor(i, 0);
            for (j = 0; j < 128; j++){
                write_data(0x00);
            }
        }
    }
    
    // 初始化函数
    void OLED_Init(){
        u32 i, j;
        for (i = 0; i < 1000; i++){
            for (j = 0; j < 1000; j++);
        }
        write_command(CLOSESHOW);
        write_command(SETCLS);
        write_command(0x80);
        write_command(RATE);
        write_command(0x3F);
        write_command(OFFSET);
        write_command(0x00);
        write_command(START);
        write_command(LEFTRIG);
        write_command(UPDOWN);
        write_command(HARD);
        write_command(0x12);
        write_command(RATION);
        write_command(0xCF);
        write_command(CYCLE);
        write_command(0xF1);
        write_command(VCOM);
        write_command(0x30);
        write_command(SHOWUP);
        write_command(0xA6);
        write_command(BEN);
        write_command(0x14);
        write_command(SHOWOK);
        clear();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    // oled.h
    #ifndef __OLED_H
    #define __OLED_H
    
    #include "stm32f10x.h"
    #include "gpio.h"
    #include "oledfont.h"
    #include "sys.h"
    
    #define ADDR 0x78
    
    #define CMD 0x00
    #define DATA 0x40
    #define CLOSESHOW 0xAE
    #define SETCLS 0xD5
    #define RATE    0xA8
    #define OFFSET  0xD3
    #define START   0x40
    #define LEFTRIG 0xA1
    #define UPDOWN  0xC8
    #define HARD    0xDA
    #define RATION  0x81
    #define  CYCLE  0xD9
    #define VCOM    0xDB
    #define SHOWUP  0xA4
    #define BEN     0x8D
    #define SHOWOK  0xAF
    
    void OLED_Init();
    void clear();
    void show_char(u8 row, u8 col, u8 word);
    void set_currsor(u8 row, u8 col);
    void show_Twistchar(u8 row, u8 col, u8 word);
    void show_string(u8 row, u8 col, u8* str);
    void show_hz(u8 row, u8 col, u8 len);
    
    #endif
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    // sys.c
    #include "sys.h"
    
    void delay_us(u32 time){
        u32 temp;
        SysTick -> LOAD = 9 * time;
        SysTick -> CTRL = 0x01;
        SysTick -> VAL = 0;
        do{
            temp = SysTick -> CTRL;
        }while((temp & 0x01) && (!(temp & (1 << 16))));
        SysTick -> CTRL = 0;
        SysTick -> VAL = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // sys.h
    #ifndef __SYS_H
    #define __SYS_H
    
    #include "stm32f10x.h"
    
    void delay_us(u32 time);
    
    #endif
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    总结

    学会了这个显示屏如何显示后后面我们可以对传感器进行操作了,到时候传感器接收到的数据就可以直接显示在OLED上,这样就能很好的观察其中的变化了。

    下一章准备介绍一下显示屏的一些操作,比如显示进度条,显示动图或者其他内容。

  • 相关阅读:
    Mysql三种日志(binlog,redolog,undolog)的作用和区别
    TypeScrtpt学习
    享元设计模式
    2024年公司加密软件排行榜(企业加密软件推荐)
    kettle如何设计数据流转逻辑
    计算结构体成员相对于起始位置的偏移量 —— 宏 offsetof
    纠删码创新点整理
    C++ 语法基础课5 —— 字符串
    Android 13.0 SystemUI下拉状态栏增加响铃功能
    【原创】java+swing+mysql运动会管理系统设计与实现
  • 原文地址:https://blog.csdn.net/zagzag001/article/details/138202355