STM32与ESP32的硬件SPI通信(个人学习记录)

这篇具有很好参考价值的文章主要介绍了STM32与ESP32的硬件SPI通信(个人学习记录)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、硬件配置

        STM32F103ZET6作为主机,使用SPI2,ESP32S2作为从机,进行SPI双向通信;硬件接线如下:

                                                主机                        从机

CS                                           PB12 ——————  14

MOSI                                        PB6 ——————    2

MISO                                       PB14 ——————  13

CLK                                         PB15 ——————  12

HANDSHAKE                         PB13 ——————   15

GND                                        GND ——————   GND   

(地线一定相连在一起,不然传输的数据会乱码)

二、主机代码

#define SPI2READY	PBin(6)    //读取握手线是否准备好

void SPI2_Init(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;

	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE );
	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能 	
	
    //CS片选线
	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //PB12推挽输出 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
	
    //HANDSHAKE 握手线
	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6;	     
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;     //PB6下拉输入 
	GPIO_Init(GPIOB, &GPIO_InitStructure);            
	
	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB

 	GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	//SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		    //串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	    //第一个跳变沿数据被采样
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		    //软件管理
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//预分频值为256
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;        	//CRC值计算的多项式
	SPI_Init(SPI2, &SPI_InitStructure);                 //初始化外设SPIx寄存器
 
	SPI_Cmd(SPI2, ENABLE);                             //使能SPI外设
}  

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI2_ReadWriteByte(u8 TxData)
{		
	u8 retry=0;	
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) 
	{
        retry++;
        if(retry>200) return 0;    //发送上一个数据时间过长,报错
    }			  
	SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
	retry=0;
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) 
	{
		retry++;
		if(retry>200) return 0;
	}	  						    
	return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据					    
}

u8 TXBuffer[128];
u8 RXBuffer[128];

 int main(void)
 {	 
	u16 i=0;
	delay_init();	    	 //延时函数初始化	  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2
	uart_init(115200);	 	//串口初始化为115200
	LED_Init();		  		//初始化与LED连接的硬件接口	
	SPI2_Init();
	
	 for (i = 0; i < 10; i++)    //给发送数组赋初值
    {
        TXBuffer[i] = 0x47+i;
    }
	 
	while(1)
	{
		
		if(SPI2READY==1)        //如果从机准备好接收
		{
			GPIO_ResetBits(GPIOB,GPIO_Pin_12);	    //拉低CS
			for(i=0;i<10;i++)                       //发送数据并接收从机返回数据
			{
				RXBuffer[i]=SPI2_ReadWriteByte(TXBuffer[i]);
			}
			GPIO_SetBits(GPIOB,GPIO_Pin_12);        //拉高CS
			LED0 = ~LED0;                           //指示灯闪烁
		}
		printf("%s\r\n",RXBuffer);                  //串口打印从机接收到的数据
		delay_ms(1000);                                
	}
}




 三、从机代码

根据官方所给例程修改

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include "driver/spi_slave.h"
#include "driver/gpio.h"

#define GPIO_HANDSHAKE 2
#define GPIO_MOSI 12
#define GPIO_MISO 13
#define GPIO_SCLK 15
#define GPIO_CS 14

#ifdef CONFIG_IDF_TARGET_ESP32
#define RCV_HOST    HSPI_HOST
#else
#define RCV_HOST    SPI2_HOST
#endif

在事务进入队列并准备由master提取时调用。我们用这个来设置握手线
void my_post_setup_cb(spi_slave_transaction_t *trans) {
    gpio_set_level(GPIO_HANDSHAKE, 1);
}

//事务发送/接收后调用。我们用这个来降低握手线。
void my_post_trans_cb(spi_slave_transaction_t *trans) {
    gpio_set_level(GPIO_HANDSHAKE, 0);
}

//Main application
void app_main(void)
{
    int n=0;
    esp_err_t ret;

    //Configuration for the SPI bus
    spi_bus_config_t buscfg={
        .mosi_io_num=GPIO_MOSI,
        .miso_io_num=GPIO_MISO,
        .sclk_io_num=GPIO_SCLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
    };

    //Configuration for the SPI slave interface
    spi_slave_interface_config_t slvcfg={
        .mode=0,                    //CPOL 0,CPHA 0 (注意模式配置,需要与主机一致) 
        .spics_io_num=GPIO_CS,
        .queue_size=3,              
        .flags=0,
        .post_setup_cb=my_post_setup_cb,
        .post_trans_cb=my_post_trans_cb
    };

    //Configuration for the handshake line
    gpio_config_t io_conf={
        .intr_type=GPIO_INTR_DISABLE,
        .mode=GPIO_MODE_OUTPUT,
        .pin_bit_mask=(1<<GPIO_HANDSHAKE)
    };

    //Configure handshake line as output
    gpio_config(&io_conf);
    //Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
    gpio_set_pull_mode(GPIO_MOSI, GPIO_PULLUP_ONLY);
    gpio_set_pull_mode(GPIO_SCLK, GPIO_PULLUP_ONLY);
    gpio_set_pull_mode(GPIO_CS, GPIO_PULLUP_ONLY);

    //Initialize SPI slave interface
    ret=spi_slave_initialize(RCV_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO);
    assert(ret==ESP_OK);

    WORD_ALIGNED_ATTR char sendbuf[129]="";
    WORD_ALIGNED_ATTR char recvbuf[129]="";
    memset(recvbuf, 0, 33);     //将前33个字节填充为0     
    spi_slave_transaction_t t;  
    memset(&t, 0, sizeof(t));

    while(1) {
        //Clear receive buffer, set send buffer to something sane
        memset(recvbuf, 0x00, 129);     //将129个字节全部填充为0xA5

        for(int j=0;j<26;j++)    //给从机发送缓存区赋值
        {
            sendbuf[j]=0x41+j;
        }

        //Set up a transaction of 128 bytes to send/receive
        t.length=20*8;             //设置一次接收/发送的最大值,必须比主机一次发送的数据大小要大,否则会乱序
        t.tx_buffer=sendbuf;
        t.rx_buffer=recvbuf;
        
        ret=spi_slave_transmit(RCV_HOST, &t, portMAX_DELAY);
       // spi_slave_queue_trans(RCV_HOST, &t, portMAX_DELAY);    //可以用这个函数,但是没有验证,容易出错

        printf("Received: %s\n", recvbuf);
        n++;
    }
}

 esp32 spi stm32,学习,单片机,嵌入式硬件,stm32

运行顺序应该是从机接收先复位,再等待主机复位;如果主机先复位,则接收时序可能会不正确。

 四、运行结果

主机接收到从机返回的数据

esp32 spi stm32,学习,单片机,嵌入式硬件,stm32 

从机接收到主机发送的数据

esp32 spi stm32,学习,单片机,嵌入式硬件,stm32文章来源地址https://www.toymoban.com/news/detail-729967.html

到了这里,关于STM32与ESP32的硬件SPI通信(个人学习记录)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【0基础自研记录】ESP32-CAM自制个人网络监控

    目的:实现一个小型家庭监控 esp32-acm+烧录板+烧录线 Arduion IDE +CH340串口驱动 下载地址如下 Arduion IDE:https://www.arduino.cc/en/software CH340串口驱动 链接:https://pan.baidu.com/s/1ri8dK7wW6KFz8rOPsF-e-A 提取码:28ft 说明:Thony软件也可烧录,但或许是由于烧录板的原因,开发板与thony连接未成

    2024年02月09日
    浏览(36)
  • ESP8266与手机App通信(STM32)

            ESP8266是一种低成本的Wi-Fi模块,可用于连接物联网设备,控制器和传感器等。它具有小巧、高度集成和低功耗的特点,因此在物联网应用中被广泛使用。ESP8266模块由Espressif Systems开发,具有单芯片的封装和多种功能,包括Wi-Fi网络连接、GPIO控制、PWM控制和模拟输入

    2023年04月09日
    浏览(36)
  • 入门stm32:STM32hal库实现ESP8266与手机通信(不定长数据收发和ESP8266使用的一些问题)

    目录 前言 一、stm32cubeMX的串口配置 二、空闲中断+dma接收 三、ESP8266.c和ESP8266.h ESP8266.h ESP8266.c 注意事项 四、与手机通信例程 步骤:  例程代码main.c 运行结果 五、相关问题 总结 相关的app和源码         前提: 1.掌握串口通信和ESP8266的使用方法 串口通信:单片机串口通信

    2024年02月04日
    浏览(68)
  • 基于stm32 ESP8266WiFi模块的基本通信

    本篇涉及到的模块与工具为: 1. ATK-ESP8266wifi模块 2. USB-UART模块 3. 串口调试助手 提取链接:https://pan.baidu.com/s/17xRlpnjp8j-VvyD2VDxNXw?pwd=ufms 提取码:ufms 4. 网络调试助手 提取链接:https://pan.baidu.com/s/10spxZmwMGI70USlzkOzdxg?pwd=fmxe 提取码:fmxe 程序源码提取连接放置文章底部,需者自提

    2024年02月02日
    浏览(83)
  • 利用stm32+app inventor与esp8266通信

    本章实验的目的是将手机连接上ESP8266提供的WIFI网络,打开自定义的app连接ESP8266的ip地址及端口号,实现app与ESP8266模块的通信,进而达到app控制32开发板的目的,并将开发板上面的数据返回到app上显示出来。   关于stm32与esp8266之间的通信,在前面的文章中已经介绍得差不多

    2023年04月11日
    浏览(37)
  • (2)STM32+ESP8266+手机网络助手实现AP模式通信

    根据手头要实现的需求, 我需要通过手机端向32端发送指令,32端进行判断执行,所以采用esp8266的AP模式,将esp8266模块本身作为热点服务器,手机端作为客户端,连接热点WiFi发送数据 。 STM32rct6板、esp8266(ESP-01S)、手机端网络助手app wifi模块直接与TTL转串口模块相连即可,RX

    2024年02月07日
    浏览(48)
  • STM32+ESP8266(AT固件)连接阿里云物联网 保姆级教学(附代码) --3. STM32硬件连接+keil代码修改

    提示:这里是从实际应用如何使用教学配置,未从原理讲解,适合小白从零开始到成功,比较有成就感 STM32+ESP8266(AT固件)连接阿里云物联网系列保姆级教学 1. 创建产品和设备 2. 设置产品Topic数据和功能定义设备物模型数据显示 3. 硬件连接+代码修改 4. Web数据可视化 5.功能

    2024年02月05日
    浏览(40)
  • ESP8266 -- STM32与阿里云物联网平台建立通信(四)

    目录 链接快速定位 前沿 1 准备工作 2 硬件环境介绍 3 软件环境介绍 3.1 串口初始化及配置 3.2 编写AT MQTT指令代码 3.2.1 ESP8266_Cmd函数介绍 3.2.2 wifi连接函数介绍 3.2.3 云端连接语句介绍 3.2.4 环回消息测试语句介绍 3.2.5 属性上报语句介绍 3.2.6 设置属性语句介绍 4 实验现象 4.1 代码

    2024年02月04日
    浏览(49)
  • 入门小白:STM32hal库实现ESP8266与手机通信(不定长数据收发和ESP8266使用的一些问题)

    目录 前言 一、stm32cubeMX的串口配置 二、空闲中断+dma接收 三、ESP8266.c和ESP8266.h ESP8266.h ESP8266.c 注意事项 四、与手机通信例程 步骤:  例程代码main.c 运行结果 五、相关问题 总结 相关的app和源码         前提: 1.掌握串口通信和ESP8266的使用方法 串口通信:单片机串口通信

    2024年02月07日
    浏览(54)
  • STM32+esp8266实现单片机与服务器的WiFi通信

             源码已上传至gitee: stm32: 一些stm32模块使用经验记录 - Gitee.com https://gitee.com/lrf1125962926/stm32/tree/esp8266wifi%E9%80%9A%E4%BF%A1/         本实验采用STM32F1系列+esp8266 01s模块,采用HAL库开发。主控芯片哪个系列和型号都可以,只要有两个串口(UART或者USART,以下统称串口)

    2024年02月07日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包