历史上的今天
今天是:2025年04月11日(星期五)
2020年04月11日 | ESP8266与单片机之间通过SPI进行双向数据传输的一种方案
2020-04-11 来源:eefocus
背景: 在我的毕业设计中需要单片机将采集到的数据上传到服务器,同时需要接收来自服务器的一些天气信息,我的单片机的型号是 Stm32F407; ESP8266 刷入了 micropython 的固件,使用python进行开发; 协议是 SPI协议 ESP8266 主机 Stm32F4作为 从机
单片机侧使用的是 Stm32F407 的硬件 SPI + DMA 接收发送。 ESP8266 侧使用的也是硬件SPI1 ; 通讯速度应该可以跑满 单片机这一侧的极限速度(42MHz),但是我在测试时候发现数据在40M 就很不稳定了(逻辑分析仪测试,可能是导线有点长) 最终就选择了4MHz.。
整体的这个实现的机制就是在单片机里面设置好 SPI的从机模式 + DMA收发 DMA使用循环模式(自动重复覆盖内存) 然后让ESP8266 侧也是开辟相同大小的 空间,读取发送同步进行;通过控制 单片机侧的开启时间进而实现 两侧的内存的同步(近似的同步 有点类似于镜像)底层的着四块空间 两两相互可以实现单向映射。
程序实现的介绍
ESP8266
import network
#import simple
import time
import json
import machine
from machine import UART,SPI,Pin
machine.freq(160000000) # 提高主频
#import esps
#esp.osdebug(None)
CS = Pin(16, Pin.OUT) #片选引脚
#spi = SPI(baudrate=10000000, polarity=1, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) #软件模拟
spi = SPI(1, baudrate=4000000, polarity=1, phase=1) #硬件实现
send_buf = bytearray(60) #创建两个数组大小是 60个byte
recv_buf = bytearray(60)
for i in range(60):
send_buf[i] =i # 赋值 实际应用中我们应该是放自己想要传递的数据
cnt =0
print('ok')
while True:
cnt +=1
CS.value(0) #
spi.write_readinto(send_buf,recv_buf)
CS.value(1)
print(recv_buf)
time.sleep_ms(200)
print(cnt)
这个是python的代码实现 没啥特殊的 很简单 就是 发送的时候同步进行读取 两个同时进行。
比较难实现的是单片机侧的程序 我们需要配置 SPI 然后 SPI 配置两个DMA的数据流。
声明:我下面的代码是在其他网友的代码的基础上修改出来的,在这里向原作者致敬

uint8_t SPI_RX_BUFFER[RX_LEN]= {0,};
uint8_t SPI_TX_BUFFER[TX_LEN]= {0x1,0x2,0x3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};
/**
* @breif The spi gpio init function.
* @param None
* @retval None
*/
static void _gpio_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1); // CS Òý½Å Èí¼þÄ£Äâ
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
static void spi_dma_init(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* ??DMA2?? */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* DMA RX config */
DMA_InitStructure.DMA_Channel = DMA_Channel_3; // DMA ͨµÀ
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_ADDR; // ÍâÉèµØÖ·
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_RX_BUFFER; // ½ÓÊÕ»º³åÇø£¨ÄÚ´æÖеÄÓÐÒ»¸öÊý×飩
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //DMA ´«Êä·½Ïò
DMA_InitStructure.DMA_BufferSize = 100; // DMA ´«ÊäµÄÊýÁ¿ Õâ¸öºóÆÚ»¹¿ÉÒÔÔÙ¸Ä
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // ÍâÉèµØÖ·×ÔÔö È¡Ïû
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // ÄÚ´æµØÖ·×ÔÔö ʹÄÜ
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // ´«ÊäµÄ µ¥Î» £¨byte 8bit£©
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;// ´«ÊäµÄ µ¥Î» £¨byte 8bit£©
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // ÆÕͨģʽ ´«ÊäÍê³ÉÒ»´Î¾Í×Ô¶¯½áÊø
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; // ÓÅÏȼ¶ ÖеÈ
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //²»Ê¹Óà FIFO
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; //
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //
DMA_Init(DMA2_Stream2, &DMA_InitStructure); //³õʼ»¯
//
/* DMA TX Config */ //
DMA_InitStructure.DMA_Channel = DMA_Channel_3; // DMA ͨµÀ
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_ADDR; // ÍâÉèµØÖ·
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_TX_BUFFER; // ½ÓÊÕ»º³åÇø£¨ÄÚ´æÖеÄÓÐÒ»¸öÊý×飩
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // DMA ´«Êä·½Ïò
DMA_InitStructure.DMA_BufferSize = 100; // DMA ´«ÊäµÄÊýÁ¿ Õâ¸öºóÆÚ»¹¿ÉÒÔÔÙ¸Ä
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // ÍâÉèµØÖ·×ÔÔö È¡Ïû
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // ÄÚ´æµØÖ·×ÔÔö ʹÄÜ
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // ´«ÊäµÄ µ¥Î» £¨byte 8bit£©
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;// ´«ÊäµÄ µ¥Î» £¨byte 8bit£©
// DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // ÆÕͨģʽ ´«ÊäÍê³ÉÒ»´Î¾Í×Ô¶¯½áÊø
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // ÆÕͨģʽ ´«ÊäÍê³ÉÒ»´Î¾Í×Ô¶¯½áÊø
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; // ÓÅÏȼ¶ ÖеÈ
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; //
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //
DMA_Init(DMA2_Stream3, &DMA_InitStructure); //³õʼ»¯
}
/**
* @breif The spi init function.
* @param None
* @retval None
*/
void bsp_spi_init(void)
{
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
_gpio_init();
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // Ë«Ïßȫ˫¹¤
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; // Ö÷»úģʽ
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8bit λ¿í
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //SCK ¿ÕÏÐʱÖÓΪ¸ßµçƽ
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // µÚ¶þ¸öʱÖÓ±ßÔµ ²¶»ñ
SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; //NSSʹÓõÄÊÇÈí¼þÄ£Äâ
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; // SPI ʱÖӵķ֯µÏµÊý
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // MSB £¨ ¸ßλÔÚǰ£©
史海拾趣
|
各位大哥大姐好,工作就是问题叠问题,小弟我又来了... 开发板上有几个跳线,我写了一个测试的程序,却出问题了,大家帮忙看看... 跳线驱动部分内容: BOOL Addr_Init() { //地址映射 } BOOL WINAPI DllEntry(HANDLE hI ...… 查看全部问答> |
|
很奇怪的事情,是这样的: 在OAL初始化里添加了对GPIO的操作,很简单的操作,就是拉高拉低的操作; 写代码的地方是在OEMInit函数里的OALTimerInit,里面对GPB2操作(电路上接的是蜂鸣器),操作顺序如下: 1.设置GPB的控制寄存器,设定其为输出 ...… 查看全部问答> |
|
我用make zImage编译好2.6.13的内核文件后,把/arch/arm/boot/zImage 文件烧进板子后,linux解压出错.错误信息如下: VIVI version 0.1.4 (root@localhost.localdomain) (gcc version ...… 查看全部问答> |
|
RT 我在查阅资料时,发现《电子测量仪器设计》 主编:赵茂泰,这本书上P178页,谈到触发控测器,貌似是个很神奇的 器件,但是图书馆和网上都找不到相关资料啊!!! 求助!!!!… 查看全部问答> |




