一、
1.节选百度百科,介绍的很好
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,
正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议。
SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。
也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。
(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;
(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
(3)SCLK – Serial Clock,时钟信号,由主设备产生;
(4)CS – Chip Select,从设备使能信号,由主设备控制。
其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。
SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
2.好的资料
介绍OLED的SPI通讯资料:http://www.lcdwiki.com/zh/0.96inch_SPI_OLED_Module
二、
#ifndef SPI_OLED_H #define SPI_OLED_H /* SPI2 4线制SPI GND GND OLED屏电源地 VCC DC 5V/3.3V OLED屏电源正 D0 PB13 SPI2_SCK OLED屏SPI时钟信号 D1 PB15 SPI2_MOSI OLED屏SPI写信号 RES PB12 SPI2_NSS OLED屏复位控制信号 DC PB10 OLED屏数据/命令选择控制信号 CS PB11 OLED屏片选控制信号 */ #include "stm32f10x.h" void spi_oled_init(void); uint8_t spi_oled_write_byte(uint8_t byte); #endif
#include "spi_oled.h" #include <stdio.h> /* SPI2 4线制SPI GND GND OLED屏电源地 VCC DC 5V/3.3V OLED屏电源正 D0 PB13 SPI2_SCK OLED屏SPI时钟信号 D1 PB15 SPI2_MOSI OLED屏SPI写信号 RES PB12 SPI2_NSS OLED屏复位控制信号 DC PB10 OLED屏数据/命令选择控制信号 CS PB11 OLED屏片选控制信号 */ void spi_oled_init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE); //配置SPI2管脚 PB13 SPI2_SCK, PB15 SPI2_MOSI,PB14 SPI2_MISO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出 GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //SPI2配置选项 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); //使能SPI2 SPI_Cmd(SPI2, ENABLE); } uint8_t spi_oled_write_byte(uint8_t byte) { while((SPI2->SR&SPI_I2S_FLAG_TXE)==RESET); //等待发送区空 SPI2->DR = byte; //发送一个byte while((SPI2->SR&SPI_I2S_FLAG_RXNE)==RESET);//等待接收完一个byte return SPI2->DR; //返回收到的数据 }