ucos 学习笔记

1 sourceInsight 使用

CSDN参考链接

  • 新建工程

    第一步:project中new project

    第二步:在高亮部分输入工程的地址,工程文件夹与IAR工程文件夹放在同一目录下

​ 第三步:其他不用修改,只需要修改工程源目录即可,系统默认是我们刚才建立存放Sourceinsight工程的目录,其实不是,我们要删掉最后的路径,将路径定位到IAR工程的主目录去。

第四步:填写好File name

第五步:选择add all,将所有文件都加载进去。

第六步:将两个勾都打上(两个勾的意思是包含顶级子目录以及递归添加其他子级目录(文件)),选择OK



2 IAR使用

2.1 创建工程

  • 创建工程前先要创建一个新的工作空间

  • 工作空间创建成功后再创建工程

    点击create new project后会出现下面的窗口:

  • 在工程界面下可以添加分组:

    • 添加分组:Add->Add Group

      • 添加文件: Add->Add Files


2.2 调试方法

  • debug模式:点击图中高亮部门,即开启debug

  • debug模式下的基本运行方法

上图中各编号图标的解释:

  1. 重新生成然后再开始debug

    1. 停止debug
  2. 逐过程

  3. 逐语句

  4. 全速运行,在断点处停止

  5. 暂停

  • 条件断点设置方法

    • 首先在断点处右击,选择Edit Breakpoint,进入到断点条件编辑状态

    • 在Expression中输入条件表达式

  • 调试过程中,各窗口视图的打开方式

调试时的窗口打开方式如上图所示,分别有查看堆栈、查看内存、查看变量、查看堆栈调用信息等。



3 ucos操作系统详细分析

3.1 ucos介绍

​ uC/OS II:Micro Control Operation System Two。是一个可以基于ROM运行的、可裁减的、抢占式、实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,适合很多商业操作系统性能相当的实时操作系统(RTOS)。

​ 其主要特点有公开源代码,代码结构清晰、明了,注释详尽,组织有条理,可移植性好可裁剪,可固化。内核属于抢占式,最多可以有64个任务。


3.2 ucosii体系结构图

定时器的作用:为ucosii提供系统时钟节拍,实现任务切换和任务延时等功能


3.3 任务

​ 任务其实就是一个死循环函数,在函数中实现一些功能,一个工程中最多可以有255个这样的任务。ucosii就是来对这些任务进行调度管理,使得这些任务可以并发工作

​ 并发指的是各任务轮流占用CPU,并不是同时工作,任何时候都只有一个任务能够占用CPU。

 从任务的存储结构来看,uCOS-II的任务由三个组成部分构成:**任务程序代码,任务堆栈和任务控制块**。其中,任务控制块用来保存任务属性;任务堆栈用来保存任务工作环境;任务程序代码是任务的执行部分。

3.4 任务控制块

​ 任务控制块用来记录任务堆栈指针,任务当前状态以及任务优先级等任务属性。UCOSII的所有任务都是通过任务控制块(TCB)来控制的,一旦任务创建了,任务控制块 OS_TCB 就会被赋值。每个任务管理块有 3 个最重要的参数:

任务函数指针;任务堆栈指针; 任务优先级;


3.5任务堆栈

存储器中的连续存储空间。为了满足任务切换和响应中断时保存 CPU 寄存器中的内容以及任务调用其他函数时的需要,每个任务都有自己的堆栈。在创建任务的时候,任务堆栈是任务创建的一个重要入口参数。


3.6 任务的链表

 为了管理上的方便,uCOS-II把每一个任务都作为一个节点,然后把它们链接成的一个任务链表。 任务链表分为空闲链表和任务链表两种。


3.7 任务就绪表

​ 用来记录系统中所有处于就绪状态的任务。它是一个位图,系统中每个任务都在这个图中占据一个进制位,该位置的状态(1 或者 0)就表示任务是否处于就绪状态。


3.8 任务调度

 一是在任务就绪表中查找优先级最高的就绪任务,二是实现任务的切换。比如说,当一个任务释放 cpu 控制权后,进行一次任务调度,这个时候任务调度器首先要去任务就绪表查询优先级最高的就绪任务,查到之后,进行一次任务切换,转而去执行下一个任务。

3.9 任务状态

在ucos中,每一个任务都有多种运行状态,他们的状态迁移图如下:

对于上面图中迁移状态过程的解释:

  • (1):创建任务→就绪态(Ready):任务创建完成后进入就绪态, 表明任务已准备就绪,随时可以运行,只等待调度器进行调度。
  • (2):就绪态→运行态(Running):发生任务切换时,就绪列表中最高优先级的任务被执行,从而进入运行态。
  • (3):运行态→就绪态:有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪列表中最高优先级任务变为运行态, 那么原先运行的任务由运行态变为就绪态,依然在就绪列表中, 等待最高优先级的任务运行完毕继续运行原来的任务(此处可以看作CPU使用权被更高优先级的任务抢占了)。
  • (4):运行态→阻塞态(或者称为挂起态Suspended):正在运行的任务发生阻塞(挂起、延时、读信号量等待)时, 该任务会从就绪列表中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪列表中当前最高优先级任务。
  • (5):阻塞态→就绪态:阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等), 此时被恢复的任务会被加入就绪列表,从而由阻塞态变成就绪态;如果此时被恢复任务的优先级高于正在运行任务的优先级, 则会发生任务切换,将该任务再次转换任务状态,由就绪态变成运行态。
  • (6)(7)(8):就绪态、阻塞态、运行态→删除态(Delete): 任务可以通过调用OSTaskDel() API 函数都可以将处于任何状态的任务删除,被删除后的任务将不能再次使用,关于任务的资源都会被系统回收。
  • (9):删除态→就绪态:这就是创建任务的过程,一个任务将会从无到有,创建成功的任务可以参与系统的调度。

ucos系统的任务状态通常分为下面几种:

  • 就绪(OS_TASK_STATE_RDY):该任务在就绪列表中,就绪的任务已经具备执行的能力, 只等待调度器进行调度,新创建的任务会初始化为就绪态。
  • 延时(OS_TASK_STATE_DLY):该任务处于延时调度状态。
  • 等待(OS_TASK_STATE_PEND):任务调用OSQPend()、OSSemPend()这类等待函数, 系统就会设置一个超时时间让该任务处于等待状态, 如果超时时间设置为0,任务的状态,无限期等下去,直到事件发生。如果超时时间为N(N>0),在N个时间内任务等待的事件或信号都没发生, 就退出等待状态转为就绪状态。
  • 运行(Running):该状态表明任务正在执行,此时它占用处理器,ΜC/OS调度器选择运行的永远是处于最高优先级的就绪态任务, 当任务被运行的一刻,它的任务状态就变成了运行态,其实运行态的任务也是处于就绪列表中的。
  • 挂起(OS_TASK_STATE_SUSPENDED):任务通过调用 OSTaskSuspend()函数能够挂起自己或其他任务, 调用 OSTaskResume()是使被挂起的任务回复运行的唯一的方法。挂起一任务意味着该任务再被恢复运行以前不能够取得CPU的使用权, 类似强行暂停一个任务。
  • 延时+挂起(OS_TASK_STATE_DLY_SUSPENDED):任务先产生一个延时,延时没结束的时候被其他任务挂起, 挂起的效果叠加,当且仅当延时结束并且挂起被恢复了,该任务才能够再次运行。
  • 等待+挂起(OS_TASK_STATE_PEND_SUSPENDED):任务先等待一个事件或信号的发生(无限期等待), 还没等待到就被其他任务挂起,挂起的效果叠加,当且仅当任务等待到事件或信号并且挂起被恢复了,该任务才能够再次运行。
  • 超时等待+挂起(OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED):任务在指定时间内等待事件或信号的产生, 但是任务已经被其他任务挂起。
  • 删除(OS_TASK_STATE_DEL):任务被删除后的状态,任务被删除后将不再运行,除非重新创建任务。

3.10 任务的挂起

​ 挂起指定任务。被挂起的任务绝不会得到CPU的使用权,不管该任务具有什么优先级。 任务可以通过调用**OSTaskSuspend()**函数都可以将处于任何状态的任务挂起,被挂起的任务得不到CPU的使用权,也不会参与调度, 它相对于调度器而言是不可见的,除非它从挂起态中解除。

​ 函数接口原型:INT8U OSTaskSuspend (INT8U prio)

​ prio为所需要挂起的任务的优先级。


3.11 任务恢复

​ 既然有任务的挂起,那么当然一样有恢复,不然任务怎么恢复呢,任务恢复就是让挂起的任务重新进入就绪状态,恢复的任务会保留挂起前的状态信息, 在恢复的时候根据挂起时的状态继续运行。如果被恢复任务在所有就绪态任务中,处于最高优先级列表的第一位,那么系统将进行任务上下文的切换。

​ 函数接口原型:INT8U OSTaskResume (INT8U prio)

​ prio为所需要恢复的任务的优先级。

3.12 任务优先级

​ 在ucosii中每个任务都是有他唯一的一个优先级,不允许有多个任务优先级相同。在ucosii中,使用CPU的时候, 优先级高(数值小)的任务比优先级低的任务具有优先使用权, 即任务就绪表中总是优先级最高的任务获得 CPU 使用权,只有高优先级的任务让出 CPU 使用权(比如延时)时,低优先级的任务才能获得 CPU 使用权。

3.13 信号量

​ 信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间同步或临界资源的互斥访问,常用于协助一组相互竞争的任务来访问临界资源。 在多任务系统中,各任务之间需要同步或互斥实现临界资源的保护,信号量功能可以为用户提供这方面的支持。 信号量可分为二值信号量和计数信号量。

创建信号量接口原型OS_EVENT *OSSemCreate (INT16U cnt)

 cnt:这个值表示初始化时候资源的个数或事件是否发生标志, 一般信号量是二值信号量的时候,这个值一般为0或者为1,而如果信号量作为计数信号量的时候,这个值一般定义为初始资源的个数。

信号量等待接口原型void OSSemPend (OS_EVENT *pevent,INT32U timeout,INT8U *perr)

​ pevent:是一个指向与所需信号量相关联的事件控制块的指针。

​ timeout:超时时间

​ perr:接收错误

信号量释放接口原型INT8U OSSemPost (OS_EVENT *pevent)

​ pevent:是一个指向与所需信号量相关联的事件控制块的指针。

信号量删除接口原型OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *perr)

​ pevent:是一个指向与所需信号量相关联的事件控制块的指针。

​ opt:删除选项

​ perr:接收错误


3.14互斥信号量

​ 互斥信号量 是一种特殊的二值信号量,它和信号量不同的是, 它支持互斥量所有权、递归访问以及防止优先级翻转的特性,用于实现对临界资源的独占式处理。任意时刻互斥量的状态只有两种, 开锁或闭锁。当互斥量被任务持有时,该互斥量处于闭锁状态,这个任务获得互斥量的所有权。当该任务释放这个互斥量时, 该互斥量处于开锁状态,任务失去该互斥量的所有权。当一个任务持有互斥量时,其他任务将不能再对该互斥量进行开锁或持有。

互斥量创建接口原型OS_EVENT *OSMutexCreate (INT8U prio, INT8U *perr)

​ prio:访问互斥信号量时使用的优先级

​ perr:接收错误

互斥量等待接口原型void OSMutexPend (OS_EVENT *pevent,INT32U timeout, INT8U *perr)

​ pevent: 是一个指向与所需互斥量相关联的事件控制块的指针。

​ timeout:超时时间

​ perr:接收错误

互斥量释放接口原型INT8U OSMutexPost (OS_EVENT *pevent)

​ pevent:是一个指向与所需信号量相关联的事件控制块的指针。


3.15 邮箱

​ 可以在任务和ISR中使用信息邮箱发送消息,但是接收信息只能在任务中,在ISR中不能接收邮箱信息。 OSMboxPost()函数只能给一个任务发送消息,如果有多个任务在等待邮箱的消息,那么只有优先级最高的任务才能得到这个消息,并且在将该消息返回以后,就会清除该消息,即消息指针指向“NULL”,因此低优先级低的任务是得不到消息的。 、

邮箱创建接口原型OS_EVENT *OSMboxCreate (void *pmsg)

​ pmsg:是一个指向希望存入邮箱的消息的指针

邮箱发送消息接口原型**:INT8U OSMboxPost (OS_EVENT *pevent, void *pmsg)

​ Pevent:是一个指向与所需邮箱关联的事件控制块的指针

​ PMSG是一个指向要发送的消息的指针。你绝对不能发送一个NULL指针。

邮箱接收消息接口原型void *OSMboxPend (OS_EVENT *pevent, INT32U timeout, INT8U *perr)

​ Pevent:是一个指向与所需邮箱关联的事件控制块的指针

​ timeout:超时时间

​ perr:接收错误

邮箱删除接口原型**:OS_EVENT *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *perr)

​ Pevent:是一个指向与所需邮箱关联的事件控制块的指针。

​ opt:删除选项

​ perr:接收错误


3.16 队列

​ 队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息, 实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息,当队列中的消息是空时, 读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间timeout,在这段时间中,如果队列为空, 该任务将保持阻塞状态以等待队列数据有效。当队列中有新消息时,被阻塞的任务会被唤醒并处理新消息; 当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。消息队列是一种异步的通信方式。

​ 通过消息队列服务,任务或中断服务程序可以将消息放入消息队列中。同样,一个或多个任务可以从消息队列中获得消息。当有多个消息发送到消息队列时, 通常是将先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的消息,即先进先出原则(FIFO)。

消息队列创建接口原型OSQCreate (void **start, INT16U size)

​ Start:是一个指向消息队列存储区基址的指针。

​ size: 是存储区域中元素的数量

消息队列等待接口原型void *OSQPend (OS_EVENT *pevent, INT32U timeout, INT8U *perr)

​ Pevent:是一个指向与所需队列关联的事件控制块的指针

​ timeout:超时时间

​ perr:接收错误

消息队列发送接口原型INT8U OSQPost (OS_EVENT *pevent, void *pmsg)

​ Pevent:是一个指向与所需队列关联的事件控制块的指针

​ pmsg:是一个指向要发送的消息的指针

消息队列删除接口原型OS_EVENT *OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *perr)

​ Pevent:是一个指向与所需队列关联的事件控制块的指针

​ opt:删除选项

​ perr:接收错误



4 ucos移植


4.1 stm32固件库移植

  1. 创建工程,分组如下:

  1. 在工程文件文件夹中创建下面几个文件夹,用来存放不同的文件,目录如下:

  1. 固件库内文件介绍说明:

    固件库源文件目录如下:

    • libraries: 文件夹下是驱动库的源代码及启动文件
    • project: 文件夹下是用驱动库写的例子和工程模板
    • utilities: 包含了基于ST官方实验板的例程,以及第三方软件库

    STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Libraries\CMSIS目录下文件夹:

STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Libraries\STM32F4xx_StdPeriph_Driver目录下文件夹:

  1. 将固件库中需要的文件复制到自己创建的工程目录下的文件夹中

    • 将固件库的库函数添加到drivers文件夹中:

    • 将启动文件添加到iar文件夹中

    • 将内核相关的头文件加到cmsis文件夹中

    • 添加系统时钟文件到cmsis文件夹中

    这个文件包含了STM32芯片上电后初始化系统时钟、扩展外部存储器用的函数,例如我们前两章提到供启动文件调用的"SystemInit"函数,用于上电后初始化时钟,该函数的定义就存储在system_stm32f4xx.c文件。STM32F429系列的芯片,调用库的这个SystemInit函数后,系统时钟被初始化为180MHz,如有需要可以修改这个文件的内容,设置成自己所需的时钟频率。 芯片底层头文件

    • 芯片底层头文件和系统时钟头文件添加到cmsis文件夹中

    stm32f4xx.h 这个文件非常重要,是一个STM32芯片底层相关的文件, 包含了STM32中所有的外设寄存器地址和结构体类型定义,在使用到STM32标准库的地方都要包含这个头文件。下面这个文件是系统时钟的头文件:system_stm32f4xx.h

    • 将官方的库工程模板添加到cmsis文件夹中

    在这个文件目录下,存放了官方的一个库工程模板,我们在用库建立一个完整的工程时,还需要添加这个目录下的stm32f4xx_it.cstm32f4xx_it.hstm32f4xx_conf.h这三个文件。 stm32f4xx_it.c:这个文件是专门用来编写中断服务函数的,在我们修改前,这个文件已经定义了一些系统异常(特殊中断)的接口,其它普通中断服务函数由我们自己添加。 stm32f4xx_conf.h:这个文件被包含进stm32f4xx.h 文件。ST标准库支持所有STM32F4型号的芯片,但有的型号芯片外设功能比较多,所以使用这个配置文件根据芯片型号增减ST库的外设文件。

  2. 在IAR软件中,将相应文件夹中的文件添加到相应的组里面

  3. 工程配置:

    • 点击options,选择相应的单片机型号。

    • 添加文件路径:

    • 进行编译,会提示以下错误:

    ​ 解决方案:添加宏定义:STM32F40_41xxx 和 USE_STDPERIPH_DRIVER

    • 再次编译会有如下错误:

    解决方法:fmc.c文件我们不需要使用,将其移除。


4.2 UCOSII 移植

  1. 源码文件分析:

    • ucosii源码的文件目录如下:

    Examples文件下是官方提供的例程,Software文件下是ucosII源文件。

    • Software目录下的文件分析

    **µC-CPU:**这是和 CPU 紧密相关的文件,我们不需要使用。
    **µC-LIB:**Micrium 公司提供的官方库文件,如字符串操作、内存操作等函数接口,可用可不用。
    **µCOS-II:**这是关键目录文件,我们接下来要详细分析的文件,跟移植、使用密切相关的。
    **µC-Serial:**µC/OS-II 接口文件文件。

    • Software -> µCOS-II -> Source 下的文件内容

    • Software\uCOS-II\Ports\ARM-Cortex-M4\Generic\IAR 下的文件内容

    前三个是与CPU有关的文件,最后一个是系统调试时需要用的文件。

    os_cpu.h: 进行数据类型的定义,以及处理器相关代码和几个函数原型;

    **os_cpu_a.asm:**是移植过程中需要汇编完成的一些函数,主要就是任务切换函数;

    **os_cpu.c:**定义一些用户 HOOK 函数。


  2. 将ucosii源文件中需要的文件复制到自己创建的工程目录下的文件夹中

  • cfg文件中:存放的文件的作用是配置ucos各个功能,其存放的文件如下:

  • ports文件中:与CPU有关的文件

    Software\uCOS-II\Ports\ARM-Cortex-M4\Generic\IAR 下的文件全部内容复制到ports文件中。

  • source文件中:放置的是ucos的源文件

    Software -> µCOS-II -> Source 下的文件全部内容复制到source文件中。

  1. 在工程中,分组ucos下再创建三个分组:cfg、ports、source,分别将文件夹中相应的文件添加进去。然后进行环境配置:

    • 配置文件路径:C/C++ Compiler -> preprocessor
    • 配置Linker: Linker -> Config ,勾选Override default
    • 配置Debugger:

    • ST-LINK配置:

  2. 进行移植后的代码系统配置

    • 编译后会提示无法打开app_cfg.h文件,工程中不需要该文件,将其注释。

    • 编译后会提示无法打开lib_def.h文件,该文件在software\uc-LIB中,工程中不需要该文件,将其注释。

    • 在启动文件中,把所有PendSV_Handler替换为OS_CPU_PendSVHandler

      ​ 把所有SysTick_Handler替换成OS_CPU_SysTickHandler。

    • 到这一步为止,ucosii移植就结束了。

IAR中移植UCOS II系统以及sourceInsight 使用相关推荐

  1. 51单片机中使用ucos ii的优缺点(好文)

    摘要:近年来,在单片机系统中嵌入操作系统已经成为人们越来越关心的一个话题.本文通过对一种源码公开的嵌入式实时操作系统ucos ii的分析,以51系列单片机为例,阐述了在单片机中使用该嵌入式操作系统的优 ...

  2. 用C语言写ucos中断服务程序,在ARM处理器上移植uCOS II的中断处理

    uCOS II是一个源码公开.可移植.可固化.可剪裁和抢占式的实时多任务操作系统,其大部分源码是用ANSI C编写,与处理器硬件相关的部分使用汇编语言编写.总量约200行的汇编语言部分被压缩到最低限度 ...

  3. UCOS II移植到STM32F103开发板

    早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念.通常把程序分为两部分:前台系统和后台系统. 简单的小系统通常是前后台系统,这样的程序包 ...

  4. 基于STM32的简易示波器的UCOS II嵌入式实时操作系统实现

    基于STM32的简易示波器的UCOS II嵌入式实时操作系统实现 在基于STM32的示波器的实现的基础上,在STM32上移植UCOS II嵌入式实时操作系统. 在UCOS II操作系统中将各个功能分发 ...

  5. 关于正点原子STM32的MDK例程移植到IAR中遇到的错误解决方法 __use_no_semihosting

    在移植过程中,估计大部分人应该都又遇到这类问题,主要是usart.c和sys.c这两个文件. 现贴出修改之前和修改之后的代码: usart.c: 之前的代码: #include "sys.h ...

  6. lwip协议栈在linux运行,LwIP协议栈在uCOS II下的实现

    1.概述: LwIP协议栈在设计时就考虑到了将来的移植问题,因此把所有与硬件.OS.编译器相关的部份独立出来,放在ucosii&LwIPsource etlwiparch目录下.因此LwIP在 ...

  7. STM32(Cortex-M3)启动过程+IAR中xcl及icf文件详解

    一:STM32(Cortex-M3)启动过程(入口地址) ARM7和ARM9启动时从绝对地址0X00000000开始执行复位中断程序,即固定了复位后的起始地址,但中断向量表的位置是可变的. Corte ...

  8. IAR中map文件全解析

    推荐 分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang 推荐在我的公 ...

  9. IAR中eww、ewp、ewd···等各文件的含义和用途

    推荐 分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang 我的网站:h ...

最新文章

  1. java web项目调用rest接口404
  2. Hibernate基本配置
  3. python导入模块时的路径疑惑
  4. 漏洞: RHSA-2017:3075: wget security update
  5. 存储管理实验linux,07-存储管理器实验
  6. php数组和列表,【PHP基础】1.1 所有数组函数分类与列表(目前可能不全)
  7. 亲测源码多多进鱼带VUE源码任务悬赏源码活动营销三级分销返佣积分商城版
  8. 收银系统服务器ip设置,如何修改打印机IP地址?
  9. 重启ADB的bat文件
  10. 小波同态滤波 matlab,matlab同态滤波程序
  11. mac下免费svn工具
  12. 重写和重载的区别和理解
  13. Photoshop-为图像添加一个真实投影
  14. 啥水平?谷歌程序员:我用东北方言编程
  15. 【应用C】C语言实现离散数学合式公式的递归判断
  16. 抖音短视频数据抓取实战系列(三)——Fiddler抓取抖音用户详细信息数据
  17. (详细)华为NOVA3i INE-TL00的usb调试模式在哪里开启的流程
  18. 支持向量机1-线性可分支持向量机
  19. 什么是k8s(Kubernetes)
  20. 三点软件下载工具SoftDownloader

热门文章

  1. meminfo 解释
  2. 微信小程序毕业设计 基于微信校园洗衣小程序系统开题报告
  3. CSS布局之流动布局(湖南中兴网信首页实例)
  4. 乙酰化抗体系列研究——定制化方案
  5. EXCEL截取指定字符后的中文字符
  6. HKC(红裤衩)资本
  7. hive分区对应hadoop_hive修改分区类型
  8. hive 分区表select全部数据_Hive分区表实战
  9. xgboost 调参经验
  10. 猜1~10的随机数字