mr-library SPI设备使用教程

mr-library 是一个专为嵌入式系统设计的轻量级框架,模块化的软件架构充分考虑了嵌入式系统的资源和性能要求。 通过提供标准化的设备管理等,极大地简化了嵌入式应用的开发难度,帮助开发者快速构建嵌入式应用程序。

设备框架 为开发者提供标准化的接口(open、close、ioctl、read、write),解耦应用程序与底层硬件驱动,使应用开发无需硬件驱动的实现细节。 当硬件变动时,只需要适配底层驱动,上层应用可以无缝地迁移到新硬件上,大大提高了软硬件的可重用性和可扩展性。

GITEE仓库链接


概述

SPI(Serial Peripheral Interface)是一种串行外设接口,用于连接和控制嵌入式系统中的外部设备。 是一种全双工、同步的通信协议,通过时钟和数据线实现高速数据传输。SPI常用于存储器、传感器、显示器等外围设备的通信,具有简单、可靠和高速传输的特点。


准备

  1. 调用SPI设备初始化函数(如果实现了自动初始化,则无需调用)。
  2. 使能 mrconfig.h 头文件中SPI宏开关。

添加SPI设备

c 复制代码
mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_off_t cs_number);
参数 描述
spi_device SPI设备
name SPI设备名
cs_number SPI设备片选引脚编号
返回
MR_ERR_OK 添加设备成功
错误码 添加设备失败

控制SPI设备

c 复制代码
mr_err_t mr_device_ioctl(mr_device_t device, int cmd, void *args);
参数 描述
device SPI设备
cmd 控制命令
args 控制参数
返回
MR_ERR_OK 控制设备成功
错误码 控制设备失败

SPI设备支持以下命令:

c 复制代码
MR_DEVICE_CTRL_SET_CONFIG                                           /* 设置参数 */
MR_DEVICE_CTRL_GET_CONFIG                                           /* 获取参数 */
MR_DEVICE_CTRL_CONNECT                                              /* 连接总线 */
MR_DEVICE_CTRL_SET_RX_CB                                            /* 设置接收(接收中断)回调函数 */
MR_DEVICE_CTRL_SET_RX_BUFSZ                                         /* 设置接收缓冲区大小 */
MR_DEVICE_CTRL_SPI_TRANSFER                                         /* 同步传输 */

配置SPI设备

c 复制代码
struct mr_spi_config
{
    mr_uint32_t baud_rate;                                          /* 波特率 */
    mr_uint32_t host_slave: 1;                                      /* 主从模式 */
    mr_uint32_t mode: 2;                                            /* 极性、相位模式 */
    mr_uint32_t data_bits: 6;                                       /* 数据位数 */
    mr_uint32_t bit_order: 1;                                       /* 高低位 */
    mr_uint32_t cs_active: 2;                                       /* 片选激活电平 */
    mr_uint32_t pos_bits: 6;                                        /* 位置位数 */
}
  • 波特率:SPI的通信速率,表示每秒传输的比特数,常见的有18M、36M、72M等。
  • 主从模式:主机模式还是从机模式。
c 复制代码
MR_SPI_HOST                                                         /* 主机模式 */
MR_SPI_SLAVE                                                        /* 从机模式 */
  • 极性、相位模式:时钟的极性和相位。
c 复制代码
MR_SPI_MODE_0                                                       /* CPOL = 0, CPHA = 0 */
MR_SPI_MODE_1                                                       /* CPOL = 0, CPHA = 1 */
MR_SPI_MODE_2                                                       /* CPOL = 1, CPHA = 0 */
MR_SPI_MODE_3                                                       /* CPOL = 1, CPHA = 1 */
  • 数据位:表示每次能发送的位数。
c 复制代码
MR_SPI_DATA_BITS_8                                                  /* 8位数据 */
MR_SPI_DATA_BITS_16                                                 /* 16位数据 */
MR_SPI_DATA_BITS_32                                                 /* 32位数据 */
  • 高低位:数据高位在前还是低位在前。
c 复制代码
MR_SPI_BIT_ORDER_MSB                                                /* 高位在前 */
MR_SPI_BIT_ORDER_LSB                                                /* 低位在前 */
  • 片选激活电平:片选引脚有效的电平。
c 复制代码
MR_SPI_CS_ACTIVE_LOW                                                /* 低电平有效 */
MR_SPI_CS_ACTIVE_HIGH                                               /* 高电平有效 */
MR_SPI_CS_ACTIVE_HARDWARE                                           /* 硬件控制 */
  • 位置位数:发送位置时的位置的位数。
c 复制代码
MR_SPI_POS_BITS_8                                                   /* 8位位置 */
MR_SPI_POS_BITS_16                                                  /* 16位位置 */
MR_SPI_POS_BITS_32                                                  /* 32位位置 */

SPI设备配置,连接、断开总线

SPI设备添加后并不能立即进行读写操作,其读写操作依赖总线。SPI从机设备挂载总线后其余设备将无法进行读写操作,直至从机设备断开连接。

使用示例:

c 复制代码
/* 定义SPI设备 */
#define SPI_DEVICE0_CS_NUMBER           10
#define SPI_DEVICE1_CS_NUMBER           20
struct mr_spi_device spi_device0, spi_device1;

/* 添加SPI设备 */
mr_spi_device_add(&spi_device0, "spi10", SPI_DEVICE0_CS_NUMBER);
mr_spi_device_add(&spi_device1, "spi11", SPI_DEVICE1_CS_NUMBER);

/* 查找SPI设备 */
mr_device_t spi0_device = mr_device_find("spi10");
mr_device_t spi1_device = mr_device_find("spi11");

/* 设置默认参数 */
struct mr_spi_config spi_config = MR_SPI_CONFIG_DEFAULT;
mr_device_ioctl(spi0_device, MR_DEVICE_CTRL_SET_CONFIG, &spi_config);
mr_device_ioctl(spi1_device, MR_DEVICE_CTRL_SET_CONFIG, &spi_config);

/* 连接总线 */
mr_device_ioctl(spi0_device, MR_DEVICE_CTRL_CONNECT, "spi1");
mr_device_ioctl(spi1_device, MR_DEVICE_CTRL_CONNECT, "spi1");

/* 断开总线 */
mr_device_ioctl(spi0_device, MR_DEVICE_CTRL_CONNECT, MR_NULL);
mr_device_ioctl(spi1_device, MR_DEVICE_CTRL_CONNECT, MR_NULL);

设置SPI设备从机模式接收回调函数

  • 回调函数:device为触发回调设备,args传入缓冲区数据长度。

使用示例:

c 复制代码
/* 定义回调函数 */
mr_err_t spi_device_rx_cb(mr_device_t device, void *args)
{
    mr_size_t length = *(mr_size_t *)args;                          /* 获取接收缓冲区数据长度 */
    
    /* Do something */
}

/* 查找SPI1设备 */    
mr_device_t spi_device = mr_device_find("spi10");

/* 设置接收回调函数 */
mr_device_ioctl(spi_device, MR_DEVICE_CTRL_SET_RX_CB, spi_device_rx_cb);

设置SPI设备接收缓冲区大小

设备关闭时会重置缓冲区数据,请在关闭设备前确保数据不再需要。

设备所有操作都不会主动释放缓冲区,如不再使用,请主动设置缓冲区为0。

mrconfig.h 中配置的缓冲区大小将在spi-device类设备添加时自动申请设定字节大小的缓冲区(不论主机还是从机都将自动申请,请注意资源消耗)。

使用示例:

c 复制代码
/* 查找SPI1设备 */
mr_device_t spi_device = mr_device_find("spi10");

/* 设置接收缓冲区大小 */
mr_size_t bufsz = 64;
mr_device_ioctl(spi_device, MR_DEVICE_CTRL_SET_RX_BUFSZ, &bufsz);

SPI设备同步传输

c 复制代码
struct mr_spi_transfer
{
    void *write_buffer;                                             /* 写入数据 */
    void *read_buffer;                                              /* 读取数据 */

    mr_size_t size;                                                 /* 传输大小 */
};

使用示例:

c 复制代码
/* 查找SPI1设备(在此之前请先添加设备并连接总线) */
mr_device_t spi_device = mr_device_find("spi10");

/* 以可读可写的方式打开SPI设备 */
mr_device_open(spi_device, MR_DEVICE_OFLAG_RDWR);

/* 传输数据 */
mr_uint8_t buffer_w[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
mr_uint8_t buffer_r[10];
struct mr_spi_transfer spi_transfer;
spi_transfer.write_buffer = buffer_w;
spi_transfer.read_buffer = buffer_r;
spi_transfer.size = sizeof(buffer_w);
mr_device_ioctl(spi_device, MR_DEVICE_CTRL_SPI_TRANSFER, &spi_transfer);

SPI设备读取数据

c 复制代码
mr_ssize_t mr_device_read(mr_device_t device, mr_off_t pos, const void *buffer, mr_size_t size);
参数 描述
device SPI设备
pos 读取位置
buffer 读取数据
size 读取数据大小
返回
实际读取的数据大小
  • 读取位置:需要读取的(寄存器)地址,如读取0x23地址数据,则pos = 0x23,有效范围:0-2147483647。地址长度根据设置的pos_bits,如不使用时请赋值:-1。

使用示例:

c 复制代码
/* 查找SPI1设备(在此之前请先添加设备并连接总线) */
mr_device_t spi_device = mr_device_find("spi10");

/* 以可读可写的方式打开SPI设备 */
mr_device_open(spi_device, MR_DEVICE_OFLAG_RDWR);

/* 读取数据 */
mr_uint8_t buffer[10];
mr_device_read(spi_device, -1, buffer, sizeof(buffer));

/* 读取0x23地址数据*/
mr_device_read(spi_device, 0x23, buffer, sizeof(buffer));

SPI设备写入数据

c 复制代码
mr_ssize_t mr_device_write(mr_device_t device, mr_off_t pos, const void *buffer, mr_size_t size);
参数 描述
device SPI设备
pos 写入位置
buffer 写入数据
size 写入数据大小
返回
实际写入的数据大小
  • 写入位置:需要写入的(寄存器)地址,如写入0x23地址数据,则pos = 0x23,有效范围:0-2147483647。地址长度根据设置的pos_bits,如不使用时请赋值:-1。

使用示例:

c 复制代码
/* 查找SPI1设备(在此之前请先添加设备并连接总线) */
mr_device_t spi_device = mr_device_find("spi10");

/* 以可读可写的方式打开SPI设备 */
mr_device_open(spi_device, MR_DEVICE_OFLAG_RDWR);

/* 写入数据 */
char buffer[] = "hello";
mr_device_write(spi_device, -1, buffer, sizeof(buffer) - 1);

/* 向0x23地址写入数据*/
mr_device_write(spi_device, 0x23, buffer, sizeof(buffer) - 1);
相关推荐
杨荧11 小时前
【JAVA毕业设计】基于Vue和SpringBoot的宠物咖啡馆平台
java·开发语言·jvm·vue.js·spring boot·spring cloud·开源
喔喔咿哈哈12 小时前
【手撕 Spring】 -- Bean 的创建以及获取
java·后端·spring·面试·开源·github
luoganttcc14 小时前
能否推荐开源GPU供学习GPU架构
学习·开源
ai产品老杨14 小时前
部署神经网络时计算图的优化方法
人工智能·深度学习·神经网络·安全·机器学习·开源
檀越剑指大厂17 小时前
开源AI大模型工作流神器Flowise本地部署与远程访问
人工智能·开源
weixin_4462608517 小时前
开源vs闭源:你更看好哪一方?
开源
技术仔QAQ17 小时前
【tokenization分词】WordPiece, Byte-Pair Encoding(BPE), Byte-level BPE(BBPE)的原理和代码
人工智能·python·gpt·语言模型·自然语言处理·开源·nlp
tumu_C18 小时前
C++模板特化实战:在使用开源库boost::geometry::index::rtree时,用特化来让其支持自己的数据类型
c++·开源
AI服务老曹19 小时前
不仅能够实现前后场的简单互动,而且能够实现人机结合,最终实现整个巡检流程的标准化的智慧园区开源了
大数据·人工智能·深度学习·物联网·开源
william82319 小时前
Information Server 中共享开源服务中 kafka 的__consumer_offsets目录过大清理
分布式·kafka·开源