大家好,欢迎来到IT知识分享网。
第一部分*!!!!!!!!蓝牙模块HC-05
蓝牙概述
蓝牙(Bluetooth)是一种用于无线通信的技术标准,允许设备在短距离内进行数据交换和通信。它是由爱立信(Ericsson)公司在1994年推出的,以取代传统的有线连接方式,使设备之间能够实现低功耗、低成本的数据传输和通信。
蓝牙作为一种小范围无线连接技术,具有低功耗、低成本、方便快捷的特点,被广泛应用于无线耳机、智能手表、无线遥控等场景,是实现无线通信的主流技术之一。
蓝牙协议各个版本
HC-05模块简介
HC-05参数
HC-05工作模式
HC-05角色
1. Master(主角色)——查询周围 SPP 蓝牙从设备,并主动发起连接,从而建立主、从蓝牙设备间的透明数据传输通道。
2. Slave(从角色)——被动连接;
3. Slave-Loop(回环角色)——被动连接,接收远程蓝牙主设备数据并将数据原样返回给远程蓝牙主设备;
引脚定义
怎么进入命令响应工作模式(AT指令模式)
用手按着模块上的按键,再给蓝牙模块上电。当蓝牙模块上的灯慢闪的时候就说明进入了配置模式了。
1 按下模块上的按键(PIO11置高)
2 对HC-05重新上电,模块进入AT命令响应工作模式。
3 使用串口助手,配置成波特率38400,数据位8 位,停止位1 位,无校验位,无流控制。
4 串口助手发送字符串“AT\r\n”,正常情况下模块会给出“OK\r\n”,“\r\n”为回车换行,也叫做新行。
HC-05工作流程
AT指令模式配置HC-05模块
重新上电模块,进入自动连接工作模块,连接从模块(也可以使用AT指令,在AT指令模式下连接从模块)。
建立蓝牙连接,LED常量,直接使用串口完成通信
电脑串口助手配置
在配置蓝牙的时候一定要将串口助手按这个要求配置:设置波特率 38400,数据位 8 位,停止位 1 位,无校验位,这是固定操作!
常见指令
常见的指令
首先我们要明确串口通信的条件,我们需要设置8位数据位,1为停止位,无检验,波特率为38400,这样才可以与HC-05进行串口通信,当然这些配置都可以在后续的AT指令中更改。
并且要以文本模式发送指令,编码格式为 utf-8,每个指令后面也要加上换行(‘\r\n’)。
1 第一个测试指令,我们直接通过串口发送“AT”即可,然后就会给我们回复“OK”,用这个没什么意义的指令可以来测试我们是否成功进入到了AT指令模式(其实通过LED的闪烁情况也可以知道)。
2 发送复位指令之后,HC-05进入复位,如果没有按下按钮的话,会默认进入到配对模式。成功后回复“OK”。
恢复的默认配置同上图。发送完成后貌似是自动复位了,也可能不是,反正我的HC-05从原本的AT指令模式变成配对模式了。
而且设备名称也不是上面说的“H-C-2010-06-01”而是“HC-05”,也可能是因为我的是兼容版HC-05,具体的情况以你们自己手上的HC-05为准。
不带参数的话就是回复设备名称,加“OK”,带参数的话就是修改蓝牙名称并且回复“OK”。
默认就是从机,当然我们也可以修改为主机。
这边要注意的是,配对码(密码)需要用英文半角的双引号括起来。
LED和蓝牙模块代码对比1:
实验现象:
代码部分(详解)
hc05.c
#include "hc05.h" #include "delay.h" //代码片段是一些预处理指令,用于定义宏和一些常量。 #define HC05_DelayMs(t) Delay_Ms(t)//当调用 HC05_DelayMs(t) 时,实际上会调用 Delay_Ms(t) 函数。 #define HC05_GPIO_LOW 0 //这通常用于表示某种特定状态,例如在这里,可能表示低电平或关闭状态。 #define HC05_GPIO_HIGH 1 //它被赋值为1。类似地,这个宏可能表示高电平或打开状态。 #if defined (STM32F40_41xxx) //配置输入输出 //用于配置一个GPIO引脚为输出模式。它接受两个参数:port 表示GPIO端口,pin 表示端口上的引脚。 #define HC05_CONFIG_IO_OUTPUT(port, pin) {GPIO_InitTypeDef GPIO_InitStructure; \ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; \ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;\ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; \ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; \ GPIO_InitStructure.GPIO_Pin = pin ; \ GPIO_Init(port, &GPIO_InitStructure);} //读取一个GPIO引脚的当前值。它接受两个参数:port 和 pin,分别表示GPIO端口和引脚。 #define HC05_CONFIG_IO_INPUT(port, pin) {GPIO_InitTypeDef GPIO_InitStructure; \ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; \ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; \ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; \ GPIO_InitStructure.GPIO_Pin = pin ; \ GPIO_Init(port, &GPIO_InitStructure);} //用于读取一个GPIO引脚的当前值。它接受两个参数:port 和 pin,分别表示GPIO端口和引脚。 #define HC05_IO_GET_VALUE(port, pin) GPIO_ReadInputDataBit(port, pin) //用于设置一个GPIO引脚的输出值。它接受三个参数:port、pin 和 value,分别表示GPIO端口、引脚和要设置的值(HC05_GPIO_HIGH 或 HC05_GPIO_LOW)。 #define HC05_IO_SET(port, pin, value) { if(value == HC05_GPIO_HIGH) \ GPIO_SetBits(port, pin); \ else \ GPIO_ResetBits(port, pin);} //时钟开启 时钟使能 #define RCC_GPIO_CLOCK_ENABLE(GPIOX) { if (GPIOX == GPIOA) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); \ else if (GPIOX == GPIOB) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); \ else if (GPIOX == GPIOC) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); \ else if (GPIOX == GPIOD) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); \ else if (GPIOX == GPIOE) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); \ else if (GPIOX == GPIOF) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); \ else if (GPIOX == GPIOG) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE); \ else printf("gpio clock no enable\r\n"); \ } #endif //调试模式 //如果 HC05_DEBUG_MODE 的值为1,表示处于调试模式,那么 hc05_log 会被定义为 printf 函数,用于打印格式化的日志信息。 #if (HC05_DEBUG_MODE == 1) #define hc05_log(format, ...) printf(format, __VA_ARGS__) #else #define hc05_log(format, ...) //如果 HC05_DEBUG_MODE 的值不为1,表示不处于调试模式,那么 hc05_log 会被定义为空,即不执行任何操作,这样就可以在不需要输出调试信息时避免编译器产生多余的代码。 #endif / * @brief 发送一个字符 * * @param[in] bt : BlueTooth_t结构体指针 * @param[in] ch : 要发送的字符 * * @return 0, 表示成功, 其他值表示失败 *函数的作用是通过蓝牙发送一个字符。 / //函数的声明,指定了函数名 send_char,参数类型为指向 BlueTooth_t 结构的指针 bt 和一个字符 ch,返回类型为 int。 static int send_char(BlueTooth_t* bt, char ch) { while((bt->uart->SR & 0X40) == 0); bt->uart->DR = (uint16_t)ch;//一旦蓝牙模块准备好发送字符,就会将要发送的字符 ch 写入 bt 结构体中的 uart 成员的 DR(数据寄存器)中。 return 0; } //这是一个 while 循环,它的条件是等待蓝牙模块准备好发送下一个字符。这里使用了位运算和与操作,检查 bt //结构体中的 uart 成员的 SR(状态寄存器)的第六位是否为 1,如果不为 1,则表示蓝牙模块还没有准备好 //发送下一个字符,程序会一直在这里循环等待。 / * @brief 发送字符串 * * @param[in] bt : BlueTooth_t结构体指针 * @param[in] str : 字符串 * * @return 返回具体发送的字节数 *用于向蓝牙模块发送字符串数据。 / static int send_string(BlueTooth_t* bt, const char* str) { uint32_t i = 0; uint32_t len = strlen(str); for (i = 0; i < len; i++) { send_char(bt, str[i]); } return i; } / * @brief 发送AT指令函数 * * @param[in] bt : BlueTooth_t结构体指针 * @param[in] at_cmd : AT指令 * @param[in] response : AT指令的回响 * @param[in] timeout_ms : 超时时间 * * @return 0, 表示成功, 其他值表示失败 *用于发送 AT 指令并等待响应的函数。以下是对注释的解释: / static int send_at_cmd(BlueTooth_t *bt, const char *at_cmd, const char *response, uint32_t timeout_ms) { //用于发送 AT 指令并等待响应。它接受一个指向 BlueTooth_t 结构的指针 bt,一个表示要发送的 AT 指令的字符串 at_cmd, //一个表示期望的响应的字符串 response,以及一个表示超时时间的毫秒数 timeout_ms。它返回一个整数值,表示执行结果。 bt->rx_buffer_current_cnt = 0;// 这行代码将接收缓冲区的当前计数器置为0,准备接收新的响应数据。 memset(bt->rx_buffer, 0, sizeof(bt->rx_buffer));//这行代码用于将接收缓冲区中的所有元素都设置为0,以清除其中的任何残留数据。 send_string(bt, at_cmd);//这行代码调用了一个名为 send_string 的函数,用于发送字符串类型的数据至蓝牙模块。 send_string(bt, "\r\n");// 这行代码发送一个回车换行符,以结束当前的 AT 指令。 timeout_ms = timeout_ms == 0 ? 0xFFFFFFFF : timeout_ms; //timeout_ms为0,表示延时最长时间,0xFFFFFFFF ms do { if (strstr((const char *)bt->rx_buffer, response) != NULL) { //回应信息正确 return 0; } HC05_DelayMs(1); }while(timeout_ms--); //循环条件为 timeout_ms 不为0。在循环内部,检查接收缓冲区中是否包含期望的响应字符串, //如果包含,则返回0表示成功;否则,等待1毫秒,直到超时。 if (!timeout_ms) //发送超时 return -1; //如果超时时间为0,即等待时间已经用尽,则返回-1表示发送超时。 return -2; } / * @brief 使用AT指令对蓝牙模块配置参数,重新复位 * * @param[in] bt : BlueTooth_t结构体指针 * * @return 0, 表示初始化成功, 其他值表示失败 *通过发送一系列的 AT 指令给蓝牙模块,来执行重置操作,并记录每个指令的执行结果和模块的响应内容。 / int bt_software_reset(struct blue_tooth *bt) //这是一个函数定义,它接受一个指向 struct blue_tooth 结构的指针作为参数,并返回一个整数值。 { char tmp_buffer[20]; int ret = 0; HC05_IO_SET(bt->port[HC05_EN], bt->pin[HC05_EN], HC05_GPIO_HIGH); //这行代码设置蓝牙模块的使能引脚为高电平,以便激活模块。 Delay_Ms(1000); //暂停执行代码1秒钟。 memset(tmp_buffer, 0, sizeof(tmp_buffer)); //这行代码用于将 tmp_buffer 数组中的所有元素都设置为0,以清除其中的任何残留数据。 sprintf(tmp_buffer, "AT"); //这行代码将字符串 "AT" 格式化并存储到 tmp_buffer 中,表示发送 AT 指令给蓝牙模块。 ret = send_at_cmd(bt, tmp_buffer, "OK", 1000); //这行代码调用了一个名为 send_at_cmd 的函数,该函数用于发送 AT 指令给蓝牙模块,并等待接收到 "OK" 响应,最多等待1秒钟。 hc05_log("AT: %d %s\r\n", ret, bt->rx_buffer); //这行代码记录了发送 AT 指令的结果和接收到的响应内容。 memset(tmp_buffer, 0, sizeof(tmp_buffer)); sprintf(tmp_buffer, "AT+NAME=HC-05");//指令的作用是设置蓝牙模块的名称为 "HC-05"。 ret = send_at_cmd(bt, tmp_buffer, "OK", 1000); hc05_log("AT+NAME: %d %s\r\n", ret, bt->rx_buffer); memset(tmp_buffer, 0, sizeof(tmp_buffer)); sprintf(tmp_buffer, "AT+ROLE=0"); ret = send_at_cmd(bt, tmp_buffer, "OK", 1000); //调用 send_at_cmd 函数发送命令给蓝牙模块,并等待蓝牙模块返回 "OK"。 hc05_log("AT+ROLE: %d %s\r\n", ret, bt->rx_buffer); memset(tmp_buffer, 0, sizeof(tmp_buffer)); sprintf(tmp_buffer, "AT+PSWD=\"\""); ret = send_at_cmd(bt, tmp_buffer, "OK", 1000); hc05_log("AT+PSWD: %d %s\r\n", ret, bt->rx_buffer); memset(tmp_buffer, 0, sizeof(tmp_buffer)); sprintf(tmp_buffer, "AT+UART=38400,0,0"); hc05_log("AT+UART: %d %s\r\n", ret, bt->rx_buffer); memset(tmp_buffer, 0, sizeof(tmp_buffer)); sprintf(tmp_buffer, "AT+RESET"); ret = send_at_cmd(bt, tmp_buffer, "OK", 1000); hc05_log("AT+RESET: %d %s\r\n", ret, bt->rx_buffer); HC05_IO_SET(bt->port[HC05_EN], bt->pin[HC05_EN], HC05_GPIO_LOW); //最后一行代码将蓝牙模块的使能引脚设置为低电平,以便关闭模块。 return 0; } //通过发送一系列的AT指令给蓝牙模块,来配置其名称、角色、密码、波特率等参数,并通过 hc05_log 函数输出每个AT指令执行的结果。 / * @brief 初始化HC-05模块用到的硬件资源 * * @param[in] bt : BlueTooth_t结构体指针 * * @return 无 * / static void bt_hw_init(BlueTooth_t* bt) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* 初始化用大的时钟 */ RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_TX]); RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_RX]); RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_EN]); RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_STATE]); /* USART端口配置 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_TX]; GPIO_Init(bt->port[HC05_TX], &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_RX]; GPIO_Init(bt->port[HC05_RX], &GPIO_InitStructure); /* 配置EN、STATUS引脚 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //EN引脚配置为输出 GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_EN]; GPIO_Init(bt->port[HC05_EN], &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //STATUS引脚配置为输入 GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_STATE]; GPIO_Init(bt->port[HC05_STATE], &GPIO_InitStructure); /* USART 初始化设置 */ USART_InitStructure.USART_BaudRate = HC05_UART_BAUD_RATE; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据位长 USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(bt->uart, &USART_InitStructure); //初始化串口 USART_Cmd(bt->uart, ENABLE); //使能串口 USART_ITConfig(bt->uart, USART_IT_RXNE, ENABLE); //开启串口接受中断 /* 串口的NVIC配置 */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } / * @brief 初始化HC-05模块 * * @param[in] bt : BlueTooth_t结构体指针 * * @return 0, 表示初始化成功, 其他值表示失败 * / int BT_Init(BlueTooth_t *bt) { if(!bt) return -1; bt->rx_buffer_current_cnt = 0; bt->rx_buffer_total_length = HC05_RECEIVE_BUFFER_SIZE; memset(bt->rx_buffer, 0, sizeof(bt->rx_buffer)); /* 初始化用到的硬件 */ bt_hw_init(bt); /* 使用AT指令初始化HC-05模块 */ bt_software_reset(bt); return 0; } / * @brief 获得蓝牙模块连接的状态 * * @param[in] bt : BlueTooth_t结构体指针 * * @return HC05_STATUS_CONNECT, 表示蓝牙模块已连接, * HC05_STATUS_DISCONNECT,其他值表示失败 * / BT_ConnectStatus_t BT_GetBlueToothStatus(BlueTooth_t *bt) { uint8_t pin_status = 0; pin_status = HC05_IO_GET_VALUE(bt->port[HC05_STATE], bt->pin[HC05_STATE]); if (pin_status) { //连接 return HC05_STATUS_CONNECT; } else { return HC05_STATUS_DISCONNECT; } } / * @brief 蓝牙模块缓存区里面是否有数据 * * @param[in] bt : BlueTooth_t结构体指针 * * @return true 表示缓存区有数据, * false 表示缓存区没有数据 * / bool BT_IsReceiveData(BlueTooth_t *bt) { if (bt->rx_buffer_current_cnt) { return true; } else { return false; } } / * @brief 读取蓝牙模块缓存区里面的数据 * * @param[in] bt : BlueTooth_t结构体指针 * @param[in] pReadBuffer : 读缓存区指针 * @param[in] u32ReadCount : 读取的数据量 * * @return 返回读取到的数据 * / int BT_ReceiveData(BlueTooth_t *bt, uint8_t *pReadBuffer, uint32_t u32ReadCount) { if (u32ReadCount >= bt->rx_buffer_current_cnt) { memcpy(pReadBuffer, bt->rx_buffer, bt->rx_buffer_current_cnt); bt->rx_buffer_current_cnt = 0; return bt->rx_buffer_current_cnt; } else { memcpy(pReadBuffer, bt->rx_buffer, u32ReadCount); bt->rx_buffer_current_cnt = 0; return u32ReadCount; } } / * @brief 向蓝牙模块发送数据 * * @param[in] bt : BlueTooth_t结构体指针 * @param[in] pReadBuffer : 写缓存区指针 * @param[in] u32ReadCount : 要发送的数据量 * * @return 返回读取到的数据 * / int BT_SendData(BlueTooth_t *bt, uint8_t *pWriteBuffer, uint32_t u32WriteCount) { int i = 0; for (i = 0; i < u32WriteCount; i++) { send_char(bt, pWriteBuffer[i]); } return i; }
hc05.h
#ifndef __HC05_H #define __HC05_H #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include "delay.h" #define HC05_UART_BAUD_RATE (38400U) #define HC05_RECEIVE_BUFFER_SIZE (1024U) #define HC05_DEBUG_MODE 0 //与芯片相关的部分 换芯片只需改动此处 #if defined (STM32F40_41xxx) #include "stm32f4xx.h" typedef GPIO_TypeDef* GPIO_Port_t; typedef USART_TypeDef* UART_t; //与芯片相关的部分 换芯片只需改动此处 #else #error hc05.h: No processor defined! #endif typedef GPIO_Port_t gpio; //蓝牙的链接状态 typedef enum bt_status { HC05_STATUS_DISCONNECT = 0, HC05_STATUS_CONNECT = 1, }BT_ConnectStatus_t; //四个引脚 enum HC05Pin_t { HC05_TX = 0, HC05_RX = 1, HC05_EN = 2, HC05_STATE = 3, HC05_COUNT // }; //初始化蓝牙结构体 //串口资源收发 引脚 typedef struct blue_tooth{ UART_t uart; GPIO_Port_t port[HC05_COUNT]; uint16_t pin[HC05_COUNT]; uint32_t rx_buffer_current_cnt; uint32_t rx_buffer_total_length; //缓冲区总的长度 char rx_buffer[HC05_RECEIVE_BUFFER_SIZE]; //接受AT指令的缓冲区 }BlueTooth_t; int BT_Init(BlueTooth_t *bt); BT_ConnectStatus_t BT_GetBlueToothStatus(BlueTooth_t *bt); bool BT_IsReceiveData(BlueTooth_t *bt); int BT_ReceiveData(BlueTooth_t *bt, uint8_t *pReadBuffer, uint32_t u32ReadCount); int BT_SendData(BlueTooth_t *bt, uint8_t *pBuffer, uint32_t u32WriteCount); #endif
main.c
#include "main.h" BlueTooth_t gBL; int main(void) { BT_ConnectStatus_t s = 0; char buffer[100]; int i = 0; char rx_buffer[100]; Delay_Init(); Debug_Init(); printf("BL\r\n"); /* 初始化串口2对应时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /* 串口2对应引脚复用映射 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); gBL.uart = USART2; gBL.port[HC05_TX] = GPIOA; gBL.pin[HC05_TX] = GPIO_Pin_2; gBL.port[HC05_RX] = GPIOA; gBL.pin[HC05_RX] = GPIO_Pin_3; gBL.port[HC05_EN] = GPIOA; gBL.pin[HC05_EN] = GPIO_Pin_4; gBL.port[HC05_STATE] = GPIOA; gBL.pin[HC05_STATE] = GPIO_Pin_5; BT_Init(&gBL); while (1) { s = BT_GetBlueToothStatus(&gBL); //判断蓝牙是否连接 if (s) { printf("蓝牙连接\r\n"); sprintf(buffer, "i: %d\r\n", i++); BT_SendData(&gBL, buffer, strlen(buffer)); if (BT_IsReceiveData(&gBL)) { memset(rx_buffer, 0, sizeof(rx_buffer)); BT_ReceiveData(&gBL, rx_buffer, 100); printf("rx_buffer: %s\r\n", rx_buffer); } } Delay_Ms(500); } } void USART2_IRQHandler(void) { uint16_t ret = 0; if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { ret= USART2->DR; gBL.rx_buffer[gBL.rx_buffer_current_cnt % sizeof(gBL.rx_buffer)] = ret; gBL.rx_buffer_current_cnt++; } }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/137677.html