stm32使用hal库模拟spi模式3

因为网上模拟spi模拟的都是模式0,很少有模式3的。

模式3的时序图,在clk的下降沿切换电平状态,在上升沿采样, SCK空闲为高电平

初始化cs,clk,miso,mosi四个io。miso配置为输入,cs、clk、mosi配置为推挽输出。

c 复制代码
  HAL_GPIO_WritePin(GPIOD, spi_sck_Pin|spi_cs_Pin, GPIO_PIN_SET);	//sck,cs空闲时为高

  GPIO_InitStruct.Pin = spi_miso_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(spi_sdo_GPIO_Port, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = spi_mosi_Pin|spi_sck_Pin|spi_cs_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

my_spi.h

c 复制代码
#ifndef __MY_SPI_H
#define __MY_SPI_H
#include "main.h"
#include "gpio.h"

#define		SCK_H		HAL_GPIO_WritePin(GPIOD, spi_sck_Pin, GPIO_PIN_SET)
#define		SCK_L		HAL_GPIO_WritePin(GPIOD, spi_sck_Pin, GPIO_PIN_RESET)
#define		MOSI_H		HAL_GPIO_WritePin(GPIOD, spi_sdi_Pin, GPIO_PIN_SET)
#define		MOSI_L		HAL_GPIO_WritePin(GPIOD, spi_sdi_Pin, GPIO_PIN_RESET)
#define		MISO		HAL_GPIO_ReadPin(spi_sdo_GPIO_Port,spi_sdo_Pin)
#define		CS_H		HAL_GPIO_WritePin(GPIOD, spi_cs_Pin, GPIO_PIN_SET)
#define		CS_L		HAL_GPIO_WritePin(GPIOD, spi_cs_Pin, GPIO_PIN_RESET)


uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat );


void Delay5us(U8 delaycnt);

#endif

my_spi.c

c 复制代码
#include "my_spi.h"
#include "stdint.h"


void delay_us(uint16_t i){
	uint8_t a;
	while(i--){
		for(a=6;a>0;a--);	//64mhz,6大概1us
	}
}

void Delay5us(U8 delaycnt)
{
    U8 i;

    for(i=0; i<delaycnt; i++)
    {
			delay_us(5);
    }
}

//模式3测试通过
uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat )
{
    uint8_t i=0, read_dat=0;
    for( i = 0; i < 8; i++ )
    {
				SCK_L;
        if( write_dat & 0x80 )
            MOSI_H;
        else
            MOSI_L;
        write_dat <<= 1;
        delay_us(2);
        SCK_H;
        read_dat <<= 1;
        if( MISO )
            read_dat++;
				delay_us(2);
        __nop();
    }
    return read_dat;
}

/*
// CPOL = 0, CPHA = 0, MSB first
uint8_t SOFT_SPI_RW_MODE0( uint8_t write_dat )
{
    uint8_t i, read_dat;
    for( i = 0; i < 8; i++ )
    {
        if( write_dat & 0x80 )
            MOSI_H;  
        else                    
            MOSI_L;  
        write_dat <<= 1;
        delay_us(1);  
        SCK_H; 
        read_dat <<= 1;  
        if( MISO ) 
            read_dat++; 
    delay_us(1);
        SCK_L; 
        __nop();
    }
  
    return read_dat;
}
 
 
// CPOL=0,CPHA=1, MSB first 
uint8_t SOFT_SPI_RW_MODE1(uint8_t byte) 
{
    uint8_t i,Temp=0;
 
  for(i=0;i<8;i++)     // 循环8次
  {
    SCK_H;     //拉高时钟
    if(byte&0x80)
        {
      MOSI_H;  //若最到位为高,则输出高
        }
    else      
    {
      MOSI_L;   //若最到位为低,则输出低
    }
    byte <<= 1;     // 低一位移位到最高位
    delay_us(1);
    SCK_L;     //拉低时钟
    Temp <<= 1;     //数据左移
 
    if(MISO)
      Temp++;     //若从从机接收到高电平,数据自加一
    delay_us(1);
 
  }
  return (Temp);     //返回数据
}
 
// CPOL=1,CPHA=0, MSB first 
uint8_t SOFT_SPI_RW_MODE2(uint8_t byte) 
{
    uint8_t i,Temp=0;
 
  for(i=0;i<8;i++)     // 循环8次
  {
    if(byte&0x80)
        {
      MOSI_H;  //若最到位为高,则输出高
        }
    else      
    {
      MOSI_L;   //若最到位为低,则输出低
    }
    byte <<= 1;     // 低一位移位到最高位
    delay_us(1);
    SCK_L;     //拉低时钟
    Temp <<= 1;     //数据左移
 
    if(MISO)
      Temp++;     //若从从机接收到高电平,数据自加一
    delay_us(1);
    SCK_H;     //拉高时钟
    
  }
  return (Temp);     //返回数据
}
*/

使用示例:

c 复制代码
 	CS_L;		// SPI_CS脚拉低,开始SPI通讯
	Delay5us(1);
	for (i=0; i<5; i++) {
		AFERxBuf[i]=SOFT_SPI_RW_MODE3(AFETxBuf[i]);
	}
	Delay5us(1);
	CS_H;		// SPI_CS脚拉高,结束SPI通讯
相关推荐
CC呢1 小时前
基于单片机智能热水壶/养生壶设计
单片机·嵌入式硬件·单片机设计
贾亚超2 小时前
【STM32外设】DAC
stm32·单片机·嵌入式硬件
明天见~~3 小时前
硬件基础:串口通信
嵌入式硬件
sheepwjl4 小时前
《嵌入式硬件(三):串口通信》
网络·嵌入式硬件·网络协议·串口通信
嵌入式牛马在努力帮老板娶老婆5 小时前
十四、STM32-----低功耗
stm32·单片机·嵌入式硬件
来生硬件工程师6 小时前
【硬件笔记】负载是如何烧MOS的?
笔记·嵌入式硬件·硬件架构·硬件工程·硬件设计
少男的脸红藏不住心事6 小时前
GD32入门到实战34--ARM启动流程
单片机·嵌入式硬件
日更嵌入式的打工仔6 小时前
PHY的自适应协商简析
网络·嵌入式硬件·自适应·phy
CC呢7 小时前
基于单片机坐姿提醒系统/久坐提醒设计
stm32·单片机·嵌入式硬件·单片机设计·久坐提醒
曙曙学编程8 小时前
stm32——寄存器操作,蜂鸣器原理
c语言·c++·stm32·单片机·嵌入式硬件