软件模拟SPI通讯
(1) CKPOL (Clock Polarity) = CPOL = POL = Polarity = (时钟)极性
(2) CKPHA (Clock Phase) = CPHA = PHA = Phase = (时钟)相位
(3) SCK=SCLK=SPI的时钟
(4) Edge=边沿,即时钟电平变化的时刻,即上升沿(rising edge)或者下降沿(falling edge)
soft_spi.h
#ifndef __SOFT_SPI_H
#define __SOFT_SPI_H
#include "main.h"
#ifndef HIGH
#define HIGH 1
#endif /* HIGH */
#ifndef LOW
#define LOW 0
#endif /* LOW */
#define SPI_SCK(x) HAL_GPIO_WritePin(SPI6_SCK_GPIO_Port,SPI6_SCK_Pin,(GPIO_PinState)x)
#define SPI_MOSI(x) HAL_GPIO_WritePin(SPI6_MOSI_GPIO_Port,SPI6_MOSI_Pin,(GPIO_PinState)x)
#define SPI_MISO HAL_GPIO_ReadPin(SPI6_MISO_GPIO_Port,SPI6_MISO_Pin)
uint8_t write_spi_byte(uint8_t Byte);
uint8_t read_spi_byte(void);
#endif /* __BSP_SPI_H */
soft_spi.c
#include "soft_spi.h"
#define WAIT_TIME 2
/*
* MODE 0:CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第 1个边沿, \
* 也就是 SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。
* MODE 1:CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第 2个边沿, \
* 也就是 SCLK由高电平到低电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。
* MODE 2:CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第 1个边沿, \
* 也就是 SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。
* MODE 3:CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第 2个边沿, \
* 也就是 SCLK由低电平到高电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。
*/
#define _CPOL 1
#define _CPHA 1
/************************************************
函数名称 : SPI_Delay_us
功 能 : 软件毫秒延时
参 数 : Count ---- 次数
返 回 值 : 无
*************************************************/
static void spi_delay_us( uint32_t Count )
{
delay_us(Count);
}
#if (0 == _CPOL && 0 == _CPHA) /* ----- MODE 0 ----- */
/************************************************
函数名称 : Write_SPI_Byte
功 能 : SPI写读一个字节
参 数 : Byte ---- 数据
返 回 值 : Byte ---- 数据
*************************************************/
uint8_t write_spi_byte( uint8_t Byte )
{
uint8_t i;
for(i = 0;i < 8;i++)
{
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
#if 0
SPI_MOSI((Byte & 0x80) >> 7);
#else
if(Byte & 0x80)
{
SPI_MOSI(HIGH);
}
else
{
SPI_MOSI(LOW);
}
#endif
Byte <<= 1;
spi_delay_us(WAIT_TIME); // 空等待
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
Byte |= SPI_MISO;
}
SPI_SCK(LOW);
return Byte;
}
/************************************************
函数名称 : Read_SPI_Byte
功 能 : SPI只读一个字节
参 数 : 无
返 回 值 : temp ---- 数据
*************************************************/
uint8_t read_spi_byte(void)
{
uint8_t i;
uint8_t temp = 0;
for(i = 0;i < 8;i++)
{
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
temp <<= 1;
#if 1
temp |= SPI_MISO;
#else
if(SPI_MISO)
{
temp++;
}
#endif
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
}
SPI_SCK(LOW);
return temp;
}
#elif (0 == _CPOL && 1 == _CPHA) /* ----- MODE 1 ----- */
/************************************************
函数名称 : Write_SPI_Byte
功 能 : SPI写读一个字节
参 数 : Byte ---- 数据
返 回 值 : Byte ---- 数据
*************************************************/
uint8_t write_spi_byte( uint8_t Byte )
{
uint8_t i;
SPI_SCK(LOW);
for(i = 0;i < 8;i++)
{
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
#if 0
SPI_MOSI((Byte & 0x80) >> 7);
#else
if(Byte & 0x80)
{
SPI_MOSI(HIGH);
}
else
{
SPI_MOSI(LOW);
}
#endif
Byte <<= 1;
spi_delay_us(WAIT_TIME); // 空等待
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
Byte |= SPI_MISO;
}
return Byte;
}
/************************************************
函数名称 : Read_SPI_Byte
功 能 : SPI只读一个字节
参 数 : 无
返 回 值 : temp ---- 数据
*************************************************/
uint8_t read_spi_byte(void)
{
uint8_t i;
uint8_t temp = 0;
SPI_SCK(LOW);
for(i = 0;i < 8;i++)
{
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
temp <<= 1;
#if 1
temp |= SPI_MISO;
#else
if(SPI_MISO)
{
temp++;
}
#endif
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
}
return temp;
}
#elif (1 == _CPOL && 0 == _CPHA) /* ----- MODE 2 ----- */
/************************************************
函数名称 : Write_SPI_Byte
功 能 : SPI写读一个字节
参 数 : Byte ---- 数据
返 回 值 : Byte ---- 数据
*************************************************/
uint8_t write_spi_byte( uint8_t Byte )
{
uint8_t i;
for(i = 0;i < 8;i++)
{
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
#if 0
SPI_MOSI((Byte & 0x80) >> 7);
#else
if(Byte & 0x80)
{
SPI_MOSI(HIGH);
}
else
{
SPI_MOSI(LOW);
}
#endif
Byte <<= 1;
spi_delay_us(WAIT_TIME); // 空等待
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
Byte |= SPI_MISO;
}
SPI_SCK(HIGH);
return Byte;
}
/************************************************
函数名称 : Read_SPI_Byte
功 能 : SPI只读一个字节
参 数 : 无
返 回 值 : temp ---- 数据
*************************************************/
uint8_t read_spi_byte(void)
{
uint8_t i;
uint8_t temp = 0;
for(i = 0;i < 8;i++)
{
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
temp <<= 1;
#if 1
temp |= SPI_MISO;
#else
if(SPI_MISO)
{
temp++;
}
#endif
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
}
SPI_SCK(HIGH);
return temp;
}
#elif (1 == _CPOL && 1 == _CPHA) /* ----- MODE 3 ----- */
/************************************************
函数名称 : Write_SPI_Byte
功 能 : SPI写读一个字节
参 数 : Byte ---- 数据
返 回 值 : Byte ---- 数据
*************************************************/
uint8_t write_spi_byte( uint8_t Byte )
{
uint8_t i;
SPI_SCK(HIGH);
for(i = 0;i < 8;i++)
{
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
#if 0
SPI_MOSI((Byte & 0x80) >> 7);
#else
if(Byte & 0x80)
{
SPI_MOSI(HIGH);
}
else
{
SPI_MOSI(LOW);
}
#endif
Byte <<= 1;
spi_delay_us(WAIT_TIME); // 空等待
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
Byte |= SPI_MISO;
}
return Byte;
}
/************************************************
函数名称 : Read_SPI_Byte
功 能 : SPI只读一个字节
参 数 : 无
返 回 值 : temp ---- 数据
*************************************************/
uint8_t read_spi_byte(void)
{
uint8_t i;
uint8_t temp = 0;
SPI_SCK(HIGH);
for(i = 0;i < 8;i++)
{
SPI_SCK(LOW);
spi_delay_us(WAIT_TIME); // 空等待
temp <<= 1;
#if 1
temp |= SPI_MISO;
#else
if(SPI_MISO)
{
temp++;
}
#endif
SPI_SCK(HIGH);
spi_delay_us(WAIT_TIME); // 空等待
}
return temp;
}
#endif /* SPI MODE */
/*---------------------------- END OF FILE ----------------------------*/