STM32F10x - SPI与I2S - 图文

更新时间:2024-03-29 00:07:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

SPI与I2S

Table.0-1 SPI寄存器 No 1 2 3 4 5 6 7 8 9 寄存器 CR1 CR2 SR DR CRCPR RxCRCR TxCRCR I2S_CFGR I2SPR 描述 SPI控制寄存器1 SPI控制寄存器2 SPI状态寄存器 SPI数据寄存器 SPI CRC多项式寄存器 SPI接收CRC寄存器 SPI发送CRC寄存器 I2S配置寄存器 I2S预分频寄存器 SPI √ √ √ √ √ √ √ I2S √ √ √ √ √ 备注:小容量和中容量没有I2S接口。故STM32F103RBT6不需要考虑I2S库函数。 Table.0-2 库函数列表

No 函数名 描述 1 SPI_I2S_DeInit 将外设SPIx\\I2Sx寄存器重设为缺省值 2 SPI_Init 根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 3 I2S_Init 根据I2S_InitStruct中指定的参数初始化外设I2Sx寄存器 4 SPI_StructInit 把SPI_InitStruct中的每一个参数按缺省值填入 5 I2S_StructInit 把I2S_InitStruct中的每一个参数按缺省值填入 6 SPI_Cmd 使能或失能SPI外设 7 I2S_Cmd 使能或失能I2S外设 8 SPI_I2S_ITConfig 使能或失能指定的SPIx\\I2Sx中断 9 SPI_I2S_DMACmd 使能或失能指定SPIx\\I2Sx的DMA请求 10 SPI_I2S_SendData 通过外设SPIx\\I2Sx发送一个数据 11 SPI_I2S_ReceiveData 返回通过SPIx\\I2Sx最近接收的数据 12 SPI_NSSInternalSoftwareConfig 为选定的SPI软件配置内部NSS管脚 13 SPI_SSOutputCmd 使能或失能指定的SPI SS输出 14 SPI_DataSizeConfig 设置选定的SPI数据大小 15 SPI_TransmitCRC 发送SPIx的CRC值 16 SPI_CalculateCRC 使能或失能指定SPI的传输字CRC值计算 17 SPI_GetCRC 返回指定SPI的发送或者接受CRC寄存器值 18 SPI_GetCRCPolynomial 返回指定SPI的CRC多项式寄存器值 19 SPI_BiDirectionalLineConfig 选择指定SPI在双向模式下的数据传输方向 20 SPI_I2S_GetFlagStatus 检查指定的SPIx\\I2Sx标志位设置与否 21 SPI_I2S_ClearFlag 清除SPIx\\I2Sx的待处理标志位 22 SPI_I2S_GetITStatus 检查指定的SPI\\I2Sx中断发生与否 23 SPI_I2S_ClearITPendingBit 清除SPIx\\I2Sx的中断待处理位 注 标有SPI_I2S的函数,既符合SPI接口,也符合I2S接口;标示I2S的只能对应I2S接口 串行外设接口(SPI)提供与外部设备进行同步串行通讯的功能。接口可以被设置工作在主模式或者从模式。

/*【01】函数SPI_I2S_DeInit

****************************************************************************** * Function Name : SPI_I2S_DeInit

* Description : Deinitializes the SPIx peripheral registers to their default * reset values (Affects also the I2Ss).

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * Output : None * Return : None

*******************************************************************************/ void SPI_I2S_DeInit(SPI_TypeDef* SPIx) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

switch (*(u32*)&SPIx) {

case SPI1_BASE:

/* Enable SPI1 reset state */

RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE); /* Release SPI1 from reset state */

RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE); break;

case SPI2_BASE:

//I2S只有I2S2、I2S3,分别对应SPI2、SPI3。先开启SPI2外设,然后设置I2SCFGR可以开启I2S2或SPI2 /* Enable SPI2 reset state */

RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE); /* Release SPI2 from reset state */

RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE); break;

case SPI3_BASE:

/* Enable SPI3 reset state */

RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE); /* Release SPI3 from reset state */

RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE); break;

default: break; } }

/*【02】函数SPI_Init

****************************************************************************** * Function Name : SPI_Init

* Description : Initializes the SPIx peripheral according to the specified * parameters in the SPI_InitStruct.

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.

* - SPI_InitStruct: pointer to a SPI_InitTypeDef structure that contains the * configuration information for the specified SPI peripheral. * Output : None * Return : None

******************************************************************************/ SPI_InitTypeDef structure:

typedef struct {

u16 SPI_Direction; u16 SPI_Mode; u16 SPI_DataSize; u16 SPI_CPOL; u16 SPI_CPHA; u16 SPI_NSS;

u16 SPI_BaudRatePrescaler; u16 SPI_FirstBit;

u16 SPI_CRCPolynomial; }SPI_InitTypeDef;

SPI_Direction:设置了SPI单向或者双向的数据模式。 Table.02-1 SPI_Direction值

SPI_Direction SPI_Direction_2Lines_RxOnly SPI_Direction_1Line_Rx SPI_Direction_1Line_Tx SPI_Mode:设置了SPI 工作模式。 Table .02-2 SPI_Mode值

SPI_Mode 描述/CR1.8/2 组合的意义 SPI_Mode_Master 设置为主SPI SPI_Mode_Slave 设置为从SPI SPI_DataSize:设置了SPI的数据大小。 Table.02-3 SPI_DataSize值

SPI_DataSize SPI_DataSize_16b SPI_DataSize_8b 描述/CR1.DFF/bit11 SPI发送接收16位帧结构 SPI发送接收8位帧结构 0x0800 0x0000 0x0104 SSI=1;MSTR=1 0x0000 描述CR.15/14/10 SPI设置为双线单向接收 SPI设置为单线双向接收 SPI设置为单线双向发送 组合的意义 SPI_Direction_2Lines_FullDuplex SPI设置为双线双向全双工 0x0000 BIDIMODE=0(双线双向): 0x0400 RXONLY:全双工、只接收 0x8000 BIDIMODE=1(单线双向): 0xC000 BIDIOE:只接收、只发送 SPI_CPOL:选择了串行时钟的稳态。 Table.02-4 SPI_ SPI_CPOL 值

SPI_CPOL 描述/CR1.CPOL SPI_CPOL_High 时钟悬空高 SPI_CPOL_Low 时钟悬空低 bit1 0x0002 0x0000 SPI_CPHA:设置了位捕获的时钟活动沿。 Table.02-5 SPI_SPI_CPHA值

SPI_CPHA SPI_CPHA_2Edge SPI_CPHA_1Edge 描述/CR1.CPHA/bit0 数据捕获于第二个时钟沿 数据捕获于第一个时钟沿 0x0001 0x0000 SPI_NSS:指定了NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理。 Table .02-6 SPI_NSS值

SPI_NSS SPI_NSS_Hard SPI_NSS_Soft 描述/CR1.SSM/bit9 NSS由外部管脚管理 0x0000 内部NSS信号由SSI位控制 0x0200 SPI_BaudRatePrescaler:用来定义波特率预分频的值,这个值用以设置发送和接收的SCK时钟。 Table.02-7 SPI_BaudRatePrescaler值

SPI_BaudRatePrescaler SPI_BaudRatePrescaler2 SPI_BaudRatePrescaler4 SPI_BaudRatePrescaler8 描述/CR1.BR[2:0] 波特率预分频值为2 波特率预分频值为4 波特率预分频值为8 bit5-4 0x0000 0x0008 0x0010 SPI_BaudRatePrescaler16 SPI_BaudRatePrescaler32 SPI_BaudRatePrescaler64 SPI_BaudRatePrescaler128 SPI_BaudRatePrescaler256 波特率预分频值为16 波特率预分频值为32 波特率预分频值为64 波特率预分频值为128 波特率预分频值为256 0x0018 0x0020 0x0028 0x0030 0x0038 注意:通讯时钟由主SPI的时钟分频而得,不需要设置从SPI的时钟。 SPI_FirstBit:指定了数据传输从MSB位还是LSB 位开始。 Table.02-8 SPI_FirstBit值 SPI_FirstBit 描述/CR1. LSBFIRST SPI_FisrtBit_MSB SPI_FisrtBit_LSB 例:

/* Initialize the SPI1 according to the SPI_InitStructure members */ SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DatSize = SPI_DatSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure);

函数原型如下:

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct) {

u16 tmpreg = 0;

/* check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

/* Check the SPI parameters */

assert_param(IS_SPI_DIRECTION_MODE(SPI_InitStruct->SPI_Direction)); assert_param(IS_SPI_MODE(SPI_InitStruct->SPI_Mode));

assert_param(IS_SPI_DATASIZE(SPI_InitStruct->SPI_DataSize)); assert_param(IS_SPI_CPOL(SPI_InitStruct->SPI_CPOL)); assert_param(IS_SPI_CPHA(SPI_InitStruct->SPI_CPHA));

assert_param(IS_SPI_NSS(SPI_InitStruct->SPI_NSS));

assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_InitStruct->SPI_BaudRatePrescaler)); assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->SPI_FirstBit));

assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->SPI_CRCPolynomial));

/*---------------------------- SPIx CR1 Configuration ------------------------*/ /* Get the SPIx CR1 value */ tmpreg = SPIx->CR1;

/* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */ tmpreg &= CR1_CLEAR_Mask;// 0x3040,CR1除了CRCEN、CRCNEXT、SPE三个控制位,其他都清除。

bit7 数据传输从MSB位开始 0x0000 数据传输从LSB位开始 0x0080 SPI_CRCPolynomial:定义了用于CRC值计算的多项式:>= 0x1。

/* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler master/salve mode, CPOL and CPHA */

/* Set BIDImode, BIDIOE and RxONLY bits according to SPI_Direction value */ /* Set SSM, SSI and MSTR bits according to SPI_Mode and SPI_NSS values */ /* Set LSBFirst bit according to SPI_FirstBit value */

/* Set BR bits according to SPI_BaudRatePrescaler value */ /* Set CPOL bit according to SPI_CPOL value */

/* Set CPHA bit according to SPI_CPHA value */

tmpreg |= (u16)((u32)SPI_InitStruct->SPI_Direction | SPI_InitStruct->SPI_Mode | SPI_InitStruct->SPI_DataSize | SPI_InitStruct->SPI_CPOL | SPI_InitStruct->SPI_CPHA | SPI_InitStruct->SPI_NSS |

SPI_InitStruct->SPI_BaudRatePrescaler | SPI_InitStruct->SPI_FirstBit); /* Write to SPIx CR1 */ SPIx->CR1 = tmpreg;

/* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */

SPIx->I2SCFGR &= SPI_Mode_Select; // 0xF7FF,bit11:I2SMOD( 0--SPI;1--I2S )

/*---------------------------- SPIx CRCPOLY Configuration --------------------*/ /* Write to SPIx CRCPOLY */

SPIx->CRCPR = SPI_InitStruct->SPI_CRCPolynomial; }

/*【03】函数I2S_Init

****************************************************************************** * Function Name : I2S_Init

* Description : Initializes the SPIx peripheral according to the specified * parameters in the I2S_InitStruct.

* Input : - SPIx: where x can be 2 or 3 to select the SPI peripheral * (configured in I2S mode).

* - I2S_InitStruct: pointer to an I2S_InitTypeDef structure that * contains the configuration information for the specified * SPI peripheral configured in I2S mode. * Output : None

* Return : None

******************************************************************************/ 结构体I2S_InitTypeDef定义如下:

typedef struct {

u16 I2S_Mode;

u16 I2S_Standard; u16 I2S_DataFormat; u16 I2S_MCLKOutput; u16 I2S_AudioFreq; u16 I2S_CPOL; }I2S_InitTypeDef; [1]、I2S_Mode:

Table.03-1 I2S模式设置,设置主/从模式的发送/接收。 I2S_Mode 意义/I2SCFGR.bit9-8 #define Val

I2S_Mode_SlaveTx I2S_Mode_SlaveRx I2S_Mode_MasterTx I2S_Mode_MasterRx 从模式发送 从模式接收 主模式发送 主模式接收 0x0000 0x0100 0x0200 0x0300 [2]、I2S_Standard:I2S标准选择 Table.03-2 I2S 标准选择值如下表

I2S_Standard I2S_Standard_MSB I2S_Standard_LSB I2S_Standard_PCMLong 意义/I2SCFGR 左<高位>对齐标准 右<低位>对齐标准 PCM模式下的长帧同步 #define 0x0000 0x0010 0x0020 0x0030 0x00B0 单位或组合意义 bit5-4 = I2SSTD =0b00 bit5-4 = I2SSTD =0b01 bit5-4 = I2SSTD =0b10 I2SSTD=11(bit5-4/PCM标准)下,PMCSYNC(bit7)才有意义:0-短帧同步,1-短帧同步 I2S_Standard_Phillips I2S飞利浦标准 I2S_Standard_PCMShort PCM模式下的短帧同步 [3]、I2S_DataFormat:设定通道数据长度值 Table.03-3通道数据长度

I2S_DataFormat I2S_DataFormat_16b 意义/I2SCFGR 待传输数据长度16位 #define 0x0000 单位或组合意义 bit0(CHLEN)=0:通道数据长度固定为16位。 bit2-1(DATLEN)为任何值都是16位数据。 bit0=1(32位位宽): bit2-1=00—16位扩展数据 bit2-1=01—24位数据 bit2-1=10—32位数据 bit2-1=11—保留 I2S_DataFormat_16bextended 待传输数据长度扩展16位 0x0001 I2S_DataFormat_24b 待传输数据长度24位 0x0003 I2S_DataFormat_32b 待传输数据长度32位 0x0005 上述“扩展16位”、“24位”、“32位”表示数据以32位包的形式传输。由CHLEN = 1(32位包)决定。对于“扩展16位”,数据16位放在32位包的MSB处,后16位LSB强制位0填充;对于“24位”、“32位”,放在MSB除,LSB也强制填充为0,发送时分2次发送。 [4]、I2S_MCLKOutput:主设备时钟输出使能 Table.03-4主设备时钟输出使能

I2S_MCLKOutput I2S_MCLKOutput_Enable 意义/I2SPR.bit9 使能主设备时钟输出 #define 0x0200 I2S_MCLKOutput_Disable 关闭主设备时钟输出 0x0000 [5]、I2S_AudioFreq:从定义的音频通道采样频率计算出I2SDIV[7:0]的值。 Table.03-5音频通道采样频率

I2S_AudioFreq I2S_AudioFreq_48k I2S_AudioFreq_44k I2S_AudioFreq_22k I2S_AudioFreq_16k I2S_AudioFreq_8k 意义:实际目标值[Fs] 通道数据频率48KHz 通道数据频率44.1KHz 通道数据频率16KHz 通道数据频率8KHz 目标频率值 (u16)48000 (u16)44100 (u16)16000 (u16)8000 (u16)2 获取I2SDIV值的方法 I2S的音频采样频率[Fs]: 通过RCC_GetClocksFreq()获取系统时间,然后根据I2SPR的ODD位及I2SDIV位,计算出填入I2SDIV[7:0]内的线性分频值。而不是直接把“目标频率值”直接填入I2SDIV[7:0]内。 同时I2SDIV的最终值,要受MCKOE控制。 通道数据频率22.05KHz (u16)22050 I2S_AudioFreq_Default 通道数据频率2Hz 下图是I2S时钟发生器的结构图

线性分频器需要按照以下的公式来设置,以获得需要的频率:

1、当需要生成主时钟时(寄存器SPI->I2SPR的MCKOE =‘1’) :

A、声道的帧长为16位时,Fs = I2SxCLK / [(16*2) * ((2*I2SDIV) + ODD)*8]

B、声道的帧长为32位时,Fs = I2SxCLK / [(32*2) * ((2*I2SDIV) + ODD)*4]

即:在MCKOE=1时,不管声道帧长为16位或32或,固定Fs= I2SxCLK / [256 * ((2*I2SDIV) + ODD)] 2、当关闭主时钟时(MCKOE =‘0’) :

A、声道的帧长为16位时,Fs = I2SxCLK / [(16*2) * ((2*I2SDIV) + ODD)] B、声道的帧长为32位时,Fs = I2SxCLK / [(32*2) * ((2*I2SDIV) + ODD)] 上述

1、I2SxCLK 的时钟源是系统时钟(即驱动AHB时钟的HSI、HSE或PLL )

2、第一个“2”表示左右声道; 3、“(2*I2SDIV) + ODD”表示I2SPR内bit8-0控制关系;

4、“16”或“32”表示帧长度,指的是I2SCFGR.CHLEN控制下的位宽;

5、“8”或“4”表示“I2S主时钟可以输出到外部音频设备,比率固定为256*Fs”模式下的256对齐系数。 6、Fs = 音频通道采样频率(参看I2S_AudioFreq取值); 7、I2SxCLK为I2Sx的外设时钟。 而:

I2S 的比特率即确定了在I2S 数据线上的数据流和I2S的时钟信号频率。 I2S比特率 = 每个声道的比特数 × 声道数目 × 音频采样频率 对于一个左右声道,16位音频,I2S比特率计算为:I2S 比特率 = 16 × 2 × Fs 如果包长为32位,则有:I2S 比特率 = 32 × 2 × Fs

[6]、I2S_CPOL:I2S静止态时钟极性:为高电平还是位低电平。 Table.03-6 空闲状态下,时钟的电平取值

I2S_CPOL I2S_CPOL_Low 描述/I2SCFGR.bit3 #define I2S时钟静止态为低电平 ((u16)0x0000) I2S_CPOL_High I2S时钟静止态为高电平 ((u16)0x0008) 在调用本函数之前,必须对上述结构体成员进行数据初始化设置。 函数原型如下:

void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct) {

u16 tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; u32 tmp = 0;

RCC_ClocksTypeDef RCC_Clocks;

/* Check the I2S parameters */

assert_param(IS_SPI_23_PERIPH(SPIx));

assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode));

assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard));

assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat)); assert_param(IS_I2S_MCLK_OUTPUT(I2S_InitStruct->I2S_MCLKOutput)); assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->I2S_AudioFreq)); assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL));

/*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/

/* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits *///全配置 SPIx->I2SCFGR &= I2SCFGR_CLEAR_Mask; //0xF040

//Bit6、Bit12-15为保留位,不改变,保持为0;

//备注:凡Mask直接清0寄存器位,保留位对应的Mask值一律保持为1,以保证不改变原0值状态。 SPIx->I2SPR = 0x0002;

/* Get the I2SCFGR register value */

tmpreg = SPIx->I2SCFGR;

/* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default)//缺省频率为2Hz

{

i2sodd = (u16)0;//偶系数:Freq = i2sdiv*2。如果设置为1(奇系数),则Freq = i2sdiv*2+1 i2sdiv = (u16)2; //2分频值,结合上句,则实际时钟为2*2=4分频。

}

/* If the requested audio frequency is not the default, compute the prescaler */ else {

/* Check the frame length (For the Prescaler computing) */

if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b)//通道位宽16位 {

/* Packet length is 16 bits */

packetlength = 1;//包长为1表示16位。此时,CHLEN = 0。 }

else//扩展16位?24位?32位? {

/* Packet length is 32 bits */

packetlength = 2; //包长为2表示32位。此时,CHLEN = 1。包长这里起到控制程序作用。 }

/* Get System Clock frequency */

RCC_GetClocksFreq(&RCC_Clocks);//来源于SYSCLK(AHB)—HSI? PLLCLK? HSE?

/* Compute the Real divider depending on the MCLK output state with a flaoting point */ if(I2S_InitStruct->I2S_MCLKOutput == I2S_MCLKOutput_Enable)//MCKOE = 1 {

/* MCLK output is enabled */

tmp = (u16)(((10 * RCC_Clocks.SYSCLK_Frequency) / (256 * I2S_InitStruct->I2S_AudioFreq)) + 5); }// RCC_Clocks.SYSCLK_Frequency = HSI或HSE或PLLCLK = 8M、16M、24M、48M、72M。 else//MCKOE = 0 {

/* MCLK output is disabled */

tmp = (u16)(((10 * RCC_Clocks.SYSCLK_Frequency) / (32 * packetlength * \\

I2S_InitStruct->I2S_AudioFreq)) + 5);// packetlength* AudioFreq = I2S 比特率。 }

/* Remove the flaoting point */

tmp = tmp/10;

//*10、 +5、/10,以保证tmp取值为四舍五入。

//仅在(MCKOE = 1)8M时钟 48K、44.1K、22.05K取值,

// 16M时钟 48K、44.1K取值下,tmp = 1,其他取值都能保证>=2。 /* Check the parity of the divider */

i2sodd = (u16)(tmp & (u16)0x0001);//获取分频系数的奇偶性(LSB)。

/* Compute the i2sdiv prescaler */

i2sdiv = (u16)((tmp - i2sodd) / 2);//去除奇偶性后的分频值,即去掉LSB。

/* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */

i2sodd = (u16) (i2sodd << 8);//把决定奇偶性的LSB位左移8位,用于控制I2SPR.ODD位。 }

/* Test if the divider is 1 or 0 */ if ((i2sdiv < 2) || (i2sdiv > 0xFF)) {

/* Set the default values */ i2sdiv = 2;

i2sodd = 0; //如果分频系数小于2或大于0xFF,都把分频系数设置为:Default、偶分频。 }

/* Write to SPIx I2SPR register the computed value */

SPIx->I2SPR = (u16)(i2sdiv | i2sodd | I2S_InitStruct->I2S_MCLKOutput);

/* Configure the I2S with the SPI_InitStruct values */

tmpreg |= (u16)(I2S_Mode_Select | I2S_InitStruct->I2S_Mode | \\

I2S_InitStruct->I2S_Standard | I2S_InitStruct->I2S_DataFormat | \\ I2S_InitStruct->I2S_CPOL);

/* Write to SPIx I2SCFGR */

SPIx->I2SCFGR = tmpreg; }

被调用函数RCC_GetClocksFreq(&RCC_Clocks);如下

/*【04】函数SPI_StructInit

****************************************************************************** * Function Name : SPI_StructInit

* Description : Fills each SPI_InitStruct member with its default value. * Input : - SPI_InitStruct : pointer to a SPI_InitTypeDef structure * which will be initialized.

* Output : None * Return : None

*******************************************************************************/ Table 420. 给出了SPI_InitStruct各个成员的缺省值 Table.04-1 SPI_InitStruct缺省值

成员 SPI_Direction SPI_Mode SPI_DataSize SPI_CPOL SPI_CPHA SPI_NSS SPI_BaudRatePrescaler SPI_FirstBit 缺省值 SPI_Direction_2Lines_FullDuplex SPI_Mode_Slave SPI_DataSize_8b SPI_CPOL_Low SPI_CPHA_1Edge SPI_NSS_Hard SPI_BaudRatePrescaler_2 SPI_FirstBit_MSB SPI_CRCPolynomial 7 结构体I2S_InitTypeDef定义如下: typedef struct {

u16 I2S_Mode;

u16 I2S_Standard; u16 I2S_DataFormat; u16 I2S_MCLKOutput; u16 I2S_AudioFreq; u16 I2S_CPOL; }I2S_InitTypeDef;

例:

/* Initialize an SPI_InitTypeDef structure */ SPI_InitTypeDef SPI_InitStructure;

SPI_StructInit(&SPI_InitStructure); 函数原型如下:

void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct) {

/*--------------- Reset SPI init structure parameters values -----------------*/ /* Initialize the SPI_Direction member */

SPI_InitStruct->SPI_Direction = SPI_Direction_2Lines_FullDuplex;

/* initialize the SPI_Mode member */ SPI_InitStruct->SPI_Mode = SPI_Mode_Slave;

/* initialize the SPI_DataSize member */

SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b;

/* Initialize the SPI_CPOL member */

SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low;

/* Initialize the SPI_CPHA member */ SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge;

/* Initialize the SPI_NSS member */

SPI_InitStruct->SPI_NSS = SPI_NSS_Hard;

/* Initialize the SPI_BaudRatePrescaler member */

SPI_InitStruct->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;

/* Initialize the SPI_FirstBit member */

SPI_InitStruct->SPI_FirstBit = SPI_FirstBit_MSB;

/* Initialize the SPI_CRCPolynomial member */ SPI_InitStruct->SPI_CRCPolynomial = 7; }

/*【05】函数I2S_StructInit

****************************************************************************** * Function Name : I2S_StructInit

* Description : Fills each I2S_InitStruct member with its default value. * Input : - I2S_InitStruct : pointer to a I2S_InitTypeDef structure

* which will be initialized. * Output : None

* Return : None

*******************************************************************************/ void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct) {

/*--------------- Reset I2S init structure parameters values -----------------*/ /* Initialize the I2S_Mode member */

I2S_InitStruct->I2S_Mode = I2S_Mode_SlaveTx;

/* Initialize the I2S_Standard member */

I2S_InitStruct->I2S_Standard = I2S_Standard_Phillips;

/* Initialize the I2S_DataFormat member */

I2S_InitStruct->I2S_DataFormat = I2S_DataFormat_16b;

/* Initialize the I2S_MCLKOutput member */

I2S_InitStruct->I2S_MCLKOutput = I2S_MCLKOutput_Disable;

/* Initialize the I2S_AudioFreq member */

I2S_InitStruct->I2S_AudioFreq = I2S_AudioFreq_Default;

/* Initialize the I2S_CPOL member */

I2S_InitStruct->I2S_CPOL = I2S_CPOL_Low; }

/*【06】函数SPI_Cmd

****************************************************************************** * Function Name : SPI_Cmd

* Description : Enables or disables the specified SPI peripheral.

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * - NewState: new state of the SPIx peripheral. * This parameter can be: ENABLE or DISABLE. * Output : None

* Return : None

*******************************************************************************/ void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx)); assert_param(IS_FUNCTIONAL_STATE(NewState));

if (NewState != DISABLE) {

/* Enable the selected SPI peripheral */

SPIx->CR1 |= CR1_SPE_Set;// 0x0040,开启SPI设备 } else {

/* Disable the selected SPI peripheral */ SPIx->CR1 &= CR1_SPE_Reset;// 0xFFBF } }

/*【07】函数I2S_Cmd

****************************************************************************** * Function Name : I2S_Cmd

* Description : Enables or disables the specified SPI peripheral (in I2S mode). * Input : - SPIx: where x can be 2 or 3 to select the SPI peripheral. * - NewState: new state of the SPIx peripheral. * This parameter can be: ENABLE or DISABLE. * Output : None * Return : None

*******************************************************************************/ void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) {

/* Check the parameters */

assert_param(IS_SPI_23_PERIPH(SPIx)); assert_param(IS_FUNCTIONAL_STATE(NewState));

if (NewState != DISABLE)

{

/* Enable the selected SPI peripheral (in I2S mode) */ SPIx->I2SCFGR |= I2SCFGR_I2SE_Set;// 0x0400,开启I2S } else

{

/* Disable the selected SPI peripheral (in I2S mode) */ SPIx->I2SCFGR &= I2SCFGR_I2SE_Reset;// 0xFBFF }

}

/*【08】函数SPI_I2S_ITConfig

****************************************************************************** * Function Name : SPI_I2S_ITConfig

* Description : Enables or disables the specified SPI/I2S interrupts. * Input : - SPIx: where x can be :

* - 1, 2 or 3 in SPI mode * - 2 or 3 in I2S mode

* - SPI_I2S_IT: specifies the SPI/I2S interrupt source to be enabled or disabled. * This parameter can be one of the following values: * - SPI_I2S_IT_TXE: Tx buffer empty interrupt mask

* - SPI_I2S_IT_RXNE: Rx buffer not empty interrupt mask * - SPI_I2S_IT_ERR: Error interrupt mask

* - NewState: new state of the specified SPI/I2S interrupt. * This parameter can be: ENABLE or DISABLE. * Output : None * Return : None

*******************************************************************************/

SPI_IT:输入参数SPI_IT使能或者失能SPI的中断。可以取下表的一个或者多个取值的组合作为该参数的值。 Table.08-1 SPI_IT值 SPI_I2S_IT 描述/CR2 SPI_I2S_IT_TXE 发送缓存空中断屏蔽 SPI_I2S_IT_RXNE 接收缓存非空中断屏蔽 SPI_I2S_IT_ERR 错误中断屏蔽 例:

/* Enable SPI2 Tx buffer empty interrupt */ SPI_ITConfig(SPI2, SPI_IT_TXE, ENABLE); 函数原型如下:

void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, u8 SPI_I2S_IT, FunctionalState NewState) {

u16 itpos = 0, itmask = 0 ;

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_FUNCTIONAL_STATE(NewState)); assert_param(IS_SPI_I2S_CONFIG_IT(SPI_I2S_IT));

/* Get the SPI/I2S IT index */

itpos = SPI_I2S_IT >> 4;//取出IT在CR2的位置 /* Set the IT mask */

itmask = (u16)((u16)1 << itpos);

if (NewState != DISABLE) {

/* Enable the selected SPI/I2S interrupt */ SPIx->CR2 |= itmask;//开启中断允许 } else {

/* Disable the selected SPI/I2S interrupt */ SPIx->CR2 &= (u16)~itmask; } }

/*【09】函数SPI_I2S_DMACmd

****************************************************************************** * Function Name : SPI_I2S_DMACmd

* Description : Enables or disables the SPIx/I2Sx DMA interface. * Input : - SPIx: where x can be : * - 1, 2 or 3 in SPI mode

* - 2 or 3 in I2S mode

* - SPI_I2S_DMAReq: specifies the SPI/I2S DMA transfer request * to be enabled or disabled.

* This parameter can be any combination of the following values: * - SPI_I2S_DMAReq_Tx: Tx buffer DMA transfer request * - SPI_I2S_DMAReq_Rx: Rx buffer DMA transfer request

#Val CR2中的位置 0x71 bit7 0x60 bit6 0x50 bit5 * - NewState: new state of the selected SPI/I2S DMA transfer * request.

* This parameter can be: ENABLE or DISABLE. * Output : None

* Return : None

*******************************************************************************/ SPI_DMAReq:SPI_DMAReq使能或者失能SPI Tx和/或SPI Rx的DMA传输请求。 Table.09-1 SPI_DMAReq值 SPI_I2S_DMAReq 描述/CR2 SPI_I2S_DMAReq_Tx 选择Tx缓存DMA传输请求 0x0002 bit1 SPI_I2S_DMAReq_Rx 选择Rx缓存DMA传输请求 0x0001 bit0 例:

/* Enable SPI2 Rx buffer DMA transfer request */ SPI_DMACmd(SPI2, SPI_DMAReq_Rx, ENABLE); 函数原型如下:

void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, u16 SPI_I2S_DMAReq, FunctionalState NewState) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_FUNCTIONAL_STATE(NewState)); assert_param(IS_SPI_I2S_DMAREQ(SPI_I2S_DMAReq));

if (NewState != DISABLE)

{

/* Enable the selected SPI/I2S DMA requests */ SPIx->CR2 |= SPI_I2S_DMAReq;//开启DMA请求。 } else

{

/* Disable the selected SPI/I2S DMA requests */ SPIx->CR2 &= (u16)~SPI_I2S_DMAReq; }

}

/*【10】函数SPI_I2S_SendData

****************************************************************************** * Function Name : SPI_I2S_SendData

* Description : Transmits a Data through the SPIx/I2Sx peripheral. * Input : - SPIx: where x can be :

* - 1, 2 or 3 in SPI mode * - 2 or 3 in I2S mode * - Data : Data to be transmitted.. * Output : None

* Return : None

*******************************************************************************/ void SPI_I2S_SendData(SPI_TypeDef* SPIx, u16 Data) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

/* Write in the DR register the data to be sent */ SPIx->DR = Data; }

/*【11】函数SPI_I2S_ReceiveData

****************************************************************************** * Function Name : SPI_I2S_ReceiveData

* Description : Returns the most recent received data by the SPIx/I2Sx peripheral. * Input : - SPIx: where x can be : * - 1, 2 or 3 in SPI mode * - 2 or 3 in I2S mode

* Output : None

* Return : The value of the received data.

*******************************************************************************/ u16 SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

/* Return the data in the DR register */ return SPIx->DR; }

/*【12】函数SPI_NSSInternalSoftwareConfig

****************************************************************************** * Function Name : SPI_NSSInternalSoftwareConfig

* Description : Configures internally by software the NSS pin for the selected * SPI.

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * - SPI_NSSInternalSoft: specifies the SPI NSS internal state. * This parameter can be one of the following values: * - SPI_NSSInternalSoft_Set: Set NSS pin internally

* - SPI_NSSInternalSoft_Reset: Reset NSS pin internally * Output : None

* Return : None

* Note : NSS = Slave Select

*******************************************************************************/ SPI_NSSInternalSoft:内部设置或者重置NSS管脚。 Table.12-1 SPI_DMAReq值

SPI_NSSInternalSoft SPI_NSSInternalSoft_Set SPI_NSSInternalSoft_Reset 例: 描述/CR1.SSI/bit8 内部设置NSS管脚 内部重置NSS管脚 #Val 0x0100 0xFEFF /* Set internaly by software the SPI1 NSS pin */

SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set); /* Reset internaly by sofwtare the SPI2 NSS pin */

SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Reset);

函数原型如下:

void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, u16 SPI_NSSInternalSoft)

{

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_SPI_NSS_INTERNAL(SPI_NSSInternalSoft));

if (SPI_NSSInternalSoft != SPI_NSSInternalSoft_Reset) {

/* Set NSS pin internally by software */ SPIx->CR1 |= SPI_NSSInternalSoft_Set; } else

{

/* Reset NSS pin internally by software */ SPIx->CR1 &= SPI_NSSInternalSoft_Reset; } }

/*【13】函数SPI_SSOutputCmd

****************************************************************************** * Function Name : SPI_SSOutputCmd

* Description : Enables or disables the SS output for the selected SPI. * Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * - NewState: new state of the SPIx SS output. * This parameter can be: ENABLE or DISABLE. * Output : None

* Return : None

*******************************************************************************/ void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx)); assert_param(IS_FUNCTIONAL_STATE(NewState));

if (NewState != DISABLE)

{

/* Enable the selected SPI SS output */

SPIx->CR2 |= CR2_SSOE_Set;// 0x0004,开启在主模式下SS输出,该设备不能工作在多主设备模式 } else {

/* Disable the selected SPI SS output */

SPIx->CR2 &= CR2_SSOE_Reset;// 0xFFFB,禁止在主模式下SS输出,该设备可以工作在多主设备模式 } }

/*【14】函数SPI_DataSizeConfig

****************************************************************************** * Function Name : SPI_DataSizeConfig

* Description : Configures the data size for the selected SPI.

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * - SPI_DataSize: specifies the SPI data size.

* This parameter can be one of the following values:

* - SPI_DataSize_16b: Set data frame format to 16bit. * - SPI_DataSize_8b: Set data frame format to 8bit. * Output : None * Return : None

*******************************************************************************/ SPI_DataSize:设置8 位或者16位数据帧结构。 Table.14-1 SPI_DMAReq值

SPI_DataSize SPI_DataSize_8b 例: /* Set 8bit data frame format for SPI1 */ SPI_DataSizeConfig(SPI1, SPI_DataSize_8b); /*Set 16bit data frame format for SPI2 */ SPI_DataSizeConfig(SPI2, SPI_DataSize_16b);

函数原型如下:

void SPI_DataSizeConfig(SPI_TypeDef* SPIx, u16 SPI_DataSize) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx)); assert_param(IS_SPI_DATASIZE(SPI_DataSize));

/* Clear DFF bit */

SPIx->CR1 &= (u16)~SPI_DataSize_16b;//用“16b”值复位DFF位值。 /* Set new DFF bit value */ SPIx->CR1 |= SPI_DataSize; }

/*【15】函数SPI_TransmitCRC

****************************************************************************** * Function Name : SPI_TransmitCRC

* Description : Transmit the SPIx CRC value.

* Input : - SPIx(Not Include I2Sx): where x can be 1, 2 or 3 to select the SPI peripheral. * Output : None * Return : None

*******************************************************************************/ void SPI_TransmitCRC(SPI_TypeDef* SPIx) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

/* Enable the selected SPI CRC transmission */

SPIx->CR1 |= CR1_CRCNext_Set;// 0x1000,下一个发送CRC:1--下一个发送的值来自发送CRC寄存器 }//若为0--下一个发送的值来自发送缓冲区

/*【16】函数SPI_CalculateCRC

描述/CR1.DFF/bit11 设置数据帧格式为8位 #Value 0x0000 0x0800 SPI_DataSize_16b 设置数据帧格式为16位 ****************************************************************************** * Function Name : SPI_CalculateCRC

* Description : Enables or disables the CRC value calculation of the * transfered bytes.

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * - NewState: new state of the SPIx CRC value calculation. * This parameter can be: ENABLE or DISABLE. * Output : None * Return : None

*******************************************************************************/ void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx)); assert_param(IS_FUNCTIONAL_STATE(NewState));

if (NewState != DISABLE) {

/* Enable the selected SPI CRC calculation */

SPIx->CR1 |= CR1_CRCEN_Set;// 0x2000,硬件CRC校验使能:开启CRC计算 } else

{

/* Disable the selected SPI CRC calculation */ SPIx->CR1 &= CR1_CRCEN_Reset;// 0xDFFF } }

/*【17】函数SPI_GetCRC

****************************************************************************** * Function Name : SPI_GetCRC

* Description : Returns the transmit or the receive CRC register value for * the specified SPI.

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * - SPI_CRC: specifies the CRC register to be read. * This parameter can be one of the following values: * - SPI_CRC_Tx: Selects Tx CRC register * - SPI_CRC_Rx: Selects Rx CRC register * Output : None

* Return : The selected CRC register value..

*******************************************************************************/ SPI_CRC:SPI_CRC选择SPI Rx 或SPI Tx的 CRC 寄存器。 Table.17-1 SPI_CRC值 SPI_CRC SPI_CRC_Tx SPI_CRC_Rx 例:

描述 选择Tx CRC寄存器 选择Rx CRC寄存器 (u8)0x00 (u8)0x01 /* Returns the SPI1 transmit CRC register */ u16 CRCValue;

CRCValue = SPI_GetCRC(SPI1, SPI_CRC_Tx); 函数原型如下:

u16 SPI_GetCRC(SPI_TypeDef* SPIx, u8 SPI_CRC) {

u16 crcreg = 0;

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx)); assert_param(IS_SPI_CRC(SPI_CRC));

if (SPI_CRC != SPI_CRC_Rx)//如果是TXCRC,读TXCRCR {

/* Get the Tx CRC register */ crcreg = SPIx->TXCRCR; }

else//否则是RXCRC,读RXCRCR {

/* Get the Rx CRC register */ crcreg = SPIx->RXCRCR; }

/* Return the selected CRC register */ return crcreg; }

/*【18】函数SPI_GetCRCPolynomial

****************************************************************************** * Function Name : SPI_GetCRCPolynomial

* Description : Returns the CRC Polynomial register value for the specified SPI. * Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * Output : None

* Return : The CRC Polynomial register value.

*******************************************************************************/ u16 SPI_GetCRCPolynomial(SPI_TypeDef* SPIx) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

/* Return the CRC polynomial register */ return SPIx->CRCPR;//u16 }

/*【19】函数SPI_BiDirectionalLineConfig

****************************************************************************** * Function Name : SPI_BiDirectionalLineConfig

* Description : Selects the data transfer direction in bi-directional mode * for the specified SPI.

* Input : - SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. * - SPI_Direction: specifies the data transfer direction in

* bi-directional mode.

* This parameter can be one of the following values: * - SPI_Direction_Tx: Selects Tx transmission direction * - SPI_Direction_Rx: Selects Rx receive direction * Output : None * Return : None

*******************************************************************************/ SPI_Direction:SPI_Direction选择SPI在双向模式下的数据传输方向。 Table.19-1 SPI_CRC值

SPI_Direction 描述/CR1. SPI_Direction_Tx 选择Tx发送方向 SPI_Direction_Rx 选择Rx接受方向 例:

bit14 #Val 0x4000 0xBFFF /* Set the SPI2 in bidirectional transmit only mode */

SPI_BiDirectionalLineConfig(SPI_Direction_Tx); 函数原型如下:

void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, u16 SPI_Direction) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_SPI_DIRECTION(SPI_Direction));

if (SPI_Direction == SPI_Direction_Tx)

{

/* Set the Tx only mode */// 该位和BIDIMODE(=1)位一起决定在“单线双向”模式下数据的传输方向 SPIx->CR1 |= SPI_Direction_Tx;// 1(输出使能(只发模式)) } else {

/* Set the Rx only mode */

SPIx->CR1 &= SPI_Direction_Rx;// 0(输出禁止(只收模式)) } }

/*【20】函数SPI_I2S_GetFlagStatus

****************************************************************************** * Function Name : SPI_I2S_GetFlagStatus

* Description : Checks whether the specified SPI/I2S flag is set or not. * Input : - SPIx: where x can be :

* - 1, 2 or 3 in SPI mode

* - 2 or 3 in I2S mode

* - SPI_I2S_FLAG: specifies the SPI/I2S flag to check. * This parameter can be one of the following values: * - SPI_I2S_FLAG_TXE: Transmit buffer empty flag.

* - SPI_I2S_FLAG_RXNE: Receive buffer not empty flag. * - SPI_I2S_FLAG_BSY: Busy flag. * - SPI_I2S_FLAG_OVR: Overrun flag. * - SPI_FLAG_MODF: Mode Fault flag. * - SPI_FLAG_CRCERR: CRC Error flag.

* - I2S_FLAG_UDR: Underrun Error flag. * - I2S_FLAG_CHSIDE: Channel Side flag. * Output : None

* Return : The new state of SPI_I2S_FLAG (SET or RESET).

*******************************************************************************/ SPI_FLAG:Table 441. 给出了所有可以被函数SPI_GetFlagStatus检查的标志位列表 Table.20-1 SPI_FLAG值

SPI_FLAG SPI_I2S_FLAG_BSY SPI_I2S_FLAG_OVR SPI_I2S_FLAG_MODF SPI_I2S_FLAG_CRCERR SPI_I2S_FLAG_UDR SPI_I2S_FLAG_CHSIDE SPI_I2S_FLAG_TXE SPI_I2S_FLAG_RXNE 描述/SR.bit7-0 忙标志位 超出标志位(overrun) 模式错位标志位 CRC错误标志位 发生下溢(underrun) 需要传输或者接收右声道 发送缓存空标志位 接受缓存非空标志位 #Val 0x0080 0x0040 0x0020 0x0010 ERRIE 0x0008 0x0004 0x0002 TXEIE 0x0001 RXNEIE 控制位 —— 函数原型如下:

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, u16 SPI_I2S_FLAG) {

FlagStatus bitstatus = RESET;

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));

/* Check the status of the specified SPI/I2S flag */ if ((SPIx->SR & SPI_I2S_FLAG) != (u16)RESET) {

/* SPI_I2S_FLAG is set */ bitstatus = SET; } else

{

/* SPI_I2S_FLAG is reset */ bitstatus = RESET; }

/* Return the SPI_I2S_FLAG status */ return bitstatus; }

/*【21】函数SPI_I2S_ClearFlag

****************************************************************************** * Function Name : SPI_I2S_ClearFlag

* Description : Clears the SPIx/I2Sx pending flags. * Input : - SPIx: where x can be : * - 1, 2 or 3 in SPI mode * - 2 or 3 in I2S mode

* - SPI_I2S_FLAG: specifies the SPI/I2S flag to clear. * This parameter can be one of the following values:

* - SPI_I2S_FLAG_OVR: Overrun flag * - SPI_FLAG_MODF: Mode Fault flag. * - SPI_FLAG_CRCERR: CRC Error flag. * - I2S_FLAG_UDR: Underrun Error flag.

* Note: Before clearing OVR flag, it is mandatory to read

* SPI_I2S_DR register, so that the last data is not lost. * Output : None

* Return : None

*******************************************************************************/ 可以清除的Flag只有4个:如下表:

Table.21-1可以清除的中断标志位如下:(对照Table.20-1)

SPI_I2S_FLAG SPI_I2S_FLAG_BSY SPI_I2S_FLAG_OVR SPI_FLAG_MODF SPI_FLAG_CRCERR I2S_FLAG_UDR I2S_FLAG_CHSIDE SPI_I2S_FLAG_TXE SPI_I2S_FLAG_RXNE 函数原型如下: void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, u16 SPI_I2S_FLAG) {

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_SPI_I2S_CLEAR_FLAG(SPI_I2S_FLAG));

/* SPI_FLAG_MODF flag clear */ if(SPI_I2S_FLAG == SPI_FLAG_MODF) {

/* Read SR register */

(void)SPIx->SR;//[1]读或写SR

/* Write on CR1 register */

SPIx->CR1 |= CR1_SPE_Set; //[2]写CR1。 }//通过[1][2]步骤,可以清除MODF标志位

/* SPI_I2S_FLAG_OVR flag or I2S_FLAG_UDR flag clear */

else if ((SPI_I2S_FLAG == SPI_I2S_FLAG_OVR) || (SPI_I2S_FLAG == I2S_FLAG_UDR))

{

/* Read SR register (Before clearing OVR flag, it is mandatory to read SPI_I2S_DR register)*/ (void)SPIx->SR;//对于上溢标志OVR和下溢标志UDR,读SR即可清除这两位中断标志 }

else /* SPI_FLAG_CRCERR flag clear */ {

/* Clear the selected SPI flag */

SPIx->SR = (u16)~SPI_I2S_FLAG;//对于CRCERR,只要直接写0即可清除。 } }

描述/SR.bit7-0 忙标志位 超出标志位(overrun) 模式错位标志位 CRC错误标志位 发生下溢(underrun) 发送缓存空标志位 接收缓存非空标志位 #Val 0x0080 0x0040 0x0020 0x0010 0x0008 0x0002 0x0001 可否清除 清除方式 —— 读SR 读SR->写CR1 直接写0 读SR 读SR,但要求OVR、UDR、ERRIE被清除之后。 写数据到DR 或令I2SE =0 控制位 —— ERRIE 需要传输或者接收右声道 0x0004 从DR读数据 TXEIE RXNEIE

/*【22】函数SPI_I2S_GetITStatus

****************************************************************************** * Function Name : SPI_I2S_GetITStatus

* Description : Checks whether the specified SPI/I2S interrupt has occurred or not. * Input : - SPIx: where x can be : * - 1, 2 or 3 in SPI mode

* - 2 or 3 in I2S mode

* - SPI_I2S_IT: specifies the SPI/I2S interrupt source to check. * This parameter can be one of the following values: * - SPI_I2S_IT_TXE: Transmit buffer empty interrupt. * - SPI_I2S_IT_RXNE: Receive buffer not empty interrupt. * - SPI_I2S_IT_OVR: Overrun interrupt. * - SPI_IT_MODF: Mode Fault interrupt. * - SPI_IT_CRCERR: CRC Error interrupt. * - I2S_IT_UDR: Underrun Error interrupt.

* Output : None

* Return : The new state of SPI_I2S_IT (SET or RESET).

*******************************************************************************/ SPI_I2S_IT:下表给出了所有可以被函数SPI_ GetITStatus检查的中断标志位列表。 Table.22-1 SPI_IT值(SR中的CHSIDE和BUSY位本函数不检查)

SPI_I2S_IT SPI_I2S_IT_TXE SPI_I2S_IT_RXNE SPI_I2S_IT_OVR SPI_IT_MODF SPI_IT_CRCERR I2S_IT_UDR 例: /* Test if the SPI1 Overrun interrupt has occurred or not */ ITStatus Status;

Status = SPI_GetITStatus(SPI1, SPI_IT_OVR);

函数原型如下:

ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, u8 SPI_I2S_IT) {

ITStatus bitstatus = RESET;

u16 itpos = 0, itmask = 0, enablestatus = 0;

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_SPI_I2S_GET_IT(SPI_I2S_IT));

/* Get the SPI/I2S IT index */

itpos = (u16)((u16)0x01 << (SPI_I2S_IT & (u8)0x0F));//取出中断标志在SR中的Bit位置。

/* Get the SPI/I2S IT mask */

itmask = SPI_I2S_IT >> 4;//取出中断产生的允许位在CR2中的bit位置 /* Set the IT mask */

itmask = (u16)((u16)0x01 << itmask);

描述/SR 发送缓存空中断标志位 超出中断标志位 模式错误标志位 CRC错误标志位 下溢中断标志位 #Value (u8)0x71 (u8)0x56 (u8)0x55 (u8)0x54 (u8)0x53 SR中的位置 在CR2中控制位位置 bit1 bit0 bit6 bit5 bit4 bit3 bit7=TXEIE bit6=RXNEIE bit5=ERRIE OVR、MODF、CRCERR、UDR标志位只有在ERRIE=1时才能产生 接受缓存非空中断标志位 (u8)0x60 /* Get the SPI_I2S_IT enable bit status */ enablestatus = (SPIx->CR2 & itmask) ;

/* Check the status of the specified SPI/I2S interrupt */

if (((SPIx->SR & itpos) != (u16)RESET) && enablestatus)

//SR中的标志位与CR2对应的控制位同时为1时,表明中断已被发生,并且有效。 {

/* SPI_I2S_IT is set */ bitstatus = SET; } else

{

/* SPI_I2S_IT is reset */ bitstatus = RESET; }

/* Return the SPI_I2S_IT status */ return bitstatus; }

/*【23】函数SPI_I2S_ClearITPendingBit

****************************************************************************** * Function Name : SPI_I2S_ClearITPendingBit

* Description : Clears the SPIx/I2Sx interrupt pending bits. * Input : - SPIx: where x can be : * - 1, 2 or 3 in SPI mode

* - 2 or 3 in I2S mode

* - SPI_I2S_IT: specifies the SPI/I2S interrupt pending bit to clear. * This parameter can be one of the following values: * - SPI_I2S_IT_OVR: Overrun interrupt. * - SPI_IT_MODF: Mode Fault interrupt. * - SPI_IT_CRCERR: CRC Error interrupt. * - I2S_IT_UDR: Underrun Error interrupt. * Output : None * Return : None

*******************************************************************************/ 下表给出了可以被清除的中断标志:

Table.23-1 可被清除的中断标志如下表。

[1]、本表完全采用Table.22-1 给出的参数值。 [2]、清除方式,参考Table.20-1。

SPI_I2S_IT SPI_I2S_IT_TXE SPI_I2S_IT_RXNE SPI_I2S_IT_OVR SPI_IT_MODF SPI_IT_CRCERR I2S_IT_UDR 函数原型如下: {

描述/SR 发送缓存空中断标志位 #Value (u8)0x71 SR中的位置 在CR2中控制位位置 可清除 bit1 bit0 bit6 bit5 bit4 bit3 bit7=TXEIE bit6=RXNEIE 间接 间接 接受缓存非空中断标志位 (u8)0x60 超出中断标志位 (u8)0x56 模式错误标志位 CRC错误标志位 下溢中断标志位 (u8)0x55 (u8)0x54 (u8)0x53 bit5=ERRIE 本函数 OVR、MODF、CRCERR、直接清UDR标志位只有在除。 ERRIE=1时才能产生 void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, u8 SPI_I2S_IT)

u16 itpos = 0;

/* Check the parameters */

assert_param(IS_SPI_ALL_PERIPH(SPIx));

assert_param(IS_SPI_I2S_CLEAR_IT(SPI_I2S_IT));

/* SPI_IT_MODF pending bit clear */ if(SPI_I2S_IT == SPI_IT_MODF) {

/* Read SR register */ (void)SPIx->SR;

/* Write on CR1 register */ SPIx->CR1 |= CR1_SPE_Set;

}//清除MODF位的操作方式:先读SR,再写CR1。

/* SPI_I2S_IT_OVR or I2S_IT_UDR pending bit clear */

else if((SPI_I2S_IT == SPI_I2S_IT_OVR) || (SPI_I2S_IT == I2S_IT_UDR)) {

/* Read SR register */

(void)(SPIx->SR);//对于清除OVR和UDR位的操作方式:只要读SR即可。 }

else /* SPI_IT_CRCERR pending bit clear */ {

/* Get the SPI/I2S IT index */

itpos = (u16)((u16)0x01 << (SPI_I2S_IT & (u8)0x0F));//取出CRCERR在SR中的位值( = bit4) /* Clear the selected SPI/I2S interrupt pending bits */

SPIx->SR = (u16)~itpos;//对于清除CRCERR位的操作方式:直接写0

//本语句不必采用“SPIx->SR &= (u16)~itpos;”的“&”操作: //写‘1’不能改变SR中其他7位中断标志的状态。 } }

本文来源:https://www.bwwdw.com/article/rbkr.html

Top