ESP32学习---ESP-NOW

ESP32学习---ESP-NOW

    • 基于Arduino IDE环境
      • 获取mac地址
      • 单播通讯
      • 一对多通讯
      • 多对一通讯
      • 多对多通讯
        • 模块1代码
        • 模块2
        • 模块3
      • 广播通讯
    • 基于ESP-IDF框架

乐鑫编程指南中关于ESP-NOW的介绍:https://docs.espressif.com/projects/esp-idf/zh_CN/v5.2.1/esp32/api-reference/network/esp_now.html

乐鑫提供的esp-now仓库:https://github.com/espressif/esp-now

基于Arduino IDE环境

基于arduino环境的ESP-NOW教程:https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/
可以从左侧的目录栏找到对应的ESP-NOW教程的位置,如下所示:
在这里插入图片描述

ESP-NOW自动配对功能实现的参考链接:https://randomnerdtutorials.com/esp-now-auto-pairing-esp32-esp8266/

获取mac地址

对于ESP-NOW协议来说mac地址是个不可或缺的数据,模块之间的配对需要用到,这里是获取mac地址的方法:

#include <WiFi.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
  Serial.println(WiFi.macAddress());
}

void loop() {
  // put your main code here, to run repeatedly:

}

打开串口监视器复位模块显示信息中会包含如下信息即为mac地址

16:38:06.244 -> A0:B7:65:60:E7:B8

单播通讯

一对多通讯

多对一通讯

多对多通讯

这里使用3个模块之间互相传输数据,首先我们先要获取到3个模块的MAC地址,每个模块向外发送数据并同时接收来自于其它两个模块的数据

模块1代码

esp_now_1.ino :


//发送端的程序
#include <WiFi.h>
#include "esp_now.h"

// 1作为发送,2和3作为接收
//接收端的MAC地址 16:38:06.244 -> A0:B7:65:60:E7:B8
uint8_t broadcastAddress1[] = {0xA0,0xB7,0x65,0x4F,0x27,0x30};
uint8_t broadcastAddress2[] = {0xA0,0xB7,0x65,0x60,0xE7,0xB8};
uint8_t broadcastAddress3[] = {0xA0,0xB7,0x65,0x48,0x78,0x9C};//A0:B7:65:48:78:9C
// uint8_t broadcastAddress2[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
// uint8_t broadcastAddress3[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

//发送数据类型
typedef struct {
  char a[32];
  int b;
  float c;
  bool d;
} Message_t;

Message_t msg, rcv_msg;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

void OnDataRecv(const uint8_t *mac_addr, const uint8_t *incomingData, int len) {
  memcpy(&rcv_msg, incomingData, sizeof(rcv_msg));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.print(rcv_msg.a);
  Serial.print("Int: ");
  Serial.println(rcv_msg.b);
  Serial.print("float: ");
  Serial.println(rcv_msg.c);
  Serial.print("Bool: ");
  Serial.println(rcv_msg.d);
  Serial.println();
}

esp_now_peer_info_t peerInfo2;
esp_now_peer_info_t peerInfo3;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
  Serial.println(WiFi.macAddress());

  if(esp_now_init() != ESP_OK){
    Serial.println("Error init ESP-NOW");
    return;
  }
  esp_now_register_send_cb(OnDataSent); //注册发送回调函数
  esp_now_register_recv_cb(OnDataRecv); //注册接收回调函数

  //注册通信频道
  // esp_now_peer_info_t peerInfo;
  memcpy(peerInfo2.peer_addr, broadcastAddress2, 6);
  char macStr[18];
  snprintf(macStr,sizeof(macStr),"%02x:%02x:%02x:%02x:%02x:%02x", peerInfo2.peer_addr[0],
    peerInfo2.peer_addr[1],peerInfo2.peer_addr[2],peerInfo2.peer_addr[3],
    peerInfo2.peer_addr[4], peerInfo2.peer_addr[5]);
  Serial.print("mac addr: ");Serial.println(macStr);
  peerInfo2.channel = 1; //通道
  peerInfo2.encrypt = false; //是否加密

  if(esp_now_add_peer(&peerInfo2) != ESP_OK) {
    Serial.println("Failed to add peer 2");
    return;
  }

  // 3
  memcpy(peerInfo3.peer_addr, broadcastAddress3, 6);
  peerInfo3.channel = 1; //
  peerInfo3.encrypt = false; 
  if(esp_now_add_peer(&peerInfo3) != ESP_OK) {
    Serial.println("Failed to add peer 3");
    return;
  }

}

void loop() {
  // put your main code here, to run repeatedly:
  strcpy(msg.a, "this is a char");
  msg.b = random(1, 20);
  msg.c = 10.0f;
  msg.d = false;

  esp_err_t result = esp_now_send(0, (uint8_t *)&msg, sizeof(msg));
  if(result == ESP_OK) {
    Serial.println("Sent with success");
  } else {
    Serial.println("Error sending the data");
  }
  delay(200);
}

模块2

esp_now_2.ino

// 接收端程序
#include <WiFi.h>
#include "esp_now.h"

//2作为发送,1和3作为接收
uint8_t broadcastAddress1[] = {0xA0,0xB7,0x65,0x4F,0x27,0x30};
uint8_t broadcastAddress2[] = {0xA0,0xB7,0x65,0x60,0xE7,0xB8};
uint8_t broadcastAddress3[] = {0xA0,0xB7,0x65,0x48,0x78,0x9C};//A0:B7:65:48:78:9C

typedef struct {
  char a[32];
  int b;
  float c;
  bool d;
}Message_t;

Message_t send_msg, rcv_msg;

void OnDataSend(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

// 回调函数,当接收到消息时会调用该函数
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len){
  memcpy(&rcv_msg, incomingData, sizeof(rcv_msg));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.print(rcv_msg.a);
  Serial.print("Int: ");
  Serial.println(rcv_msg.b);
  Serial.print("float: ");
  Serial.println(rcv_msg.c);
  Serial.print("Bool: ");
  Serial.println(rcv_msg.d);
  Serial.println();
}

 esp_now_peer_info_t peerInfo1;
 esp_now_peer_info_t peerInfo3;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  Serial.println(WiFi.macAddress());
  if(esp_now_init() != ESP_OK) {
    Serial.println("Error init ESP-NOW");
    return;
  }

  esp_now_register_recv_cb(OnDataRecv); //注册接收信息回调函数
  esp_now_register_send_cb(OnDataSend);

  //设置通信频道
  //esp_now_peer_info_t peerInfo;
  memcpy(peerInfo1.peer_addr, broadcastAddress1, 6);
  peerInfo1.channel = 1; //通道
  peerInfo1.encrypt = false;
  if(esp_now_add_peer(&peerInfo1) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }

  memcpy(peerInfo3.peer_addr, broadcastAddress3, 6);
  peerInfo3.channel = 1; //通道
  peerInfo3.encrypt = false;
  if(esp_now_add_peer(&peerInfo3) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  strcpy(send_msg.a, "this is a slaver");
  send_msg.b = random(1,50);
  send_msg.c = 20.0f;
  send_msg.d = true;

  esp_err_t result = esp_now_send(0, (uint8_t *)&send_msg, sizeof(send_msg));
  if(result == ESP_OK){
    Serial.println("Send with success");
  } else {
    Serial.println("Error sending the data");
  }
  delay(200);
}

模块3

esp_now_3.ino

// 接收端程序
#include <WiFi.h>
#include "esp_now.h"

//3作为发送,1和2作为接收
uint8_t broadcastAddress1[] = {0xA0,0xB7,0x65,0x4F,0x27,0x30};
uint8_t broadcastAddress2[] = {0xA0,0xB7,0x65,0x60,0xE7,0xB8};
uint8_t broadcastAddress3[] = {0xA0,0xB7,0x65,0x48,0x78,0x9C};//A0:B7:65:48:78:9C

typedef struct {
  char a[32];
  int b;
  float c;
  bool d;
}Message_t;

Message_t send_msg, rcv_msg;

void OnDataSend(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

// 回调函数,当接收到消息时会调用该函数
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len){
  memcpy(&rcv_msg, incomingData, sizeof(rcv_msg));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.print(rcv_msg.a);
  Serial.print("Int: ");
  Serial.println(rcv_msg.b);
  Serial.print("float: ");
  Serial.println(rcv_msg.c);
  Serial.print("Bool: ");
  Serial.println(rcv_msg.d);
  Serial.println();
}

 esp_now_peer_info_t peerInfo1;
 esp_now_peer_info_t peerInfo2;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  Serial.println(WiFi.macAddress());
  if(esp_now_init() != ESP_OK) {
    Serial.println("Error init ESP-NOW");
    return;
  }

  esp_now_register_recv_cb(OnDataRecv); //注册接收信息回调函数
  esp_now_register_send_cb(OnDataSend);

  //设置通信频道
  //esp_now_peer_info_t peerInfo;
  memcpy(peerInfo1.peer_addr, broadcastAddress1, 6);
  peerInfo1.channel = 1; //通道
  peerInfo1.encrypt = false;
  if(esp_now_add_peer(&peerInfo1) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }

  memcpy(peerInfo2.peer_addr, broadcastAddress2, 6);
  peerInfo2.channel = 1; //通道
  peerInfo2.encrypt = false;
  if(esp_now_add_peer(&peerInfo2) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  strcpy(send_msg.a, "this is a slaver");
  send_msg.b = random(1,50);
  send_msg.c = 30.0f;
  send_msg.d = true;

  esp_err_t result = esp_now_send(0, (uint8_t *)&send_msg, sizeof(send_msg));
  if(result == ESP_OK){
    Serial.println("Send with success");
  } else {
    Serial.println("Error sending the data");
  }
  delay(200);
}

广播通讯

参考链接:https://dronebotworkshop.com/esp-now/中的Broadcast Mode章节

在这个模式下测试至少需要两个ESP32模块,相对于上面的多对多通讯的实现而言,这种方式可以不用提前配对且可以多个模块共用一套代码。当然广播通讯模式可也能会有一些问题:例如有些产品通过网络广播的形式形成了一个网络,可能会受到其它网络通过广播模式发数据的影响,具体的情况还需还要根据实际的应用来考虑。

这里通过广播模式每隔0.5S发送一次hello world,可以通过MAC地址确定对应的信息是由哪个模块发送来的。

esp_now_broadcast.ino

#include "WiFi.h"
#include "esp_now.h"

void formatMacAddress(const uint8_t *macAddr, char *buffer, int maxLength){
  snprintf(buffer, maxLength, "%02X:%02X:%02X:%02X:%02X:%02X", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
}

void receiveCallback(const uint8_t *macAddr, const uint8_t *data, int dataLen) {
  // 将接收到的数据复制到缓存中,最大允许250个字节 + 1个null终止字节
  char buffer[ESP_NOW_MAX_DATA_LEN+1];
  int msgLen = min(ESP_NOW_MAX_DATA_LEN, dataLen);
  strncpy(buffer, (const char *)data, msgLen);

  buffer[msgLen] = 0; //确保最后一个字节为null

  char macStr[18];
  formatMacAddress(macAddr, macStr, 18);
  Serial.printf("Received message from: %s - %s", macStr, buffer);
}

void sendCallback(const uint8_t *macAddr, esp_now_send_status_t status) {
  char macStr[18];
  formatMacAddress(macAddr, macStr, 18);
  Serial.print("Last Packet Send to: ");
  Serial.println(macStr);
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

esp_now_peer_info_t peerInfo = {};
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

void broadcast(const String &message) {
  // uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  // esp_now_peer_info_t peerInfo = {};
  memcpy(&peerInfo.peer_addr, broadcastAddress, 6);
  if(!esp_now_is_peer_exist(broadcastAddress)) {
    esp_now_add_peer(&peerInfo);
  }
  esp_err_t result = esp_now_send(peerInfo.peer_addr, (const uint8_t *)message.c_str(), message.length());
  if(result == ESP_OK) {
    Serial.println("Broadcast message success");
  } else if(result == ESP_ERR_ESPNOW_NOT_INIT) {
    Serial.println("ESP-NOW not Init");
  } else if(result == ESP_ERR_ESPNOW_ARG) {
    Serial.println("Invalid Argument");
  } else if(result == ESP_ERR_ESPNOW_INTERNAL) {
    Serial.println("Internal Error");
  } else if(result == ESP_ERR_ESPNOW_NO_MEM) {
    Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  } else if(result == ESP_ERR_ESPNOW_NOT_FOUND) {
    Serial.println("Peer not found");
  } else {
    Serial.println("Unknown error");
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(1000);

  WiFi.mode(WIFI_STA);
  Serial.println("ESP-NOW Broadcast Demo");

  Serial.print("MAC Address: ");
  Serial.println(WiFi.macAddress());

  WiFi.disconnect();

  if(esp_now_init() == ESP_OK) {
    Serial.println("ESP-NOW init success");
    esp_now_register_recv_cb(receiveCallback);
    esp_now_register_send_cb(sendCallback);
  } else {
    Serial.println("ESP-NOW init failed");
    delay(3000);
    ESP.restart();
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  broadcast("hello world!");
  delay(500);
}

基于ESP-IDF框架

github上找到的基于网状网络的ESP-NOW协议组件:https://github.com/aZholtikov/zh_network/tree/main

  1. 无需配对即可进行数据传输
  2. 支持广播模式和单播模式

  3. 详细的说明可到链接地址查看,后续有时间可以研究下。

后续内容待添加。。。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探秘开发公司内部,开发小程序只要几百块?

做一个微信小程序大概需要多少钱&#xff1f; 在考虑开发微信小程序之前&#xff0c;许多商家和企业都会关心开发费用这个问题&#xff0c;并且可能会对比多家公司的报价。那么&#xff0c;开发一个微信小程序大概需要多少费用呢&#xff1f;下面我们简单介绍一下小程序开发的…

思考:开启MMU瞬间可能出现的多种问题以及多种解决方案

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; (说明本文的介绍都是基于armv8-aarch64或armv9硬件架构) 在mmu未开启阶段&#xff0c;PC操作的都是物理地址执行程序&#xff0c;这样看起来一切正常&#xff0c;没啥问题。 例如…

【Leetcode】top 100 图论

基础知识补充 1.图分为有向图和无向图&#xff0c;有权图和无权图&#xff1b; 2.图的表示方法&#xff1a;邻接矩阵适合表示稠密图&#xff0c;邻接表适合表示稀疏图&#xff1b; 邻接矩阵&#xff1a; 邻接表&#xff1a; 基础操作补充 1.邻接矩阵&#xff1a; class GraphAd…

蓝桥杯第1593题——二进制问题

题目描述 小蓝最近在学习二进制。他想知道 1 到 N 中有多少个数满足其二进制表示中恰好有 K 个 1。你能帮助他吗&#xff1f; 输入描述 输入一行包含两个整数 N 和 K。 输出描述 输出一个整数表示答案。 输入输出样例 示例 输入 7 2输出 3评测用例规模与约定 对于 30% …

软件测试工作中需要的Linux知识,一篇文章就够了

01、Linux基础 1、Linux系统简单介绍 Linux是一套免费使用, 支持多用户、多任务、支持多线程和多个核心CPU的操作系统&#xff1b;很多中型, 大型甚至是巨型项目都在使用Linux。 Linux的发行版说简单点就是将Linux与应用软件做一个打包, 目前市面上比较知名的发行版有: Ubun…

Free RTOS day2

1.思维导图 2.使用PWMADC光敏电阻完成光控灯的实验 int adc_val0;//用于保存ADC采样得到的数值 float volt0;//用于保存电压值 int main(void) {MX_GPIO_Init();MX_DMA_Init();MX_TIM1_Init();MX_USART1_UART_Init();MX_ADC_Init();MX_TIM3_Init();HAL_TIM_PWM_Start(&hti…

代码随想录算法训练营第二十七天|131.分割回文串、93.复原IP地址

文档链接&#xff1a;https://programmercarl.com/ LeetCode131.分割回文串 题目链接&#xff1a;https://leetcode.cn/problems/palindrome-partitioning/ 思路&#xff1a;把回溯的树画出来就好很多。startIndex用来控制切割的位置 例如对于字符串abcdef&#xff1a; 组…

实现offsetof宏以及交换一个整数二进制奇偶位的宏

目录 1. offsetof宏2. 交换奇偶位 1. offsetof宏 我们想用宏来实现offsetof函数,首先要了解这个函数的用法。 1.1 offsetof函数的介绍及用法 &#xff08;1&#xff09;功能&#xff1a;用来计算结构体中一个成员在该结构体中的相对起始位置的偏移量&#xff0c;单位是字节。 …

Golang goroutine 同步原语:sync 包让你对并发控制得心应手

在 Go 语言中&#xff0c;不仅有 channel 这类比较易用且高级的同步机制&#xff0c;还有 sync.Mutex、sync.WaitGroup 等比较原始的同步机制。通过它们&#xff0c;我们可以更加灵活地控制数据的同步和多协程的并发。 资源竞争 在一个 goroutine 中&#xff0c;如果分配的内存…

Python多任务处理---多线程

引入 生活中&#xff0c;我们在电脑上打开了一个word, 这个word对操作系统来说就是一个进程。我们在进行word操作的时候&#xff0c;比如在你打字的时候&#xff0c;该word同时可以进行文字检查。发现了没&#xff0c;在同一个进程中&#xff0c;我们也可以进行同时操作。…

【Pytorch学习笔记(二)】张量的创建(补充)

一、知识回顾 我们在博客《张量的创建与访问》中已经讨论了一些张量的创建方法如torch.CharTensor()、torch.FloatTensor()以及torch.zeros()等张量创建方法&#xff0c;但由于其仅仅介绍了cpu版本torch下张量的创建方法和只有具体数据类型张量&#xff0c;本节内容旨在补充gp…

论文速览 | IEEE TCI, 2022 | 单光子级非视距成像:估计强度与优化重建

注1:本文系"计算成像最新论文速览"系列之一,致力于简洁清晰地介绍、解读非视距成像领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, SIGGRAPH, TPAMI; Light‑Science & Applications, Optica 等)。 本次介绍的论文是:<2…

【Git】命令行使用体验大大优化的方法

Git的优化使用 相信很多人&#xff0c;在使用git作为版本管理工具时都会感受到它的方便&#xff0c;但是也会有一些问题困扰着我们&#xff0c;让我们觉得使用体验不是很好。我在使用git的过程中就发现了几个问题&#xff1a;写commit费时、怎么做多人开发的代码审查等等。今天…

代码随想录算法训练营第二十五天| 216.组合总和III,17.电话号码的字母组合

题目与题解 216.组合总和III 题目链接&#xff1a;216.组合总和III 代码随想录题解&#xff1a;216.组合总和III 视频讲解&#xff1a;和组合问题有啥区别&#xff1f;回溯算法如何剪枝&#xff1f;| LeetCode&#xff1a;216.组合总和III_哔哩哔哩_bilibili 解题思路&#xf…

Linux之用户账号、用户组和与账号有关的系统文件

目录 一、基本介绍 1.用户和用户组 2.UID和GID 二、 账户管理 1.查看用户的UID和GID 2.添加账户 3.删除账号 4.修改账号 5.账户口令 三、分组管理 1.新增用户组 2.删除用户组 3.修改用户组 4.用户组切换 四、与账号有关的系统文件 1./etc/passwd 2./etc/shado…

组蛋白脱乙酰酶介导的胃癌肿瘤微环境特征及协同免疫治疗(多组学文献学习)

目录 ①HDAC转录组多数据NMF一次聚类 ②ACRG队列中HDAC单独NMF聚类 ③HDS评分在胃癌中的临床特征和基因组特征 ④高 HDS 可能提示胃癌的“热”肿瘤状态 ⑤HDS是胃癌免疫治疗效果的有力预测指标 ⑥单细胞转录组测序揭示了高HDS和低HDS患者的TME ⑦内皮细胞和成纤维细胞可…

Prometheus+grafana环境搭建mysql(docker+二进制两种方式安装)(三)

由于所有组件写一篇幅过长&#xff0c;所以每个组件分一篇方便查看&#xff0c;前两篇 Prometheusgrafana环境搭建方法及流程两种方式(docker和源码包)(一)-CSDN博客 Prometheusgrafana环境搭建rabbitmq(docker二进制两种方式安装)(二)-CSDN博客 1.监控mysql 1.1官方地址:…

文本评估指标 BLEU,METEOR,ROUGE

文本评估指标 这里注意库包的版本&#xff0c;亲测这个很包敏感&#xff0c;所以一定要调好库版本 nltk 3.6.3 如果这个包的版本不对会报错&#xff0c;很难理解的那种 rouge1.0.1 定义函数 import jieba from rouge import Rouge from nltk.translate.meteor_score import …

CrossOver玩游戏会损害电脑吗 CrossOver玩游戏会卡吗 Mac玩游戏 crossover24免费激活

CrossOver是一款可以在macOS上运行Windows应用程序的软件&#xff0c;它利用了Wine技术&#xff0c;无需安装虚拟机或双系统&#xff0c;可以直接在苹果系统下运行Windows游戏。那么&#xff0c;使用CrossOver玩游戏会损害电脑吗&#xff1f;CrossOver玩游戏会卡吗&#xff1f;…

java中:print与println的区别

目录 区别 区别 print是直接打印输出 println是输出后自动回车到下一行 例如 public class test {public static void main(String[] args){System.out.println("换行");System.out.print("不换行");System.out.println();}}——————————————…