Linux应用编程——实现SPI通信(基于百问网6ULL开发板)

news2024/10/1 1:29:11

1.SPI简介

SPI 通常指串行外设接口(Serial Peripheral Interface),它是一种高速、全双工、同步的通信总线。

SPI 总线在芯片的管脚上只占用四根线,节约了芯片的管脚,也为 PCB 的布局节省了空间。这四根线分别是:

  1. SCK(Serial Clock):串行时钟线,由主设备产生,用于同步数据传输。
  2. MOSI(Master Output/Slave Input):主设备输出/从设备输入数据线。
  3. MISO(Master Input/Slave Output):主设备输入/从设备输出数据线。
  4. CS(Chip Select):从设备使能信号线,也称为片选线,由主设备控制,用于选择与之通信的从设备。

SPI分成了四种模式,见下表, 主机与从机需要工作在相同的模式下才可以正常通讯,实际中采用较多的是“模式0”与“模式3”。

* CPOL :

        极性为0,初始时钟为低电平;

        极性为1,初始时钟为高电平;

* CPHA :

        相位为0,在时钟的第一个边缘传输数据;

        相位为1,在时钟的第二个边缘传输数据;

 2.主要函数

编写应用程序需要使用到spi_ioc_transfer结构体,包含在spidev.h里

struct spi_ioc_transfer {
   __u64             tx_buf;     //发送数据缓存
   __u64             rx_buf;     //接收数据缓存

   __u32             len;        //数据长度
   __u32             speed_hz;   //通讯速率

   __u16             delay_usecs;    //两个spi_ioc_transfer之间的延时,微秒
   __u8              bits_per_word;  //数据长度
   __u8              cs_change;      //取消选中片选
   __u8              tx_nbits;       //单次数据宽度(多数据线模式)
   __u8              rx_nbits;       //单次数据宽度(多数据线模式)
   __u16             pad;

};

还需要设备控制接口函数,使用ioctl函数设置spi相关配置

 #include <sys/ioctl.h>

 int ioctl(int fd, unsigned long request, ...);

*fd为设备文件句柄

*request的常用值有:

   

  • 初始化
void spi_init(void)
{
    int ret = 0;
    //打开 SPI 设备
    fd = open(SPI_DEV_PATH, O_RDWR);
    if (fd < 0)
        printf("can't open %s\n",SPI_DEV_PATH);

    //spi mode 设置SPI 工作模式
    ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
    if (ret == -1)
        printf("can't set spi mode\n");

    //bits per word  设置一个字节的位数
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        printf("can't set bits per word\n");

    //max speed hz  设置SPI 最高工作频率
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        printf("can't set max speed hz\n");

    //打印
    printf("spi mode: 0x%x\n", mode);
    printf("bits per word: %d\n", bits);
    printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);
}
  • 数据传输
void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
   int ret;

   struct spi_ioc_transfer tr = {
       .tx_buf = (unsigned long)tx,	//发送缓冲区地址
       .rx_buf = (unsigned long)rx,	//接收缓冲区地址
       .len = len,				    //一次传输的数据长度
       .delay_usecs = delay,		//如果不为零则用于设置两次传输之间的时间延迟
       .speed_hz = speed,			//speed_hz,指定SPI通信的比特率
       .bits_per_word = bits,		//指定字节长度,既一个字节占用多少比特
       .tx_nbits = 1,					
       .rx_nbits = 1
   };

   ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
   
   if (ret < 1)

3.实现

                        参考:"\Linux-4.9.88\tools\spi\spidev_fdx.c"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <linux/types.h>
#include <linux/spi/spidev.h>


// 定义 SPI 设备文件路径
#define SPI_DEVICE "/dev/spidevx"

int main(int argc, char **argv) {
    int fd;
    unsigned int val;
    struct spi_ioc_transfer xfer[1];
    int status;

    unsigned char tx_buf[2];
    unsigned char rx_buf[2];

    if(argc != 2)
	{
		printf("Usage: %s <val>\n",argv[1]);
		return -1;
	}
	
    // 打开 SPI 设备
    fd = open(SPI_DEVICE, O_RDWR);
    if (fd < 0) {
        perror("Failed to open SPI device");
        return -1;
    }

    val = strtoul(argv[1],NULL,0);
    val <<= 2;
    val &= 0xffc;

    tx_buf[1] = val & 0xff;
    tx_buf[0] = (val>>8) & 0xff;

    memset(xfer, 0, sizeof xfer);

	xfer[0].tx_buf = tx_buf;
	xfer[0].rx_buf = rx_buf;
	xfer[0].len = 2;

	status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);
	if (status < 0) {
		printf("SPI_IOC_MESSAGE");
		return -1;
	}

	val = (rx_buf[0] << 8) | (rx_buf[1]);
	val >>= 1;
	printf("Pre val = %d\n",val);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1979772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大模型学习笔记 - InstructGPT中的微调与对齐

LLM 微调 之 InstructGPT中的微调与对齐 LLM 微调 之 InstructGPT中的微调与对齐 技术概览 InstructGPT中的微调与对齐 大体步骤标注数据量模型训练 1. SFT 是如何训练的2. Reward Model是如何训练的3. RLHF 是如何训练的具体讲解RLHF 的loss 函数 模型效果参考链接&#xf…

数据结构实验报告-图

桂 林 理 工 大 学 实 验 报 告 一、实验名称&#xff1a; 实验7 图 二、实验内容&#xff1a; 1.已知一个有向图的顶点集V和边集E分别为:V (0,1,2,3,4,5,6,7,8};E{<0,2>&#xff0c;<1,3>,<1,4>,<2,4>,<2,5>,<3,6>,<3,7>.&l…

计算机的错误计算(五十二)

摘要 用错数解释计算机的错误计算&#xff08;五十一&#xff09;中案例 的错误计算原因。 首先&#xff0c;由计算机的错误计算&#xff08;二十七&#xff09;知&#xff0c;错数公式是 上式表示&#xff0c;函数值的错误数字个数 比自变量的错误数字个数 多约 位。其中…

为智能改造赋能,提升运营效率的智慧地产开源了。

智慧地产视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。 AI是新形势下数…

稳稳的年化10%,多任务时序动量策略——基于pytorch的深度学习策略(附python代码)

原创文章第608篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 做因子挖掘这段时间&#xff0c;有一个观感。 传统的因子挖掘&#xff0c;尤其是手工构造因子&#xff0c;到遗传算法因子挖掘。——本身也是一种”拟合“&#xff0c;或者说试图”…

6 定时器

6 定时器 1、基本概念2、使用库函数实现 1、基本概念 定时器的基本工作框架 STM32F103共支持8个定时器 假如分频器PSC的值0,则PSC分频系数1,表示输入1个时钟信号,CNT计数器加1,1S加1&#xff0c;当CNT计数器的值3&#xff0c;跟ARR自动重载寄存器的值21相等时&#xff0c;就…

Linux基于设备树的字符设备驱动框架

掌握设备树是 Linux 驱动开发人员必备的技能&#xff01;因为在新版本的 Linux 中&#xff0c;ARM 相关的驱动全部采用了设备树(也有支持老式驱动的&#xff0c;比较少)&#xff0c;最新出的 CPU 其驱动开发也基本都是基于设备树的&#xff0c;比如 ST 新出的 STM32MP157、NXP的…

【React】详解 index.js 文件

文章目录 一、index.js文件的基本结构1. 引入必要的模块2. 渲染根组件3. 注册服务工作者&#xff08;可选&#xff09; 二、index.js文件的详细解析1. ReactDOM.render的作用2. 为什么使用React.StrictMode3. 服务工作者的注册 三、index.js文件的最佳实践1. 使用模块化引入2. …

缓存常见问题总结

目录 一&#xff1a;缓存穿透 解决方案 1.对请求增加校验机制 2.缓存空值或者特殊值 3.使用布隆过滤器 布隆过滤器原理图​编辑 哈希函数的基本特性 布隆过滤器为什么会存在误判 如何降低误判率 如何使用布隆过滤器 布隆过滤器的应用场景 如何使用布隆过滤器 第一…

QT 建立tcp服务端 TcpServer TcpSocket

基于正点原子教程&#xff0c;个人改编一点点(先写着&#xff0c;还没学客户端来验证) QTcpServer 服务端&#xff0c;下控制多个socket QTcpSocket 可以理解为一个TCP连接 使用客户端的流程为 1.包含network和include 2.声明QTcpServer信号 整个流程都要使用QTcpServer对象&a…

搭建pxe网络安装环境实现服务器自动部署

1.首先配置自动化脚本工具 根据自己的主机设置自己的IP 这张图选择红框下面的选则剩余空间 红帽7的初始网卡为ens33&#xff0c;所以部署后新机器的网卡为ens33 根据自己所要部署的版本编写合适的脚本 使用vim.ks.cfg进入脚本编写 2.配置DHCP 使用vim编写/etc/dhcp/dhcpd.conf …

深入研究Java的String常量池

文章目录 一、StringTable分析一段代码示例一示例二示例三 二、 intern1、StringTable位置2、StringTable 性能调优3、intern深入分析3.1 思考3.2 JDK6中的解释3.3 JDK7中的解释3.4 详细分析3.5 intern正确使用的例子3.6 intern使用不当的例子 一、StringTable 常量池中的字符…

清华计算几何-ElementUniqueness, MinMap, MaxGap

ElementUniqueness问题(EU) 给出一组数给出一组数据,, 判断每个数都是唯一性的或者说判断是否存在重复的. 算法思路很简单, 快速排序 遍历判断: Max(O(nlogn) O(n)) O(nlogn)算法复杂度 代码实现 bool IsEelementUniqueness(const vector<float>& Elemnts) {vect…

【数学建模】 机器学习与统计模型

文章目录 机器学习与统计模型1. 统计分布与假设检验1.1 统计量与常见统计分布常见统计分布Python代码示例 1.2 正态性检验Shapiro-Wilk检验Python代码示例 1.3 独立性检验卡方检验Python代码示例 1.4 两组样本的差异性检验独立样本t检验Python代码示例 1.5 方差分析与事后多重比…

基于Django+MySQL球馆场地预约系统的设计与实现(源码+论文+部署讲解等)

博主介绍&#xff1a;✌全网粉丝10W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术栈介绍&#xff1a;我是程序员阿龙&#xff…

学习STM32(1)--Keil软件安装与基本操作和Keil 软件高级应用

目录 1 引 言 2 实验目的 3 实验内容 3.1 认识单片机和STM32 3.2 安装、认识软件Keil和硬件STM32F103开发板 3.3 学习调试工程 3.4 Keil工程软件的配置 4 深入解析 思考一 1.以项目“12-GPIO输出—使用固件库点亮LED”为例子&#xff0c;认识本地工程文件夹&#xf…

2024下《信息安全工程师》案例简答题,刷这些就够了!

距离2024下半年软考已经越来越近了&#xff0c;不知道今年备考软考信息安全工程师的同学们开始准备了吗&#xff1f; 简答题一直是信安拿分的重点区域&#xff0c;对于许多考生来说&#xff0c;也往往是最具挑战性的部分。今天我就把那些重要的案例简答题类型整理汇总给大家&am…

招聘网站的头像如何上传?

1、某招聘网站 显示的是圆形的&#xff0c;但是上传却需要正方形的300300像素。 2、某某招聘网站 仅支持jpg格式&#xff0c;不支持png 3、某某招聘网站 支持1mb以内图片&#xff0c;格式gif,jpg,png都支持。比较友好 4、某招聘网站 这里仅支持200200像素&#xff0c;图片格…

贪心系列专题篇四

​​​​​​​ 目录 整数替换 解法一 解法二 俄罗斯套娃信封问题 堆箱子 可被三整除的最大和 距离相等的条形码 重构字符串 声明&#xff1a;接下来主要使用贪心法来解决问题&#xff01;&#xff01;&#xff01; 整数替换 题目 思路 下面将使用两种方法来解决这…

【论文阅读】—RTDETR

《DETRs Beat YOLOs on Real-time Object Detection》 最近&#xff0c;基于端到端DETR取得了显著的性能。然而&#xff0c;DETR的高计算成本限制了它们的实际应用&#xff0c;并阻碍了它们充分利用无后处理&#xff08;如非最大抑制&#xff08;NMS&#xff09;&#xff09;的…