51单片机第15步_串口多机通讯使用CRC8校验
本章重点介绍串口多机通讯使用CRC8校验。
数据格式:"$123xxxx*crc8\r\n";
如:"$1234567890ABCDEF*06\r\n"
如:"$1231234567890*31\r\n"
crc8是CRC校验值,为十六进制的ASCII码,不包含'$'和校验值前面的那个'*'
#include <REG51.h> //包含头文件REG51.h,使能51内部寄存器;
#include <intrins.h> //包含头文件intrins.h,要放在stdio.h的头文件之前;
//使能函数: _nop_(); 相当于汇编的NOP指令;
//使能函数: bit _testbit_( bit bit_value ); 对bit_value进行测试,若bit_value=1,返回1,否则返回0;
//使能函数: _cror_( unsigned char x, unsigned char n ); 将字节型变量x的值,向右循环移动n位,然后将其
//值返回;
//相当于汇编的RR A命令;
//使能函数: _iror_( unsigned int x, unsigned char n ); 将双字节型变量x的值,向右循环移动n位,然后将
//其值返回;
//使能函数: _lror_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向右循环移动n位,然后将
//其值返回;
//使能函数: _crol_( unsigned char x, unsigned char n ); 将字节型变量x的值,向左循环移动n位,然后将其
//值返回;
//使能函数: _irol_( unsigned int x, unsigned char n ); 将双字节型变量x的值,向左循环移动n位,然后将
//其值返回;
//使能函数: _lrol_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向左循环移动n位,然后将
//其值返回;
//以上的循环左移和循环右移,同C语言的左移和右移是不同的,使用时要小心;
#include <string.h>
#define OSC_FREQ 11059200L
//#define BAUD_115200 256 - (OSC_FREQ/192L)/115200L //
//#define BAUD_38400 256 - (OSC_FREQ/192L)/38400L //
#define BAUD_Time 1
#if(BAUD_Time==1)
//若波特率加倍,则使用下面参数;
#define BAUD_57600 256 - (OSC_FREQ/192L)/57600L //255
#define BAUD_28800 256 - (OSC_FREQ/192L)/28800L //254
#define BAUD_19200 256 - (OSC_FREQ/192L)/19200L //253
#define BAUD_14400 256 - (OSC_FREQ/192L)/14400L //252
#define BAUD_9600 256 - (OSC_FREQ/192L)/9600L //250
#define BAUD_4800 256 - (OSC_FREQ/192L)/4800L //244
#define BAUD_2400 256 - (OSC_FREQ/192L)/2400L //232
#define BAUD_1200 256 - (OSC_FREQ/192L)/1200L //208
#else
//若波特率不加倍,则使用下面参数;
#define BAUD_9600 256 - (OSC_FREQ/384L)/9600L
#define BAUD_4800 256 - (OSC_FREQ/384L)/4800L
#define BAUD_1200 256 - (OSC_FREQ/384L)/1200L
#endif
#define receive_buffer_size 30
unsigned char receive_buffer[receive_buffer_size];
bit Start_Flag,Receive_End_Flag;
unsigned char next_in;
//unsigned char crc8;
//函数功能:将y的第i_bit位,设置为1;
unsigned char bit_set( unsigned char y,unsigned char i_bit)
{ unsigned char temp;
temp=1<<i_bit;
y=temp|y;
return(y);
}
//函数功能:将y的第i_bit位,设置为0;
unsigned char bit_clear(char y,char i_bit)
{ char temp;
temp=1<<i_bit;
temp=~temp;
y&=temp;
return(y);
}
//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;
bit bit_test(char test_data,char test_bit)
{ char temp;
bit bit_value;
temp=test_data;
temp=temp>>test_bit;
if( (temp&0x01)==0x01 ) bit_value=1;
else bit_value=0;
return(bit_value);
}
//函数功能:产生8位的CRC校验值;
unsigned char generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char pattern)
{ unsigned char *current_data;
unsigned char crc_byte;
unsigned int byte_counter;
unsigned char bit_counter;
current_data = ptr;
crc_byte = *current_data++;
for(byte_counter=0; byte_counter < (length-1); byte_counter++)
{ for(bit_counter=0; bit_counter < 8; bit_counter++)
{ if( !bit_test(crc_byte,7) )
{ crc_byte=crc_byte<<1;
bit_test( *current_data, 7 - bit_counter ) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);
continue;
}
crc_byte <<= 1;
bit_test(*current_data, 7 - bit_counter) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);
crc_byte ^= pattern;
}
current_data++;
}
for(bit_counter=0; bit_counter < 8; bit_counter++)
{ if(!bit_test(crc_byte,7))
{ crc_byte <<= 1;
continue;
}
crc_byte <<= 1;
crc_byte ^= pattern;
}
return(crc_byte);
}
//函数功能:将'0'~'9','A'~'F'的ASCII码转换为十六进制(0x00~0x09,0x0a~0x0f)输出;
unsigned char ASCII_To_HEX(unsigned char ASCII )
{ unsigned char temp;
if(ASCII<='9') temp=ASCII-'0';
else temp=ASCII-0x37;
return(temp);
}
//函数功能:从串口读入一个字符;
char getc()
{ char c;
while (!RI);
c = SBUF;
RI = 0;
return (c);
}
//函数功能:从串口输出一个字符;
void putc(char c)
{ SBUF=c;
while (!TI);
TI = 0;
}
//函数功能:接收和发送中断服务函数;
//数据格式:"$123xxxx*crc8\r\n";
//如:"$1234567890ABCDEF*06\r\n"
//如:"$1231234567890*31\r\n"
//crc8是CRC校验值,为十六进制的ASCII码,不包含'$'和校验值前面的那个'*'
void isr_UART(void) interrupt 4 using 0
{ unsigned char temp,crc8,crc_data;
if( RI&&(!Receive_End_Flag) ) //处理接收数据;
{ temp=getc(); //从串口接收一个字节;
receive_buffer[next_in]=temp;
putc(temp);//调试时,使用;
temp=next_in; //保存下标值;
next_in++; //修改下标值;
if(temp<3) //比对从机地址是否为"$123"
{ if( Start_Flag )
{ if( (temp==0)&&(receive_buffer[0]!='1') ) next_in=0;
if( (temp==1)&&(receive_buffer[1]!='2') ) next_in=0;
if( (temp==2)&&(receive_buffer[2]!='3') ) next_in=0;
}
else
{ if(receive_buffer[0]=='$') Start_Flag=1;
next_in=0;
}
}
else
{ if( (receive_buffer[temp-1]=='\r')&&(receive_buffer[temp]=='\n') ) //接收到"\r\n"
{ crc8=generate_8bit_crc( receive_buffer,temp-4,1); //计算接收到数据的CRC8校验值;
crc_data=ASCII_To_HEX(receive_buffer[temp-3]);
crc_data=(crc_data<<4)&0xf0; //获取CRC校验值的高4位值;
temp=ASCII_To_HEX(receive_buffer[temp-2]); //获取CRC校验值的低4位值;
crc_data=crc_data+temp; //获取接收到的CRC校验值;
if(crc8==crc_data) //若CRC校验值正确,则执行下面语句;
{ Receive_End_Flag=1;
}
next_in=0; //接收完成;
Start_Flag=0; //为下次接收起始标志做备;
}
}
if(next_in>=receive_buffer_size)
{ next_in=0; //接收数据太长,取消接收;
Start_Flag=0; //为下次接收起始标志做备;
}
}
}
//函数功能:若接收到的数据有效,则打印出来;
void Print_Receive_data()
{ unsigned char i;
i=0;
if(Receive_End_Flag)
{ while(receive_buffer[i]!='\n')
{ putc(receive_buffer[i]);
i++;
}
putc(receive_buffer[i]); //打印'\n';
Receive_End_Flag=0;
}
}
//函数功能:初始化串口,设置波特率为9600bps@11.0592MHz,使能接收,使用8位UART;
void Serial_Port_Initialization()
{ PCON = 0x80;
SCON=0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI
//SM1:SM0=01,选择方式1,SM2=0,表示非多机通讯,8-bit UART;
//REN=1,使能接收;
TMOD&=0x0f;
TMOD|= 0x20;
//定时器方式控制寄存器:GATE1,C/T1,M11,M10,GATE0,C/T0,M01,M00
//GATE=0,TR置1便可以启动Timer;GATE=1,TR置1,且INT脚输入高电平,才可以启动Timer;
//M11:M10=10,选择方式2,8位自动重装载;
TH1=BAUD_9600; //TH1: reload value for 9600 baud @11.0592MHz;
TL1=TH1;
TR1=1; //启动Timer1;
TI=0; //为下次发送做准备;
RI=0;
next_in=0;
Start_Flag=0;
Receive_End_Flag=0; //将接收完成标志设置为0;
ES=1; //使能串口接收和发送中断;
EA=1; //开总中断
}
//函数功能: Delay 50us
void delay_50us(unsigned char _50us)
{ while(_50us--)
{ _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
void main(void)
{
Serial_Port_Initialization(); //初始化串口,设置波特率9600bps@11.0592MHz,使能接收,使用8位UART;
for(;;)
{ Print_Receive_data(); //若接收到的数据有效,则打印出来;
delay_50us(20); //延时1ms;
}
}
/*
//函数功能:将hex8的低4位(0~9,a~f)转换为'0'~'9','A'~'F'输出;
unsigned char HEX_To_ASCII(unsigned char hex8 )
{unsigned char temp;
temp=hex8;
temp=(unsigned char)(temp&0x0f); //求低4位值;
if(temp<0x0a) temp+=0x30; //将低4位值(在0~9中)转换为ASCII码;
else temp+=0x37; //将低4位值(在a~f中)转换为大写字母的ASCII码;
return(temp);
}
//函数功能:将'0'~'9','A'~'F'的ASCII码转换为十六进制(0x00~0x09,0x0a~0x0f)输出;
unsigned char ASCII_To_HEX(unsigned char ASCII )
{ unsigned char temp;
if(ASCII<='9') temp=ASCII-'0';
else temp=ASCII-0x37;
return(temp);
}
//函数功能:将y的第i_bit位,设置为1;
unsigned char bit_set( unsigned char y,unsigned char i_bit)
{ unsigned char temp;
temp=1<<i_bit;
y=temp|y;
return(y);
}
//函数功能:将y的第i_bit位,设置为0;
unsigned char bit_clear(char y,char i_bit)
{ char temp;
temp=1<<i_bit;
temp=~temp;
y&=temp;
return(y);
}
//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;
bit bit_test(char test_data,char test_bit)
{ char temp;
bit bit_value;
temp=test_data;
temp=temp>>test_bit;
if( (temp&0x01)==0x01 ) bit_value=1;
else bit_value=0;
return(bit_value);
}
//函数功能:产生8位的CRC校验值;
unsigned char generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char pattern)
{ unsigned char *current_data;
unsigned char crc_byte;
unsigned int byte_counter;
unsigned char bit_counter;
current_data = ptr;
crc_byte = *current_data++;
for(byte_counter=0; byte_counter < (length-1); byte_counter++)
{ for(bit_counter=0; bit_counter < 8; bit_counter++)
{ if( !bit_test(crc_byte,7) )
{
crc_byte=crc_byte<<1;
bit_test( *current_data, 7 - bit_counter ) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);
continue;
}
crc_byte <<= 1;
bit_test(*current_data, 7 - bit_counter) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);
crc_byte ^= pattern;
}
current_data++;
}
for(bit_counter=0; bit_counter < 8; bit_counter++)
{ if(!bit_test(crc_byte,7))
{ crc_byte <<= 1;
continue;
}
crc_byte <<= 1;
crc_byte ^= pattern;
}
return(crc_byte);
}
//函数功能:将y的第i_bit位,设置为1;调用方式: sbit_set(&x,i);
void bit_set( unsigned char *y,unsigned char i_bit)
{ unsigned char temp;
temp=1<<i_bit;
y[0]=temp|y[0];
}
//函数功能:将y的第i_bit位,设置为0;调用方式: sbit_clear(&x,i);
void bit_clear(char *y,char i_bit)
{ char temp;
temp=1<<i_bit;
temp=~temp;
y[0]&=temp;
}
//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;
void bit_test(char test_data,char test_bit,unsigned char *return_value)
{ char temp;
//bit bit_value;
temp=test_data;
temp=temp>>test_bit;
if( (temp&0x01)==0x01 ) return_value[0]=1;
else return_value[0]=0;
//return(bit_value);
}
//函数功能:产生8位的CRC校验值;
void generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char *return_value )
{ unsigned char tenp_value;
unsigned char *current_data;
unsigned char crc_byte;
unsigned int byte_counter;
unsigned char bit_counter;
unsigned char pattern=0x01;
current_data = ptr;
crc_byte = *current_data++;
for(byte_counter=0; byte_counter < (length-1); byte_counter++)
{ for(bit_counter=0; bit_counter < 8; bit_counter++)
{ bit_test( crc_byte,7,&tenp_value );
//if( !bit_test(crc_byte,7) )
if(tenp_value==0)
{
crc_byte=crc_byte<<1;
bit_test( *current_data, 7 - bit_counter,&tenp_value );
//bit_test( *current_data, 7 - bit_counter ) ? bit_set(crc_byte,0) : bit_clear(crc_byte,0);
if(tenp_value==1) bit_set(&crc_byte,0);
else bit_clear(&crc_byte,0);
continue;
}
crc_byte <<= 1;
bit_test( *current_data, 7 - bit_counter,&tenp_value );
//bit_test(*current_data, 7 - bit_counter) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);
if(tenp_value==1) bit_set(&crc_byte,0);
else bit_clear(&crc_byte,0);
crc_byte ^= pattern;
}
current_data++;
}
for(bit_counter=0; bit_counter < 8; bit_counter++)
{ bit_test( crc_byte,7,&tenp_value );
//if(!bit_test(crc_byte,7))
if(tenp_value==0)
{ crc_byte <<= 1;
continue;
}
crc_byte <<= 1;
crc_byte ^= pattern;
}
return_value[0]=crc_byte;
//return(crc_byte);
}
*/
相关文章:
51单片机第15步_串口多机通讯使用CRC8校验
本章重点介绍串口多机通讯使用CRC8校验。 数据格式:"$123xxxx*crc8\r\n"; 如:"$1234567890ABCDEF*06\r\n" 如:"$1231234567890*31\r\n" crc8是CRC校验值,为十六进制的ASCII码,不包含$和校验值前面的那个* #include <REG51.h> //包含…...
WPF----进度条ProgressBar(渐变色)
ProgressBar 是一种用于指示进程或任务的进度的控件,通常在图形用户界面(GUI)中使用。它提供了一种视觉反馈,显示任务的完成程度,帮助用户了解任务的进展情况。 基本特性 Minimum 和 Maximum 属性: 这些属…...
Apipost接口测试工具的原理及应用详解(四)
本系列文章简介: 随着软件行业的快速发展,API(应用程序编程接口)作为不同软件组件之间通信的桥梁,其重要性日益凸显。API的质量直接关系到软件系统的稳定性、性能和用户体验。因此,对API进行严格的测试成为…...
【图论】200. 岛屿问题
200. 岛屿问题 难度:中等 力扣地址:https://leetcode.cn/studyplan/top-100-liked/ 问题描述 给你一个由 1(陆地)和 0(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围&…...
AI学习指南机器学习篇-随机森林的优缺点
AI学习指南机器学习篇-随机森林的优缺点 引言 机器学习是人工智能领域的重要分支,其中随机森林(Random Forest)算法以其高性能和广泛应用而备受瞩目。然而,就像任何其他算法一样,随机森林也有其优缺点。本文将深入探讨随机森林算法的优势和…...
基于boost::beast的http服务器(上)
文章目录 1.beast网落库介绍2.相关类及api3.异步读写的处理3.1异步写案例3.2异步读案例 1.beast网落库介绍 Beast网络库是一个基于Boost库的C网络库,特别用于开发高性能的网络应用程序。它提供了一组易于使用的API,主要用于处理HTTP和WebSocket协议&…...
深度学习之近端策略优化(Proximal Policy Optimization,PPO)
PPO(Proximal Policy Optimization,近端策略优化)是深度强化学习中的一种算法,属于策略梯度方法中的一种。PPO通过优化策略来最大化累积奖励,具有稳定性好、易于调参等优点,是目前广泛应用的一种深度强化学习算法。下面介绍PPO的基本原理和流程。 PPO基本原理 PPO算法的…...
用pycharm进行python爬虫的步骤
使用 pycharm 进行 python 爬虫的步骤:下载并安装 pycharm。创建一个新项目。安装 requests 和 beautifulsoup 库。编写爬虫脚本,包括获取页面内容、解析 html 和提取数据的代码。运行爬虫脚本。保存和处理提取到的数据。 用 PyCharm 进行 Python 爬虫的…...
重写功能 rewrite
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之 一,用于实现URL的重写,URL的…...
ISO19110操作要求类中/req/operation/operation-attributes的详细解释
/req/operation/operation-attributes 要求: 只有要素属性(feature attributes)可以通过‘observesValueOf’、‘triggeredByValuesOf’或‘affectsValuesOf’关联角色与要素操作(feature operations)关联。 具体解释 定义 要…...
访客(UV)、点击量(PV)、IP、访问量(VV)概念
1、https://www.cnblogs.com/QingPingZm/articles/13855808.htmlhttps://www.cnblogs.com/QingPingZm/articles/13855808.html...
C++系统编程篇——Linux第一个小程序--进度条
(1)先引入一个概念:行缓冲区 \r和\n \r表示回车 \n表示回车并换行 ①代码一 #include<stdio.h> #include<unistd.h> int main()…...
一个中文和越南语双语版本的助贷平台开源源码
一个中文和越南语双语版本的助贷平台开源源码。后台试nodejs。 后台 代理 前端均为vue源码,前端有中文和越南语。 前端ui黄色大气,逻辑操作简单,注册可对接国际短信,可不对接。 用户注册进去填写资料,后台审批&…...
【游戏引擎之路】登神长阶(五)
5月20日-6月4日:攻克2D物理引擎。 6月4日-6月13日:攻克《3D数学基础》。 6月13日-6月20日:攻克《3D图形教程》。 6月21日-6月22日:攻克《Raycasting游戏教程》。 6月23日-6月30日:攻克《Windows游戏编程大师技巧》。 …...
FireAct:使用智能体(agent)微调大语言模型
1.概述 近年来,针对语言模型(LMs)的研究致力于探索其与外部工具或环境互动的能力,以推进新型语言代理的发展。此类代理具备从环境反馈中汲取新知识、通过语言推理进行连续决策,以及借助自我反思提升任务解决能力的能力。工业界的进展,如ChatGPT插件,凸显了语言代理在实际…...
20240626让飞凌的OK3588-C开发板在相机使用1080p60分辨率下预览
20240626让飞凌的OK3588-C开发板在相机使用1080p60分辨率下预览 2024/6/26 15:15 4.2.1 全编译测试 在源码路径内,提供了编译脚本 build.sh,运行该脚本对整个源码进行编译,需要在终端切换到解压 出来的源码路径,找到 build.sh 文件…...
python数据分析——数据分类汇总与统计
数据分类汇总与统计 前言一、Groupby分类统计语法按列分组示例一示例二示例三 遍历各分组示例 使用字典和Series分组示例 使用函数分组示例 二、数据聚合groupby的聚合函数示例一示例二 逐列及多函数应用示例一示例二 返回不含行索引的聚合数据示例 三、一般性的“拆分-应用-合…...
iOS17系统适配
iOS17 新功能 文章目录 iOS17 新功能iOS17支持哪几款机型Xcode15新特性iOS17-开发适配指南 横屏待机 在iOS 17中,还带来了横屏待机功能,苹果将这个新功能命名为“Standby”模式,为 iPhone 带来了全新的玩法。iPhone启用之后,默认情…...
树洞陪聊陪玩交友程序系统源码,解锁交友新体验
在繁忙的都市生活中,你是否渴望找到一片属于自己的秘密花园,倾诉心声、分享快乐?今天,就让我带你走进这片名为“树洞”的神秘之地,感受陪聊陪玩交友的全新魅力! 🌳树洞陪聊陪玩交友程序系统 你…...
区间动态规划——最长回文子序列长度(C++)
把夜熬成粥,然后喝了它。 ——2024年7月1日 书接上回:区间动态规划——最长回文子串(C)-CSDN博客,大家有想到解决办法吗? 题目描述 给定一个字符串s(s仅由数字和英文大小写字母组成࿰…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
