Harmony鸿蒙南向驱动开发-SPI接口使用

功能简介

SPI指串行外设接口(Serial Peripheral Interface),是一种高速的,全双工,同步的通信总线。SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信。

SPI接口定义了操作SPI设备的通用方法集合,包括:

  • SPI设备句柄获取和释放。

  • SPI读写:从SPI设备读取或写入指定长度数据。

  • SPI自定义传输:通过消息传输结构体执行任意读写组合过程。

  • SPI设备配置:获取和设置SPI设备属性。

运作机制

在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,若设备过多可能增加内存占用。

独立服务模式下,核心层不会统一发布一个服务供上层使用,因此这种模式下驱动要为每个控制器发布一个服务,具体表现为:

  • 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。

  • device_info.hcs文件中deviceNode的policy字段为1或2,不能为0。

图 1 SPI独立服务模式结构图

SPI独立服务模式结构图

SPI模块各分层作用:

  • 接口层提供打开SPI设备、SPI写数据、SPI读数据、SPI传输、配置SPI设备属性、获取SPI设备属性、关闭SPI设备的接口。

  • 核心层主要提供SPI控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。

  • 适配层主要是将钩子函数的功能实例化,实现具体的功能。

SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是:

  • SCLK:时钟信号,由主设备产生;

  • MOSI:主设备数据输出,从设备数据输入;

  • MISO:主设备数据输入,从设备数据输出;

  • CS:片选,从设备使能信号,由主设备控制。

一个主设备和两个从设备的连接示意图如图2所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。

图 2 SPI主从设备连接示意图

SPI主从设备连接示意图

  • SPI通信通常由主设备发起,通过以下步骤完成一次通信:

    1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。

    2. 通过SCLK给选中的从设备提供时钟信号。

    3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。

  • 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式:

    • CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。

    • CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。

    • CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。

    • CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。

约束与限制

SPI模块当前只支持主机模式,不支持从机模式。

使用指导

场景介绍

SPI通常用于与闪存、实时时钟、传感器以及模数/数模转换器等支持SPI协议的设备进行通信。

接口说明

SPI模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/spi_if.h。

表 1 SPI驱动API接口功能介绍

接口名接口描述
DevHandle SpiOpen(const struct SpiDevInfo *info)获取SPI设备句柄
void SpiClose(DevHandle handle)释放SPI设备句柄
int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len)读取指定长度的数据
int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len)写入指定长度的数据
int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count)SPI数据传输接口
int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg)根据指定参数,配置SPI设备
int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg)获取SPI设备配置参数

使用流程

使用SPI的一般流程如下图所示。

图 3 SPI使用流程图

SPI使用流程图

获取SPI设备句柄

在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。

DevHandle SpiOpen(const struct SpiDevInfo *info); 

表 2 SpiOpen参数和返回值描述

参数参数描述
info结构体类型,SPI设备描述符
返回值返回值描述
NULL获取SPI设备句柄失败
设备句柄获取对应的SPI设备句柄成功

假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下:

struct SpiDevInfo spiDevinfo;       // SPI设备描述符
DevHandle spiHandle = NULL;         // SPI设备句柄
spiDevinfo.busNum = 0;              // SPI设备总线号
spiDevinfo.csNum = 0;               // SPI设备片选号// 获取SPI设备句柄
spiHandle = SpiOpen(&spiDevinfo);
if (spiHandle == NULL) {HDF_LOGE("SpiOpen: spi open fail!\n");return HDF_FAILURE;
}
获取SPI设备属性

在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示:

int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg);

表 3 SpiGetCfg参数和返回值描述

参数参数描述
handleDevHandle类型,SPI设备句柄
cfg结构体指针类型,SPI设备配置参数
返回值返回值描述
HDF_SUCCESS获取设备属性成功
负数获取设备属性失败
int32_t ret;
struct SpiCfg cfg = {0};                // SPI配置信息
ret = SpiGetCfg(spiHandle, &cfg);       // 获取SPI设备属性
if (ret != HDF_SUCCESS) {HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret);return ret;
}
配置SPI设备属性

在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示:

int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg);

表 4 SpiSetCfg参数和返回值描述

参数参数描述
handleDevHandle类型,SPI设备句柄
cfg结构体指针类型,SPI设备配置参数
返回值返回值描述
HDF_SUCCESS配置设备属性成功
负数配置设备属性失败
int32_t ret;
struct SpiCfg cfg = {0};                     // SPI配置信息
cfg.mode = SPI_MODE_LOOP;                    // 以回环模式进行通信
cfg.transferMode = PAL_SPI_POLLING_TRANSFER; // 以轮询的方式进行通信
cfg.maxSpeedHz = 115200;                     // 最大传输频率
cfg.bitsPerWord = 8;                         // 读写位宽为8比特
ret = SpiSetCfg(spiHandle, &cfg);            // 配置SPI设备属性
if (ret != HDF_SUCCESS) {HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret);return ret;
}
进行SPI通信
  • 向SPI设备写入指定长度的数据

    如果只向SPI设备写一次数据,则可以通过以下函数完成:

    int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len);

    表 5 SpiWrite参数和返回值描述

    参数参数描述
    handleDevHandle类型,SPI设备句柄
    bufuint8_t类型指针,待写入数据
    lenuint32_t类型,待写入的数据长度
    返回值返回值描述
    HDF_SUCCESS写入成功
    负数写入失败
    int32_t ret;
    uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78};
    // 向SPI设备写入指定长度的数据
    ret = SpiWrite(spiHandle, wbuff, 4);
    if (ret != HDF_SUCCESS) {HDF_LOGE("SpiWrite: failed, ret %d\n", ret);return ret;
    }
  • 从SPI设备读取指定长度的数据

    如果只读取一次数据,则可以通过以下函数完成:

    int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len); 

    表 6 SpiRead参数和返回值描述

    参数参数描述
    handleDevHandle类型,SPI设备句柄
    bufuint8_t类型指针,待读取数据
    lenuint32_t类型,待读取的数据长度
    返回值返回值描述
    HDF_SUCCESS读取成功
    负数读取失败
    int32_t ret;
    uint8_t rbuff[4] = {0};
    // 从SPI设备读取指定长度的数据
    ret = SpiRead(spiHandle, rbuff, 4);
    if (ret != HDF_SUCCESS) {HDF_LOGE("SpiRead: failed, ret %d\n", ret);return ret;
    }
  • 自定义传输

    如果需要发起一次自定义传输,则可以通过以下函数完成:

    int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count);

    表 7 SpiTransfer参数和返回值描述

    参数参数描述
    handleDevHandle类型,SPI设备句柄
    msgs结构体指针,待传输数据的数组
    countuint32_t类型,msgs数组长度
    返回值返回值描述
    HDF_SUCCESS传输执行成功
    负数传输执行失败
    int32_t ret;
    uint8_t wbuff[1] = {0x12};
    uint8_t rbuff[1] = {0};
    struct SpiMsg msg;        // 自定义传输的消息
    msg.wbuf = wbuff;         // 写入的数据
    msg.rbuf = rbuff;         // 读取的数据
    msg.len = 1;              // 读取、写入数据的长度都是1
    msg.csChange = 1;         // 进行下一次传输前关闭片选
    msg.delayUs = 0;          // 进行下一次传输前不进行延时
    msg.speed = 115200;       // 本次传输的速度
    // 进行一次自定义传输,传输的msg个数为1
    ret = SpiTransfer(spiHandle, &msg, 1);
    if (ret != HDF_SUCCESS) {HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);return ret;
    }
销毁SPI设备句柄

SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示:

void SpiClose(DevHandle handle);

该函数会释放掉申请的资源。

表 8 SpiClose参数描述

参数参数描述
handleDevHandle类型,SPI设备句柄
SpiClose(spiHandle); // 销毁SPI设备句柄

使用实例

本例拟对Hi3516DV300开发板上SPI设备进行操作。

SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。

#include "hdf_log.h"
#include "spi_if.h"void SpiTestSample(void)
{int32_t ret;struct SpiCfg cfg;                      // SPI配置信息struct SpiDevInfo spiDevinfo;           // SPI设备描述符DevHandle spiHandle = NULL;             // SPI设备句柄struct SpiMsg msg;                      // 自定义传输的消息uint8_t rbuff[4] = { 0 };uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 };uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 };spiDevinfo.busNum = 0;                  // SPI设备总线号spiDevinfo.csNum = 0;                   // SPI设备片选号spiHandle = SpiOpen(&spiDevinfo);       // 根据spiDevinfo获取SPI设备句柄if (spiHandle == NULL) {HDF_LOGE("SpiTestSample: spi open fail!\n");return;}// 获取SPI设备属性ret = SpiGetCfg(spiHandle, &cfg);if (ret != HDF_SUCCESS) {HDF_LOGE("SpiTestSample: spi get cfg fail, ret:%d!\n", ret);goto err;}cfg.maxSpeedHz = 115200;                // 将最大时钟频率改为115200cfg.bitsPerWord = 8;                    // 传输位宽改为8比特// 配置SPI设备属性ret = SpiSetCfg(spiHandle, &cfg);if (ret != HDF_SUCCESS) {HDF_LOGE("SpiTestSample: spi set cfg fail, ret:%d!\n", ret);goto err;}/* 向SPI设备写入指定长度的数据 */ret = SpiWrite(spiHandle, wbuff, 4);if (ret != HDF_SUCCESS) {HDF_LOGE("SpiTestSample: spi write fail, ret:%d!\n", ret);goto err;}/* 从SPI设备读取指定长度的数据 */ret = SpiRead(spiHandle, rbuff, 4);if (ret != HDF_SUCCESS) {HDF_LOGE("SpiTestSample: spi read fail, ret:%d!\n", ret);goto err;}msg.wbuf = wbuff2;                      // 写入的数据msg.rbuf = rbuff;                       // 读取的数据msg.len = 4;                            // 读取写入数据的长度为4msg.keepCs = 0;                         // 当前传输完成后是否保持CS活动,1表述保持,0表示关闭CSmsg.delayUs = 0;                        // 进行下一次传输前不进行延时msg.speed = 115200;                     // 本次传输的速度// 进行一次自定义传输,传输的msg个数为1ret = SpiTransfer(spiHandle, &msg, 1);if (ret != HDF_SUCCESS) {HDF_LOGE("SpiTestSample: spi transfer fail, ret:%d!\n", ret);goto err;}HDF_LOGD("SpiTestSample: function tests end!");
err:// 销毁SPI设备句柄SpiClose(spiHandle);
}

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

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

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

相关文章

算法练习第16天|101. 对称二叉树

101. 对称二叉树 力扣链接https://leetcode.cn/problems/symmetric-tree/description/ 题目描述: 给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true示例 2&#x…

品牌百度百科词条创建多少钱?

百度百科作为国内最具权威和影响力的知识型平台,吸引了无数品牌和企业争相入驻。一个品牌的百度百科词条,不仅是对品牌形象的一种提升,更是增加品牌曝光度、提高品牌知名度的重要途径。品牌百度百科词条创建多少钱,这成为了许多企…

玻璃生产线 Web 组态应用案例介绍

玻璃生产线组态可视化 概述 随着工厂信息化、数字化发展,智慧生产车间成为必然发展趋势,通过智能硬件、物联网、大数据等智慧化技术与手段,提高车间生产设备、工艺设备的智能执行能力,从而提升整个车间乃至工厂的智能化、网络化与…

【SpringBoot XSS存储漏洞 拦截器】Java纯后端对于前台输入值的拦截校验实现 一个类加一个注解结束

先看效果: 1.js注入拦截: 2.sql注入拦截 生效只需要两步: 1.创建Filter类,粘贴如下代码: package cn.你的包命.filter; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IO…

macos 查看 远程服务器是否开放某个端口

想要使用mac查看远程服务器某个端口是否开发&#xff0c;可通过 nc 命令&#xff0c;如下&#xff1a; nc -zv <服务器IP> <端口号>如果该端口开发&#xff0c;结果为&#xff1a;succeeded! Connection to <服务器IP> port <端口号> [类型] succeed…

CLion 2024:为Mac与Win打造的卓越跨平台集成开发环境

CLion 2024作为一款跨平台IDE&#xff0c;CLion 2024不仅完美支持Mac和Windows两大操作系统&#xff0c;更在细节之处展现了其出色的跨平台兼容性。无论你是在Mac的优雅界面下工作&#xff0c;还是在Windows的实用环境中编程&#xff0c;CLion 2024都能为你提供一致且流畅的开发…

Day98:云上攻防-云原生篇K8s安全Config泄漏Etcd存储Dashboard鉴权Proxy暴露

目录 云原生-K8s安全-etcd(Master-数据库)未授权访问 etcdV2版本利用 etcdV3版本利用 云原生-K8s安全-Dashboard(Master-web面板)未授权访问 云原生-K8s安全-Configfile鉴权文件泄漏 云原生-K8s安全-Kubectl Proxy不安全配置 知识点&#xff1a; 1、云原生-K8s安全-etcd未…

Springboot实现链路追踪功能

前言 在日常开发中&#xff0c;一个业务的实现往往会调用很多个方法&#xff0c;当我们去看日志的时候&#xff0c;各种接口的日志打印出来&#xff0c;看着就头疼&#xff0c;压根没办法去定位&#xff0c;而链路追踪就能很好的帮助我们去查看接口从头至尾依次调用了哪些方法…

MacOS13搭建安卓逆向环境

MacOS中用apktool解包 这里是所有链接&#xff1a;123云盘下载 https://www.123pan.com/s/9QRqVv-JE7Y.html安装apktool https://apktool.org/docs/install/ 或者下载单独的jar包 brew install wgethttps://apktool.org/blog/apktool-2.9.3下载直链&#xff1a;https://co…

使用Python批量将PDF转Word

简述 以下全部代码无法完美对图片、表格等非文字形式的内容转化。要较好的效果需要使用光学字符分析等方法进行转化 我懒&#xff0c;不想将代码模块拆分出来写注释 除代码1中有详细注释外&#xff0c;剩下的代码仅在关键部分进行注释 代码1&#xff1a;小规模文件的转换 代码…

TikTok如何矩阵养号?TK防关联引流系统助力TK账号安全运营

TK是 TikTok旗下的短视频社交媒体&#xff0c;平台目前是全球最火的短视频平台&#xff0c;目前全球活跃用户已经超过8亿。其中 TikTok的用户已经达到8亿。TK这款短视频社交媒体平台在海外的发展潜力非常大&#xff0c;也是国内很多人的创业目标&#xff0c;很多人都想从 TK这个…

文件上传阿里云OSS准备工作及入门程序(保姆级手把手教你)

使用阿里云作为第三方&#xff0c;来存储文件。 登录阿里云官网&#xff0c;开通对象存储OSS 这样就开通成功了。点击 管理控制台 &#xff0c;出现下面页面。 不过我们也可以不充值购买&#xff0c;先叉掉&#xff0c;它有30天试用的。 创建Bucket 点这个创建Bucket。 创建存…

[论文笔记] Pai-megatron Qwen1.5-14B-CT 后预训练 踩坑记录

1. 模型权重转换报错 hf2mcore_1.5_v2.py 报错为: /mnt/cpfs/kexin/dlc_code/qwen1.5/PAI-Megatron-Patch/toolkits/model_checkpoints_convertor/qwen/hf2mcore_1.5_v2.py 正确文件替换如下,更改了477行,删除了 args.hidden_size 这个维度,在tp>1时也支持转换: eli…

TCM SRAM等五块内存的使用和动态分配

TCM SRAM等五块内存的使用和动态分配 配置sct文件内存使用动态内存分配rtx_lib.hrtx_memory.cmain.c 配置sct文件 LR_IROM1 0x08000000 0x00200000 { ; load region size_regionER_IROM1 0x08000000 0x00200000 { ; load address execution address*.o (RESET, First)*(InRoo…

Spring Boot 学习(4)——开发环境升级与项目 jdk 升级

各种版本都比较老&#xff0c;用起来也是常出各样的问题&#xff0c;终于找到一个看来不错的新教程&#xff0c;是原先那个教程的升级。遂决定升级一下开发环境&#xff0c;在升级遇到一些问题&#xff0c;摸索将其解决&#xff0c;得些体会记录备查。 最终确定开发环境约束如下…

蓝桥杯基础18——第13届省赛真题与代码详解

目录 0.心得体会 1.题目如下 2.代码实现的思路 键值扫描 数码管窗口切换 数码管的动态扫描 继电器工作时L3闪烁&#xff0c;整点时刻L1灯光亮5秒 3.变量列表 定义的常量和数组 功能控制和状态变量 定时器和计数变量 4.代码参考 4.1 头文件 onewire.h ds1302.h 4…

gpu服务器与cpu服务器的区别在哪?

GPU服务器与CPU服务器的区别主要体现在处理能力、应用场景、能源消耗和成本等方面。 处理能力&#xff1a;CPU&#xff08;中央处理器&#xff09;是计算机的“大脑”&#xff0c;负责执行指令和处理数据&#xff0c;它的设计注重于逻辑运算和串行处理能力。而GPU&#xff08;…

全球媒体发稿:海外发稿数字期刊Digital Journal

全球媒体发稿&#xff1a;海外发稿数字期刊Digital Journal ​官网&#xff1a; digitaljournal.com 数字期刊&#xff0c;加拿大知名门户&#xff0c;月访量超过30万。 是一个全球媒体平台和内容合作伙伴&#xff0c;通过捕捉和报道第一&#xff0c;提升新闻周期中的声…

文件上传【2】--靶场通关

1.前端禁用js绕过 上传文件&#xff0c;进行抓包&#xff0c;没有抓到&#xff0c;说明这里的验证是前端js验证跳出的弹窗 禁用js后&#xff0c;php文件上传成功。 2.文件上传.htaccess 上传png木马后连接不上 代码中存在.htaccess&#xff0c;判断此时应该就是需要用到.htac…

【通信原理笔记】【三】——3.7 频分复用

文章目录 前言一、时分复用&#xff08;TDM&#xff09;二、频分复用&#xff08;FDM&#xff09;总结 前言 现在我们学习了几种调制模拟基带信号的方法&#xff0c;这些调制方法可以将基带信号搬移到频带进行传输。那么如果采用不同的载波频率把多个基带信号搬移到不同的频带…