串行外设接口(SPI)是一种同步串行数据通信接口,常用于 MCU 与外部设备之间进行同步串行通信。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间。CW32L083 内部集成 2 个串行外设 SPI 接口,支持双向全双工、单线半双工和单工通信模式,可配置 MCU 作为 主机或从机,支持多主机通信模式,支持直接内存访问(DMA)。
单工通信模式
SPI 支持单工通信模式,主机和从机通过一根单向数据线进行单发或单收通信。主机使用 MOSI 信号线进行单发通信,使用 MISO 信号线进行单收通信;从机使用 MOSI 信号线进行单收通信, 使用 MISO 信号线进行单发通信,未使用的信号线可供其它功能使用。
主机单发,从机单收应用场景下,连接框图如下:
主机单发配置:
设置 SPIx_CR1.MODE 为 0x1,SPI 工作于单工单发通信模式;
设置 SPIx_CR1.MSTR 为 1,SPI 工作于主机模式。
设置 SPIx_SSI.SSI 为 0,在从机选择 CS 引脚输出低电平,作为通信起始信号。
当发送缓冲器为空时,即 SPIx_ISR.TXE 标志位为 1,将待发送的一帧数据写入 SPIx_DR 寄存器,数据在同步移位时钟信号的控制下从 MOSI 引脚输出。
当写入最后一帧数据后,必须等待发送缓冲空标志位 SPIx_ISR.TXE 变为 1,同时 SPI 总线忙标志位 SPIx_ISR. BUSY 变为 0,以确保数据发送完毕。然后设置 SPIx_SSI.SSI 为 1,使从机选择 CS 引脚输出高电平,结束本次通信。
从机单收配置:
设置 SPIx_CR1.MODE 为 0x2,SPI 工作于单工单收通信模式;
设置 SPIx_CR1.MSTR 为 0,SPI 工作于从机模式。
当检测到 CS 引脚变为低电平时,从机开始与主机通信。当接收缓冲器非空时,即 SPIx_ISR.RXNE 标志位为 1,表示已经接收完成一帧数据,此时可以读取 SPIx_DR 寄存器。当检测到 CS 引脚变为高电平时,本次通信结束。
主机单收,从机单发应用场景下,连接框图如下:
具体设置与主机单发和从机单收类似,详情可查看用户手册。
SPI中断
SPI 控制器支持 8 个中断源,当 SPI 中断触发事件发生时,中断标志位会被硬件置位,如果设置了对应的中断使能控制位,将产生中断请求。
在用户 SPI 中断服务程序中,应查询相关 SPI 中断标志位,以进行相应的处理,在退出中断服务程序之前,要清除该中断标志位,避免重复进入中断程序。
实例演示:SPI单工模式进行主从机通信,主机单发,从机单收。
SPIy(主机)采用中断方式发送TxBuffer缓冲区中的数据,SPIz(从机)采用中断方式接收数据并存储到RxBuffer缓冲区,比较TxBuffer和RxBuffer,如果数据一致LED1亮,否则LED2亮。
1. 配置RCC
voidRCC_Configuration(void) { RCC_HSI_Enable(RCC_HSIOSC_DIV2);//SYSCLK=HSI=24MHz=HCLK=PCLK RCC_AHBPeriphClk_Enable(SPIy_GPIO_CLK|SPIz_GPIO_CLK|RCC_AHB_PERIPH_GPIOC,ENABLE);//外设时钟使能 SPIy_APBClkENx(SPIy_CLK,ENABLE); SPIz_APBClkENx(SPIz_CLK,ENABLE); }
2. 配置GPIO
voidGPIO_Configuration(void) { GPIO_InitTypeDefGPIO_InitStructure={0}; SPIy_AF_SCK;//SPISCKMOSI复用 SPIy_AF_MOSI; SPIz_AF_SCK; SPIz_AF_MOSI; GPIO_InitStructure.Pins=SPIy_SCK_PIN;//推挽输出 GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP; GPIO_Init(SPIy_GPIO, GPIO_InitStructure); GPIO_InitStructure.Pins=SPIy_MOSI_PIN; GPIO_Init(SPIy_GPIO, GPIO_InitStructure); GPIO_InitStructure.Pins=SPIz_SCK_PIN;//浮空输入 GPIO_InitStructure.Mode=GPIO_MODE_INPUT; GPIO_Init(SPIz_GPIO, GPIO_InitStructure); GPIO_InitStructure.Pins=SPIz_MOSI_PIN; GPIO_Init(SPIz_GPIO, GPIO_InitStructure); GPIO_InitStructure.Pins=GPIO_PIN_3|GPIO_PIN_2;//PC3LED1/PC2LED2 GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP; GPIO_Init(CW_GPIOC, GPIO_InitStructure); PC03_SETLOW();//LED灭 PC02_SETLOW(); }
3. 配置SPI
voidSPI_Configuration() { SPI_InitTypeDefSPI_InitStructure={0}; SPI_InitStructure.SPI_Direction=SPI_Direction_1Line_TxOnly;//单工单发 SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//主机模式 SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//帧数据长度为8bit SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;//时钟空闲电平为低 SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;//第一个边沿采样 SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//片选信号由SSI寄存器控制 SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;//波特率为PCLK的8分频 SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//最高有效位MSB收发在前 SPI_InitStructure.SPI_Speed=SPI_Speed_Low;//低速SPI SPI_Init(SPIy, SPI_InitStructure); SPI_InitStructure.SPI_Direction=SPI_Direction_1Line_RxOnly;//单工单收 SPI_InitStructure.SPI_Mode=SPI_Mode_Slave;//从机模式 SPI_Init(SPIz, SPI_InitStructure); SPI_Cmd(SPIy,ENABLE); SPI_Cmd(SPIz,ENABLE); }
4. 配置NVIC中断函数
voidNVIC_Configuration(void) { NVIC_SetPriority(SPIy_IRQ,1);//优先级,无优先级分组 NVIC_SetPriority(SPIz_IRQ,0); NVIC_EnableIRQ(SPIy_IRQ);//SPI中断使能 NVIC_EnableIRQ(SPIz_IRQ); } voidSPI1_IRQHandler(void)//SPI1中断函数 { if(SPI_GetITStatus(CW_SPI1,SPI_IT_TXE)!=RESET) { if(TxCounter==BufferSize-1) { SPI_ITConfig(CW_SPI1,SPI_IT_TXE,DISABLE); } SPI_SendData(CW_SPI1,TxBuffer[TxCounter++]); } } voidSPI2_IRQHandler(void)//SPI2中断函数 { if(SPI_GetITStatus(CW_SPI2,SPI_IT_RXNE)!=RESET) { RxBuffer[RxCounter++]=SPI_ReceiveData(CW_SPI2); } }
5. 比较两个buffers区
TestStatusBuffercmp(uint8_t*pBuffer1,uint8_t*pBuffer2,uint16_tBufferLength) { while(BufferLength--) { if(*pBuffer1!=*pBuffer2) { returnFAILED; } pBuffer1++; pBuffer2++; } returnPASSED; }
6. 主程序
int32_tmain(void) { RCC_Configuration();//配置RCC GPIO_Configuration();//配置GPIO SPI_Configuration();//配置SPI NVIC_Configuration();//配置NVIC SPI_ITConfig(SPIz,SPI_IT_RXNE,ENABLE);//使能SPIzRXNE中断 SPI_NSSInternalSoftwareConfig(SPIz,SPI_NSSInternalSoft_Reset);//软件NSS,选中SPIz SPI_ITConfig(SPIy,SPI_IT_TXE,ENABLE);//使能SPIyTXE中断 while(RxCounter< BufferSize); //等待收发完成 SPI_NSSInternalSoftwareConfig(SPIz, SPI_NSSInternalSoft_Set); //释放SPIz TransferStatus = Buffercmp(TxBuffer, RxBuffer, BufferSize); //检查收发数据一致性 if(TransferStatus == PASSED) //PASSED { PC03_SETHIGH();//LED1亮 } else //FAILED { PC02_SETHIGH();//LED2亮 } while(1) { } }
7.实验结果显示:LED1亮起,buffers区数据相等,SPI单工模式主从通讯(中断方式)功能实现。
来源:武汉芯源半导体
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理
审核编辑 黄宇
-
mcu
+关注
关注
146文章
16956浏览量
350132 -
通信
+关注
关注
18文章
5965浏览量
135819 -
SPI
+关注
关注
17文章
1696浏览量
91275
发布评论请先 登录
相关推荐
评论