STM32之IO口模拟SPI

您所在的位置:网站首页 软件模拟spi方式读写用来干嘛的 STM32之IO口模拟SPI

STM32之IO口模拟SPI

2023-07-06 18:37| 来源: 网络整理| 查看: 265

本文介绍如何使用STM32标准外设库的GPIO端口模拟SPI,本例程使用PA5、PA6和PA7模拟一路SPI。SPI有4种工作模式,模拟SPI使用模式0,即空闲时SCK为低电平,在奇数边沿采样。

本文适合对单片机及C语言有一定基础的开发人员阅读,MCU使用STM32F103VE系列。

 

1.   简介

SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在要求通讯速率较高的场合。SPI用于多设备之间通讯,分为主机Master和从机Slave,主机只有一个,从机可以有多个,通过片选信号对从机进行选择,一次只能选择一个从机。通讯只能由主机发起,支持的操作分为读取和写入,即主机读取从机的数据,以及向从机写入数据。

SPI一般有4根线,分别是片选线SS、时钟线SCK、主设备输出\从设备输入MOSI、主设备输入\从设备输出MISO,其中除MISO对于主机为输入引脚外,其他引脚对于主机均为输出引脚。因为有独立的输入和输出引脚,因此SPI支持全双工工作模式,即可以同时接收和发送。

2.    总线传输信号 空闲状态:片选信号SS低电平有效,那么空闲状态片选信号SS为高。 开始信号及结束信号:开始信号需要将片选信号SS拉低,结束信号需要将片选信号SS拉高。 通讯模式:SPI有4种通讯模式,分别为0、1、2、3,根据时钟极性和时钟相位确定,时钟极性分别为空闲低电平和空闲高电平,时钟相位分别为SCK奇数边沿采样和偶数边沿采样。常用的模式为模式0和模式3。 SPI模式 时钟极性(空闲时SCK时钟) 时钟相位(采样时刻) 0 低电平 奇数边沿 1 低电平 偶数边沿 2 高电平 奇数边沿 3 高电平 偶数边沿

 

3.    时序说明

以模式0举例说明:

空闲状态:片选信号SS为高,SCK输出低电平。 开始信号:片选信号SS变低,SCK输出低电平。 结束信号:片选信号SS变高,SCK输出低电平。 读取:SCK由低变高之后,读取MISO引脚信号。 写入:SCK输出低电平,MOSI引脚输出相应的电平,然后SCK输出高电平。 一个时钟周期同时读取和写入:SCK输出低电平,主设备控制MOSI输出相应电平,从设备控制MISO输出相应电平,然后SCK输出高电平,从设备读取MOSI引脚电平,主设备读取MISO引脚电平。即无论主设备还是从设备,均在SCK为低电平时输出信号,在SCK为高电平时读取信号。 4.    初始化

初始化跟普通GPIO类似,SCK和MOSI设置为推挽输出,而MISO设置为浮空输入。

GPIO初始化完成之后,SCK置为低电平,进入空闲状态。

5.    模拟信号

由于SPI支持一个周期内同时读取和写入,因此读取和写入操作可以用一个函数实现,而单独的读取函数和写入函数可以通过调用该读写函数实现。

 

完整代码(仅自己编写的部分) 1 #define SPI_SCK_1 GPIO_SetBits(GPIOA, GPIO_Pin_5) /* SCK = 1 */ 2 #define SPI_SCK_0 GPIO_ResetBits(GPIOA, GPIO_Pin_5) /* SCK = 0 */ 3 4 #define SPI_MOSI_1 GPIO_SetBits(GPIOA, GPIO_Pin_7) /* MOSI = 1 */ 5 #define SPI_MOSI_0 GPIO_ResetBits(GPIOA, GPIO_Pin_7) /* MOSI = 0 */ 6 7 #define SPI_READ_MISO GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) /* 读MISO口线状态 */ 8 9 #define Dummy_Byte 0xFF //读取时MISO发送的数据,可以为任意数据 10 11 12 //初始化SPI 13 void SPI_IoInit(void) 14 { 15 GPIO_InitTypeDef GPIO_InitStructure; 16 17 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE); 18 19 //CS引脚初始化 20 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 21 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 22 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 23 GPIO_Init(GPIOC, &GPIO_InitStructure); 24 25 //SCK和MOSI引脚初始化 26 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7; 27 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 28 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 29 GPIO_Init(GPIOA, &GPIO_InitStructure); 30 31 //MISO引脚初始化 32 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; 33 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //浮空输入 34 GPIO_Init(GPIOA, &GPIO_InitStructure); 35 36 SPI_CS_1; 37 SPI_SCK_1; 38 } 39 40 //SPI可以同时读取和写入数据,因此一个函数即可满足要求 41 uint8_t SPI_ReadWriteByte(uint8_t txData) 42 { 43 uint8_t i; 44 uint8_t rxData = 0; 45 46 for(i = 0; i < 8; i++) 47 { 48 SPI_SCK_0; 49 delay_us(1); 50 //数据发送 51 if(txData & 0x80){ 52 SPI_MOSI_1; 53 }else{ 54 SPI_MOSI_0; 55 } 56 txData


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3