工程文件参考——CubeMX+LL库+SPI主机 阻塞式通用库

news2024/10/6 10:31:53

文章目录

  • 前言
  • CubeMX配置
  • SPI驱动实现
    • spi_driver.h
    • spi_driver.c
  • 额外的接口补充


前言

SPI,想了很久没想明白其DMA或者IT比较好用的方法,可能之后也会写一个
我个人使用场景大数据流不多,如果是大批量数据交互自然是DMA更好用,但考虑到多从机通讯,感觉还是阻塞式更灵活一些,毕竟大部分通讯片选延时1us,但一个数据传进去也就不到1us。
以后有时间改个DMA或者IT升级版

spix = new_SPI_Driver(SPIx_Port, CS_GPIOx, CS_Pin);//完成初始化
RxData = spix->tr16(spix, TxData);//数据传递
spix->cs_l(spix);;//CS拉低
spix->cs_h(spix);;//CS拉搞

SPI的多从机任务可以自己挂CS,并在上层实现数据流读取
上层实现可以参考工程文件参考——ADS1118多从机驱动(base on spi_driver)
需要8位传输的可以自己改


CubeMX配置

开了就能用,注意匹配下,数据长度,8bit还是16bit。MSB是先高位还是先低位,以及CPOL与CPHA的设置。NSS硬件片选没什么用,包括从机的NSS,感觉不如外部触发中断。
在这里插入图片描述
CS直接开GPIO,根据自己从机数量需求设计
在这里插入图片描述

SPI驱动实现

spi_driver.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SPI_DRIVER_H
#define __SPI_DRIVER_H
/* =================================================================================
File name:       __SPI_DRIVER_H
Author: Mr.NoFish
===================================================================================*/

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/

#include "main.h"

#include "spi.h"

typedef struct SPI_Driver_ SPI_Driver;

typedef void (*SPIfptrCS_H)(SPI_Driver*);
typedef void (*SPIfptrCS_L)(SPI_Driver*);
typedef uint16_t (*SPIfptrTranRecv16)(SPI_Driver*, uint16_t);
typedef void (*SPIfptrTran16)(SPI_Driver*, uint16_t);

struct SPI_Driver_
{
	SPI_TypeDef* SPIx;
	GPIO_TypeDef* CS_GPIOx;
	uint32_t CS_Pin;
	
	uint16_t TxData;
	uint16_t RxData;
	
	SPIfptrCS_H cs_h;
	SPIfptrCS_L cs_l;
	SPIfptrTranRecv16 tr16;
	SPIfptrTran16 tran16;
};


SPI_Driver* new_SPI_Driver(SPI_TypeDef* SPIx_Port, GPIO_TypeDef* CS_GPIOx, uint32_t CS_Pin);

void spi_chip_select_set(SPI_Driver* const pSPIObj);
void spi_chip_select_reset(SPI_Driver* const pSPIObj);
void spi_transmit_16(SPI_Driver* const pSPIObj, uint16_t TxData);
uint16_t spi_transmit_receive_16(SPI_Driver* const pSPIObj, uint16_t TxData);
#endif


spi_driver.c

/* =================================================================================
File name:       __SPI_DRIVER_C
Author: Mr.NoFish
===================================================================================*/
#include "spi_driver.h"

SPI_Driver* new_SPI_Driver(SPI_TypeDef* SPIx_Port, GPIO_TypeDef* CS_GPIOx, uint32_t CS_Pin)
{
	SPI_Driver* pObj = NULL;
	uint8_t i = 0;
	pObj = (SPI_Driver*)malloc(sizeof(SPI_Driver));
	if (pObj == NULL)
	{
		printf("WARN: SPI_Driver initialization failed.\r\n");
		return NULL;
	}
	

	pObj->SPIx = SPIx_Port;
	pObj->CS_GPIOx = CS_GPIOx;
	pObj->CS_Pin = CS_Pin;

	pObj->cs_h = spi_chip_select_set;
	pObj->cs_l = spi_chip_select_reset;
	pObj->tran16 = spi_transmit_16;
	pObj->tr16 = spi_transmit_receive_16;
	
	pObj->cs_h(pObj);
	//LL_SPI_Enable(pObj->SPIx);
	printf("INFO: SPI_Driver initialization succeeded.\r\n");
	return pObj;			
}

void spi_chip_select_set(SPI_Driver* const pSPIObj)
{
	LL_GPIO_SetOutputPin(pSPIObj->CS_GPIOx, pSPIObj->CS_Pin);
}

void spi_chip_select_reset(SPI_Driver* const pSPIObj)
{
	LL_GPIO_ResetOutputPin(pSPIObj->CS_GPIOx, pSPIObj->CS_Pin);
}

void spi_transmit_16(SPI_Driver* const pSPIObj, uint16_t TxData)
{	
	pSPIObj->TxData = TxData;
	
	while(!LL_SPI_IsActiveFlag_TXE(pSPIObj->SPIx));
	LL_SPI_TransmitData16(pSPIObj->SPIx, pSPIObj->TxData);
}

uint16_t spi_transmit_receive_16(SPI_Driver* const pSPIObj, uint16_t TxData)
{	
	pSPIObj->TxData = TxData;
	
	while(!LL_SPI_IsActiveFlag_TXE(pSPIObj->SPIx));
	LL_SPI_TransmitData16(pSPIObj->SPIx, pSPIObj->TxData);
	
	while(LL_SPI_IsActiveFlag_BSY(pSPIObj->SPIx));
	while(!LL_SPI_IsActiveFlag_RXNE(pSPIObj->SPIx));
	pSPIObj->RxData =  LL_SPI_ReceiveData16(pSPIObj->SPIx);
		
  return pSPIObj->RxData;
}

额外的接口补充

LL_SPI_Enable(SPIx);别忘记自己加一下,但留意别在初始化之前Enable。
SPI每个设备的实现方式都不同,所以需要根据数据手册进一步实现上层设计。
这个库设计用来提供给多从机控制,一些范例的应用可以参考如下文章。
工程文件参考——ADS1118多从机驱动(base on spi_driver)

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

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

相关文章

【Java12】封装

封装(Encapsulation)是面向对象的三大特征之一(另两个是继承和多态),指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象的内部信息,而是通过该类所提供的方法来实现对内部信息的…

期末成绩老师怎么发?

期末考试的钟声终于敲响,学生们紧张而期待地等待着成绩的揭晓。而作为老师,我们面临的不仅仅是成绩的评判,还有一项看似简单却极其繁琐的任务——将成绩单一一私信给每位学生的家长。在成绩公布的那一刻,我们不仅要确保每一份成绩…

CDNOW_master.txt数据分析实战

一、数据详情 该数据集是常见的销售数据集,数据展示的是美国1997后的商品销售数据。包含四个字段,分别是用户id,购买时间,销售量,与销售金额。 二、数据读取与数据清洗 导入必要的包 \s代表的许多空格作为分割,names重…

kafka-3

Kafka 消费组 consumer-offsets-N 稀疏索引 Kafka集群 集群搭建 集群启动和验证 Topic的意义 Topic和Partition 分区 副本 集群操作指令 多分区&多副本 多分区消费组 Rebalance机制 Rebalance机制处理流程 Rebalance机制-Range Rebalance机制-RoudRobin Rebalance机制-St…

PyQt5开发笔记:2. 2D与3D散点图、水平布局和边框修饰

一、装pyqtgraph和PyOpenGL库 pip install pyqtgraph pip install PyOpenGL 注意:一定不要pip install OpenGL,否则会找不到 二、3D散点图效果 import pyqtgraph as pg import pyqtgraph.opengl as gl import numpy as np# 创建应用程序 app pg.mkQ…

护网在即,助力安服仔漏洞扫描~

整合了个漏扫系统,安服仔必备~ 使用场景 网前布防,漏洞扫描,资产梳理 使用方法: 启动虚拟机后运行命令: ./StartSystemScript.sh 输入密码attack 启动完成后浏览器打开网站: http://IP:5000 相关账户…

【Rust基础入门】Hello Cargo

文章目录 前言Cargo是什么?Cargo的作用查看cargo版本使用cargo创建项目Cargo.toml文件cargo build命令cargo runcargo check为发布构建 总结 前言 在Rust编程中,Cargo扮演着至关重要的角色。它是Rust的包管理器,负责处理许多任务&#xff0c…

JAVA之(方法的重载与重写、this关键字、super关键字)

方法的重载与重写 一、方法的重载与重写1、回顾方法的定义2、重载的概念3、重写 二、this关键字1、何为this方法2、使用方法(1)在构造方法中指构造器所创建的新对象(2) 方法中指调用该方法的对象(3) 在类本…

【Unity2D 2022:UI】制作角色血条

一、创建血底UI 1. 创建画布(Canvas) 2. 在画布上添加血底图像(Image)子物体 二、编辑血底UI 1. 将血底图片拖入源图像(Source Image)中 2. 点击设置为图片的原大小(Set Native Size&#x…

AIGC时代,“人”的核心价值在何处?

随着科技的浪潮汹涌向前,人工智能生成内容(AIGC)已悄然渗透至我们生活的每一个角落,从创意设计到信息传播,其影响力与变革力愈发显著。在这一由算法驱动的新纪元里,人类社会运作模式、学习途径及职业形态均…

【操作系统】进程管理——调度算法(个人笔记)

学习日期:2024.7.4 内容摘要:各种调度算法的思想、规则、优缺点介绍 为什么要有调度算法? 调度算法就好比一群人在银行办理业务,准备办理业务的人就是进程/作业,银行窗口的工作人员就是CPU,进程往往是比C…

【论文解读】可灵(快手)|LivePortrait:具有拼接和重定向控制的高效肖像动画

📜 文献卡 英文题目: LivePortrait: Efficient Portrait Animation with Stitching and Retargeting Control;作者: Jianzhu Guo; Dingyun Zhang; Xiaoqiang Liu; Zhizhou Zhong; Yuan Zhang; Pengfei Wan; Di ZhangDOI: 10.48550/arXiv.2407.03168摘要翻译: *旨在…

为什么固定尺寸 AdSense 广告依旧会出现并非指定的尺寸广告?

经常在网站上投放谷歌 AdSense广告的站长应该都碰到过,明明投放的是固定尺寸的广告位里旧会出现并非指定尺寸的AdSense 广告,很诡异的感觉。其实这都是因为你的 AdSense 账号广告优化造成的,其中里面就包含了广告尺寸优化,只需要在…

嵌入式鸿蒙系统openharmony编译方法详解

大家好,时光如梭,今天主要给大家分享一下,鸿蒙系统的使用方法,以及源码该如何编译,其中要注意的细节有哪些? 第一:OpenHarmony系统简介 OpenHarmony 是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目, 目标是面向全场景、全连接、全智能时代,基于…

浏览器插件利器-allWebPluginV2.0.0.14-stable版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品,致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX插件直接嵌入浏览器,实现插件加载、界面显示、接口调用、事件回调等。支持谷歌、火狐等浏…

puppeteer 爬虫初探

1. puppeteer 和 puppeteer-core 安装 puppeteer 会默认下载一个最新版本的 chrome 浏览器; 安装 puppeteer-core ,不会安装 chrome, 若要程序打开浏览器运行时,需手动指定电脑系统安装的 chrome 浏览器路径; 2. puppeteer-core …

【TB作品】51单片机 Proteus仿真 超声波读取+LCD1602显示仿真12MHZ

实验报告:51单片机 Proteus仿真 超声波读取LCD1602显示仿真 一、实验背景 本实验旨在使用51单片机(AT89C51)结合超声波传感器HC-SR04和LCD1602液晶显示屏,通过Proteus仿真平台实现超声波测距功能,并将测得的距离显示…

# [0705] Task06 DDPG 算法、PPO 算法、SAC 算法【理论 only】

easy-rl PDF版本 笔记整理 P5、P10 - P12 joyrl 比对 补充 P11 - P13 OpenAI 文档整理 ⭐ https://spinningup.openai.com/en/latest/index.html 最新版PDF下载 地址:https://github.com/datawhalechina/easy-rl/releases 国内地址(推荐国内读者使用): 链…

SAP已下发EWM的交货单修改下发状态

此种情况针对EWM未接收到ERP交货单时,可以使用此程序将ERP交货单调整为未分配状态,在进行调整数据后,然后使用VL06I(启用自动下发EWM配置,则在交货单修改保存后会立即下发EWM)重新下发EWM系统。 操作步骤如…