DJYOS驱动开发系列二:基于DJYOS的IIC驱动编写指导手册

news2025/1/12 12:15:39

1.概述

DJYOS的DjyBus总线模型为IIC、SPI之类的器件提供统一的访问接口,IICBUS模块是DjyBus模块的一个子模块,为IIC器件提供统一的编程接口,实现通信协议层与器件层的分离。也标准化了IIC总线和 Device驱动接口,本手册指导驱动工程师编写IIC的接口程序。
IIC总线使用手册,请参见《都江堰操作系统用户手册》。

2.总线资源结构

IIC通信协议是一种总线通信方式,这意味着一条总线上可以挂多个符合总线通信协议的设备,DjyBus资源组织结构就是符合这样一种物理的连接方式。在如图 21资源组织结构图,总线类型 “IIC”、第n条总线“IICn”、第n条总线上面的设备“Devn”,它们都是DjyBus资源树上面的资源结点,每次向总线“IICn”上面增加一个设备,便向资源树上面增加了一个资源结点,它是“IICn”的子结点。
在这里插入图片描述

图 2-1 总线资源结构

3.准备工作

在编写IIC 器件驱动前,建议完成必要的准备工作,如:
1、认真阅读器件手册,了解通信协议、参数、操作流程等内容;
2、熟悉iicbus.h头文件中提供的API,懂得参数的使用方法;
3、阅读IIC总线协议文档,熟练掌握IIC总线。

4.IIC 总线驱动接口

4.1.驱动架构

IICBus是DjyBus模块的一个子模块,其结构如图 41所示,它为IIC器件提供标准的、一致的应用程序编程接口,并且规范了硬件驱动接口。驱动接口分为总线控制器接口和IIC器件接口两部分,驱动的重点是总线控制器,而器件接口实际上就是配置一下该器件的物理参数。
建议文件路径:在eclipse工程中的链接目录如下,如果是导入官方提供的example工程,那么该目录已经建立,在硬盘中添加文件后,只需要刷新工程即会自动添加进工程中。
src->OS_code->bsp->cpudrv->src->cpu_peri_iic.c。
相应的头文件目录为:
src->OS_code->bsp->cpudrv-> src->cpu_peri_iic.h。
在文件系统(硬盘)中的目录结构是:
djysrc\bsp\cpudrv\cpu_name\src\cpu_peri_iic.c。
djysrc\bsp\cpudrv\cpu_name\include\cpu_peri_iic.h。
1、IIC驱动程序编写重点有:初始化IIC控制器,并且把IIC总线添加到DjyBus上。
2、实现图 41中的5个回调函数(哪些需要实现,参考后续章节)。
3、如果采用中断方式,须编写中断服务函数(实际上也是为4个回调函数服务)
在这里插入图片描述

图 4-1 IICBus总线驱动架构

4.2.初始化函数

4.2.1.step1:初始化硬件

1、IIC控制器硬件的初始化,包括传输速度、IO配置等;
2、挂载IIC中断到中断系统,并配置中断类型,如配置为异步信号(若只采用轮询方式,则此功能可省略);

4.2.2.step2:初始化参数结构体

添加IIC总线的参数类型为struct tagIIC_Param,由函数IIC_BusAdd或IIC_BusAdd_r完成对IIC总线控制块ICB的初始化和添加IICn总线结点到DjyBus资源树。
代码 4-1 IIC参数结构体

//IIC初始化参数结构体
struct tagIIC_Param
{
	char 				*BusName;					//总线名称,如IIC1
	u8 	 				*IICBuf;					//总线缓冲区指针
	u32  				IICBufLen;					//总线缓冲区大小,字节
	ptu32_t 			SpecificFlag;				//指定标记,如IIC寄存器基址
	WriteReadPoll      pWriteReadPoll;			//轮询或中断未开时使用
	WriteStartFunc     pGenerateWriteStart;		//写过程启动
	ReadStartFunc      pGenerateReadStart;		//读过程启动
	GenerateEndFunc    pGenerateEnd;				//结束通信
	IICBusCtrlFunc     pBusCtrl;					//控制函数
};

根据IIC总线通信的特点可知,无论IIC总线主设备有多少从设备,在同一时刻,IIC主设备与从设备的通信只能单一单向,即单点通信,单向通信,因此,接收与发送使用同一个缓冲区。
IIC参数结构体的回调函数参数的原型如代码 42所示,其中PrivateTag就是结构体中IIC的私有指定标签,即IICn寄存器基址。
代码 4-2 IIC回调函数类型定义

typedef bool_t (*WriteStartFunc)(ptu32_t  SpecificFlag,u8 DevAddr,
                                       u32 MemAddr,u8 MenAddrLen, u32 Length,
                                       struct tagSemaphoreLCB *IIC_BusSemp);
typedef bool_t (*ReadStartFunc)(ptu32_t  SpecificFlag,u8 DevAddr,
                                      u32 MemAddr,u8 MemAddrLen, u32 Length,
                                      struct tagSemaphoreLCB *IIC_BusSemp);
typedef void (*GenerateEndFunc)(ptu32_t  SpecificFlag);
typedef s32 (*IICBusCtrlFunc)(ptu32_t SpecificFlag,u32 cmd,
								  ptu32_t data1,ptu32_t data2);
typedef bool_t (*WriteReadPoll)(ptu32_t  SpecificFlag,u8 DevAddr,
u32 MemAddr,u8 MenAddrLen,u8* Buf, 
u32 Length,u8 WrRdFlag);

4.2.3.step3:挂载总线

有多少IIC总线是由具体的平台决定,因此,增加IIC总线到DjyBus上是由总线驱动程序员完成,成功添加的“IICn”结点会成为“IIC”结点的子结点。
增加IIC总线的API函数可以调用IIC_BusAdd函数或IIC_BusAdd_s函数,两者的区别在于,IIC_BusAdd只需调用者提供已初始化好的参数结构体struct tagIIC_Param,而后者更需要提供struct tagIIC_CB结构体控制块,该控制块为静态或全局变量(建议定义为本C文件内部静态变量)。

4.3.回调函数

4.3.1.轮询函数

如果采用轮询方式收发,5个回调函数中只需要实现这一个,其他指针置为NULL即可。
轮询函数使用场合:
1、收发方式被设为轮询方式,则总是用轮询函数收发数据。默认值为中断方式,可调用IIC_BusCtrl函数设为轮询方式。
2、在禁止调度(即禁止异步信号中断)期间,强制使用轮询方式。
3、pGenerateReadStartNULL,则使用轮询方式接收;pGenerateWriteStartNULL,则使用轮询方式发送。
4、系统初始化未完成,多事件调度尚未启动期间。
如果使用中断方式收发,且不考虑在2~4三种情况下收发数据,则无须实现本函数,WriteReadPoll指针设为NULL即可。

回调函数说明如下:
typedef bool_t (WriteReadPoll)(ptu32_t SpecificFlag,u8 DevAddr,u32 MemAddr, u8 MenAddrLen,u8 Buf, u32 Length,u8 WrRdFlag);
参数:
SpecificFlag:IIC控制器寄存器基址。
DevAddr:设备地址,低七位有效。
MemAddr:设备内部地址,若为存储设备,则为存储地址。
MemAddrLen:设备内部地址字节数。
Buf:数据缓冲区。
Length:Buf中数据字节数。
WrRdFlag:读写标志,0为写,1为读。
返回:true, 执行成功;false,执行失败。
说明:轮询函数在执行前必须关闭中断,否则将执行失败。轮询函数示例代码如代码 4-3所示。

代码 4-3 轮询函数示例
Bool_t __IIC_WriteReadPoll((tagI2CReg *reg,u8 DevAddr,u32 MemAddr,\
                             u8 MemAddrLen,u8* Buf, u32 Length,u8 WrRdFlag)
{
    __IIC_IntDisable(reg);
    if(WrRdFlag == CN_IIC_WRITE_FLAG)   //写
    {
        if(Length == __IIC_WritePoll(reg,DevAddr,MemAddr,
MemAddrLen,Buf,Length))
            return true;
        else
            return false;
    }
    else                                //读
    {
        if(Length == __IIC_ReadPoll(reg,DevAddr,MemAddr, MemAddrLen,Buf,Length))
            return true;
        else
            return false;
}
}

4.3.2.启动发送

启动发送函数(WriteStartFunc)是为中断方式收发服务的,轮询方式不需要,置为NULL即可。
启动发送的回调函数WriteStartFunc完成了发送数据时IIC的启动时序,其执行的流程为start---->发送器件地址---->发送内部地址,并开启中断,然后返回。对应在时序上,如图 42所示。
在这里插入图片描述

图 4-2 启动发送
如图中所示,写时序是以主控制器发送start信号为起始条件,紧接最低位为0从器件地址表示写操作,当收到ACK信号后会将从器件的存储地址(图中地址为2字节,具体多少字节视情况而定)发送到总线,最后发送正式的正文。
回调函数说明如下:
typedef bool_t (*WriteStartFunc)(ptu32_t SpecificFlag,u8 DevAddr,
u32 MemAddr,u8 MenAddrLen, u32 Length,
struct tagSemaphoreLCB *IIC_BusSemp);
功能:产生IIC写数据时序,并发送内部地址
参数:
SpecificFlag,寄存器基址
DevAddr,器件地址的前7比特,已将内部地址所占的bit位更新,该函数需将该地址左移一位增加最后一位读/写比特;
MemAddr,存储器内部地址,即发送到总线上的地址,该地址未包含放在设备地址上的比特位;
MenAddrLen,存储器内部地址的长度,字节单位,未包含在设备地址里面的比特位;
Length,发送的数据总量,最后一个字节发送完时,需产生停止时序,并释放信号量;
IIC_BusSemp,总线控制信号量,发送完数据后需底层驱动释放;
返回:true,启动发送过程正确,false,发生错误

4.3.3.启动接收

启动发送函数(ReadStartFunc)是为中断方式收发服务的,轮询方式不需要,置为NULL即可。
启动接收的回调函数ReadStartFunc主要完成了IIC时序上面读数据时的总线控制,读时序的时序控制过程如图 43所示。该函数依次实现了写start---->器件地址(写)---->写存储地址---->start(或者restart)---->器件地址(读)的时序过程。在启动接收时序正确完成后,需使能中断(若不使用中断,则需配置接收到数据pop的事件),并配置回复ACK,在中断中接收从器件发送的数据。
在这里插入图片描述

图 4-3 启动接收
如图所示的时序图中,有两个start时序,可以通过配置repeated来重新启动一次新的时序,而不产生停止位。
回调函数说明如下:
typedef bool_t (*ReadStartFunc)(ptu32_t SpecificFlag,u8 DevAddr,
u32 MemAddr,u8 MemAddrLen, u32 Length,
struct tagSemaphoreLCB *IIC_BusSemp);
功能:完成读时序的启动,并使能中断
参数:
SpecificFlag,寄存器基址
DevAddr,从器件地址的高七比特(同__IIC_GenerateWriteStart参数说明)
MemAddr,存储器件的内部地址(同__IIC_GenerateWriteStart参数说明)
MemAddrLen,存储器件地址长度,字节单位(同__IIC_GenerateWriteStart参数说明)
Length,接收的数据总量,接收数据的倒数第一字节,即count-1,停止产生ACK信号,当接收的字节数为count时,产生停止时序,并释放信号量iic_buf_semp;
IIC_BusSemp,发送完成的缓冲区信号量,告知上层,本次发送已经完成。
返回:TRUE,启动读时序成功,FALSE失败

4.3.4.结束传输

结束传输的回调函数__IIC_GenerateEnd主要用于停止当前正在进行的传输,特别是在发生超时传输时,用于停止本次发送或接收,实际上,该函数调用了产生停止时序的函数,使IIC主器件停止本帧数据的传输。启动和停止时序如图 44所示。
在这里插入图片描述

图 4-4 IIC启动和停止时序

4.3.5.控制函数

目前,控制IIC的底层驱动只需要实现对IIC总线传输时钟的控制即可,相对较为简单,此处不作详细说明,请参看源码cpu_peri_iic.c。

4.4.中断服务函数

4.4.1.中断实现过程

如果使用轮询方式实现驱动,则无须编写中断服务函数。
相比轮询通信方式,中断方式的执行效率更高,对CPU的消耗更少。由于各种控制器五花八门,因此,中断的具体实现方式也不同。但是基于DjyBus设计的IIC中断方式接收与发送数据大体的框架和流程基本相似。
IIC模块对IIC总线驱动程序在中断中需要完成的功能作如下要求:
第一,根据中断线或中断标志判断使用的IIC控制块和静态变量参数;
第二,发送数据中断时,调用API函数IIC_ReadPort读取需要发送的参数,并将静态变量计数器IntParam->TransCount递增;
第三,若发送结束,即IIC_ReadPort读不到数据,且IntParam->TransCount = IntParam->TransTotalLen,则需要产生停止时序和释放信号量;
第四,若为接收数据中断,则需调用IIC_WritePort将接收到的数据写入缓冲区,并将计数器IntParam->TransCount递增,接收到倒数第二个数据时,还需配置寄存器不发送ACK信号;
第五,若接收到所有数据,则需产生停止时序和释放信号量。
下面以p1020的IIC控制器连接铁电为例,简要讲解一下中断服务函数中的流程。
在中断服务函数内部,通过寄存器判断是发送中断还是接收中断,如图 45所示。发送中断时,需要判断是否收到IIC从器件ACK信号,然后读简易缓冲区中的数据,并发送之;若缓冲区中为空,判断发送的总量count是否为零,若是,则表示该帧数据已经全部发送完毕,需产生停止时序,释放信号量IntParam->pDrvPostSemp,该信号量是__IIC_GenerateWriteStart的参数。
在接收中断中,需要判断是否为倒数第二个接收的字节,若是,需要配置控制寄存器不发送ACK信号,使控制器接收到倒数第二个字节时不发送ACK信号,用于通知从设备接收的数据足够。接收到数据后调用IIC_PortWrite,该函数将接收到的数据保存到用户缓冲区。若接收到最后一个字节数据,则产生停止时序,并释放信号量IntParam->pDrvPostSemp,本次接收完成。
在这里插入图片描述

图 4-5 中断方式接收发送流程图

4.4.2.注意事项

使用中断方式实现IIC主设备与从设备通信,需要注意以下几点:
1、发送中断不仅要判断中断标志位,清标志位,同时还需判断是否接收到ACK信号;
2、正常的发送结束时,IIC_PortRead读到数据为0,计数值IntParam->TransCount 与 IntParam->TransTotalLen应该相等,若不等,则可能出现逻辑错误;
3、读数据的倒数第二个字节时,需停止时序,因为,此时数据已经发送到总线上面;
4、通信结束后,需释放信号量和停止时序。

4.5.移植建议

由于大部分的IIC控制器的设计基本相似,因此,BSP程序人员可采取下面的步骤快速的完成DJYOS驱动架构下IIC底层驱动的开发。
1、拷贝其他工程已测试通过的IIC驱动文件cpu_peri_iic.c/cpu_peri_iic.h;
2、添加IIC的中断号到critical.c文件下面tg_IntUsed数组;
3、修改cpu_peri_iic.c/cpu_peri_iic.h中与具体IIC寄存器相关的部分;
4、回调函数的具体实现和中断收发数据。
测试驱动前,确保已经调用初始化函数ModuleInstall_DjyBus(0)和ModuleInstall_IICBus(0)。

5.IIC器件驱动接口

建议将器件驱动的存放目录为djysrc\bsp\chip\xxx,其中,xxx是具体芯片的文件夹名称。
IIC总线初始化完成后,添加一个器件到总线上的过程,非常简单,就是初始化一下该器件的寻址特性参数,然后调用IIC_DevAdd_s或IIC_DevAdd函数把器件添加到总线上即可。需配置的参数,都在iicbus.h文件中定义的struct tagIIC_Device中描述。struct tagIIC_Device结构定义如下:
代码 5-1 IIC器件结构体
//IIC总线器件结构体

struct tagIIC_Device
{
    struct tagRscNode DevNode;
    u8 DevAddr;                 //七位的器件地址
    u8 BitOfMemAddrInDevAddr;//器件地址中内部地址所占比特位数
    u8 BitOfMemAddr;  //器件内部地址寻址总bit数,包含了BitOfMemAddrInDevAddr
};

对tagIIC_Device结构体作如下详细说明:

1)器件地址DevAddr是七个比特地址,如0x50,在总线上体现的地址为0x80/0x81;
2) BitOfMemAddrInDevAddr是指dev_addr的低三个比特中,有多少个bit用于器件内部存储空间寻址,取值范围:0~3。
3) BitOfMemAddr表示被操作的器件内部地址的总位数,包含器件地址上的比特位;

举例说明:存储大小为128K的铁电,器件地址为0x50,页大小为64K,则地址范围为0x00000 ~ 0x1FFFF,若存储地址占用器件地址的1个比特,则 dev_addr为0x50,BitOfMemAddrInDevAddr为1,BitOfMemAddr为17,构成了128K的寻址空间。

5.1.初始化过程

添加器件到总线的过程就是将器件结点挂到相应的“IICn”总线结点的过程,同时,配置好相应的总线通信参数。
1、定义static struct tagIIC_Device类型的静态变量;
2、初始化该变量的各成员;
3、调用IIC_DevAdd_s或IIC_DevAdd添加设备到总线结点。
4、调用IIC_BusCtrl设置总线参数
下面用FreeScale公司的CRTOUCH触摸芯片为例说明添加设备过程。如代码 52所示,将CRTOUCH芯片添加到总线“IIC0”,并命名为“IIC_Dev_CRTCH”,并配置了总线速度和采用轮询通信方式。
代码 522 添加IIC设备实例

ptu32_t CRT_Init(ptu32_t para)
{
	bool_t result = false;
	static struct tagIIC_Device s_CRT_Dev;

	//初始化IIC设备结构体
	s_CRT_Dev.DevAddr 					= CRT_ADDRESS;
	s_CRT_Dev.BitOfMemAddr 				= 8;
	s_CRT_Dev.BitOfMemAddrInDevAddr  	= 0;

	//添加CRTCH到IIC0总线
	if(NULL != IIC_DevAdd_s("IIC0","IIC_Dev_CRTCH",&s_CRT_Dev))
	{
		ps_CRT_Dev = &s_CRT_Dev;
		IIC_BusCtrl(ps_CRT_Dev,CN_IIC_SET_CLK,CRT_CLK_FRE,0);
		IIC_BusCtrl(ps_CRT_Dev,CN_IIC_SET_POLL,0,0);
		result = true;
	}

	return result;
}

6.访问器件

器件装载到IIC总线之后,可以通过访问IIC总线实现访问器件,具体就是调用iicbus.h提供的API函数IIC_Write()和IIC_Read()。

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

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

相关文章

树与二叉树(二)

**🛀 ♡ ♢ ♤ ♧ ♣ ♦ ♥ ♠🛀** 💥**欢迎来到半之半的博客**,**这篇文章主要讲述数据结构中非常重要的一块内容, 即树与二叉树,相信大家学完必会加深自己的理解。💥****🕝我是半只…

Android BLE HIDS Data ,从问询DB 到写入Android 节点的flow 之三

问题点5:Android BLE具体连接flow 并问询DB的API flow 之第二阶段问询; 表示第二阶段的log “Start service discovery: srvc_idx ”在Android9没有,但在Android 8.0中有,所以后续截图基于Android8.0。 -->执行API bta_gattc_…

ORB-SLAM2 ---- Initializer::ReconstructH函数

目录 1.函数作用 2.函数解析 2.1 调用函数解析 2.2 Initializer::ReconstructH函数总体思路 2.2.1 代码 2.2.2 总体思路解析 3.Initializer::CheckRT 3.1 函数作用 3.2 构造函数 3.3 代码 3.4 流程解析 3.4.0 初始化参数 3.4.1 计算初始化两帧的投影矩阵 3.…

[计算机毕业设计]基于SM9的密钥交换方案的实现与应用

前言 📅大四是整个大学期间最忙碌的时光,一边要忙着准备考研,考公,考教资或者实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过…

VMware虚拟机安装黑苹果步骤与常见问题,VMware16,MacOS12.01(Moterey)

资源准备: 链接:https://pan.baidu.com/s/1JFtpMVrULiky9l3SvCXX-w 提取码:c452 说明: 1.镜像版本10.14和12.01根据需要选择其一即可,10.14的后缀为cdr,12.01的后缀为ISO,这两种文件VMware都支…

排名前十的运动蓝牙耳机品牌,2022年值得推荐的运动耳机

现在越来越多人使用耳机了,无论是在公交上还是地铁上又或者在运动时,都能看见很多人使用耳机。大多数人群都喜欢在运动健身的时候佩戴着耳机听音乐,音乐能让我们释放压力,并且心情也能够得到愉悦,相比传统有线运动耳机…

抖店token的生成和刷新的实际开发笔记

目录 前言 一、获取token准备事宜 第1点,app_key的获取 第2点,获取method 第3点,获取grant_type 二、token的生成使用步骤 1.token的生成的代码逻辑 三、刷新token的准备事宜 1.refresh_token的获取 2.grant_type的获取 四、token的刷…

AIOT在数字化转型中的机遇和挑战

目录 引言 为什么 IOT 要结合 AI 数字化转型机遇 什么是企业数字化转型 AIOT 在数字化转型中的作用 面临的挑战 架构挑战 安全风险 安全挑战分析 常见安全问题 如何应对 产业赋能 问题分析 如何应对 算力建设 总结 引言 传统的安防市场已经逐渐接近业务成长天花…

一棵完全二叉树的第7层(根节点为第0层)有12个叶子节点,求整棵树最多有多少个节点和最少有多少个节点

答案 一棵完全二叉树的第7层(根节点为第0层)有12个叶子节点,求整棵树最多有487487487个节点和最少有139139139个节点。 完全二叉树 定义:一棵深度为kkk的有nnn个节点的二叉树,对树中的节点按从上至下、从左到右的顺序进行编号&am…

Python 对象保存优化机制

Python 为了减少开销与内存的使用而设置一些规则: * 1. 但凡是不可变对象, 在同一个代码块中的对象, 只要是值相同的对象, 就不会重复创建, 而是直接引用已经存在的对象.交互环境下: 不写在一行, 字符类型数据指向一个内存地址, 整型超出小整数则执指向不同的地址. 代码块缩进相…

Hexo搭建Github博客教程

CONTENTS1. 环境配置2. 本地博客搭建3. 部署至Github4. 博客主题设置1. 环境配置 (1)安装Git Bash:Windows安装配置Git教程(2022.11.18 Git2.38.1)。 (2)安装NodeJS:NodeJS的安装及…

基于51单片机的花样流水灯设计

资料编号:113 下面是相关功能视频演示: 113-基于51单片机的花样流水灯设计(源码仿真设计报告)功能讲解: 采用51单片机的IO控制多个LED灯,实现多种模式的流水灯,全套资料齐全:流水灯…

Aspose.OCR for Java Crack by Xacker

Aspose.OCR for Java 允许您从图像、屏幕截图、图像的特定区域中提取文本,并在任何支持 Java 的平台上从扫描文件创建可搜索的 PDF。凭借其强大且易于使用的 API,即使是复杂的 OCR 任务也只需不到 10 行代码。您无需使用公式和机器学习 - 该库将处理所有…

<C++>深度学习继承

目录 一、继承概念 二、继承的语法 2.1继承关系和访问限定符 2.2派生类继承基类后的成员权限 三、基类和派生类的对象赋值转换 四、继承中的作用域 五、派生类的默认成员函数 六、继承与友元 七、继承与静态成员 八、复杂的菱形继承及菱形虚拟继承 单继承&am…

CS下载、安装以及简单使用

Cobalt Strike4.0中文版下载 渗透利器CobaltStrike 4.0 免费汉化版(含原版补丁) 下载-脚本之家 (jb51.net)下载解压,有中文版本和原版 server:kali(自带Java环境) clinet:win10 这里直接把原版拖进kali运行不了&#x…

买卖股票的最好时机(一、二)

目录 买卖股票的最好时机(一) 动态规划解决 贪心思想解决 买卖股票的最好时机(二) 贪心思想解决 动态规划解决 买卖股票是经典的动态规划问题,在动态规划的学习与练习中,最令我煎熬的就是状态方程递推,经常出现状态定义好后&#xff0c…

【毕业设计】10-基于单片机的车站安检门/磁性霍尔传感器系统设计(原理图+源码+仿真工程+论文)

【毕业设计】10-基于单片机的车站安检门/磁性霍尔传感器系统设计(原理图源码仿真工程论文) 文章目录【毕业设计】10-基于单片机的车站安检门/磁性霍尔传感器系统设计(原理图源码仿真工程论文)资料下载链接任务书设计说明书摘要设计…

css的三种引入方式

目录 三种引入方式 1.行内样式 2.内部样式(内嵌式) 3.外部样式 3.1外链式 3.2导入式 引入方式的优先级 三种引入方式 1.行内样式 行内样式就是直接把css样式添加在HTML标签中,作为style样式的属性值 <!-- 行内/内嵌/嵌入式/内联样式 --><!-- 背景颜色 backgr…

动力节点索引优化解决方案学习笔记——查询优化

3.查询优化 创建一张测试表并插入数据&#xff1a; drop table if exists students; CREATE TABLE students (id INT PRIMARY KEY AUTO_INCREMENT COMMENT "主键id",sname VARCHAR (24) COMMENT 学生姓名,age INT COMMENT 年龄,score INT COMMENT 分数,time TIMEST…

微服务与中间件系列——GateWay整合Swagger3增强Knife4j

微服务与中间件系列——GateWay整合Swagger3增强Knife4jGateWay整合Swagger3增强Knife4j&#xff08;easy模式&#xff09;目的服务端1.导入依赖2.编写配置类3.yaml配置GateWay网关1.文档枚举2.SwaggerProvider3.yaml配置结果增强版服务端1.增加配置参数类2.修改配置类3.修改ya…