C语言常用的工具函数(模拟SPI)

310 阅读1分钟

C语言常用的工具函数(模拟SPI)

#define CLK_DELAY  6  //us (1/2的SPI时钟周期  程序执行带来1us左右误差 1-2 2-3)
#define DATA_DELAY 200 //同一帧读写指令之间的间隔
#define CMD_DELAY  10000 //不同帧读写指令之间的间隔

#define SET_CLK_LOW    GPIOA->BRR = (uint32_t)GPIO_PIN_8
#define SET_CLK_HIGH   GPIOA->BSRR = (uint32_t)GPIO_PIN_8

#define SET_MOSI_LOW   GPIOB->BRR = (uint32_t)GPIO_PIN_10
#define SET_MOSI_HIGH  GPIOB->BSRR = (uint32_t)GPIO_PIN_10  

#define SET_CS_LOW     GPIOB->BRR = (uint32_t)GPIO_PIN_5
#define SET_CS_HIGH    GPIOB->BSRR = (uint32_t)GPIO_PIN_5 

#define READ_MISO      HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)

#define Dummy_Byte     0xFF    //读取时MISO发送的数据,可以为任意数据

/**
	* @brief SPI读写函数
	* @note
	* @param byte 发送的字节
	* 
	* @retval 收到的字节
	* @author yangFei
	* @date   20210728
	* @note   本函数内部需实现CPOL=0,CPHA=1, MSB first格式的模拟SPI
	*/
static uint8_t spi_rw(uint8_t byte)
{
    uint8_t i, rx_data=0;

    for(i=0; i<8; i++)      // 循环8次
    {
        SET_CLK_HIGH;       //拉高时钟
        if(byte&0x80)
        {
            SET_MOSI_HIGH;  //若最高位为高,则输出高
        }
        else
        {
            SET_MOSI_LOW;   //若最低位为低,则输出低
        }
        byte <<= 1;         // 低一位移位到最高位
        delay_us(CLK_DELAY);
        SET_CLK_LOW;        //拉低时钟
        rx_data <<= 1;      //数据左移

        if(READ_MISO)
            rx_data++;      //若从从机接收到高电平,数据自加一
        delay_us(CLK_DELAY);

    }
    return (rx_data);       //返回数据
}

/**
	* @brief SPI多读
	* @note
	* @param data 存储读取数据的存放缓存区
	* @param len  读取的数据长度
	* 
	* @retval
	* @author yangFei
	* @date   20210728
	* @note   本函数内部需实现多字节读取功能
	*/
void spi_read(uint8_t *data, uint8_t len)
{
    for(uint8_t i=0; i<len; i++)
    {
        data[i] = spi_rw(Dummy_Byte);
    }
}

/**
  * @brief SPI多写.
  * @note
  * @param data 存储发送数据的存放缓存区
  * @param len  发送的数据长度
  *
  * @retval 写入成功返回0;失败返回非0
  * @author yangFei
  * @date   20210728
  * @note   本函数内部需实现多字节发送功能
  */
uint8_t spi_write(uint8_t *data, uint8_t len)
{
    uint8_t rx_data[len];
	
	  memset(rx_data, 0, len);

    for(uint8_t i=0; i<len; i++)
    {
        spi_rw(data[i]);
    }

    delay_us(CLK_DELAY);

    spi_read(rx_data, len);

    if(memcmp(data, rx_data, len))//tx != rx
        return 1;
    else return 0;
}