MCU开发学习记录15* - SPI学习与实践(HAL库) - 软件/硬件SPI - W25Q系列NOR FLASH与电阻屏触摸IC(XPT2406) - STM32CubeMX

名词解释:

SPI:​Serial Peripheral interface
CPOL:Clock Polarity
CPHA:Clock Phase
​​

统一文章结构(数字后加*):

        第一部分: 阐述外设工作原理;第二部分:芯片参考手册对应外设的学习;第三部分:使用STM32CubeMX进行外设初始化;第四部分:添加应用代码;第五部分:附上本篇文章的工程代码的下载地址。

        本文将介绍SPI的相关概念以及STM32CubeMX生成SPI的配置函数,实现软件/硬件控制SPI读写W25Q系列NOR FLASH与电阻屏触摸IC(XPT2406)。

一、什么是SPI?(串行同步全双工,MSB -> LSB,边沿采样)

1.1 SPI 简介

1.1.1 SPI 介绍(Serial Peripheral interface

        · SPI(Serial Peripheral interface)是串行外围设备接口。
        · SPI 是一种高速的,全双工,同步,串行的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。
        · SPI 主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。

1.2 SPI 物理层

1.2.1 SPI 接口(四根线)

        SDI(Serial Data Input)数据输入,SDO(Serial Data Output)数据输出,SCK(Serial Clock)时钟,SS/CS(Serial/Chip Select)片选

· MISO(Master Input Slave Output):
        主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。
· MOSI(Master Output Slave Input):
        主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。
· SCLK:
        串行时钟信号,由主设备产生。
· CS/SS:
        从设备片选信号,由主设备控制。它的功能是用来作为“片选引脚”,也就是选择指定的从设备,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。

1.2.2 SPI接口不同厂商命名

· MISO(Master In Slave Out)​:
        
SDO(对从机而言,Serial Data Out)、SDI(对主机而言,Serial Data In)
· MOSI(Master Out Slave In)​:
        
SDI(对从机而言,Serial Data In)、SDO(对主机而言,Serial Data Out)
· SCLK(Serial Clock)​:SCK
· CS(Chip Select)/SS(Slave Select):
        
NSS(Negative Slave Select,低电平有效的片选信号)

1.2.3 SPI 物理寻址

        当主设备要和某个从设备进行通信时,主设备需要先向对应从设备的片选线上发送使能信号(高电平或者低电平,根据从机而定)表示选中该从设备。

        

1.2.4 SPI 硬件结构框图

1. 引脚接口

2. 数据缓冲区与移位寄存器

· 发送缓冲区 (TX Buffer) :
        主机将要发送的数据写入此缓冲区。
        当移位寄存器空闲时,数据从TX Buffer自动加载到移位寄存器,开始逐位输出。
· 接收缓冲区(RX Buffer):
        移位寄存器接收到的数据存入此缓冲区,等待主机读取。
· 移位寄存器(Shift Register) :
        
每个SCK时钟周期移出1位数据(MOSI)并移入1位数据(MISO)。
        数据长度由SPL_CR1的 DFF 位决定(8位或16位)。

3. 时钟信号与波特率配置

· 时钟源:
        由主机内部时钟分频产生(如APB总线时钟)。
· 分频系数:
        通过SPLCR1的 BR[2:0] 位配置,决定SCK频率。
        公式: SCK频率 = 主时钟频率 /(2^(BR值+1))
        例如:BR=001,分频系数为4(2^(1+1)=4 )。
· 时钟极性与相位:
        CPOL (Clock Polarity):SPLCR1的 CPOL 位,决定SCK空闲状态电平。
        CPHA (Clock Phase):SPL_CR1的 CPHA 位,决定数据在SCK的上升沿或下降沿采样。

4. 主控制逻辑

· SPI_CR1:主模式核心配置
        MSTR:强制设为1 (主机模式)。
        LSBFIRST:数据位顺序(0=MSB在前,1=LSB在前)。
        BR[2:0]:波特率分频系数。
        CPOL / CPHA:时钟极性和相位。
        DFF:数据帧格式(0=8位,1=16位)。
· SPI_CR2:高级功能配置
        SSOE:硬件NSS管理(0=手动控制NSS, 1=自动拉低NSS)。
        FRF:帧格式(标准SPI/TI协议等)。
· SPI_SR:状态寄存器
        ·
TXE (Transmit Buffer Empty)
                1:发送缓冲区为空,可写入新数据;0:缓冲区有数据未发送。
        · RXNE (Receive Buffer Not Empty)
                1:接收缓冲区有数据待读取;0:缓冲区为空。
        · BSY (Busy)
                1: SPI正在传输数据;0: 空闲状态。
        · OVR (Overrun):
                1:接收缓冲区数据未及时读取,被新数据覆盖(需软件清除)。

        

1.3 SPI 协议层

1.3.1 SPI 传输工作原理

1. SPI 传输工作原理 - 移位寄存器

主机只向从机进行写操作,可以忽略接收到的从机数据。
主机要对从机进行读操作,需要发送一个空数据来引发从机发送数据

        

2. SPI 传输工作原理 - 读写工作原理

        

1.3.2 SPI 工作模式

· 时钟极性(CPOL)
        没有数据传输时时钟线的空闲状态电平
        0:SCK在空闲状态保持低电平
        1:SCK在空闲状态保持高电平
· 时钟相位(CPHA)
        时钟线在第几个时钟边沿采样数据
        0:SCK的第一(奇数)边沿进行数据位采样,数据在第一个时钟边沿被锁存
        1:SCK的第二(偶数)边沿进行数据位采样,数据在第二个时钟边沿被锁存

1.3.3 SPI 工作时序

        

1.4 硬件SPI外设

1.4.1 硬件SPI外设简介

1. 自动时钟生成与数据收发
        STM32的SPI硬件能够自动生成时钟信号,并根据配置自动完成数据的发送和接收。这意味着CPU无需手动控制时钟和数据线,从而可以专注于其他任务,提升系统效率。
2. 数据帧配置
        支持8位或16位的数据帧,用户可以根据应用需求选择合适的数据宽度。
        传输模式可配置为高位先行(MSB first)低位先行(LSB first),以适应不同设备的通信要求。
3. 时钟频率
        SPI时钟频率可通过将外设时钟(fPCLK)除以2、4、8、16、32、64、128或256来设置。这种灵活的分频方式提供了广泛的频率选择,以满足不同通信速度的需求。
4. 多主机模型与主从操作
        支持多主机模型,允许多个主机设备共存于同一SPI总线上。
        可配置为**主机(Master)从机(Slave)**模式,灵活适应不同的应用场景。
5. 通信模式
        除了标准的全双工通信外,SPI硬件还可精简为:
        半双工:数据只能在一个方向上传输。
        单工:数据只能发送或只能接收。 这种灵活性使其适用于特定的通信需求。
6. DMA支持
        支持DMA(直接内存访问),允许数据在内存和SPI外设之间直接传输,而无需CPU干预。这在高速通信或大数据量传输场景下,能够显著提高系统性能和效率。
7. I2S协议兼容
        SPI硬件兼容I2S(Inter-IC Sound)协议,这是一种用于传输数字音频数据的串行总线标准。I2S支持使得STM32能够轻松与音频设备(如音频编解码器、DAC等)进行通信,非常适合音频相关的嵌入式应用。

1.4.2 硬件SPI - 连续模式

        效率高,但是对软件设计要求高,且每个标志位产生时,需要程序即使处理,否则会造成数据覆盖。请连续模式下,对于读写切换的软件程序设计要求高。一般采用非连续模式的硬件SPI。

        硬件SPI(串行外设接口,Serial Peripheral Interface)在连续模式下是一种适用于高速、不间断数据传输的模式。该模式是对TXE中断触发模式的扩展,特别适用于SPI总线忙碌(BSY标志为1)的场景。在连续模式中,数据被连续写入SPI数据寄存器(SPI DR),确保移位寄存器始终有数据待发送,从而实现无缝的数据传输。

        在TXE中断触发后,​立即写入下一数据到SPI_DR,确保移位寄存器始终有数据待发送。
        结果​:SCLK时钟持续生成,无间隙。BSY标志保持为1(总线始终忙碌)。

1.4.3 硬件SPI - 非连续模式

        数据帧之间存在间隙,SCLK时钟暂停,BSY标志短暂清零。
        若未及时响应TXE中断,移位寄存器发送完当前数据后无新数据加载。
        结果​:SCLK时钟暂停,总线空闲。BSY标志清零(总线释放)。

        硬件SPI在非连续模式下适用于数据传输之间需要间断的场景。在这种模式下,SCK信号会在传输间隙暂停,BSY标志在每次传输完成后清零(BSY=0)。这使得非连续模式适合低速通信或需要精确控制传输时序的应用。

1.4.3 硬件SPI - 连续模式与非连续模式具体差异

TXEIE(发送缓冲区空中断使能)
        连续模式:通常禁用TXEIE(TXEIE=0),因为数据通过DMA或软件连续写入,避免中断开销。传输由BSY标志控制。
        非连续模式:可启用TXEIE(TXEIE=1),通过中断检测TXE标志,逐帧手动写入数据

RXNEIE(接收缓冲区非空中断使能)
        连续模式:若使用DMA,RXNEIE通常禁用(RXNEIE=0);若不使用DMA,可启用以处理接收数据。
        非连续模式:常启用RXNEIE(RXNEIE=1),通过中断读取接收数据。

DMA使能(TXDMAEN/RXDMAEN)
        连续模式:通常启用TXDMAEN和RXDMAEN(置1),通过DMA实现数据流的自动传输,避免CPU干预。
        非连续模式:DMA通常禁用(TXDMAEN=0, RXDMAEN=0),由CPU或中断逐帧处理数据。

1.4.4 硬件SPI - 中断标志位

二、什么是NOR FLASH?

2.1 NOR FLASH 简介

2.1.1 FLASH功能与种类

        FLASH是常用的用于储存数据的半导体器件,它具有容量大,可重复擦写、按“扇区/块”擦除、掉电后数据可继续保存的特性。

        FLASH是有一个物理特性:只能写0,不能写1,写1靠擦除

        FLASH主要有NOR Flash和NAND Flash两种类型,NOR和NAND是两种数字门电路。

2.1.2 FLASH操作注意事项

· 写入操作时:

        1. 写使能:在每次执行写入操作前,必须通过特定命令使芯片进入“写使能”状态。
        2. 写入数据:只能从1改写为0​,不能从0改写为1;写入数据前必须擦除,擦除后所有数据位变为1(例如擦除后存储单元全为0xFF)。
        3. 擦除操作:写入数据前必须擦除,擦除后所有数据位变为1,必须按最小擦除单元进行,如W25Qxx可以对 all、block、sector进行擦除。
        4. 连续写入限制:芯片内部按“页”管理数据,连续写入时,若数据超过当前页的末尾地址,会自动回到页首覆盖写入​。
        5. BUSY状态:入操作结束后,芯片进入忙状态,不响应新的读写操作。

· 读取操作时:

        ​1. 直接读取:
                · 无需使能
​:读取操作不需要类似“读使能”的命令,直接发送读取时序即可。
                · 无页限制​:可跨页连续读取任意长度数据(仅受接口协议限制)。
        ​2. BUSY状态:读取操作结束后不会进入忙状态,但不能在忙状态时读取。

2.2 NOR FLASH - W25Qxx系列

2.2.1 NOR Flash - W25Qxx系列

        W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器,常应用于数据存储、字库存储、固件程序存储等场景。支持SPI模式0 和 模式3。
        存储介质:Nor Flash(闪存)
        时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)
        W25Qxx系列具有24位地址的存储地址(W25Q256除外,它具有256Mbit-32MByte(需要25位地址表达),其具有3字节和4字节的操作方法)。W25Qxx,xx代表了Flash具有xxMbit容量。

2.2.2 NOR Flash - W25Qxx系列 - 引脚图

        

        

2.2.3 NOR Flash - W25Qxx系列 - 存储结构

        

2.2.4 NOR Flash - W25Qxx系列 - 常用设置命令

三、电阻屏触摸IC(SPI协议)

3.1 电阻屏介绍

3.1.1 电阻式触摸屏分类

        分类:四线,五线,七线和八线。

3.1.2 电阻式触摸屏优缺点

        · 触摸点(X,Y)转换代表X坐标和Y坐标的电压。

        · 优点:精度高,价格便宜,抗干扰能力强,稳定性好。
        · 缺点:需校准,容易被划伤,透光性较差,不支持多点触摸
        · 应用场景:广泛用于工业领域

        

3.2 电阻式触摸屏原理

3.2.1 电阻式触摸屏多层结构

        · 表面硬涂层起保护作用,主要是一层外表面硬化处理、光滑防擦的塑料层。
        · 玻璃底层用于支撑上面的结构,主要是玻璃或者塑料平板。
        · 透明隔离点用来分离开外层 ITO 和内层 ITO。
        · ITO 层是触摸屏关键结构,是涂有铟锡金属氧化物的导电层。
        · 还有一个结构上图没有标出,就是 PET 层。PET 层是聚酯薄膜,处于外层 ITO 和表面硬涂层之间,很薄很有弹性,触摸时向下弯曲,使得两个 ITO 层接触。

3.2.2 电阻式触摸屏的XY的ITO层结构

        两个 ITO 涂层的两端分别引出 X-X+Y-Y+ 四个电极,见28_4,这是电阻屏最常见的四线结构,通过这些电极,外部电路向这两个涂层可以施加匀强电场或检测电压。

        

3.2.3 电阻式触摸屏的触摸检测等效电路

        当触摸屏被按下时,两个 ITO 层相互接触,从触点处把 ITO 层分为两个电阻,且由于 ITO 层均匀导电,两个电阻的大小与触点离两电极的距离成比例关系,利用这个特性,可通过以下过程来 检测坐标,这也正是电阻触摸屏名称的由来。

        计算 X 坐标时,在 X+ 电极施加驱动电压 VrefX-极接地,所以 X+ X-处形成了匀强电场,而触点处的电压通过 Y+ 电极采集得到,由于 ITO 层均匀导电,触点电压与 Vref 之比等于触点 X 坐标与屏宽度之比,从而:

        

        计算 Y 坐标时,Y+ 电极施加驱动电压 VrefY-极接地,所以 Y+ Y-处形成了匀强电场,而触点处的电压通过 X+ 电极采集得到,由于 ITO 层均匀导电,触点电压与 V:sub:ref之比等于触点 Y 坐标与屏高度之比,从而:

        

3.3 电阻式触摸屏驱动IC介绍

3.3.1 常用电阻式触摸屏驱动IC

        XPT2046、TSC2046、HR2046。

3.3.2 常用电阻式触摸屏驱动IC - XPT2046应用电路与引脚介绍

        XPT2046是4线触摸屏控制器,支持SPI的3线接口。
        XPT2046是一个内含12位分辨率125KHz转换速率逐步逼近型AD转换器。通过执行两次A/D转换查出被按的屏幕位置。

        · XP/YP/XN/YN:接触摸屏
        · BUSY:转换状态信号
        · VREF:电压参考源
        · PENINQ:中断线
        · DIN:串行数据输入线
        · DOUT:串行数据输出线
        · CS:片选线
        · DCLK:时钟线

3.3.3 常用电阻式触摸屏驱动IC - XPT2046通信时序

        具体过程:拉低片选,选中器件→发送命令字→清除 BUSY读取 16 位数据(高 12 位数据有效即转换的 AD 值)→拉高片选,结束操作。

3.3.4 常用电阻式触摸屏驱动IC - XPT2046命令

        命令字的详情如下图:位 7,开始位,置 1 即可。位 3,为了提供精度,MODE 位清 0 选择 12 位分辨率。位 2,是进行工作模式选择,为了达到最佳性能,首选差分工作模式即该位清 0 即可。位 1-0 是功耗相关的,直接清 0 即可。而位 6-4 的值要取决于工作模式,在确定了差分功能模式后,通道选择位也确定了

        检测 Y 轴位置时,A2A1A0 赋值为 001;检测 X 轴位置时,A2A1A0 赋值为 101。结合前面对其他位的赋值,在 XY 方向与屏幕相同的情况下,命令字 0xD0 就是读取 X 坐标 AD 值,0x90 就是读取 Y 坐标的 AD 值。假如 XY 方向与屏幕相反,0x90 就是读取 X 坐标的 AD 值,而 0xD0 就是读取 Y 坐标的 AD 值。

3.3.5 常用电阻式触摸屏驱动IC - 电阻触摸屏的工作流程

        

3.3.6 常用电阻式触摸屏驱动IC - 电阻触摸屏触摸校准(五点校准法)

        建立一个映射函数,进行线性校准,精确算出X和Y方向的比例缩放系数。

· 校正相关的变量主要有:

        x[5] , y[5] 五点定位的物理坐标
        xl[5] , yl[5] 五点定位的逻辑坐标
        KX、KY横纵方向伸缩系数
        XLC , YLC 中心基点逻辑坐标
        XC、YC中心基点物理坐标(数值采用LCD显示屏的物理长宽分辨率的一半)

· 校正步骤:
        1. 通过先后点击LCD的4个角落的矫正点,获取4个角落的逻辑坐标值。
        2. 计算 s1’ = xl[2] - xl[1] 、 s3’ = xl[3] - xl[4] 、 s2’ = yl[3] - yl[2] 、 s4’ = yl[4] - yl[1]
            计算 s1 = x[2] - x[1] 、 s3 = x[3] - x[4] 、 s2 = y[3] - y[2] 、 s4 = y[4] - y[1],一般取点可以人为的设定s1 = s3 和 s2 = s4,以方便运算。+ Y  m* w+ A8 `% l+ _! m- F
            计算 KX = ( s1’ + s3’ )/2/s1 、KY = ( s2’ + s4’ )/2/s2
        3. 点击LCD正中心,获取中心点的逻辑坐标,作为矫正的基准点。! n1 E! R. }, W1 k
        4. 完成以上步骤则校正完成。下次点击触摸屏的时候获取的逻辑值XL和YL,可根据公式转换成物理值:0 k2 O4 v- L/ P+ a
            X = ( XL - XLC ) / KX + XC
            Y = ( YL - YLC ) / KY + YC5 U2 L, t* i8 }4 N) j
        换算出来的X , Y即是和LCD像素相对应的物理坐标值,方便对触屏响应程序做区域判别。
        

四、基于HAL库配置模拟SPI/硬件SPI

4.1 基于STM32CubeMX配置模拟SPI

4.2 模拟SPI函数

void bsp_spi_start(void)
{
	SPI_CS(0);				//拉低SS,开始时序
}

void bsp_spi_stop(void)
{
	SPI_CS(1);				//拉高SS,终止时序
}

uint8_t bsp_spi_SwapByte(uint8_t ByteSend)
{
	uint8_t i, ByteReceive = 0x00;					//定义接收的数据,并赋初值0x00,此处必须赋初值0x00,后面会用到
	
	for (i = 0; i < 8; i ++)						//循环8次,依次交换每一位数据
	{
		/*两个!可以对数据进行两次逻辑取反,作用是把非0值统一转换为1,即:!!(0) = 0,!!(非0) = 1*/
		SPI_MOSI(!!(ByteSend & (0x80 >> i)));	//使用掩码的方式取出ByteSend的指定一位数据并写入到MOSI线
		SPI_SCK(1);								//拉高SCK,上升沿移出数据
		if (SPI_MISO()){ByteReceive |= (0x80 >> i);}	//读取MISO数据,并存储到Byte变量
															//当MISO为1时,置变量指定位为1,当MISO为0时,不做处理,指定位为默认的初值0
		SPI_SCK(0);								//拉低SCK,下降沿移入数据
	}
	
	return ByteReceive;								//返回接收到的一个字节数据
}

4.3 基于STM32CubeMX配置硬件SPI

        

4.4 硬件SPI函数

void bsp_spi_init(void)
{
	
	/*设置默认电平*/
	SPI_CS(1);											//SS默认高电平
	SPI_SCK(0);											//SCK默认低电平
}

void bsp_spi_init(void)
{
    SPI_CS(1);
}

void bsp_spi_start(void)
{
    SPI_CS(0); // 拉低SS,开始时序
}


void bsp_spi_stop(void)
{
    SPI_CS(1); // 拉高SS,终止时序
}


uint8_t bsp_spi_SwapByte(uint8_t ByteSend)
{
    uint8_t ByteReceive = 0;

    while (__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE) == RESET)
        ;                                        // 等待发送缓冲区为空
    HAL_SPI_TransmitReceive(&hspi1, &ByteSend, &ByteReceive, 1, 1000);

    return ByteReceive; // 返回接收到的一个字节数据
}

五、本文的工程文件下载链接

工程Github下载链接:https://github.com/chipdynkid/MCU-DL-STM32
(国内)工程Gitcode下载链接https://gitcode.com/chipdynkid/MCU-DL-STM32

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值