文章目录
一.概要
SPI总线是由Motorola公司提出,是一种三线同步接口:同步信号、输入信号和输出信号。
另外每个扩展芯片还需要一根片选线,主器件通过片选线选通与其通信的从器
件。
SPI是全双工的,即数据的发送和接收可同时进行。如果仅对从器件写数据,主器件可以丢弃同时读入的数据;反之,如果仅读数据,可以在命令字节后,写入任意数据。数据传送以字节为单位,并采用高位在前的格式。
二.SPI总线基本概念
SPI总线一般由四个信号组成。
MISO:主设备输入/从设备输出管脚。该管脚在从模式下发送数据,在主模式下接收数据。
MOSI:主设备输出/从设备输入管脚。该管脚在主模式下发送数据,在从模式下接收数据。
SCK:串口时钟,作为主设备的输出,从设备的输入
/SS:从设备选择,低电平有效。这是一个可选的管脚,用来选择从设备。它的功能是用来作为“片选管脚”,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。从设备的/SS管脚可以由主设备当作一个标准的IO来驱动。/SS管脚作为输出管脚,并在SPI设置为主模式时拉低;从机的/SS管脚连接到主设备/SS管脚的SPI设备,会检测到低电平,如果它们被设置为/SS硬件模式,就会自动进入从设备状态
1.SPI总线内部框图
一个主机跟一个从机典型应用连接如下图:
MOSI脚相互连接,MISO脚相互连接。这样,数据在主和从之间串行地传输(MSB位在前)。 通信总是由主设备发起。主设备通过MOSI脚把数据发送给从设备,从设备通过MISO引脚回传数据。这意味全双工通信的数据输出和数据输入是用同一个时钟信号同步的;时钟信号由主设备通过SCK脚提供。
2.总体特征
● 3线全双工同步传输
● 带或不带第三根双向数据线的双线单工同步传输
● 8或16位传输帧格式选择
● 主或从操作
● 支持多主模式
● 8个主模式波特率预分频系数(最大为fPCLK/2)
● 从模式频率 (最大为fPCLK/2)
● 主模式和从模式的快速通信
● 主模式和从模式下均可以由软件或硬件进行NSS管理:主/从操作模式的动态改变
● 可编程的时钟极性和相位
● 可编程的数据顺序,MSB在前或LSB在前
● 可触发中断的专用发送和接收标志
● SPI总线忙状态标志
● 支持可靠通信的硬件CRC
3.通讯时序
数据传输的时钟依靠主处理器的时钟脉冲。时钟的设置是根据时钟极性(CPOL)和时钟相位(CPHA)两个参数来决定的。
主和从必须配置成相同的时序模式。
CPOL 0:SCK在空闲状态保持低电平。
CPOL 1:SCK在空闲状态保持高电平。
CPHA 0:SCK的第1个(奇数)边沿进行数据位采样接收,数据在第2个时钟边沿发送数据。
CPHA 1:SCK的第2个(偶数)边沿进行数据位采样接收,数据在第1个时钟边沿发送数据。
根据CPOL和CPHA的不同组合,可以有四种不同的时钟极性和相位模式,分别为:
模式0:CPOL=0,CPHA=0
模式1:CPOL=0,CPHA=1
模式2:CPOL=1,CPHA=0
模式3:CPOL=1,CPHA=1
目前最常用的是CPOL 0,CPHA 0,就是空闲时SCK时钟为低电平,采样时刻为第1个边沿即上升沿。
总线空闲时:
SCK信号强制为低,SS强制为高,MOSI/MISO管脚处于高阻状态。
在传输数据时:
SS被拉低,从设备选中,主设备开始控制SPI时钟,1/2个SCK周期后,主机发送数据到MOSI管脚,从机发送数据到MISO管脚。此时数据在SCK信号的上升沿被捕获,保持到SCK的下降沿。
在发送单个帧的时候,当数据帧的所有位发送完成后,最后一个数据位被捕获的一个SCK周期后,SS返回高电平。
三.RC522介绍
RC522 刷卡模块是应用于13.56MHz 非接触式通信中高集成度读写卡系列芯片中的一员,是NXP 公司针对“三表”应用推出的一款低电压、低成本、体积小的非接触式读卡器芯片。
1.NFC基本介绍
2.RC522模块基本特点
3.RC522模块原理图
4.RC522模块SPI通讯时序
对RC522基本命令码
对卡片操作的0x0C数据通讯命令中的基本指令
由上面的SPI讲解知识可知,RC522的SPI通讯时序中的CPOL=0,CPHA=0
四.RC522模块读卡实验
硬件准备:
STLINK接STM32F103C8T6小系统板,STLINK接电脑USB口,
1.用杜邦线连接板子跟刷卡模块:
开发板3.3V <->模块VCC
开发板PA4脚 <->模块SDA(SS引脚)
开发板PA5脚 <->模块SCK
开发板PA6脚 <->模块MISO
开发板PA7脚 <->模块MOSI
开发板GND <->模块GND
开发板3.3V <->模块RST
2.用杜邦线连接板子与OLED显示屏:
板子3.3V--模块VCC
板子GND---模块GND
板子PB10--模块SCL
板子PB11--模块SDA
打开STM32CubeMX软件,新建工程
Part Number处输入STM32F103C8,再双击就创建新的工程
配置下载口引脚
配置外部晶振引脚
配置系统主频
配置PA4引脚为GPIO输出,配置SPI1,使用PA5,PA6,PA7引脚
配置工程文件名,保存路径,KEIL5工程输出方式
生成工程
用Keil5打开工程
添加代码
主要代码
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();//8M外部晶振,72M主频
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();//配置SPI1引脚,
/* USER CODE BEGIN 2 */
MFRC522_Init();//RC522初始化,使用SPI驱动
OLED_Init();//OLED初始化
OLED_Clear();//清屏
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
OLED_Clear();//清屏
OLED_ShowCHinese(18,0,0);//光
OLED_ShowCHinese(36,0,1);//子
OLED_ShowCHinese(54,0,2);//物
OLED_ShowCHinese(72,0,3);//联
OLED_ShowCHinese(90,0,4);//网
OLED_ShowString(6,3,"NFC RC522 TEST");//显示字符串
OLED_ShowString(3,6,"ID:");//显示字符串
OLED_ShowString(30,6,txBuffer);//显示读到的ID值
HAL_Delay(1000);//等待1秒
if (!MFRC522_Request(PICC_REQIDL, str)) {//寻卡
if (!MFRC522_Anticoll(str)) {//获得卡序列号
j = 0;
b = 0;
for (i=0; i<4; i++) if (lastID[i] != str[i]) j = 1; // 如果读到ID不同,需要显示更新
if (j) {
for (i=0; i<4; i++) lastID[i] = str[i];
for (i=0; i<4; i++) {
char_to_hex(str[i]);
txBuffer[b] = retstr[0];//序列号存在txBuffer中
b++;
txBuffer[b] = retstr[1];
b++;
}
}
}
}
}
/* USER CODE END 3 */
}
//初始化复位跟配置
void MFRC522_Init(void) {
MFRC522_Reset();
MFRC522_WriteRegister(MFRC522_REG_T_MODE, 0x8D);
MFRC522_WriteRegister(MFRC522_REG_T_PRESCALER, 0x3E);
MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_L, 30);
MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_H, 0);
MFRC522_WriteRegister(MFRC522_REG_RF_CFG, 0x7F); // 48dB gain
MFRC522_WriteRegister(MFRC522_REG_RX_THRESHOLD, 0x84);<<<<<<<<<<<<<<<<<<<<
MFRC522_WriteRegister(MFRC522_REG_TX_AUTO, 0x40);
MFRC522_WriteRegister(MFRC522_REG_MODE, 0x3D);
MFRC522_AntennaOn(); // Open the antenna
}
void MFRC522_Reset(void) {
MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_RESETPHASE);
}
void MFRC522_AntennaOn(void) {
uint8_t temp;
temp = MFRC522_ReadRegister(MFRC522_REG_TX_CONTROL);
if (!(temp & 0x03)) MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x03);
}
//SPI口写一字节内容
uint8_t SPI1SendByte(uint8_t data) {
unsigned char writeCommand[1];
unsigned char readValue[1];
writeCommand[0] = data;
HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&writeCommand, (uint8_t*)&readValue, 1, 10);//调用HAL库生成的SPI收发驱动函数
return readValue[0];
}
//写寄存器
void SPI1_WriteReg(uint8_t address, uint8_t value) {
cs_reset();
SPI1SendByte(address);
SPI1SendByte(value);
cs_set();
}
//获取卡序列号
uint8_t MFRC522_Anticoll(uint8_t* serNum) {
uint8_t status;
uint8_t i;
uint8_t serNumCheck = 0;
uint16_t unLen;
MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x00); // TxLastBists = BitFramingReg[2..0]
serNum[0] = PICC_ANTICOLL;
serNum[1] = 0x20;
status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
if (status == MI_OK) {
// Check card serial number
for (i = 0; i < 4; i++) serNumCheck ^= serNum[i];
if (serNumCheck != serNum[i]) status = MI_ERR;
}
return status;
}
五.CubeMX工程源代码下载
链接:https://pan.baidu.com/s/11yqx3uEpEFb5WWkIibICLg
提取码:5uqi
如果链接失效,可以联系博主给最新链接
程序下载下来之后解压就行
六.小结
STM32的SPI口是一种同步、全双工的通信标准,常用于短距离通信,如与Flash、传感器、显示驱动器等设备的通信,所以学会SPI能驱动各种模块传感器。