在SPI接口使用之前,需要实现SPI提供的服务,包括:
SPI接口的初始化、配置、打开、关闭、发送、接收等,如果使能了中断,还需要提供中断服务程序,使能了DAM,需要提供DMA的收发程序等。
实现上述功能服务前,还需要提供一些基础的服务,比如寄存器配置、状态获取、配置参数获取和设置、GPIO相关初始化和配置控制等。
通过前面学习可知,SPI寄存器的基地址获取方式:
spi_regs[SPI0]
spi_regs[SPI1]
spi_regs[SPI2]
其中SPI0、SPI1、SPI2为SPI编号。
通过基地址和寄存器配置相关的宏定义,可以实现对寄存器的配置。
对于SPI GPIO的访问,需要知道使用了哪个SPI,即SPI的编号,使用了哪个组。
当上层使用SPI接口时,传入参数为SPI设备。这里提供函数,通过SPI设备返回其编号,函数实现如下:
static u8 spi_get_info_id(spi_dev spi)//获取ID
{
ASSERT(spi < SPI_MAX_HW_NUM);
return spi;
}
这里SPI设备号和SPI编号一致,因此为相同的值。
上层调用SPI接口时传入SPI设备即为SPI的编号。
通过SPI设备,获取其用了哪个端口,即哪个组,函数实现如下:
static u8 spi_get_info_port(spi_dev spi)
{
u8 port = (u8) - 1;
u8 id = spi_get_info_id(spi);
switch (id) {
#if SPI0_ENABLE
case SPI0:
port = spi0_p_data.port;
break;
#endif
#if SPI1_ENABLE
case SPI1:
port = spi1_p_data.port;
break;
#endif
#if SPI2_ENABLE
case SPI2:
port = spi2_p_data.port;
break;
#endif
default:
break;
}
ASSERT(port - ‘A’ < spi_io_map[id].num);
return port;
}
有了SPI的编号和组,就可以知道使用了哪些GPIO。
GPIO的相关操作:映射、初始化、配置等。
根据SPI的选择,需要配置端口的映射,将端口关联到SPI接口上。
0-3分别对应A-D:
A组IO: DI: PD2 DO: PD1 CLK: PD0 D2:PB7 D3:PD5
B组IO: DI: PA14 DO: PD1 CLK: PD0 D2:PA15 D3:PD5
C组IO: DI: PA6 DO: PA8 CLK: PA3 D2:PA7 D3:PA2
D组IO: DI: PB8 DO: PB10 CLK: PB5 D2:PB9 D3:PB4
static void spi0_iomc_config(spi_dev spi)//SPI0端口映射,A、B、C、D组
{
u8 port = spi_get_info_port(spi);//获取端口,即组
if (port == ‘A’) {
JL_IOMAP->CON0 &= ~(BIT(16) | BIT(17));//配置IOMAP的CON0的16和17bit
} else if (port == ‘B’) {
JL_IOMAP->CON0 &= ~(BIT(16) | BIT(17));
JL_IOMAP->CON0 |= (BIT(16));
} else if (port == ‘C’) {
JL_IOMAP->CON0 &= ~(BIT(16) | BIT(17));
JL_IOMAP->CON0 |= (BIT(17));
} else {
JL_IOMAP->CON0 |= (BIT(16) | BIT(17));
}
}
SPI1 模块 IO 选择
0:选择 PB0/PB1/PB2 作为 SPI1 的 CLK/DO/DI;
1:选择 PC4/PC5/PC3 作为 SPI1 的 CLK/DO/DI
static void spi1_iomc_config(spi_dev spi)//SPI1端口映射
{
u8 port = spi_get_info_port(spi);
if (port == ‘A’) {
JL_IOMAP->CON1 &= ~BIT(4);
} else if (port == ‘B’) {
JL_IOMAP->CON1 |= BIT(4);
}
}
SPI2 IO 选择
0: PB9/PB10/PB8 => CLK/DO/DI
1: USBDP/USBDM/PA13 => CLK/DO/DI
static void spi2_iomc_config(spi_dev spi)//SPI2端口映射
{
u8 port = spi_get_info_port(spi);
if (port == ‘A’) {
JL_IOMAP->CON1 &= ~BIT(16);
} else if (port == ‘B’) {
JL_IOMAP->CON1 |= BIT(16);
}
}
配置映射寄存器。进行GPIO与SPI的关联。
对于GPIO,需要配置其输入、输出、上下拉电阻等
static void spi_io_port_init(u8 port, u8 dir)//IO初始化
{
if (port != (u8) - 1) {
if (dir == 1) {
gpio_set_direction(port, 1);//输入
} else {
gpio_set_direction(port, 0);//输出
}
gpio_set_die(port, 1);//IO普通输入
gpio_set_pull_up(port, 0);//不上拉
gpio_set_pull_down(port, 0);//不下拉
}
}
static void spi_io_port_uninit(u8 port)//IO un int
{
if (port != (u8) - 1) {
gpio_set_direction(port, 1);//输入
gpio_set_die(port, 0);//IO模拟输入
gpio_set_pull_up(port, 0);//不上拉
gpio_set_pull_down(port, 0);//不下拉
}
}
注意:这里的port不是组,而是GPIO的端口号。
需要将SPI使能的组的GPIO进行初始化操作:
spi_set_bit_mode函数配置了SPI的位宽,不同位宽对应GPIO数量不同。
根据SPI编号和组,对相应GPIO进行了初始化。
void spi_set_bit_mode(spi_dev spi, int mode)//设置spi[单向/双向,位数]模式
{
u8 id = spi_get_info_id(spi);//ID
u8 port = spi_get_info_port(spi);//端口
u8 role = spi_get_info_role(spi);//主从
switch (mode) {
case SPI_MODE_BIDIR_1BIT://1bit
spi_bidir(spi_regs[id]);//双向
spi_data_width(spi_regs[id], 0);//1bit 数据宽度
break;
case SPI_MODE_UNIDIR_1BIT://1bit
spi_unidir(spi_regs[id]);//单向
spi_data_width(spi_regs[id], 0);//1bit 数据宽度
break;
case SPI_MODE_UNIDIR_2BIT://单向2bit
/* ASSERT(id == 0, “spi%d not support SPI_MODE_UNIDIR_2BIT\n”, id); /
spi_unidir(spi_regs[id]);//单向
spi_data_width(spi_regs[id], 1);//2bit 数据宽度
break;
case SPI_MODE_UNIDIR_4BIT://单向4bit
ASSERT(id == 0, “spi%d not support SPI_MODE_UNIDIR_4BIT\n”, id);//SPI0才支持4bit
spi_unidir(spi_regs[id]);//单向
spi_data_width(spi_regs[id], 2);//4bit 数据宽度
break;
}
//port为A、B、C
port -= ‘A’;
if (id == SPI2 && port + ‘A’ == ‘B’) {//如果使用的是SPI2的B组
JL_USB_IO->CON0 |= BIT(11); //IO MODE,配置USB端口为IO模式,USB两个端口当IO使用
spi_io_port_init(spi_io_map[id].io[port].di_pin, 1);//IO配置为输入
JL_USB_IO->CON0 &= ~BIT(2); //DP DIR OUT,DP配置为输出
JL_USB_IO->CON0 &= ~BIT(3); //DM DIR OUT,DM配置为输出
JL_USB_IO->CON0 |= BIT(9); //DP 1.2V digital input en,1.2V DP 数字输入使能
JL_USB_IO->CON0 |= BIT(10); //DM 1.2V digital input en,1.2V DM 数字输入使能
} else {
spi_io_port_init(spi_io_map[id].io[port].clk_pin, role == SPI_ROLE_MASTER ? 0 : 1);//主机模式下,CLK配置为输出,否则为输入
spi_io_port_init(spi_io_map[id].io[port].do_pin, 0);//DO配置为输出
//单向1bit下,DI不使用
if (mode == SPI_MODE_BIDIR_1BIT) {//双向1bit
spi_io_port_init(spi_io_map[id].io[port].di_pin, 1);//DI配置为输入
} else if (mode == SPI_MODE_UNIDIR_2BIT) {//单向2bit
spi_io_port_init(spi_io_map[id].io[port].di_pin, 0);//DI配置为输出
} else if (mode == SPI_MODE_UNIDIR_4BIT) {//单向4bit
spi_io_port_init(spi_io_map[id].io[port].di_pin, 0);//DI配置为输出
spi_io_port_init(spi_io_map[id].io[port].d2_pin, 0);//D2配置为输出
spi_io_port_init(spi_io_map[id].io[port].d3_pin, 0);//D4配置为输出
}
}
}*
相关推荐
高通平台SPI外设的片选信号配置
spi master 和spi device有各自的dts配置: 这是spi master的配置示例,也就是spi控制器 这是一个spi device的配置示例,也就是spi外设(从设备) 一个spi控制器上可以连接多个从设备,在任何时刻只有一个从设备可以通过spi控制器的数据线进行通信。片选信号就是用来确认当前和哪个外设进行通信的选择机制。一般情况下控制器想和哪个外设通讯时,会将连接到这个外...
杰里之. 输出 3 路 PMW【篇】
user_pwm_init(IO_PORTA_14,100 ,0,1); user_pwm_init(IO_PORTA_05,200 ,1,0); user_pwm_init(IO_PORTA_07,150 ,2,1); #define PWM_FRE 3000 void user_pwm_init(u32 port,u16 pwm_wide,u32 pwn_chl,bool output) { #if 1 log_info(“mio pwm init -> pwn_chl : %d\n”, pwn_
基于FPGA的SPI协议实现
一、SPI协议 1、SPI协议概括 SPI(Serial Peripheral Interface)——串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在EEPROM、FLASH、实时时钟,AD转换器以及数字信号处理器和数字信号解码器之间。SPI是一种高速,全双工,同步的通信总线,在芯片上只占用四根线(CS、MOSI、MISO、SCK),极大的...
杰理之复位IO维持电平使用说明【篇】
1、复位前设置IO状态 注意有些封装多IO内绑在一起,则需要设置另外IO为高阻模式,如PB8高阻: gpio_set_die(IO_PORTB_08, 0); gpio_set_pull_up(IO_PORTB_08, 0); gpio_set_pull_down(IO_PORTB_08, 0); gpio_direction_input(IO_PORTB_08); 硬件没外置上拉电阻则使用内部上下拉电阻 硬件外部上下拉,则需要关闭内部的上下拉 硬件没有上下拉,则使用内部上下拉:根据输出1开上拉关下拉,输出
SPI接口协议创新方向及实施路径分析
SPI接口协议创新方向及实施路径分析
20- ESP32-S3 SPI 外设,主设备编程方法
ESP32-S3 芯片集成了四个SPI 控制器,分别为和SPI3。SPI0 和SPI1 控器主要供内部使用以访问外部 FLASH 和 PSRAM,所以只能使用SPI2 和 SPI3。SPI2 又称为HSPI,SPI3 又称为VSPI,这两个属于GP-SPI。特性描述支持模式主机模式和从机模式支持通信方式半双工通信和全双工通信支持的数据模式。
SPI接口协议
SPI(Serial Peripheral Interface)是由Motorola公司定义的接口协议标准,串行外设接口(SPI)是微控制器和外围IC(如传感器、 ADC、 DAC、移位寄存器、 SRAM等)之间使用最广泛的接口之一。SPI是一种同步、全双工、主从式接口,来自主机或从机的数据在时钟上升沿或下降沿同步,主机和从机可以同时传输数据, SPI接口可以是3线式或4线式。
嵌入式(3):10大核心接口协议深度解析与实战指南
在嵌入式开发领域,设备间的数据交互离不开各类接口与协议,它们如同不同设备沟通的“数字语言”。从智能手环的传感器数据传输,到自动驾驶汽车的ECU协同控制,掌握这些“语言”是每一位嵌入式工程师的必修课。本文将深入剖析10大核心接口协议,结合实战代码、时序图和选型指南,助力你快速成长为嵌入式开发高手!
SPI接口协议的学习1
SPI接口的学习,包含SPI的模式,接口连线、定义等说明
深入解析 ReDoc:从零构建高性能 API 文档的终极指南
ReDoc 是一个强大的开源工具,用于将 OpenAPI 规范转换为高质量、响应式的 API 文档。本文详细介绍了如何使用 ReDoc 构建和自定义 API 文档,包括如何编写支持 OpenAPI 的 API 注解、配置 HTML 页面以加载文档,以及如何利用 ReDoc 的高级功能进行定制。通过实例代码,您将学会如何灵活地展示 API 文档,提升用户体验。无论是初学者还是经验丰富的开发者,都能从本文中获得实用的技巧与方案,帮助快速搭建符合需求的 API 文档界面。
用HFSS复现经典论文:从零搭建带孔缝屏蔽箱体模型(附完整建模步骤与避坑指南)
本文详细介绍了如何使用HFSS电磁仿真软件复现经典论文中的带孔缝屏蔽箱体模型,包括从零搭建模型、设置激励与边界条件、求解优化及结果验证的全过程。特别提供了建模中的布尔运算陷阱、激励设置技巧等实操难点的避坑指南,帮助工程师和学生深入理解电磁屏蔽效能研究。
FPGA常用接口协议--SPI
SPI是一种高速的、全双工、同步的通信总线, 常用于MCU和 EEPROM、FLASH、实时时钟、数字信号处理器等器件的通信。现如今,SPI总线已经成为被广泛应用的一种数据传输方式,由于其简单的接口、灵活性和易用性,SPI 已成为一种标准,SPI被半导体制造商广泛应用于IC芯片。
【多模态融合】TransFusion学习笔记(1)
工作上主要还是以纯lidar的算法开发,部署以及系统架构设计为主。对于多模态融合(这里主要是只指Lidar和Camer的融合)这方面研究甚少。最近借助和朋友们讨论论文的契机接触了一下这方面的知识,起步是晚了一点,但好歹是开了个头。下面就借助TransFusion论文及其开源代码来串一串这方面的知识。这个很好理解,参考FPointNet网络图示。就是利用现有的2D检测器在图像上提取2D初始框,根据Camera成像原理,捕获2D框视锥内的点云,再利用点云分类模型(如:PointNet)做进一步分类。
ESP32-S3的SPI接口
串行外设接口 (SPI) 是一种同步串行接口,可用于与外围设备进行通信。ESP32-S3 芯片集成了四个 SPI 控制器:• SPI0• SPI1• 通用 SPI2,即 GP-SPI2• 通用 SPI3,即 GP-SPI3SPI0 和 SPI1 控制器主要供内部使用以访问外部 flash 及 PSRAM。
新能源知识库(98)SOC曲线介绍
:一条异常的健康SOC曲线,往往能提前反映出电池性能的衰退或系统存在的隐患。BMS和EMS通过实时跟踪SOC值,能在电池电量过高(如>95%)时停止充电,电量过低(如<20%)时停止放电,从而避免因过度充放电引发的。:OCV-SOC曲线上较为平坦的部分(例如,磷酸铁锂电池通常在20%-80% SOC范围)。:在光伏、储能、电网协同的系统中,SOC曲线是能量调度的核心依据。:电池的寿命很大程度上取决于它的工作方式。:利用电池静置后电压与SOC的对应关系来估算,较准确但需要电池静置,无法实时使用。
汽车Bootloader流程
根据ISO14229-1 写的汽车行业 Bootloader流程 1:编程前 → 先读取软硬件版本号 22 F1 XX 软件信息 22 F1 XX 硬件信息 → 进入扩展会话extend diagnostic sessions 功能寻址 10 03 → 编程条件检测routine control:ECU升级条件的判断,如车速,检测车的型号 31 01 02 03 → 关闭DTC检测,(由于很多节点收不到其它节点的报文后会记录DTC故障)功能寻址 85 02 → 关闭诊断通讯(禁止各个节点的应用报...
基于FPGA实现SPI接口协议(一)
UART,IIC以及SPI作为三个基本的低速接口协议,是我们经常使用的,本系列将简单介绍SPI的接口协议,然后用几个简单的demo案例(对flash的操作)对SPI接口进行熟悉。 本文介绍SPI通信协议的基本内容以及FLASH芯片的相关基本的知识。 SPI通信协议的基本介绍 SPI(Serial Peripheral Interface,串行外围设备接口)通讯协议,是 Motorola 公司提出的一种同步串行接口技术,是一种高速、全双工、同步通信总线,在芯片中只占用四根管脚用来控制及数据传输,广泛用于 .
一文看懂分布式存储架构
目录一、集中存储结构二、分布式存储1 、分布式存储的兴起2 、分布式存储的重要性3 、分布式存储的种类和比较三、分布式理论浅析1 、一致性和可用性2 、数据分布3 、复制4 、分布式协议5、跨机房部署四、分布式文件系统1、 Google 文件系统( GFS )2、 Taobao 文件系统( TFS )3、 Fackbook Haystack 文件系统4、 CDN 内容分发网络五、分布式键值系统1、 Amazon Dynamo2、 Taobao Tiar3、 ETCD4 、产品选型比较( Etcd , Zoo
SPI接口协议以及性能演进案例
为,是一种的通信协议,由摩托罗拉(Motorola)在 1980 年代中期提出,最初用于其微控制器(MCU)与外设之间的短距离通信。在 SPI 协议出现之前,微控制器与外设的通信多采用方式。并行通信需要多根数据线(如 8 位、16 位),硬件布线复杂,占用大量的 GPIO 引脚,不适合小型化、低成本的嵌入式系统。此外,当时的串行通信方案(如早期 UART)多为异步通信,速率较低且不支持全双工,无法满足高速外设(如 SPI Flash、ADC/DAC)的通信需求。
工业级4~20mA转0~3V信号调理电路原理图设计,已量产(电流传感器)
在工业现场,4~20mA 电流信号是模拟量传输的 “老熟人”—— 抗干扰强、能跑长距离,但嵌入式 MCU 的 ADC 一般只认电压信号。最近做项目时,我设计了一款能覆盖 0~25mA(含超量程冗余)、线性输出 0~3V 的调理电路,经过现场调试挺稳定,分享下细节。
《C/C++等级考试(1~8级)历届真题解析》专栏总目录
中国电子学会《全国青少年软件编程等级考试》C/C++编程(1~8级)历届真题解析。订阅后可阅读专栏内所有真题解析,真题持续更新中!
ESP32S3学习——SPI
ESP32S3学习——SPI
迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)
迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)
常见接口协议介绍
温度PID控制PLC程序
温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值
SPI时序简单理解(SPI0、SPI1、SPI2、SPI3)
基本概念: CPOL CPOL:Clock Polarity,时钟的极性。 时钟的极性是什么概念呢? 通信的整个过程分为空闲时刻和通信时刻; 如果SCLK在数据发送之前和之后的空闲状态是高电平,那么就是CPOL=1; 如果空闲状态SCLK是低电平,那么就是 CPOL=0。 CPHA CPHA:Clock Phase,时钟的相位。 CPHA=1,表示一个时钟周期的第一个沿上是输出。 CPHA=0,表示一个时钟周期的第一个沿上是采样。那输出就是第二个沿。 至于这个沿是上升还是下降要视CPOL的值而定,CPOL=
SPI接口协议的学习2
SPI接口学习笔记2,包括寄存器相关学习、配置等
8679



被折叠的 条评论
为什么被折叠?



