esp8266~SPI使用

前言

最近项目上遇到困难,esp8266的SPI用起来有点晕,硬件SPI驱动代码研究不透,猜想应该像STM32操作寄存器一样,可是现在水平有限还是没啃下来,只做到esp8266 硬件SPI发送命令字(一个字节)到stm32,stm32正确的接收到了数据,但关键的问题还是想把esp8266 硬件SPI驱动搞懂,esp8266中HSPI发送数据格式为:命令字 + 地址 + 数据,分别对应不同的底层代码。现在先把硬件SPI驱动代码记录下来,待后续3.0版本的sdk 更新外设SPI驱动后对比学习下,自己也实现了IO口模拟SPI通信,使用逻辑分析仪测试觉得速度还可以接受,也附在这篇博客中。

一. 硬件HSPI

来自esp github,驱动代码也在HSPI_Master/driver路径下。
esp8266~SPI使用_第1张图片
用例:

#include "gpio.h"
#include "spi_register.h"
#include "spi_interface.h"

void spi_initialize()
{
    //Initialze Pins on ESP8266
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_HSPIQ_MISO);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_HSPI_CS0);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_HSPI_CLK);

    SpiAttr pAttr;   //Set as Master/Sub mode 0 and speed 10MHz
    pAttr.mode = SpiMode_Master;
    pAttr.subMode = SpiSubMode_0;
    pAttr.speed = SpiSpeed_10MHz;
    pAttr.bitOrder = SpiBitOrder_MSBFirst;
    SPIInit(SpiNum_HSPI, &pAttr);
}

void Send_cmd(uint8 command)
{
    SpiData pDat;
    pDat.cmd = command;	   ///< Command value
    pDat.cmdLen = 1;       ///< Command byte length
    pDat.addr = NULL;      ///< Point to address value
    pDat.addrLen = 0; 	   ///< Address byte length
    pDat.data = NULL; 	   ///< Point to data buffer
    pDat.dataLen = 0; 	   ///< Data byte length.
    SPIMasterSendData(SpiNum_HSPI, &pDat);
}

/******************************************************************************
 * FunctionName : user_init
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
 *******************************************************************************/
void user_init(void)
{
    uint8 cmd = 0xaa;
    uint32 addr = 0xbbcc;
    uint32 data[2] = { 0x11223344, 0x55667788 };
    spi_initialize();
    printf("Starting SPI Communication\n");
    while (1) {
        Send_cmd(0x34);
        SpiData pDat;
        pDat.cmd = cmd;			      ///< Command value
        pDat.cmdLen = 1;		      ///< Command byte length
        pDat.addr = &addr; 		      ///< Point to address value
        pDat.addrLen = 2; 	          ///< Address byte length
        pDat.data = data; 		      ///< Point to data buffer
        pDat.dataLen = sizeof(data);  ///< Data byte length.
        SPIMasterSendData(SpiNum_HSPI, &pDat);
        vTaskDelay(100);
    }
}

二. 软件SPI

软件SPI可能速度较慢,我自己测试了IO口速度大概是1.75翻转一次,也就是570k,比串口速度好多了。
用例:

LOCAL void spi_task(void *pvParameters)
{
	SOFT_SPI_INIT();
	while(1){
		softspi_write_byte(0x08);
		softspi_write_byte(0x03);
		softspi_write_byte(0x04);
		softspi_write_byte(0x0A);
		vTaskDelay(5);
		//printf("spi test\n");
	}
    vTaskDelete(NULL);
}

驱动代码 :

/*
 * soft spi.c
 *
 *  Created on: 2018年8月10日
 *      Author: Hynson
 */

#include "soft_spi.h"

/* spi write one byte  */
void ICACHE_FLASH_ATTR softspi_write_byte(u8 data)
{
    u8 i;
    CS_0();
	for(i = 0; i < 8; i++){
		if (data & 0x80){
			MOSI_1();
		}else{
			MOSI_0();
		}
		SCK_0();
		data <<= 1;
		SCK_1();
	}
	CS_1();
}
/* spi read one byte */
u8 ICACHE_FLASH_ATTR softspi_read_byte(void)
{
	u8 read = 0;
    u8 i;
    CS_0();
	for (i = 0; i < 8; i++){
		SCK_0();
		read = read<<1;
		if (MISO_IS_HIGH()){
			read++;
		}
		SCK_1();
	}
	CS_1();
	return read;
}

/*
 * soft_spi.h
 *
 *  Created on: 2018年11月24日
 *      Author: Hynson
 */

#ifndef __SOFT_SPI_H_
#define __SOFT_SPI_H_

#include "c_types.h"
#include "gpio.h"
#include "esp8266/gpio_register.h"
#include "esp8266/eagle_soc.h"
#include "esp8266/pin_mux_register.h"
#include "esp8266/ets_sys.h"

#define SPI_MISO	12
#define SPI_MOSI	13
#define SPI_SCK		14
#define SPI_CS		15

#define SOFT_SPI_INIT()	do{\
		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);\
		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13);\
		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);\
		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15);\
		GPIO_DIS_OUTPUT(SPI_MISO);\
	}while(0)

#define MOSI_0()	GPIO_OUTPUT_SET(SPI_MOSI, 0)
#define MOSI_1()	GPIO_OUTPUT_SET(SPI_MOSI, 1)
#define CS_0()		GPIO_OUTPUT_SET(SPI_CS, 0)
#define CS_1()		GPIO_OUTPUT_SET(SPI_CS, 1)
#define SCK_0()		GPIO_OUTPUT_SET(SPI_SCK, 0)
#define SCK_1()		GPIO_OUTPUT_SET(SPI_SCK, 1)

#define MISO_IS_HIGH()	(GPIO_INPUT_GET(SPI_MISO) != 0)

u8 ICACHE_FLASH_ATTR softspi_read_byte(void);
void ICACHE_FLASH_ATTR softspi_write_byte(u8 data);

#endif /* __SOFT_SPI_H_ */

esp8266和STM32 51单片机 spi通信网上也找了好久 查找了好多资料,关于这方面的还真是比较少,觉得比较好的文章见下面参考。
参考:

  1. stm32通过spi连接esp8266的hspi 开发
  2. WiFi-ESP8266入门开发(十三)-使用SPI
  3. esp8266 spi slave 驱动调试

你可能感兴趣的:(IoT嵌入式,#,wifi,蓝牙)