风速传感器HS-FS01 485型采用Modbus-Rtu通信协议,本代码部分基于正点原子f1战舰V3。

首先,了解一下什么是Modbus协议

Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。

Modbus通讯协议是应用层报文传输协议(OSI模型第7层),它定义了一个与通信层无关的协议数据单元(PDU),即PDU=功能码+数据域。Modbus协议只能主站和从站之间通信,从站和从站之间不能通信。Modbus某些特征是固定的,如信息帧结构,帧顺序,通信错误,异常情况处理,及所执行的功能码。其他特征是可选的(传输介质、波特率、奇偶校验、停止位个数、参数字址定义)。
Modbus协议能够应用在不同类型的总线或网络。对应不同的总线或网络,Modbus协议引入一些附加域映射成应用数据单元(ADU),即ADU=附加域+PDU。目前,Modbus有下列三种通信方式:
1. 以太网,对应的通信模式是MODBUS TCP。
2. 异步串行传输(各种介质如有线Rs232-/422/485/;光纤、无线等),对应的通信模式是MODBUS RTU或MODBUS ASCII。
3. 高速令牌传递网络,对应的通信模式是Modbus PLUS

Modbus通信协议得到广泛应用的原因是:

  • 公开发表并且无版权要求
  • 易于部署和维护
  • 对供应商来说,修改移动本地的比特或字节没有很多限制

在介绍通信协议之前,首先要明白通信协议三要素:

  1. 通信接口标准(即硬件协议,如电平高低)
  2. 通信格式      (异步通信中,双方必须统一设置的参数,数据的传送方式、传送数据的长度、校验的方法,和传输速率)
  3. 通信数据格式 (规定传输的内容,数据帧的结构)

本片内容只介绍Modbus三种通信方式的第二条,异步串行传输(Rs485)所对应的两种通信模式MODBUS  ASCII 模式和MODBUS RTU 模式。两种模式在通讯上有所不同。

  • MODBUS ASCII

主要优点是允许字符之间的时间间隔长达1s,也不会出现错误。同时也是其缺点,传输速度较慢。

ASCII模式通信格式约定

  1. 起始位 :1位
  2. 数据长度 : 7位 ,低位先送
  3. 校验位 : 1位(有校验)  , 0位(无校验)
  4. 停止位 : 1位(有校验) ,2位(无校验)
  5. 波特率 : 可选

ASCII模式数据格式约定

信息编码 : 16进制。

LRC校验码(参与校验的位置从地址码到数据区

算法:(8位校验码) 相邻2个16进制符相加求和。 取其和的低八位的补码为校验码。

例:

求和: H01+H03+H21+H02+H00+H02   =   H29  求补码 : H29的补码为 :HD7   则LRC校验码为HD7

ASCII模式数据传送约定

ASCII模式数据传送约定在数据格式中每个16进制字符都转换成ASCII码发送。

如上图则转换为:    :      0      1      0      3      2      1    ········································

对应的ASCII码 :  (0x) 30    31    30    33    32    31   ········································

  • MODBUS RTU

​​​​​​​主要优点是在相同波特率下其传输的字符的密度高于ASCII模式,每个信息必须连续传输。同时也是其缺点,传输过程中更容易出错。

RTU模式通信格式约定

  1. 起始位 : 1位
  2. 数据长度 : 8位 ,低位先送
  3. 校验位 : 1位(有校验) ,0位(无校验)
  4. 停止位 : 1位(有检验) ,2位(无校验)
  5. 波特率 : 可选

RTU模式数据格式约定

信息编码 : 16进制

CRC校验码(​​​​​​​参与校验的位置从地址码到数据区

算法 :(16位校验码) 由于算法比较复杂,附相关代码 (附一)

RTU模式数据传送约定

RTU模式数据传送约定按数据格式中16进制字符进行连续发送,如果发送帧期间,出现大于1.5个字符的停止时间时,则信息会出现错误。

发送实例:

/*******************************************************************************************************************************************/

  • 常用功能码

风速传感器HS-FS01使用的功能码。其他功能码请参考  MODBUS功能码

modbus.c 和modbus.h  (CRC校验函数在附一中)

modbus.h
/*****************************************************************/
#ifndef __MODBUS_H__
#define __MODBUS_H__
#include "stm32f10x.h"
#define T_R_Mode  PDout(7)typedef struct mod{u8 address; //设备地址u8 sendbuf[64];//发送缓冲区u8 recbuf[64]; //接受缓冲区u8 timflag;  //数据接收时间u8 timrun;   //定时器启动标志u8 reflag;   //接收到一帧数据的标志u8 recount;  //接受的数据个数u8 secount;  //发送的数据个数}Modbus;void modbus_init(void);
void modbus_fun3(u8 add,u16 readd,u16 renum);
void modbus_display(void);
void modbus_event(void);#endif/******************************************************************/modbus.c
/******************************************************************/#include "modbus.h"
#include  "sys.h"
#include "misc.h"
#include "ModbusCRC.h"
#include "stdio.h"extern vu8 temp;
Modbus modbus;void modbus_init()
{GPIO_InitTypeDef GPIO_InitTypeStruct;USART_InitTypeDef USART_InitTypeStruct;NVIC_InitTypeDef NVIC_InitTypeStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOD,&GPIO_InitTypeStruct);   //    收发控制GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_2;GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitTypeStruct);   //PA2 USART2 TXGPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_3;GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitTypeStruct);    //PA3 USART2 RXUSART_InitTypeStruct.USART_BaudRate=9600;USART_InitTypeStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USART_InitTypeStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;USART_InitTypeStruct.USART_Parity=USART_Parity_No;USART_InitTypeStruct.USART_StopBits=USART_StopBits_2;USART_InitTypeStruct.USART_WordLength=USART_WordLength_8b;USART_Init(USART2,&USART_InitTypeStruct);USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);NVIC_InitTypeStruct.NVIC_IRQChannel=USART2_IRQn;NVIC_InitTypeStruct.NVIC_IRQChannelCmd=ENABLE;NVIC_InitTypeStruct.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitTypeStruct.NVIC_IRQChannelSubPriority=2;NVIC_Init(&NVIC_InitTypeStruct);USART_Cmd(USART2,ENABLE);T_R_Mode=1;  //默认为发送模式}void modbus_fun3(u8 add,u16 readd,u16 renum)
{u16 crc,i;modbus.secount=0;modbus.sendbuf[modbus.secount++]=add; //读取设备地址modbus.sendbuf[modbus.secount++]=0x03; //功能码modbus.sendbuf[modbus.secount++]=readd/256; //读取寄存器高地址modbus.sendbuf[modbus.secount++]=readd%256; //读取寄存器低地址modbus.sendbuf[modbus.secount++]=renum/256; //读取寄存器数量高八位modbus.sendbuf[modbus.secount++]=renum%256;  //读取寄存器数量低八位crc=crc16(modbus.sendbuf,modbus.secount);   //计算CRC校验码modbus.sendbuf[modbus.secount++]=crc/256;  //校验码高八位modbus.sendbuf[modbus.secount++]=crc%256;  //校验码低八位T_R_Mode=1; //sendfor(i=0;i<modbus.secount;i++){USART_SendData(USART2,modbus.sendbuf[i]);while(!USART_GetFlagStatus(USART2,USART_FLAG_TC));}T_R_Mode=0;
}void modbus_display()
{u8 i;printf("----------------------------------\r\n");printf("-----------发送的命令为-----------\r\n");for(i=0;i<modbus.secount;i++){printf("%2X  ",modbus.sendbuf[i]);}printf("\r\n");printf("------------接收的命令为----------\r\n");for(i=0;i<modbus.recount;i++){printf("%2X  ",modbus.recbuf[i]);}printf("\r\n");printf("------------------------------------\r\n");printf("*************************************\r\n");
}void modbus_event()
{u16 crc,rccrc;if(modbus.reflag==0)  return ;  //没有数据crc=crc16(modbus.recbuf,modbus.recount);rccrc=modbus.recbuf[modbus.recount-2]*256+modbus.recbuf[modbus.recount-1];if(crc==rccrc){modbus_display();           /*使用HS-FS01风速传感器时直接显示不检查校验码*/}modbus.secount=0;modbus.recount=0;modbus.reflag=0;
}void USART2_IRQHandler()
{if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET){temp=USART_ReceiveData(USART2);if(modbus.reflag==1) return ;  //有数据正在处理modbus.recbuf[modbus.recount++]=temp;modbus.timflag=0; //清零计时位if(modbus.recount==1)   //主机发送的一个数据的第一字节modbus.timrun=1;  //启动定时}
}/******************************************************************/

tim.c 和 tim.h

tim.h
/**************************************************************/#ifndef __TIM_H__
#define __TIM_H__
#include "stm32f10x.h"void tim3_init(u16 arr,u16 psc);#endif
/***************************************************************/tim.c
/****************************************************************/
#include "tim.h"
#include "modbus.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
#include "misc.h"extern  Modbus modbus;void tim3_init(u16 arr,u16 psc)  //arr 999 psc 71
{NVIC_InitTypeDef NVIC_InitTypeStruct;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); // tim3 enableTIM_TimeBaseInitTypeStruct.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitTypeStruct.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitTypeStruct.TIM_Period=arr;TIM_TimeBaseInitTypeStruct.TIM_Prescaler=psc;TIM_TimeBaseInitTypeStruct.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypeStruct);   // tim3 base setTIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);   //tim3 it setNVIC_InitTypeStruct.NVIC_IRQChannel=TIM3_IRQn;NVIC_InitTypeStruct.NVIC_IRQChannelCmd=ENABLE;NVIC_InitTypeStruct.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitTypeStruct.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitTypeStruct);   //tim3 nvic  setTIM_Cmd(TIM3,ENABLE);  //tim3 cmd set}void TIM3_IRQHandler()   //tim it
{if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET){if(modbus.timrun==1) //定时器开始计时{modbus.timflag++; if(modbus.timflag>=8)   //8ms 计时   默认8ms接收完成{modbus.timrun=0;  //关闭计时modbus.reflag=1;   //接收到一帧数据标志 }   }       }TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}/******************************************************************/

main.c

main.c#include "stm32f10x.h"
#include "tim.h"
#include "modbus.h"
#include "misc.h"                 /*使用HS-FS01风速传感器时直接显示,不检查校验码*/
#include "usart.h"                /*请自行修改modbus_event(); 函数*/vu8 temp;int main()
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(72);tim3_init(999,71);modbus_init();while(1){modbus_fun3(0x02,0x2A,0x01);  //发送指令modbus_event();  //处理数据}
}

附一:

/* CRC 高位字节值表 */
const uchar auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC低位字节值表*/
const uchar auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;/******************************************************************
功能: CRC16校验
输入:
输出:
******************************************************************/
uint crc16( uchar *puchMsg, uint usDataLen )
{uchar uchCRCHi = 0xFF ; // 高CRC字节初始化uchar uchCRCLo = 0xFF ; // 低CRC 字节初始化unsigned long uIndex ;      // CRC循环中的索引while ( usDataLen-- )   // 传输消息缓冲区{uIndex = uchCRCHi ^ *puchMsg++ ;  // 计算CRCuchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;uchCRCLo = auchCRCLo[uIndex] ;}return ( uchCRCHi << 8 | uchCRCLo ) ;
}

Modbus通信协议应用——风速传感器HS-FS01(串口显示)相关推荐

  1. Modbus通信协议+Modbus串口调试工具+Java版协议解析源码

    网络与串口二合一调试助手TCPCOM: https://download.csdn.net/download/liuyuan_java/87454762 Modbus调试工具,模拟串口调试工具 htt ...

  2. 大神带你秒懂Modbus通信协议

    摘要:昨天有小伙伴在群里问关于Modbus通信协议的,大家都比较积极地解答,所以今天果子哥总结一下关于Modbus相关的知识,适合正在入门的小伙伴"食用".同样还是理论+实战的方式 ...

  3. 【知识分享】Modbus通信协议详解

    协议 这里分两部分,Modbus和协议,首先什么是协议?百度解释下就是:意思是共同计议,协商:经过谈判.协商而制定的共同承认.共同遵守的文件.比如大学毕业找工作的时候,一般要签一份叫"三方协 ...

  4. 干货|手把手带你搞懂Modbus通信协议

    摘要:昨天有小伙伴在群里问关于Modbus通信协议的,大家都比较积极地解答,所以今天果子哥总结一下关于Modbus相关的知识,适合正在入门的小伙伴"食用".同样还是理论+实战的方式 ...

  5. 编写一个字节数的rtu C语言校验程序,Modbus通信协议中CRC校验的快速C语言算法

    Modbus通信协议中CRC校验的快速C语言算法 2004年第11期 福 建 电 脑 63 Modbus通信协议中CRC校验的快速C语言算法 孟开元 (西安石油大学计算机学院陕西西安710065) [ ...

  6. 详解Modbus通信协议---清晰易懂

    本文旨在让您对Modbus有一个很直观的了解,总结关于Modbus相关的知识,非常适合初学的同学,同时如有错误,欢迎修改意见和建议,将在第一时间修改 什么是协议 什么是RS-485 RS-232 Mo ...

  7. STM32:RS485通信和Modbus通信协议汇总

    RS485通信和Modbus通信协议汇总 1. 主从模式 RS-485上的软件层协议ModBus主要依赖于主从模式.主从模式是指在半双工通讯方式上,2个或者2个以上的设备组成的通讯系统中: (1) 至 ...

  8. RS-485总线和Modbus通信协议的关系

    一.RS-485总线 RS-485总线技术只是规定了接口的电气标准,并没有规定RS-485接口的电缆,插件以及通信协议,只是OSI规范中物理层的一个标准,RS-485总线采用差分平衡传输方式.由于RS ...

  9. 干货分享:RS485通信和Modbus通信协议汇总

    https://zhuanlan.zhihu.com/p/24134130 在工业控制.电力通讯.智能仪表等领域,通常情况下是采用串口通信的方式进行数据交换.最初采用的方式是RS232接口,由于工业现 ...

最新文章

  1. 幼儿园语言活动包括哪几类_幼儿园小班语言游戏教案你问我答对话活动教学【幼儿教师教案】...
  2. python计算csv文件内的数据_Python利用pandas计算多个CSV文件数据值的实例
  3. OXite解读(1)----- 概述
  4. 心情随笔20180620
  5. 如何使用Appverifier ?
  6. java中CyclicBarrier的使用
  7. 以下是ECMAScript 2016、2017和2018中所有新增功能的示例
  8. system函数的返回值和执行脚本的返回值
  9. Geodatabase概述(翻译)
  10. linux下文件的相关信息
  11. 用Maven创建第一个web项目Struts2项目
  12. K8s集群部署(四)------ Flannel网络部署
  13. 2018暑假第五周总结(8.6-8.12)
  14. 打开客户端出现 sorry this application cannot run under a virtual machine错误
  15. 如何将网页转为html文件,Chrome怎样保存网页为mhtml格式
  16. python爬虫登录微博账号_python模拟登录新浪微博 python新浪微博爬虫
  17. [LOJ#3124][CTS2019]氪金手游(概率 + 树形 DP + 容斥)
  18. 【转】模糊测试(fuzzing)是什么
  19. Unity3D教程:触发器实现简单的场景跳转
  20. a1502配置 macbook_a1502的macbook pro 苹果系统和… - Apple 社区

热门文章

  1. python操作autocad_【笔记】利用Python自动化操作AutoCAD
  2. python实现xmind转excel_使用Python将xmind脑图转成excel用例(一)
  3. 垃圾分类信息管理系统
  4. MYSQL再学习2-阿里云服务器Centos安装mysql8.0
  5. 操作系统文件的逻辑结构及其文件目录
  6. 网店美工之首页设计的必胜绝招
  7. osgEarth的Rex引擎原理分析(九十五)地形变形(Terrain morphing)
  8. 百练4115 鸣人和佐助(变式BFS)
  9. 名师杀手(超级搞笑)
  10. anydesk 远程控制