IO口模拟SPI

IO口模拟SPI
根据SPI通信规范,与IO口模拟I2C类似,通过普通IO端口模拟也可以实现单片机(主设备)与从设备的SPI通信,其中使能信号CS在开始SPI通信前置低,在通信结束后置高,时钟线SCK通过IO口延时高低电平变化实现,MOSI,MISO根据SCK状态实现发送接收数据等,以下是相关代码

/*
 * spi_m_flash.c
 *
 *  Created on: 2019年7月13日
 *      Author: liangfeng
 */

#include "aworks.h"                     /* 此头文件必须被首先包含 */
#include "aw_spi.h"
#include "aw_gpio.h"
#include "aw_delay.h"
#include "imx1050_pin.h"
#include "spi_m_flash.h"
#include "pattern.h"
#include "driver/enc/awbl_enc_service.h"
#include "driver/enc/awbl_enc.h"


#define SPI_CS_PIN           20                      //GPIO1_27
#define SPI_MOSI_PIN         9                      //GPIO1_29
#define SPI_MISO_PIN         10                      //GPIO1_30
#define SPI_SCK_PIN          11                      //GPIO1_31

/** \操作代码 */
#define WREN            0x06       /* 写使能 */
#define WRDI            0x04       /* 复位写使能锁存器 */
#define RDSR            0x05       /* 读取状态寄存器 */
#define WRSR            0x01       /* 写入状态寄存器*/
#define READ            0x03       /* 读内存代码命令 */
#define WRITE           0x02       /* 写内存代码命令 */
#define RDID            0x9F       /* 读器件 ID */

#define SPI_SCK_L         aw_gpio_set(GPIO1_11,0)
#define SPI_SCK_H         aw_gpio_set(GPIO1_11,1)

#define SPI_MOSI_L        aw_gpio_set(GPIO1_9,0)
#define SPI_MOSI_H        aw_gpio_set(GPIO1_9,1)

#define SPI_CS_L          aw_gpio_set(GPIO1_20,0)
#define SPI_CS_H          aw_gpio_set(GPIO1_20,1)

//io口初始化
void IO_FM_GPIO_Init(void)
{
	 static const int spi_pins_tabe[] = {
			 GPIO1_20,
			 GPIO1_9,
			 GPIO1_10,
			 GPIO1_11,
	  };

	if(aw_gpio_pin_request("spi_pins", &spi_pins_tabe, 4)== AW_OK){

	aw_gpio_pin_cfg(GPIO1_20, AW_GPIO_OUTPUT | AW_GPIO_PULL_UP );//CS片选
	aw_gpio_pin_cfg(GPIO1_9, AW_GPIO_OUTPUT | AW_GPIO_PULL_UP );//MOSI
	aw_gpio_pin_cfg(GPIO1_10, AW_GPIO_INPUT  | AW_GPIO_PULL_UP );//MISO
	aw_gpio_pin_cfg(GPIO1_11, AW_GPIO_OUTPUT | AW_GPIO_PULL_UP );//SCK

	}
}

//发送一个字节数据
void IO_FM_SendOneByte(uint8_t data)
{
	uint8_t i;
	//aw_udelay(1);
	SPI_SCK_L;
	  for(i=0;i<8;i++)
	  {
		  SPI_SCK_L;
		  //aw_udelay(1);
	    if(data&(0x80>>i))
	    {
	    	SPI_MOSI_H;
	    }
	    else
	    {
	    	SPI_MOSI_L;
	    }
	    //aw_udelay(1);
	    SPI_SCK_H;
	    //aw_udelay(1);
	  }
	  //aw_udelay(1);


}
//接收一个字节数据
uint8_t IO_FM_ReceiveOneByte(void)
{
	uint8_t temp=0x00;
	SPI_SCK_H;
	for(int i=0;i<8;i++){
		SPI_SCK_H;
		//aw_udelay(1);
		SPI_SCK_L;
		//aw_udelay(1);

		if(aw_gpio_get(GPIO1_10)){

			temp |= 1<<(7-i);
		}
		//aw_udelay(1);
	}
	SPI_SCK_L;
	return temp;
}

//发送数据
void IO_FM_SendBytes(uint16_t length,uint8_t *sbuff)
{

    for(int i=0;i>8)&0xff);
	  //addr_H1 = (uint8_t)(Addr>>16)&0xff;
	  //addr_H2 = (uint8_t)((Addr>>24)&0xff);

	  SPI_CS_L;
	  //aw_udelay(1);
	  IO_FM_SendOneByte(WREN); //发送写使能
	  SPI_CS_H;
	  //aw_udelay(1);
	  SPI_CS_L;
	  //aw_udelay(1);
	  IO_FM_SendOneByte(WRITE);//写
	  //IO_Flash_SendOneByte(addr_H2);
	  //IO_FM_SendOneByte(addr_H1);
	  IO_FM_SendOneByte(addr_L2);
	  IO_FM_SendOneByte(addr_L1);
	  IO_FM_SendBytes(Length,sbuff);
	  SPI_CS_H;
	  //aw_udelay(1);

}

//读取数据
void IO_FM_ReadData(uint32_t Addr,uint16_t length,uint8_t *rbuff)
{
	  uint8_t addr_L1;
	  //uint8_t addr_H1;
	  uint8_t addr_L2;
	  addr_L1 = (uint8_t)(Addr&0xff);
	  addr_L2 = (uint8_t)((Addr>>8)&0xff);
	  //addr_H1 = (uint8_t)(Addr>>16)&0xff;
	  //  addr_H2 = (uint8_t)((Addr>>24)&0xff);
	  SPI_CS_L;
	  //aw_udelay(1);
	  IO_FM_SendOneByte(WREN); //发送写使能
	  SPI_CS_H;
	  //aw_udelay(1);
	  SPI_CS_L;
	  //aw_udelay(1);
	  IO_FM_SendOneByte(READ);//读
	  // IO_Flash_SendOneByte(addr_H2);
	 // IO_FM_SendOneByte(addr_H1);
	  IO_FM_SendOneByte(addr_L2);
	  IO_FM_SendOneByte(addr_L1);
	  IO_FM_ReceiveBytes(length,rbuff);
	  SPI_CS_H;
	  //aw_udelay(1);
}

上面是io口模拟spi读取,写入铁电数据。

你可能感兴趣的:(单片机)