【SPI】 M61与STM32f103双机通信

[复制链接]
查看500 | 回复13 | 2024-5-21 09:44:44 | 显示全部楼层 |阅读模式

最近在学习M61使用时候,没有找到SPI多机通讯相关的小白教程,刚好需要用到就和大家分享以下吧

前提

  • 不知道什么是spi参考timo这篇帖子嵌入式通信协议-SPI
  • 查手册发现M61SU 只有一个SPI ,可自由配置为主模式或者从模式。

image.png

  • 默认spi0的gpio 初始化时候将CLK MISO MOSI CS都定义到指定引脚,当然可以自己手动定义到别的针脚(见手册)

    image.png

目标


  • 实现stm32与M61通过spi 实现双机/多机(一主多从)通信
  • STM32(从机) 实时进行adc采集,通过spi发送给M61(主机)

这里没有给出adc 实时采集代码,说一下原理,利用DMA设置双缓冲区,当ADC采集满一个缓冲区,切换到另一个缓冲区存放数据,此时CPU处于空闲,来进行SPI的数据发送。

代码及说明

  1. 导入相关库
#include "bflb_mtimer.h"
#include "board.h"
#include "bflb_spi.h"
#include "bflb_gpio.h"
  1. 定义收发缓冲区
uint16_t tx_buff[3] = {0};
uint16_t rx_buff[3] = {0};   //数据宽度自定义我用到无符号16位了
  1. 声明初始化
struct bflb_device_s *spi0;//声明结构体指针spi0 
struct bflb_device_s *gpio; //声明结构体指针gpio

int main(void){
    board_init();  //开发板初始化
    
    board_spi0_gpio_init(); //spi0默认的gpio初始化
    // io12  -- cs
    // io13  -- clk
    // io18  -- miso
    // io19  -- mosi
    
     struct bflb_spi_config_s spi_cfg ={
        .freq = 100000,
        .role =SPI_ROLE_MASTER,   // m61作为主机模式
        .mode = SPI_MODE3,        // 模式3  相位和极性都为1
        .data_width = SPI_DATA_WIDTH_16BIT, //数据宽度我用16位
        .bit_order = SPI_BIT_MSB,    // 位顺序
        .byte_order = SPI_BYTE_MSB, // 字节序
        .tx_fifo_threshold = 0,
        .rx_fifo_threshold = 0,
    };
    spi0 = bflb_device_get_by_name("spi0");
    bflb_spi_init(spi0,&spi_cfg);  // 初始化spi0
    
    //bflb_spi_feature_control(spi0,SPI_CMD_SET_DATA_WIDTH,SPI_DATA_WIDTH_16BIT);

    
    // 下面这些都都可以不要,说明一下还要初始化gpio干嘛,由于我不知道STM32在DMA采集切换有空闲时间,所以让stm32选一个gpio作为标志位,通知M61可以进行片选
    gpio = bflb_device_get_by_name("gpio");// gpio10 输入模式 获取电平状态
    bflb_gpio_init(gpio, GPIO_PIN_10, GPIO_INPUT | GPIO_PULLUP);  
    bflb_gpio_set(gpio,GPIO_PIN_10); // 设置为高电平
}
  1. 片选用串口打印数据
while(1){
        // 1. 判断从机是否可以片选  【定义GPIO为低电平可选】
        // 2. 片选,发送数据,接收数据
        // 3. 打印数据到串口
        if(!bflb_gpio_read(gpio, GPIO_PIN_10)){
         
      //      bflb_gpio_reset(gpio, GPIO_PIN_12); // 片选(双机通讯可以不用手动设置/取消片选)         
            for(uint8_t i=0;i<3;i++){
                //这里可能会有人有疑惑,DMA才采集三个数据,速度很快的,CPU刚调度完就结束了,会不会没有时间将数据发送出来,事实上我的STM32ADC采集的缓冲区非常大的,我只是把最大值给发出来,这里三个数就是用了三个通道的找出最大值给发过来的。
                rx_buff[i] = bflb_spi_poll_send(spi0,tx_buff[i]);  //数据交换
            }
    //        bflb_gpio_set(gpio, GPIO_PIN_12);    //取消片选
            printf(":%d,%d,%d\r\n",rx_buff[0],rx_buff[1],rx_buff[2]); //打印出ADC 采集的数据 
        }
        else{
            //printf("wait");
        }
    } 
}
  1. 代码

    image.png

效果

image.png

回复

使用道具 举报

WT_0213 | 2024-5-21 09:47:58 | 显示全部楼层

回帖奖励 +1 金钱

真不错呢
回复

使用道具 举报

爱笑 | 2024-5-21 10:16:49 | 显示全部楼层
不错不错!
用心做好保姆工作
回复

使用道具 举报

lazy | 2024-5-21 10:19:45 | 显示全部楼层
回复

使用道具 举报

jkernet | 2024-5-21 10:23:34 | 显示全部楼层
学习了
回复

使用道具 举报

爱笑 | 2024-5-21 10:44:48 | 显示全部楼层
用心做好保姆工作
回复

使用道具 举报

1084504793 | 2024-5-21 10:47:32 | 显示全部楼层
回复

使用道具 举报

iiv | 2024-5-21 10:51:34 | 显示全部楼层
很棒!点个赞
回复 支持 反对

使用道具 举报

bzhou830 | 2024-5-21 10:56:05 | 显示全部楼层
好厉害。
选择去发光,而不是被照亮
回复

使用道具 举报

lovzx | 2024-5-21 14:20:03 | 显示全部楼层
学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则