历史上的今天
返回首页

历史上的今天

今天是: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 £¨ ¸ßλÔÚǰ£©

推荐阅读

史海拾趣

Corex Intervest Inc公司的发展小趣事

在技术创新和产品创新的基础上,Corex Intervest Inc公司开始积极拓展市场。公司通过参加国际电子展览、与各大电商平台合作等方式,不断提升品牌知名度和影响力。同时,公司还注重与客户的沟通与合作,根据客户需求定制产品方案,赢得了客户的广泛信任和好评。

Hasco Relays and Electronics International Corp公司的发展小趣事

Harris公司最初成立于1890年代,起初以无线电通信技术为核心业务。在早期,公司凭借其创新的无线电通信技术,在通信领域迅速崭露头角。这一时期,Harris不仅为军事领域提供了关键的通信解决方案,还逐步拓展到商业和民用市场,为当时的电话、电报等通信方式带来了革命性的变化。通过不断的技术研发和产品创新,Harris逐渐奠定了其在电子行业的重要地位。

Fairview Microwave Inc公司的发展小趣事

随着技术的不断进步和市场的不断变化,Fairview Microwave意识到只有不断创新才能保持领先地位。因此,公司加大了在研发方面的投入力度,建立起一支高素质的研发团队。他们不断推出具有自主知识产权的新产品和技术,为客户提供更加全面、高效的解决方案。这些创新成果不仅增强了公司的核心竞争力,也为公司在行业内树立了技术领先的地位。

Hirose公司的发展小趣事

Fairview Microwave Inc公司成立于1992年,最初只是一个由几位工程师组成的小团队,他们致力于开发高质量的射频和微波组件。在当时,微波技术正逐渐在通信、雷达和卫星通信等领域得到广泛应用,但市场上缺乏高性能、可靠的组件供应商。Fairview Microwave看到了这个市场空白,决定从适配器、连接器和衰减器等基础组件入手,凭借精湛的技术和不断的创新,逐渐在行业内树立了良好的口碑。

Broadband公司的发展小趣事

随着市场的不断变化和竞争的加剧,艾华集团意识到,要想在行业中立足并取得长远发展,必须走科技创新之路。于是,公司成立了多个研究院,专注于基础材料、产品、工业装备以及产品应用的研究。通过不断的科技创新和产品升级,艾华集团成功研发出了耐超高纹波和耐超强冲击电流的铝电容器技术,这一技术在市场上获得了广泛认可,赢得了飞利浦、欧司朗、GE等世界知名照明客户的青睐。

Arctic Silicon Devices公司的发展小趣事

面对全球电子市场的竞争压力,Arctic Silicon Devices制定了国际化发展战略。公司积极拓展海外市场,通过设立分支机构、与当地企业合作等方式,将产品和技术推向全球。同时,公司还加大了对国际人才的引进力度,提升了自身的研发实力和市场竞争力。这一战略的成功实施,使Arctic Silicon Devices在全球电子行业中占据了重要地位。

问答坊 | AI 解惑

直流电动机教程

直流电动机教程…

查看全部问答>

IQmath应用总结

最近对IQmath的应用做了一下总结,具体内容见附件。只是个人想法,错误再所难免,所以仅供大家参考。…

查看全部问答>

重开一贴...eVC 测试代码

各位大哥大姐好,工作就是问题叠问题,小弟我又来了... 开发板上有几个跳线,我写了一个测试的程序,却出问题了,大家帮忙看看... 跳线驱动部分内容: BOOL Addr_Init() { //地址映射 } BOOL WINAPI  DllEntry(HANDLE hI ...…

查看全部问答>

CE下操作IO无反应

很奇怪的事情,是这样的: 在OAL初始化里添加了对GPIO的操作,很简单的操作,就是拉高拉低的操作; 写代码的地方是在OEMInit函数里的OALTimerInit,里面对GPB2操作(电路上接的是蜂鸣器),操作顺序如下: 1.设置GPB的控制寄存器,设定其为输出 ...…

查看全部问答>

linux移植问题(ARM,2410)

我用make zImage编译好2.6.13的内核文件后,把/arch/arm/boot/zImage 文件烧进板子后,linux解压出错.错误信息如下: VIVI   version   0.1.4   (root@localhost.localdomain)   (gcc   version ...…

查看全部问答>

有没有卖24个交换口主板的厂家?

介绍一下24个交换口的厂家?为什么多网口主板大多数是个4,6个口的…

查看全部问答>

全彩显示屏模组

   惠佳锐光电科技有限公司是专业从事研发、生产、销售LED显示屏、LED显示驱动的高科技企业。公司拥有一支专业、稳定、高素质的研发队伍,主要核心技术人员和管理者,都具备多年的LED行业工作经验。公司本着以技术求发展,以质量求 ...…

查看全部问答>

有谁用过触发控测器,这是个什么东西啊?

RT    我在查阅资料时,发现《电子测量仪器设计》 主编:赵茂泰,这本书上P178页,谈到触发控测器,貌似是个很神奇的 器件,但是图书馆和网上都找不到相关资料啊!!! 求助!!!!…

查看全部问答>

对这个论坛很失望~

    前段时间搞了一个51征文活动,今天看了下结果,我的文应该没希望,所以有些愤慨,大家可以说我是沾小便宜,小气,但我要吐槽几句。     首先,活动是有时间限制的,你迟到了,文章再怎么好也不能参加了吧,这是 ...…

查看全部问答>