SPI接口协议的学习4
SPI的一些基础服务函数定义。
SPI有不同位宽模式,该参数由上层平台级参数进行配置。
指定SPI设备号,获取上层指定配置的位宽。
static u8 spi_get_info_mode(spi_dev spi)//获取模式
{
u8 mode = (u8) - 1;
u8 id = spi_get_info_id(spi);
switch (id) {
#if SPI0_ENABLE
case SPI0:
mode = spi0_p_data.mode;
break;
#endif
#if SPI1_ENABLE
case SPI1:
mode = spi1_p_data.mode;
break;
#endif
#if SPI2_ENABLE
case SPI2:
mode = spi2_p_data.mode;
break;
#endif
default:
break;
}
return mode;
}
根据位宽进行SPI寄存器配置、GPIO配置。
获取上层配置的主从机选择。
static u8 spi_get_info_role(spi_dev spi)//获取主从
{
u8 role = (u8) - 1;
u8 id = spi_get_info_id(spi);
switch (id) {
#if SPI0_ENABLE
case SPI0:
role = spi0_p_data.role;
break;
#endif
#if SPI1_ENABLE
case SPI1:
role = spi1_p_data.role;
break;
#endif
#if SPI2_ENABLE
case SPI2:
role = spi2_p_data.role;
break;
#endif
default:
break;
}
return role;
}
获取上层配置的时钟:
static u32 spi_get_info_clock(spi_dev spi)//获取时钟
{
u32 clock = (u8) - 1;
u8 id = spi_get_info_id(spi);
switch (id) {
#if SPI0_ENABLE
case SPI0:
clock = spi0_p_data.clk;
break;
#endif
#if SPI1_ENABLE
case SPI1:
clock = spi1_p_data.clk;
break;
#endif
#if SPI2_ENABLE
case SPI2:
clock = spi2_p_data.clk;
break;
#endif
default:
break;
}
return clock;
}
时钟为SPI的时钟信号,用于计算波特率。
/*
@brief 获取波特率
@parm spi spi句柄
@return 波特率
/
u32 spi_get_baud(spi_dev spi)//获取波特率
{
u8 id = spi_get_info_id(spi);
return spi_get_info_clock(spi);
}
/@brief 设置波特率
@parm spi spi句柄
@parm baud 波特率
@return 0 成功,< 0 失败
*/
int spi_set_baud(spi_dev spi, u32 baud)//设置波特率
{
//SPICK = sysclk / (SPIx_BAUD + 1)
//=> SPIx_BAUD = sysclk / SPICK - 1
u8 id = spi_get_info_id(spi);
u32 sysclk;sysclk = clk_get(“spi”);//获取时钟源
log_debug(“spi clock source freq %lu”, sysclk);
if (sysclk < baud) {//时钟小于baud,则返回错误
spi_w_reg_baud(spi_regs[id], 0);
return -EINVAL;
}
spi_w_reg_baud(spi_regs[id], sysclk / baud - 1);//SPICK = system clock / (SPIBAUD + 1)
return 0;
}
sysclk / baud - 1:分频系数。
其他SPI收发、中断相关的基础函数:
/*
@brief 发送1个字节
@parm spi spi句柄
@parm byte 发送的字节
@return 0 成功,< 0 失败
*/
int spi_send_byte(spi_dev spi, u8 byte)//发送1个字节
{
u8 id = spi_get_info_id(spi);//获取IDspi_dir_out(spi_regs[id]);//配置为输出
spi_w_reg_buf(spi_regs[id], byte);//写数据
return __spi_wait_ok(spi, 1);//等待完成
}
/*
@brief 发送1个字节,不等待pnd,用于中断
@parm spi spi句柄
@parm byte 发送的字节
@return null
*/
void spi_send_byte_for_isr(spi_dev spi, u8 byte)//发送1个字节,不等待pnd,用于中断
{
u8 id = spi_get_info_id(spi);//获取IDspi_dir_out(spi_regs[id]);//配置为输出
spi_w_reg_buf(spi_regs[id], byte);//写数据
}
/*
@brief 接收1个字节
@parm spi spi句柄
@parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略
@return 接收的字节
*/
u8 spi_recv_byte(spi_dev spi, int *err)//接收1字节数据
{
u8 id = spi_get_info_id(spi);
int ret;spi_dir_in(spi_regs[id]);//配置为输入
spi_w_reg_buf(spi_regs[id], 0xff);//buf中写入ff
ret = __spi_wait_ok(spi, 1);//等待接收完成,返回0表示成功
if (ret) {//接收失败
err != NULL ? *err = ret : 0;//如果err不为NULL,*err赋值错误码
return 0;
}
err != NULL ? err = 0 : 0;//接收成功,则err赋值0
return spi_r_reg_buf(spi_regs[id]);//返回读的数值
}
/*
@brief 接收1个字节,不等待pnd,用于中断
@parm spi spi句柄
@return 接收的字节
*/
u8 spi_recv_byte_for_isr(spi_dev spi)//接收1个字节,不等待pnd,用于中断
{
u8 id = spi_get_info_id(spi);//获取IDspi_dir_in(spi_regs[id]);//配置为输入
return spi_r_reg_buf(spi_regs[id]);//返回读到的数值
}
/*
@brief 发送并接收1个字节,在8个时钟内完成,仅使用于SPI_MODE_BIDIR_1BIT
@parm spi spi句柄
@parm byte 发送的字节
@parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略
@return 接收的字节
*/
u8 spi_send_recv_byte(spi_dev spi, u8 byte, int *err)//发送并接收1个字节
{
u8 id = spi_get_info_id(spi);//获取ID
int ret;spi_w_reg_buf(spi_regs[id], byte);//发送一个字节
ret = __spi_wait_ok(spi, 1);//等待发送完成
if (ret) {
err != NULL ? *err = ret : 0;//错误则返回错误码
return 0;
}
err != NULL ? *err = 0 : 0;//没错误则错误码为0
return spi_r_reg_buf(spi_regs[id]);//接收一个字节
}
SPI的等待函数:
static int __spi_wait_ok(spi_dev spi, u32 n)//等待完成
{
u8 id = spi_get_info_id(spi);
u32 baud = spi_get_info_clock(spi);
baud = clk_get(“spi”) / baud - 1;
u32 retry = baud * (clk_get(“sys”) / clk_get(“spi”)) * 8 * n * 5; //500% spi baudate
while (!spi_pnd(spi_regs[id])) {//等待标志置位__asm__ volatile("nop");//空操作if (--retry == 0) {//计数器递减,递减为0表示超时log_error("spi wait pnd timeout");return -EFAULT;//超时返回错误码}
}
spi_clr_pnd(spi_regs[id]);//清标志
return 0;
}
中断配置函数:
/*
- @brief 中断使能
- @parm spi spi句柄
- @parm en 1 使能,0 失能
- @return null
*/
void spi_set_ie(spi_dev spi, u8 en)//配置中断使能或禁能
{
u8 id = spi_get_info_id(spi);
en ? spi_ie_en(spi_regs[id]) : spi_ie_dis(spi_regs[id]);
}
/*
- @brief 判断中断标志
- @parm spi spi句柄
- @return 0 / 1
*/
u8 spi_get_pending(spi_dev spi)//获取挂起标志
{
u8 id = spi_get_info_id(spi);
return spi_pnd(spi_regs[id]) ? 1 : 0;
}
/*
- @brief 清除中断标志
- @parm spi spi句柄
- @return null
*/
void spi_clear_pending(spi_dev spi)//清除中断标志
{
u8 id = spi_get_info_id(spi);
spi_clr_pnd(spi_regs[id]);
}
SPI接口协议的学习4相关推荐
- 【常见总线接口协议】学习笔记2
https://www.cnblogs.com/zhjblogs/p/12422331.html https://www.cnblogs.com/zhjblogs/p/12464843.html ht ...
- 基于Verilog的SPI接口设计
SPI接口电路的学习 1.SPI接口电路原理 SPI, Serial Perripheral Interface, 串行外围设备接口, 是Motorola 公司推出的一种同步串行接口技术. SPI 总 ...
- SPI接口扫盲 SPI定义/SPI时序(CPHA CPOL)
SPI接口扫盲 douqingl@gmail.com 为何要写这篇文档? 百度上找出来的SPI接口中文描述都说的太过简略,没有一篇文档能够详尽的将SPI介绍清楚的.wikipedia英文版[注释1]中 ...
- nRF52832学习记录(十二、SPI接口的应用 Micro SD卡读写测试)
目录 1.nRF52xx SPI介绍 SPI接口基础介绍 SPI 寄存器 SPI 库函数介绍 SPI初始化函数 SPI数据传输函数 2.nRF52xx SPI 使用示例 w25qxx SPI Flas ...
- SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)
SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...
- 单片机软件模拟SPI接口—加深理解SPI总线协议
单片机软件模拟SPI接口-加深理解SPI总线协议 SPI(Serial Peripheral Interfacer 串行外设接口)是摩托罗拉公司推出的一种同步串行通讯接口,用于微处理器臌控制器和外 ...
- FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用
写在前面 SPI协议系列文章: FPGA实现的SPI协议(一)----SPI驱动 FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用 在上篇文章,简要介绍了SPI协 ...
- LTE学习笔记三:接口协议
上一笔记说明了LTE网络的网元组成,网元之间的联系是通过标准化的接口.接下来学习LTE终端和网络的空中接口Uu.基站之间的X2接口.基站与核心网之间的S1接口,以及LTE接口协议栈和以往无线制式相比的 ...
- AXI接口协议学习总结
AXI接口协议学习总结 下面将AXI接口协议学到的相关内容整理如下 一.AXI接口协议定义 AXI是Advanced eXtensible Interface的缩写,译为高级可扩展接口协议,是ARM公 ...
最新文章
- 【C#实践】详解三层转七层:登录
- 神经网络与机器学习 笔记—复制器(恒等)映射
- SQL基础【十三、通配符】
- JavaScript对数组的处理(一)
- 英特尔、联发科、展讯等开始支持开源的物联网轻量化操作系统AliOS Lite
- libsvm数据缩放方法
- lm723大电流可调电源电路图_高稳定大电流直流可调稳压电路
- 计算机图形学E10——Bezier曲线
- 为什么你总感觉情绪低落心情颓废?
- ajax post请求发送数组后台接收
- librdkafka自动源码编译
- java gif图片分割合成,js实现GIF图片的分解和合成
- numpy.median
- 《霍乱时期的爱情》书评
- qt:qt5.12警告消除大法之 warning: zero as null pointer constant
- 冰尘社补丁php,300英雄冰尘社盒子ios
- python的re模块替换文件字符串_Python 正则处理_re模块
- 这是什么在线客服系统?
- 首批预计才60万套。 四轮猴
- mysql 介绍 怎么下载 驱动jar包 各种细节问题大详解
热门文章
- 小辣鸡的Android开发之路-应用冻结器-4-实现应用的禁止和解禁
- 在cad中出现“代理对象不允许复制 因此写块操作被拒绝”的解决办法
- 【blender动作练习生】从零开始的骨骼绑定学习vol.2
- onethink复制、移动按钮IE8不兼容
- 如何用一台cisco1921-K9解决目前国内常见访问全网需求和流量区分策略?
- 动手学数据分析Task2第一节数据清洗及特征处理
- pythom入门_3(学习笔记)
- 等保小能手_等保测评怎么做
- 酒精加速衰老的幕后推手——DNA甲基化
- chatgpt收费吗