OpenHarmony(鸿蒙南向)——平台驱动指南【MIPI DSI】

news2024/9/27 6:06:42

往期知识点记录:

  • 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
  • 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
  • 持续更新中……

概述

功能简介

DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设(通常是LCD或者类似的显示设备),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。

MIPI DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。

图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。

图 1 DSI发送、接收接口

DSI标准对应D-PHY、DSI、DCS规范,可分为四层:

  • PHY Layer

PHY层指定传输介质(电导体)、输入/输出电路和从串行比特流中捕获“1”和“0”的时钟机制。这一部分的规范记录了传输介质的特性、信号的电气参数以及时钟与数据通道之间的时序关系。在DSI链路的发送端,并行数据、信号事件和命令按照包组织在协议层转换为包。协议层附加包协议信息和报头,然后通过Lane Management层向PHY发送完整的字节。数据由PHY进行序列化,并通过串行链路发送。DSI链路的接收端执行与发送端相反的操作,将数据包分解为并行的数据、信号事件和命令。如果有多个Lane, Lane管理层将字节分配给单独的物理层,每个Lane一个PHY。

  • Lane Management层

负责发送和收集数据流到每条Lane。数据Lane的三种操作模式 :espace mode,High-Speed(Burst) mode,Control mode。

  • Low Level Protocol层

定义了如何组帧和解析以及错误检测等。

  • Application层

描述高层编码和解析数据流。这一层描述了数据流中包含的数据的更高级的编码和解释。根据显示子系统架构的不同,它可能由具有指定格式的像素或编码的位流组成,或者由显示模块内的显示控制器解释的命令组成。DSI规范描述了像素值、位流、命令和命令参数到包集合中的字节的映射。

运作机制

MIPI DSI软件模块各分层的作用为:

  • 接口层:提供打开设备、写入数据和关闭设备的接口。

  • 核心层:主要提供绑定设备、初始化设备以及释放设备的能力。

  • 适配层:实现其它具体的功能。

说明:
核心层可以调用接口层的函数,核心层通过钩子函数调用适配层函数,从而适配层可以间接的调用接口层函数,但是不可逆转接口层调用适配层函数。

图 2 DSI无服务模式结构图

约束与限制

由于使用无服务模式,MIPI_DSI接口暂不支持用户态使用。

使用指导

场景介绍

MIPI DSI主要用于连接显示屏。

接口说明

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

表1 MIPI DSI API接口功能介绍

功能分类接口名
DevHandle MipiDsiOpen(uint8_t id)获取MIPI DSI操作句柄
void MipiDsiClose(DevHandle handle)释放MIPI DSI操作句柄
int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg *cfg)设置MIPI DSI相关配置
int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg *cfg)获取当前MIPI DSI相关配置
void MipiDsiSetLpMode(DevHandle handle)设置MIPI DSI进入Low power模式
void MipiDsiSetHsMode(DevHandle handle)设置MIPI DSI进入High speed模式
int32_t MipiDsiTx(DevHandle handle, struct DsiCmdDesc *cmd)DSI发送指令
int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc *cmd, int32_t readLen, uint8_t *out)MIPI DSI按期望长度回读数据

开发步骤

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

图 3 MIPI DSI使用流程图

获取MIPI DSI操作句柄

在进行MIPI DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。

DevHandle MipiDsiOpen(uint8_t id);

表 2 MipiDsiOpen的参数和返回值描述

参数参数描述
iduint8_t类型,MIPI DSI通道ID
返回值返回值描述
NULL获取失败
设备句柄获取到指令通道的操作句柄, 类型为DevHandle

假设系统中的MIPI DSI通道为0,获取该通道操作句柄的示例如下:

DevHandle mipiDsiHandle = NULL;  // 设备句柄
chnId = 0;                       // MIPI DSI通道ID

// 获取操作句柄
mipiDsiHandle = MipiDsiOpen(chnId);
if (mipiDsiHandle == NULL) {
    HDF_LOGE("MipiDsiOpen: mipi dsi open fail.\n");
    return NULL;
}
MIPI DSI相应配置
  • 写入MIPI DSI配置
    int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg *cfg);

表 3 MipiDsiSetCfg的参数和返回值描述

参数参数描述
handleDevHandle类型,操作句柄
cfg结构体指针类型,MIPI DSI相应配置buf 指针
返回值返回值描述
HDF_SUCCESS设置MIPI DSI配置成功
负数设置MIPI DSI配置失败
    int32_t ret;
    struct MipiCfg cfg = {0};

    // 当前对接的屏幕配置如下
    cfg.lane = DSI_4_LANES;
    cfg.mode = DSI_CMD_MODE;
    cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS;
    cfg.format = FORMAT_RGB_24_BIT;
    cfg.pixelClk = 174;
    cfg.phyDataRate = 384;
    cfg.timingInfo.hsaPixels = 50;
    cfg.timingInfo.hbpPixels = 55;
    cfg.timingInfo.hlinePixels = 1200;
    cfg.timingInfo.yResLines = 1800;
    cfg.timingInfo.vbpLines = 33;
    cfg.timingInfo.vsaLines = 76;
    cfg.timingInfo.vfpLines = 120;
    cfg.timingInfo.xResPixels = 1342;
    // 写入配置数据
    ret = MipiDsiSetCfg(mipiDsiHandle, &cfg);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiDsiSetCfg: set mipi cfg fail, ret:%d\n", ret);
        return ret;
    }
  • 获取当前MIPI DSI的配置
    int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg *cfg);

表 4 MipiDsiGetCfg的参数和返回值描述

参数参数描述
handleDevHandle类型,操作句柄
cfg结构体指针,MIPI DSI相应配置buf 指针
返回值返回值描述
HDF_SUCCESS获取当前MIPI DSI的配置成功
负数获取当前MIPI DSI的配置失败
    int32_t ret;
    struct MipiCfg cfg;
    memset(&cfg, 0, sizeof(struct MipiCfg));
    ret = MipiDsiGetCfg(mipiDsiHandle, &cfg);
    if (ret != HDF_SUCCESS) {
        HDF_LOGEMipiDsiGetCfg: get mipi cfg fail, ret:%d!\n", ret);
        return ret;
    }
发送/回读控制指令
  • 发送指令
    int32_t MipiDsiTx(PalHandle handle, struct DsiCmdDesc *cmd);

表 5 MipiDsiTx的参数和返回值描述

参数参数描述
handleDevHandle类型,操作句柄
cmd结构体指针类型,需要发送的指令数据指针
返回值返回值描述
HDF_SUCCESS发送成功
负数发送失败
    int32_t ret;
    struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc));
    if (cmd == NULL) {
        return HDF_FAILURE;
    }
    cmd->dtype = DTYPE_DCS_WRITE;
    cmd->dlen = 1;
    cmd->payload = OsalMemCalloc(sizeof(uint8_t));
    if (cmd->payload == NULL) {
        HdfFree(cmd);
        return HDF_FAILURE;
    }
    *(cmd->payload) = DTYPE_GEN_LWRITE;
    MipiDsiSetLpMode(mipiHandle);
    ret = MipiDsiTx(mipiHandle, cmd);
    MipiDsiSetHsMode(mipiHandle);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiDsiTx: mipi dsi tx fail, ret:%d\n", ret);
        HdfFree(cmd->payload);
        HdfFree(cmd);
        return ret;
    }
    HdfFree(cmd->payload);
    HdfFree(cmd);
  • 回读指令
    int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out);

表 6 MipiDsiRx的参数和返回值描述

参数参数描述
handleDevHandle类型,操作句柄
cmd结构体指针类型,需要回读的指令数据指针
readLenuint32_t类型,期望回读的数据长度
outuint8_t类型指针,回读的数据
返回值返回值描述
HDF_SUCCESS获取成功
负数获取失败
    int32_t ret;
    uint8_t readVal = 0;

    struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc));
    if (cmdRead == NULL) {
        return HDF_FAILURE;
    }
    cmdRead->dtype = DTYPE_DCS_READ;
    cmdRead->dlen = 1;
    cmdRead->payload = OsalMemCalloc(sizeof(uint8_t));
    if (cmdRead->payload == NULL) {
        HdfFree(cmdRead);
        return HDF_FAILURE;
    }
    *(cmdRead->payload) = DDIC_REG_STATUS;
    MipiDsiSetLpMode(mipiDsiHandle);
    ret = MipiDsiRx(mipiDsiHandle, cmdRead, sizeof(readVal), &readVal);
    MipiDsiSetHsMode(mipiDsiHandle);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiDsiRx: mipi dsi rx fail, ret:%d\n", ret);
        HdfFree(cmdRead->payload);
        HdfFree(cmdRead);
        return HDF_FAILURE;
    }
    HdfFree(cmdRead->payload);
    HdfFree(cmdRead);
释放MIPI DSI操作句柄

MIPI DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示:

void MipiDsiClose(DevHandle handle);

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

表 7 MipiDsiClose的参数和返回值描述

参数参数描述
handleDevHandle类型,MIPI DSI操作句柄
MipiDsiClose(mipiHandle); // 释放掉MIPI DSI操作句柄

使用实例

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

MIPI DSI完整的使用示例如下所示:

#include "hdf_log.h"
#include "mipi_dsi_if.h"
#include "osal_mem.h"

#define DTYPE_DCS_WRITE 0x05
#define DTYPE_DCS_READ 0x06
#define DTYPE_GEN_LWRITE 0x29
#define DDIC_REG_STATUS 0x0A

int32_t PalMipiDsiTestSample(void)
{
    uint8_t chnId;
    int32_t ret;  
    DevHandle mipiDsiHandle = NULL;

    // 设备通道编号
    chnId = 0; 
    // 获取操作句柄
    mipiDsiHandle = MipiDsiOpen(chnId);
    if (mipiDsiHandle == NULL) {
        HDF_LOGE("MipiDsiOpen: failed!\n");
        return HDF_FAILURE;
    }
    // 配置相应参数 
    struct MipiCfg cfg = {0};
    cfg.lane = DSI_2_LANES;
    cfg.mode = DSI_VIDEO_MODE;
    cfg.format = FORMAT_RGB_24_BIT;
    cfg.burstMode = VIDEO_BURST_MODE;
    cfg.timing.xPixels = 480;           // 480: width 
    cfg.timing.hsaPixels = 10;          // 10: horizontal sync porch 
    cfg.timing.hbpPixels = 20;          // 20: horizontal back porch 
    cfg.timing.hlinePixels = 530;       // 530: horizontal total width 
    cfg.timing.vsaLines = 2;            // 2: vertiacl sync width 
    cfg.timing.vbpLines = 14;           // 14: vertiacl back porch 
    cfg.timing.vfpLines = 16;           // 16: vertiacl front porch 
    cfg.timing.ylines = 960;            // 960: height 
    cfg.timing.edpiCmdSize = 0;         // 0 : no care 
    cfg.pixelClk = 31546;               // 31546: pixel clk   
    cfg.phyDataRate = 379;              // 379: mipi clk 
    // 写入配置数据 
    ret = MipiDsiSetCfg(mipiDsiHandle, &cfg);
    if (ret != 0) {
        HDF_LOGE("PalMipiDsiTestSample: set mipi dsi cfg fail, ret:%d\n", ret);
        return ret;
    }
    // 发送PANEL初始化指令 
    struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc));
    if (cmd == NULL) {
        return -1;
    }
    cmd->dataType = DTYPE_DCS_WRITE;
    cmd->dataLen = 1;
    cmd->payload = OsalMemCalloc(sizeof(uint8_t));
    if (cmd->payload == NULL) {
        OsalMemFree(cmd);
        return -1;
    }
    *(cmd->payload) = DTYPE_GEN_LWRITE;
    MipiDsiSetLpMode(mipiDsiHandle);
    ret = MipiDsiTx(mipiDsiHandle, cmd);
    MipiDsiSetHsMode(mipiDsiHandle);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("PalMipiDsiTestSample: mipi dsi tx fail, ret:%d\n", ret);
        OsalMemFree(cmd->payload);
        OsalMemFree(cmd);
        return ret;
    }
    OsalMemFree(cmd->payload);
    OsalMemFree(cmd);
    // 回读panel状态寄存器 
    uint8_t readVal = 0;
    struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc));
    if (cmdRead == NULL) {
        return -1;
    }
    cmdRead->dataType = DTYPE_DCS_READ;
    cmdRead->dataLen = 1;
    cmdRead->payload = OsalMemCalloc(sizeof(uint8_t));
    if (cmdRead->payload == NULL) {
        OsalMemFree(cmdRead);
        return -1;
    }
    *(cmdRead->payload) = DDIC_REG_STATUS;
    MipiDsiSetLpMode(mipiDsiHandle);
    ret = MipiDsiRx(mipiDsiHandle, cmdRead, sizeof(readVal), &readVal);
    MipiDsiSetHsMode(mipiDsiHandle);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("PalMipiDsiTestSample: mipi dsi rx fail, ret:%d\n", ret);
        OsalMemFree(cmdRead->payload);
        OsalMemFree(cmdRead);
        return ret;
    }
    OsalMemFree(cmdRead->payload);
    OsalMemFree(cmdRead);
    HDF_LOGD("PalMipiDsiTestSample: mipi dsi tests end");
    // 释放MIPI DSI设备句柄 
    MipiDsiClose(mipiDsiHandle);
    return ret;
}

最后

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

鸿蒙开发面试真题(含参考答案):

在这里插入图片描述

《OpenHarmony源码解析》:

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片
在这里插入图片描述

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

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

相关文章

防火墙的区域划分+来自公网、内网的ip欺骗攻击+防御

一、适用场景: 1、某些企业的WIFI覆盖不全面的情况下,企业职工想通过自己购置的无线路由器实现使用无线WIFI时,无意间接入无线路由器,导致ip欺骗攻击形成。 2、当企业对某个网段中的某些ip地址,限制其不能连外网&…

玩转指针(3)

一、字符指针变量 字符指针变量(如char* p)的两种赋值方式 ①将字符类型地址赋值给字符指针变量 int main() {char a w;char* p &a;*p m;return 0; }②将常量字符串赋值给字符指针变量 常量字符串的介绍:用" "引起来的就…

【有啥问啥】大型语言模型的涌现能力(Emergent Abilities):新一代AI的曙光

大型语言模型的涌现能力(Emergent Abilities):新一代AI的曙光 随着人工智能技术的飞速发展,大型语言模型(Large Language Model,LLM)展现出了令人惊叹的涌现能力。这种能力并非模型规模简单线性…

OJ在线评测系统 后端 判题机模块预开发 架构分析 使用工厂模式搭建

判题机模块预开发(架构师)(工厂模式) 判题机模块 是为了把代码交个代码沙箱去处理 得到结果返回 代码沙箱 梳理判题模块和代码沙箱的关系 判题模块:调用代码沙箱 把代码和输入交给代码沙箱去执行 代码沙箱:只负责接受代码和输入 返回编译的结果 不负…

mat (Eclipse Memory Analyzer Tool)使用以及详解

前言 在Java开发中,内存问题往往不易被发现,但它们可能导致应用性能下降甚至崩溃。Eclipse Memory Analyzer Tool(MAT)是一个强大的开源工具,专门用于分析Java堆转储(heap dumps)文件&#xff…

【含文档】基于Springboot+Vue的高校竞赛管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 系统定义了三个…

2024四川省赛 The 2024 Sichuan Provincial Collegiate Programming Contest补题记录

B - Link Summon(补) 题意 每一组样例给定五个数字,分别对应1 2 3 4 5的数量,问能凑出多少个6(每个数字都可以当对应数字或者1使用) 思路 由于数字的数量固定,所以为了尽可能凑出多个6,贪心优先选择数量最少的数字配对方式 首…

【移植】标准系统方案之瑞芯微RK3568移植案例(二)

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… Camera 基本概念 OpenHarmony 相机驱动框架模型对上实现相机 HDI …

Windows安装Vim,并在PowerShell中直接使用vim

大家好啊,我是豆小匠。 这期介绍下怎么在windows的PowerShell上使用vim,方便在命令行里修改配置文件等。 先上效果图: 1、下载Vim GitHub传送门:https://github.com/vim/vim-win32-installer/releases 选择win-64的版本下载即可&…

【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器

文章目录 C list 容器详解:从入门到精通前言第一章:C list 容器简介1.1 C STL 容器概述1.2 list 的特点 第二章:list 的构造方法2.1 常见构造函数2.1.1 示例:不同构造方法2.1.2 相关文档 第三章:list 迭代器的使用3.1 …

[大语言模型] 情感认知在大型语言模型中的近期进展-2024-09-26

[大语言模型] 情感认知在大型语言模型中的近期进展-2024-09-26 论文信息 Title: Recent Advancement of Emotion Cognition in Large Language Models Authors: Yuyan Chen, Yanghua Xiao https://arxiv.org/abs/2409.13354 情感认知在大型语言模型中的近期进展 《Recent A…

ElasticSearch安装分词器与整合SpringBoot

ElasticSearch安装分词器与整合SpringBoot 如果还没安装的点击安装ElasticSearch查看怎么安装 分词器 1.分词器 在Elasticsearch中,分词器(Tokenizer)是分析器(Analyzer)的一部分,它的主要职责是将文本输入…

MySql简介及发展

MySql简介及发展 1、MySql起源和分支 MySQL 是最流行的关系型数据库软件之一,由于其体积小、速度快、开源免费、简单易用、维护成本 低等,在集群架构中易于扩展、高可用,因此深受开发者和企业的欢迎。 Oracle和MySQL是世界市场占比最高的两…

C#图像处理学习笔记(屏幕截取,打开保存图像、旋转图像、黑白、马赛克、降低亮度、浮雕)

1、创建Form窗体应用程序 打开VS,创建新项目-语言选择C#-Window窗体应用(.NET Framework) 如果找不到,检查一下有没有安装.NET 桌面开发模块,如果没有,需要下载,记得勾选相关开发工具 接上一步,…

【ARM 嵌入式 编译系列 10.4 -- GNU Binary Utilies】

文章目录 GNU Binary Utilities 详细介绍常用工具介绍1. arm-none-eabi-objcopy2. arm-none-eabi-readelf3. arm-none-eabi-size4. arm-none-eabi-objdump5. arm-none-eabi-nm6. arm-none-eabi-strip7. arm-none-eabi-ld8. arm-none-eabi-as9. arm-none-eabi-addr2line10. arm-…

linux内核双向链表使用list klist

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、list和klist是什么?二、代码示例1.list2.klist 总结 前言 提示:这里可以添加本文要记录的大概内容: linux内核中大量使…

Spring Boot打造甘肃非遗文化传承网站

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本甘肃非物质文化网站就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信…

如何像专家一样修复任何 iPhone 上的“iPhone 已禁用”错误

“我忘记了密码,并且我的 iPhone 在多次输入错误密码后就被禁用了,如何再次访问我的手机?” 作为最安全的数字设备之一,iPhone 必须使用正确的密码解锁。即使您可以使用 Face ID 或 Touch ID 访问您的设备,在充电或重…

交警车辆通入城行证管理建设方案和必要性-———未来之窗行业应用跨平台架构

一、系统目标 建立一个高效、便捷、规范的车辆入城通行证管理系统,提高交警部门的管理效率,优化城市交通流量,减少交通拥堵,保障城市交通安全。 二、系统功能模块 1. 通行证申请模块 - 提供在线申请入口,申请人填…

【MySQL】聚合函数、group by子句

目录 聚合函数 count([distinct] column) sum([distinct] column) avg([distinct] column) max([distinct] column) min([distinct] column) group by子句 1.如何显示每个部门的平均薪资和最高薪资 2.显示每个部门每种岗位的平均薪资和最低薪资 3.显示平均工资低于200…