SPI的模拟应用——OLED以及时钟模块的应用(一)SPI协议介绍及利用协议实现两机通信(51单片机)

链接:https://pan.baidu.com/s/1g8jkENjO8v4eXq0bN0acEw?pwd=45c8 
提取码:45c8

目录

一、 什么是SPI

1-1 SPI简介

1-2 SPI的特点

1-2-1 同步和异步

1-2-2 单工和双工

1-2-3 主从式结构

二、SPI硬件认识

三、SPI时序 

3-1 时钟极性和时钟相位

3-2 四种工作模式

3-2-1 Mode 0:

3-2-2 Mode 1:

3-2-3 Mode 2:

3-2-4 Mode 3:

3-3 模式选择说明

四、SPI协议软件模拟和撰写

4-1 首先定义好I/O口(可自定义)

4-2 SPI部分发送数据/命令函数:

4-3 读数据函数:

4-4 主函数:

4-5 接线

4-6 效果图


一、 什么是SPI

1-1 SPI简介

        SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器等芯片,还有数字信号处理器和数字信号解码器之间。

1-2 SPI的特点

SPI,是一种高速的,同步的,全双工,主从式接口通信总线,SPI接口可以是3线式或4线式,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。

1-2-1 同步和异步

同步:发送方和接收方拥有相同的时钟基准,在SPI里时钟基准是由主机提供的。比如IIC,SPI。

异步:发送方和接收方时钟独立,明显的特征是它的总线没有时钟线,像我们常用的串口通信。

SPI是同步通信,因为他具有时钟线。

1-2-2 单工和双工

单工:数据只能单向传输;比如数据可以从A传输到B,但是不能从B传输到A;

双工数据允许双向传输;比如数据可以从A传输到B,也可以从B传输到A,双工又可以分为全双工和半双工;

        全双工:同一时刻数据可以双向传输,也就是说有,在同一时刻数据既有从A发往B的,又有  从B发往A的,如SPI,UART;

        半双工:同一时刻只能单向传输,如IIC,比如IIC只有两根线,一根时钟线先,一根数据线,一个设备要发送和接收数据时,只能等待发送完成或者接收完成,才能开始接收或者发送;

1-2-3 主从式结构

一般运用于一个设备挂载多个设备才有这个概念,下文会提到。 

二、SPI硬件认识

SPI主从模式硬件连接如下图:

图1 含主机和从机的SPI配置

        SPI的通信原理很简单,它以主从方式工作,产生时钟信号的器件称为主机。主机和从机之间传输的数据与主机产生的时钟同步。这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。SPI的四条通讯线是MOSI(数据输入),MISO(数据输出),SCLK(时钟),SS/CS(片选)。

四条逻辑线

SPI总线包括4条逻辑线,定义如下:

        MISO:主机输入,从机输出(数据来自从机)

        MOSI: 主机输出,从机输入(数据来自主机)

        SCLK: 串行时钟信号,由主机产生发送给从机

       SS/CS:从设备使能信号,由主设备控制。 片选信号,由主机发送,以控制与哪个从机通信,通常是低电平有效信号。

其他制造商可能会遵循其他命名规则,但是最终他们指的相同的含义。以下是一些常用术语;

        MISO:也可以是SIMO,DOUT,DO,SDO或SO(在主机端);

        MOSI:也可以是SOMI,DIN,DI,SDI或SI(在主机端);

        SCLK:也可以是SCK,SCL;

        SS/CS:也可以是CE,或SSEL;

注意:MISO 是主机的输入,从机的输出,MOSI是主机的输出,从机的输入。

         其中,SS/CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能,如图2:

        一个主机连接了3个从机设备,而主机通过3路独立的SS片选线连接到3个从机设备,假设3个从机的片选信号为低电位使能,也就是当你要用到这个从机时,你要把它的SS置0,这样就可以向使能的从机设备发送或接收数据了。

如下:(符号-:表示低电平有效)

 

 图2 一个主机多个从机的常规接法

要注意的是,SCLK(时钟信号)信号线只由主设备控制,从设备不能控制信号线。同样,在一个基于SPI的设备中,至少有一个主控设备。

这样传输的特点:

        这样的传输方式有一个优点,与普通的串行通讯不同,普通的串行通讯一次连续传送至少8位数据,而SPI允许数据一位一位的传送,甚至允许暂停,因为SCK时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据,也就是说,主设备通过对SCK时钟线的控制可以完成对通讯的控制。

        SPI还是一个数据交换协议,因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。不同的SPI设备的实现方式不尽相同,主要是数据改变和采集的时间不同,在时钟信号上沿或下沿采集有不同定义。

        在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。在多个从设备的系统中,每个从设备需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。当然了,因为SPI从设备没有地址区分,这样也存在了一个弊端,那就是没有指定的流控制,没有应答机制确认是否接收到数据。

三、SPI时序 

3-1 时钟极性和时钟相位

        在SPI中,主机可以选择时钟极性和时钟相位。在空闲状态期间,CPOL位设置时钟信号的极性。空闲状态是指传输开始时CS为高电平且在向低电平转变的期间,以及传输结束时CS为低电平且在向高电平转变的期间。CPHA位选择时钟相位。根据CPHA位的状态,使用时钟上升沿或下降沿来采样和/或移位数据。主机必须根据从机的要求选择时钟极性和时钟相位。根据CPOL和CPHA位的选择,有四种SPI模式可用。下表显示了这4种SPI模式。

CPOL时钟极性选择,为0时SPI总线空闲为低电平,为1时SPI总线空闲为高电平
CPHA时钟相位选择,为0时在SCK第一个跳变沿采样,为1时在SCK第二个跳变沿采样

表1

模式

CPOL&CPHA

介绍

Mode 0

CPOL=0;CPHA=0

SCLK 空闲是为低电平,数据在上升沿有效

Mode 1

CPOL=0;CPHA=1

SCLK 空闲是为低电平,数据在下降沿有效

Mode 2

CPOL=1;CPHA=0

SCLK 空闲是为高电平,数据在下降沿有效

Mode 3

CPOL=1;CPHA=1

SCLK 空闲是为高电平,数据在上升沿有效

表2

3-2 四种工作模式

4种工作模式波形时序如下图:

3-2-1 Mode 0:

图3 Mode 0

数据必须在第一个时钟信号上升之前可用。时钟空闲状态为零。当时钟处于高位时,MISO和MOSI线路上的数据必须稳定,当时钟处于低位时,数据可以更改。数据在时钟的低到高转换时捕获,并在高到低时钟转换时传播。在MODE0模式下,时钟在空闲时始终置0,每产生一次上升沿便会发送1 bit 数据。

3-2-2 Mode 1:

  

图4 Mode 1

第一个时钟信号上升可用于准备数据。时钟空闲状态为零。当时钟低位时,MISO和MOSI线路上的数据必须稳定,当时钟高位时,数据可以更改。数据在时钟的高-低转换上捕获,并在低-高时钟转换上传播。时钟在空闲时始终置0,每产生一次下降沿便会发送1 bit 数据。

3-2-3 Mode 2:

图5 Mode 2

数据必须在第一个时钟信号下降之前可用。时钟空闲状态为1。当时钟低位时,MISO和MOSI线路上的数据必须稳定,当时钟高位时,数据可以更改。数据在时钟的高-低转换上捕获,并在低-高时钟转换上传播。时钟在空闲时始终置1,每产生一次下降沿便会发送1 bit 数据。

3-2-4 Mode 3:

图6 Mode 3

第一个时钟信号下降可用于准备数据。时钟空闲状态为1。当时钟处于高位时,MISO和MOSI线路上的数据必须稳定,当时钟处于低位时,数据可以更改。数据在时钟的低到高转换时捕获,并在高到低时钟转换时传播。时钟在空闲时始终置1,每产生一次上升沿便会发送1 bit 数据。

比方说Mode0,时钟空闲状态为零,即SCLK=0;当SCLK=0时,MISO和MOSO的电位可改变,上面的内容说到:MISO是主机输入,从机输出(数据来自从机),可理解为主机读数据;MOSI是主机输出,从机输入(数据来自主机),可理解为主机向从机写命令;这样,在至少8次时钟信号的改变(上沿和下沿为一次),就可以完成8位数据的传输。

注意事项:

在主设备配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,因为主设备的时钟极性和相位都是以从设备为基准的。因此在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。

3-3 模式选择说明

SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性(CPOL)和相位(CPHA)可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。

SPI分主设备和从设备,两者通过SPI协议通讯。而设置SPI的模式,是从设备的模式,决定了主设备的模式。所以要先去搞懂从设备的SPI是何种模式,然后再将主设备的SPI的模式,设置和从设备相同的模式,即可正常通讯。

对于从设备的SPI是什么模式,有两种:

(1)固定的,有SPI从设备硬件决定的

        SPI从设备,具体是什么模式,相关的datasheet中会有描述,需要自己去datasheet中找到相关的描述,即:

        关于SPI从设备,在空闲的时候,是高电平还是低电平,即决定了CPOL是0还是1;

        然后再找到关于设备是在上升沿还是下降沿去采样数据,这样就是,在定了CPOL的值的前提下,对应着可以推算出CPHA是0还是1了。

举例:

SSD1289 - 240 RGB x 320 TFT LCD Controller Driver的datasheet中提到:

“SDI is shifted into 8-bit shift register on every rising edge of SCK in the order of data bit 7, data bit 6 …… data bit 0.”

        意思是,数据是在上升沿采样,所以可以断定是CPOL=0,CPHA=0,或者CPOL=1,CPHA=1的模式,但是至于是哪种模式,按理来说,接下来应该再去确定SCLK空闲时候是高电平还是低电平,用以确定CPOL是0还是1,但是datasheet中没有提到这点。

所以,此处,目前不太确定,是两种模式都支持,还是需要额外找证据却确定CPOL是0还是1.

(2)可配置的,由软件自己设定

        从设备也是一个SPI控制器,4种模式都支持,此时只要自己设置为某种模式即可。

        然后知道了从设备的模式后,再去将SPI主设备的模式,设置为和从设备模式一样,即可。

       多数都是直接去写对应的SPI控制器中对应寄存器中的CPOL和CPHA那两位,写0或写1即可。SPI工作模式选择是根据外设的工作方式,如果外设使用上升沿采样,SPI就是用1和3工作模式

四、SPI协议软件模拟和撰写

        对于不带SPI串行总线接口的AT89C52单片机来说,可以使用软件来模拟SPI的操作,接下来介绍利用单片机的I/O口通过软件模拟SPI总线驱动的实现方法。

        下面我们通过软件模拟SPI来实现两个单片机的通信。

所需:

        两个51单片机开发板(可以一样的开发板,也可以两个不同的开发板,我使用的两个开发板都是实验室的版子,也会用到仿真)、杜邦线

实现的基本功能:开发板1的按键控制开发板2的led等亮灭,实验功能很简单,但涉及两个单片机的通信,有助于理解和掌握SPI协议。

实验步骤:

4-1 首先定义好I/O口(可自定义)

sbit SDO = P2^0; //位定义,主机输入,从机输出(数据来自从机);
sbit SDI = P2^1; //位定义,主机输出,从机输入(数据来自主机);
sbit SCK = P2^2; //位定义时钟
sbit CS = P2^3;  //位定义片选(使能,CS引脚为0时主从方可互相通信)

4-2 SPI部分发送数据/命令函数:

/*-----5微秒延时函数-----*/

void delay5us()
{
    _nop_();
}

//CPHA=0;CPOL=1 模式2,时钟在空闲时始终置1,每产生一次下降沿便会发送1 bit 数据。
//SPI发送函数
//上升沿发送
void Spi_Send(unsigned char dat1)
{
    unsigned char i;
    for (i=0; i<8; ++i)    //8bit,一位一位写
    {
        SCK = 0; //下降沿发送数据
        if (dat1 & 0x80)    //判断当前最高位为1还是0对应的把SDI拉高拉低
        {
            SDI=1;
        }
        else
        {
            SDI=0;
        }
        SCK = 1;    //上升沿的时候开始可以改变数据
        dat1 <<= 1;
        delay5us();
    }
}

大家写的时候要根据时序图来写,加以理解。

4-3 读数据函数:

//SPI接收函数
//下降沿接收
unsigned char SpiReceive()
{
    unsigned char i, dat0;
    dat0 = 0x00;       //dat0初始化
    for (i=0; i<8; ++i)//8bit,一位一位读
    {
        dat0 <<= 1;//第一个接收的对应发送过来的最高位
        while(SCK == 1);//等待下降沿,下降沿读取数据
        while(SCK == 0);//下降沿读取数据
        dat0 |= SDO; //每次存入dat0的最低位
    }
    return (dat0);//收到数据(返回值)dat0
}

        到目前为止,有关SPI协议的函数就写完了,无非就是发送和接收数据。在编写和理解的过程要根据上文讲到的模式二的时序图,空闲状态和高低电平的变化。

        根据我们要实现的功能,我们要实现两个单片机的通信,那么就必须确认一个单片机为主机,另一个为从机。

首先编写主机的主函数,这个单片机要实现的功能是通过按键信号SPI通信发送数据:

4-4 主函数:

#include<reg52.h>
#include"SPI.h"

sbit s1=P3^4;  //这个是我的按键
sbit led=P1^2; //led灯

//按键消抖延时函数
void delay (unsigned int ms)
{
    unsigned char i,j;
    while(ms--)
    {
        i=2;
        j=239;
        do
        {
            while(--j);
        }while(--i);
    }
}


//这个是主机的函数,功能是通过按键发送0xAA和0xA5
void main()
{
    unsigned char n=1;
    CS=0;    //这步是关键的,如果未使能,不能通信,CS引脚为0时主从方可互相通信
    while(1)
    {
        if(s1==0)
        {
            delay(10);
            while(s1==0);
            delay(10);
            led=~led;//这个是验证按键功能是否实现的
            n=~n;//按键按下会改变n值,达到发送两个数据的目的
            if(n==1)
            {
                Spi_Send(0xAA);//向从机发送数据0xAA
            }
            else
            {
                Spi_Send(0xA5);//向从机发送数据0xA5
            }
        }
    }
}

        这样主机的功能就实现了,通过按键s1(P3^4口,每个开发板设计的按键不一定是这个,要根据每个板子的原理图选择IO口)按下发送0xAA/0xA5这两个命令给从机,从机可根据这两个命令的判断实现不同的功能,在这里,为了实验的简便,我设计了最简单的点灯/灭灯功能,当从机接收到0xAA时,led(P1^0)点亮,0xA5熄灭。如下:

#include<reg52.h>
#include"SPI.h"

sbit led2=P1^0;

void main()
{
    unsigned char dat;
    CS=0;//同样的,从机也要使能CS
    while(1)
    {
        dat=SpiReceive();//读取接收到的数据
        if(dat==0xAA)
        {
            led2=0;
        }
        if(dat==0xA5)
        {
            led2=1;
        }
    }
}

以上代码我是有封装好的,下面是放在一个main.c文件里的全部函数,可供复制粘贴,注意要根据每个实验开发板的原理图定义好IO口。

#include <reg52.h>
#include <intrins.h>

sbit s1=P3^4;  //这个是我的按键
sbit led=P1^2; //主机led灯
sbit led2=P1^0;//从机led
sbit SDO = P2^0; //位定义,主机输入,从机输出(数据来自从机);
sbit SDI = P2^1; //位定义,主机输出,从机输入(数据来自主机);
sbit SCK = P2^2; //位定义时钟
sbit CS = P2^3;  //位定义片选(使能,CS引脚为0时主从方可互相通信)

void delay5us()
{
    _nop_();
}

//CPHA=0;CPOL=1 模式2,时钟在空闲时始终置1,每产生一次下降沿便会发送1 bit 数据。
//SPI发送函数
//上升沿发送
void Spi_Send(unsigned char dat1)
{
    unsigned char i;
    for (i=0; i<8; ++i)    //8bit,一位一位写
    {
        SCK = 0; //下降沿发送数据
        if (dat1 & 0x80)    //判断当前最高位为1还是0对应的把SDI拉高拉低
        {
            SDI=1;
        }
        else
        {
            SDI=0;
        }
        SCK = 1;    //上升沿的时候开始可以改变数据
        dat1 <<= 1;
        delay5us();
    }
}

//SPI接收函数
//下降沿接收
unsigned char SpiReceive()
{
    unsigned char i, dat0;
    dat0 = 0x00;       //dat0初始化
    for (i=0; i<8; ++i)//8bit,一位一位读
    {
        dat0 <<= 1;//第一个接收的对应发送过来的最高位
        while(SCK == 1);//等待下降沿,下降沿读取数据
        while(SCK == 0);//下降沿读取数据
        dat0 |= SDO; //每次存入dat0的最低位
    }
    return (dat0);//收到数据(返回值)dat0
}

//按键消抖延时函数
void delay (unsigned int ms)
{
    unsigned char i,j;
    while(ms--)
    {
        i=2;
        j=239;
        do
        {
            while(--j);
        }while(--i);
    }
}


//这个是主机的函数,功能是通过按键发送0xAA和0xA5
void main()
{
    unsigned char n=1;
    CS=0;    //这步是关键的,如果未使能,不能通信,CS引脚为0时主从方可互相通信
    while(1)
    {
        if(s1==0)
        {
            delay(10);
            while(s1==0);
            delay(10);
            led=~led;//这个是验证按键功能是否实现的
            n=~n;//按键按下会改变n值,达到发送两个数据的目的
            if(n==1)
            {
                Spi_Send(0xAA);//向从机发送数据0xAA
            }
            else
            {
                Spi_Send(0xA5);//向从机发送数据0xA5
            }
        }
    }
}
//从机主函数,烧入第二个单片机时将上一个注释掉
//void main()
//{
//    unsigned char dat;
//    CS=0;//同样的,从机也要使能CS
//    while(1)
//    {
//        dat=SpiReceive();//读取接收到的数据
//        if(dat==0xAA)
//        {
//            led2=0;
//        }
//        if(dat==0xA5)
//        {
//            led2=1;
//        }
//    }
//}

        特别注意的,代码中有两个主函数,一个是主机的,一个是从机的,烧入对应的代码时,注释掉另一个主函数,运行警告是因为有函数未被调用。在这里片选数据一直被拉低,所以会一直写和读,为了不必要的写读,发送完一组数据,将片选拉高,停止写入 。

4-5 接线

 图7 接线图

        主机的SDO接从机的SDI(这点要注意)

        主机的SCK接从机的SCK,CS接CS,在对两个单片机供电就好了。

        达到的实验效果就是按下按键可以控制另一个单片机的亮灭。

4-6 效果图

按下主机按键前状态:

图8 主机按键未按下

 按下后:

图9 主机按键按下

4-7 仿真效果图

图10 仿真效果图 

         到这里,SPI的内容就介绍完了,加上对代码的理解和功能的实现希望对SPI的学习和理解有所帮助。

  • 12
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32单片机读写 ATGM336H(GPS)模块+液晶显示DEMO软件例程源码,可做为你的学习设计参考。 int main(void) { uint32_t lcdid; char cStr[100]; double deg_lat;//转换成[degree].[degree]格式的纬度 double deg_lon;//转换成[degree].[degree]格式的经度 nmeaINFO info; //GPS解码后得到的信息 nmeaPARSER parser; //解码时使用的数据结构 uint8_t new_parse=0; //是否有新的解码数据标志 nmeaTIME beiJingTime; //北京时间 /* 复位所有外设,初始化Flash接口和系统滴答定时器 */ HAL_Init(); /* 配置系统时钟 */ SystemClock_Config(); /* 初始化3.5寸TFT液晶模组,一般优先于调试串口初始化 */ lcdid=BSP_LCD_Init(); /* 初始化串口并配置串口中断优先级 */ MX_DEBUG_USART_Init(); MX_SPIFlash_Init(); MX_USARTx_Init(); /* 初始化LED */ LED_GPIO_Init(); /* 调用格式化输出函数打印输出数据 */ printf("LCD ID=0x%08X\n",lcdid); LCD_Clear(0,0,LCD_DEFAULT_WIDTH,LCD_DEFAULT_HEIGTH,BLACK); /* 开背光 */ LCD_BK_ON(); /* 设置用于输出调试信息的函数 */ nmea_property()->trace_func = &trace; nmea_property()->error_func = &error; nmea_property()->info_func = &gps_info; /* 初始化GPS数据结构 */ nmea_zero_INFO(&info); nmea_parser_init(&parser); /* 使用DMA传输数据到电脑端 */ HAL_UART_Receive_DMA(&husartx,gps_rbuff,GPS_RBUFF_SIZE); while(1) { if(GPS_HalfTransferEnd) /* 接收到GPS_RBUFF_SIZE一半的数据 */ { /* 进行nmea格式解码 */ nmea_parse(&parser, (const char*)&gps_rbuff[0], HALF_GPS_RBUFF_SIZE, &info); GPS_HalfTransferEnd = 0; //清空标志位 new_parse = 1; //设置解码消息标志 } else if(GPS_TransferEnd) /* 接收到另一半数据 */ { nmea_parse(&parser, (const char*)&gps_rbuff[HALF_GPS_RBUFF_SIZE], HALF_GPS_RBUFF_SIZE, &info); GPS_TransferEnd = 0; new_parse =1; } if(new_parse ) //有新的解码消息 { /* 对解码后的时间进行转换,转换成北京时间 */ GMTconvert(&info.utc,&beiJingTime,8,1); /* 输出解码得到的信息 */ printf("\r\n时间%d-%02d-%02d,%d:%d:%d\r\n", beiJingTime.year+1900, beiJingTime.mon,beiJingTime.day,beiJingTime.hour,beiJingTime.min,beiJingTime.sec); //info.lat lon中的格式为[degree][min].[sec/60],使用以下函数转换成[deg
以下是51单片机OLED SPI显示图片的详细代码,供参考: ``` #include <reg51.h> // OLED SPI引脚定义 sbit OLED_DC = P2^0; //数据/命令选择引脚 sbit OLED_RST = P2^1; //复位引脚 sbit OLED_CS = P2^2; //片选引脚 sbit OLED_SCLK = P2^3; //时钟引脚 sbit OLED_SDIN = P2^4; //数据引脚 // 延时函数 void Delay(unsigned int i) { while(i--); } // OLED SPI写命令 void OLED_WriteCmd(unsigned char I_Cmd) { OLED_DC = 0; // 选择写入命令 OLED_CS = 0; // 片选使能 OLED_SCLK = 0; // 时钟线置低 OLED_SDIN = I_Cmd; // 数据线写入 OLED_SCLK = 1; // 时钟线置高 OLED_CS = 1; // 片选禁止 } // OLED SPI写数据 void OLED_WriteData(unsigned char I_Data) { OLED_DC = 1; // 选择写入数据 OLED_CS = 0; // 片选使能 OLED_SCLK = 0; // 时钟线置低 OLED_SDIN = I_Data; // 数据线写入 OLED_SCLK = 1; // 时钟线置高 OLED_CS = 1; // 片选禁止 } // OLED SPI初始化 void OLED_Init() { OLED_RST = 0; // 复位OLED Delay(200); OLED_RST = 1; OLED_WriteCmd(0xAE); // 关闭OLED显示 OLED_WriteCmd(0x20); // 设置内存地址模式 OLED_WriteCmd(0x10); // 垂直寻址模式 OLED_WriteCmd(0xB0); // 设置页地址 OLED_WriteCmd(0xC8); // 设置COM扫描方向 OLED_WriteCmd(0x00); // 设置低列地址 OLED_WriteCmd(0x10); // 设置高列地址 OLED_WriteCmd(0x40); // 设置显示开始行 OLED_WriteCmd(0x81); // 对比度设置 OLED_WriteCmd(0xFF); // 对比度值 OLED_WriteCmd(0xA1); // 设置段重定向 OLED_WriteCmd(0xA6); // 设置正常显示 OLED_WriteCmd(0xA8); // 设置多路复用比 OLED_WriteCmd(0x3F); // 多路复用比值 OLED_WriteCmd(0xAD); // 设置电荷泵 OLED_WriteCmd(0x8B); // 电荷泵开启 OLED_WriteCmd(0xD3); // 设置显示偏移 OLED_WriteCmd(0x00); // 显示偏移值 OLED_WriteCmd(0xD5); // 设置显示时钟分频 OLED_WriteCmd(0xF0); // 显示时钟分频值 OLED_WriteCmd(0xD9); // 设置预充电期 OLED_WriteCmd(0x22); // 预充电期值 OLED_WriteCmd(0xDA); // 设置COM硬件配置 OLED_WriteCmd(0x02); // COM硬件配置值 OLED_WriteCmd(0xDB); // 设置VCOMH OLED_WriteCmd(0x49); // VCOMH值 OLED_WriteCmd(0xAF); // 打开OLED显示 } // OLED SPI显示图片 void OLED_ShowPicture(unsigned char code *I_Picture) { unsigned char i,j; for(i=0;i<8;i++) { OLED_WriteCmd(0xB0+i); // 设置页地址 OLED_WriteCmd(0x00); // 设置低列地址 OLED_WriteCmd(0x10); // 设置高列地址 for(j=0;j<128;j++) { OLED_WriteData(I_Picture[i*128+j]); // 写入数据 } } } void main() { OLED_Init(); // 初始化OLED OLED_ShowPicture(Picture_Data); // 显示图片 while(1); } ``` 在上面的代码中,需要注意以下几点: 1.在OLED SPI引脚定义中,根据实际连接的引脚进行定义。 2.OLED SPI写命令和写数据的函数分别是`OLED_WriteCmd()`和`OLED_WriteData()`。 3.OLED SPI初始化函数是`OLED_Init()`,其中设置了OLED的各种参数。 4.OLED SPI显示图片的函数是`OLED_ShowPicture()`,需要传入一个指向图片数组的指针。 5.在主函数中,调用`OLED_Init()`进行OLED SPI初始化,并调用`OLED_ShowPicture()`显示图片。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值