STM32_SPI_笔记

来源:互联网 发布:linux 浏览网页 编辑:程序博客网 时间:2024/06/05 03:13

SPI主机负责产生时钟,决定了SPI通信速率。可以同时收发数据;

时钟极性(CPOL)决定同步时钟空闲状态;

时钟相位(CPHA):0:CLK的第一个跳变沿(上升沿或下降沿)数据被采样;

1:CLK的第二个跳变沿数据被采样;


写:主机对SPIX->DR写数据,CLK产生时钟,同时数据从MOSI -> MISO

读:主机对SPIX->DR写DUMMY(空字节),CLK产生时钟,DUMMY信号从MOSI -> MISO (该数据对从机无意义),同时要读取的数据从 MISO -> MOSI,主机从SPIX->DR读取数据。然后清除DR,以便接收下一个数据。

读写SPIX -> DR是两个不同的寄存器。


SPI中断事件:

中断事件事件标志使能控制位发送缓冲器空标志TXETXEIE接收缓冲器非空标志RXNERXNEIE主模式错误事件MODFERRIE溢出错误OVRCRC错误标志CRCERR

案例1:简单SPI对接通信,SPI1主机,SPI3从机,中断方式,主机->从机

初始化代码

//步骤1 使能时钟void RCC_Configuration(void){    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOA|  RCC_APB2PERIPH_GPIOB |  RCC_APB2PERIPH_GPIOC| RCC_APB2PERIPH_AF , ENABLE);    RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_SPI1,ENABLE);    RCC_APB1PeriphClock_Enable( RCC_APB1PERIPH_SPI3 ,ENABLE );    }//步骤2 配置GPIOvoid GPIO_Configuration(void){    GPIO_InitPara GPIO_InitStructure;    GPIO_PinRemapConfig(GPIO_REMAP_SPI3, ENABLE);    /* Configure SPI_MASTER pins: SCK and MOSI */    GPIO_InitStructure.GPIO_Pin =  GPIO_PIN_5| GPIO_PIN_7;    GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;    GPIO_Init(GPIOA, &GPIO_InitStructure);    /* Configure SPI_SLAVE pins: SCK and MISO */    /* Configure SCK pin as Alternate Function */    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_10 ;    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN_FLOATING;    GPIO_Init(GPIOC, &GPIO_InitStructure);    /* Configure MISO pin as Alternate Function Push Pull */    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_11;    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;    GPIO_Init(GPIOC, &GPIO_InitStructure);}//步骤3 配置SPI,SPI1主机 SPI3从机void SPI_Configuration(void){SPI_InitPara SPI_InitStructure;SPI_InitStructure.SPI_TransType = SPI_TRANSTYPE_BDMTX;    SPI_InitStructure.SPI_Mode = SPI_MODE_MASTER;    SPI_InitStructure.SPI_FrameFormat = SPI_FRAMEFORMAT_8BIT;    SPI_InitStructure.SPI_SCKPL = SPI_SCKPL_LOW;    SPI_InitStructure.SPI_SCKPH = SPI_SCKPH_2EDGE;    SPI_InitStructure.SPI_SWNSSEN = SPI_SWNSS_SOFT;    SPI_InitStructure.SPI_PSC = SPI_PSC_16;    SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB;    SPI_InitStructure.SPI_CRCPOL = 7;    SPI_Init(SPI1, &SPI_InitStructure);    /* SPI_SLAVE configuration */    SPI_InitStructure.SPI_TransType = SPI_TRANSTYPE_BDMRX;    SPI_InitStructure.SPI_Mode = SPI_MODE_SLAVE;    SPI_Init(SPI3, &SPI_InitStructure);        /* Enable SPI_MASTER TBE interrupt */    SPI_I2S_INTConfig(SPI1, SPI_I2S_INT_TBE, ENABLE);    /* Enable SPI_SLAVE RBNE interrupt */    SPI_I2S_INTConfig(SPI3, SPI_I2S_INT_RBNE, ENABLE);    /* Enable SPI1 AND SPI3 */    SPI_Enable(SPI3, ENABLE);    SPI_Enable(SPI1, ENABLE);}//步骤4 配置中断void NVIC_Configuration(void){    NVIC_InitPara NVIC_InitStructure;    /* 1 bit for pre-emption priority, 3 bits for subpriority */    NVIC_PRIGroup_Enable(NVIC_PRIGROUP_1);    /* Configure and enable SPI_MASTER interrupt */    NVIC_InitStructure.NVIC_IRQ = SPI1_IRQn;    NVIC_InitStructure.NVIC_IRQPreemptPriority = 1;    NVIC_InitStructure.NVIC_IRQSubPriority = 2;    NVIC_InitStructure.NVIC_IRQEnable = ENABLE;    NVIC_Init(&NVIC_InitStructure);        /* Configure and enable SPI_SLAVE interrupt */    NVIC_InitStructure.NVIC_IRQ = SPI3_IRQn;    NVIC_InitStructure.NVIC_IRQPreemptPriority = 0;    NVIC_InitStructure.NVIC_IRQSubPriority = 1;    NVIC_InitStructure.NVIC_IRQEnable = ENABLE;    NVIC_Init(&NVIC_InitStructure);}

中断函数:

 void SPI1_IRQHandler(void){    if (SPI_I2S_GetIntBitState(SPI1, SPI_I2S_INT_TBE) != RESET)    {           /* Send SPI_MASTER data */        while (SPI_I2S_GetBitState(SPI1, SPI_FLAG_TBE) == RESET);        SPI_I2S_SendData(SPI1, SPI_MASTER_Buffer_Tx[ TxIdx++ ]);        if (TxIdx == BufferSize)        {            /* Disable SPI_MASTER TBE interrupt */            SPI_I2S_INTConfig(SPI1, SPI_I2S_INT_TBE, DISABLE);        }    }}void SPI3_IRQHandler(void){    /* Store SPI_SLAVE received data */    if (SPI_I2S_GetIntBitState(SPI3, SPI_I2S_INT_RBNE) == SET)        SPI_SLAVE_Buffer_Rx[RxIdx++] = SPI_I2S_ReceiveData(SPI3);}


案例2:DMA_SPI收发

 发送时,在每次TXE被设置为’1’时发出DMA请求,DMA控制器则写数据至SPI_DR寄存器,TXE标志因此而被清除。

接收时,在每次RXNE被设置为’1’时发出DMA请求,DMA控制器则从SPI_DR寄存器读出数据,RXNE标志因此而被清除。

DMA1_CHANNEL2:SPI1_RX

DMA1_CHANNEL3:SPI1_TX


配置DMA代码:

void SPI1_DMA_Configuration( void ){    DMA_InitTypeDef DMA_InitStructure;        /* DMA1 Channel2 (triggered by SPI1 Rx event) Config */  DMA_DeInit(DMA1_Channel2);    DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr;                          //设置 SPI1 发送外设(0x4001300C) 地址(目的地址)  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_RX_Buff;                    //设置 SRAM 存储地址(目的地址)  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                //传输方向 外设-内存  DMA_InitStructure.DMA_BufferSize = SPI1_ReciveBufferSize;                         //设置 SPI1 发送长度  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  DMA_Init(DMA1_Channel2, &DMA_InitStructure);    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);  /* Enable SPI1 DMA RX request */  SPI1->CR2 |= 1<<0;                                                                 //接收缓冲区DMA使能  DMA_Cmd(DMA1_Channel2, ENABLE);            /* DMA1 Channel3 (triggered by SPI1 Tx event) Config */  DMA_DeInit(DMA1_Channel3);    DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr;                          //设置  接收外设(0x4001300C) 地址(源地址)  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_TX_Buff;                    //设置 SRAM 存储地址(源地址)  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                //传输方向 内存-外设  DMA_InitStructure.DMA_BufferSize = SPI1_SendBufferSize;                           //设置 SPI1 接收长度  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                  //外设地址增量(不变)  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                           //内存地址增量(变化)  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;           //外设传输宽度(字节)  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                   //内存传输宽度(字节)  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                     //传输方式,一次传输完停止,不重新加载  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                           //中断方式-高(三级)  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                      //内存到内存方式禁止  DMA_Init(DMA1_Channel3, &DMA_InitStructure);    DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);                                   //开启 DMA1_Channel3 传输完成中断  DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE);                                   //开启 DMA1_Channel3 传输错误中断  /* Enable SPI1 DMA TX request */  SPI1->CR2 |= 1<<1;                                                                //发送缓冲区DMA使能  DMA_Cmd(DMA1_Channel3, DISABLE);                                                  //开启 DMA 通道 DMA1_Channel3}

SPI发送

关闭DMA通道3之前必须等待TXE为1,等待忙标志为0

void SPI1_Send( u8 *buff, u32 len ){    DMA1_Channel3->CPAR = SPI1_DR_Addr; //外设地址    DMA1_Channel3->CMAR = (u32) buff; //mem地址    DMA1_Channel3->CNDTR = len ; //传输长度    DMA1_Channel3->CCR = (0 << 14) | // 非存储器到存储器模式            (2 << 12) | // 通道优先级高            (0 << 11) | // 存储器数据宽度8bit            (0 << 10) | // 存储器数据宽度8bit            (0 <<  9) | // 外设数据宽度8bit            (0 <<  8) | // 外设数据宽度8bit            (1 <<  7) | // 存储器地址增量模式            (0 <<  6) | // 外设地址增量模式(不增)            (0 <<  5) | // 非循环模式            (1 <<  4) | // 从存储器读            (1 <<  3) | // 允许传输错误中断            (0 <<  2) | // 允许半传输中断            (1 <<  1) | // 允许传输完成中断            (1);        // 通道开启}


SPI接收

必须要先关闭通道2,然后再配置通道2的参数

void SPI1_Recive( u8 *buff, u32 len ){    DMA1_Channel2->CCR &= ~( 1 << 0 );          //关闭DMA通道2        DMA1_Channel2->CPAR = SPI1_DR_Addr; //外设地址    DMA1_Channel2->CMAR = (uint32_t)buff; //mem地址    DMA1_Channel2->CNDTR = len ; //传输长度    DMA1_Channel2->CCR = (0 << 14) | // 非存储器到存储器模式            (2 << 12) | // 通道优先级高            (0 << 11) | // 存储器数据宽度8bit            (0 << 10) | // 存储器数据宽度8bit            (0 <<  9) | // 外设数据宽度8bit            (0 <<  8) | // 外设数据宽度8bit            (1 <<  7) | // 存储器地址增量模式            (0 <<  6) | // 外设地址增量模式(不增)            (0 <<  5) | // 非循环模式            (0 <<  4) | // 传输方向 外设-内存            (0 <<  3) | // 允许传输错误中断            (0 <<  2) | // 允许半传输中断            (1 <<  1) | // 允许传输完成中断            (1);        // 通道开启}












0 0
原创粉丝点击