欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > OLED屏幕

OLED屏幕

2025/2/25 15:26:41 来源:https://blog.csdn.net/weixin_56459724/article/details/143990939  浏览:    关键词:OLED屏幕

目录

一、OLED屏幕的特点及原理

1、OLED的特点

2、OLED的显示原理

3、OLED的显示过程

二、OLED屏幕的使用过程

1、SH1106驱动芯片介绍

2、通信接口

3、程序设计

SPI通信相关函数

SPI所用IO口的初始化函数

SPI发送一字节函数

OLED屏幕相关函数

OLED所用到的IO初始化函数

对OLED复位函数

主控芯片发送数据/命令到OLED函数  

清屏函数

OLED屏幕初始化配置函数

4、OLED屏幕显示

①命令介绍

②功能函数

确定显示位置函数

显示可设定大小的字符函数

显示可设定大小的汉字函数

显示可选大小的汉字和字符混合函数

显示图片

显示动态图

多张照片来回切换形成动态图

动态图取模


一、OLED屏幕的特点及原理

1、OLED的特点

①本项目采用挂有 1.3 寸的 OLED 屏,分辨率为 132*64; OLED 驱动芯片为 SH1106。

②132列: 0~ 131列    64行:0 ~ 63

③ 将64行分为8份,每份8行, 共有8页     列:0~131

    页地址和列地址确定一个具体的位置(3号页的65列)

2、OLED的显示原理

直接控制发光二极管的通电就可以控制每各子像素的颜色配比,每个像素点都是独立发光的。

左:OLED   右:LCD

与LCD不同的是OLCD无液晶层和背光层,不会漏光

显示原理:

①每个像素点由一个LED灯控制亮灭

②数据每一位(二进制位)控制一个像素点   

③纵向刷屏(先确定某一页,然后确定此页中的某一列为起始 依次刷屏(页内自动列加))

       页内列地址自动自增

       页地址不会自动递增

3、OLED的显示过程

①MCU将数据传输给OLED控制器(驱动芯片)

   OLED驱动芯片----->SH1106

  一般MCU不集成LCD/OLED控制器,都是外接控制器芯片

②通过OLED控制器的作用将内容显示在屏幕上

③传输数据需要通信方式(SPI /  IIC   /   8080  /  6080  / FSMC  /DMX)

二、OLED屏幕的使用过程

1、SH1106驱动芯片介绍

本款OLED的驱动芯片是SH1106.

OLED驱动芯片SH1106是一款专为OLED显示屏设计的控制器,它负责控制屏幕上的像素点,实现图像的显示。

显存,即显示内存,是驱动芯片中用于存储图像数据的存储区域

显存:显示数据的RAM为132 *64 bits.

分辨率:SH1106支持的最大分辨率为132x64像素,但常用于驱动128x64像素的OLED显示屏。

接口支持:SH1106支持SPI(Serial Peripheral Interface)和I2C(Inter-Integrated Circuit)两种通信协议,以及8位6800系列、8080系列并行接口,这使得它可以灵活地应用于各种微控制器平台。

功能集成:SH1106内置了对比度控制、显示RAM、振荡器以及高效的DC-DC转换器,这些功能减少了外部组件的数量,并降低了功耗。

2、通信接口

        多种接口方式,该模块提供了总共4种接口。包括:6800、8080两种并行接口方式、 4线的串行SPI接口方式、IIC接口方式。

以上4种模式通过模块的BS0~2设置,BS0~2的设置与模块接口模式的关系如表所示:

通信方式选择:

根据硬件原理图我们可知000----------------------标准SPI

引脚说明:

OLED_CS: OLED 片选信号。----------------------------------PB7                   //通用推挽输出

OLED_RES:硬复位 OLED。 -----------------------------------PB13                //通用推挽输出

OLED_D/C:命令/数据标志(0,读写命令; 1,写数据)-------PA15      //通用推挽输出

OLED_SI: SPI1 的 MOSI 接口---------------------------------PB5                  //复用推挽输出

OLED_SCL: SPI1 的 SCLK 接口---------------------------------PB3                 //复用推挽输出

3、程序设计

 

 所用到的宏定义

//命令数标识宏定义
#define OLED_CMD   0
#define OLED_DAT   1//命令数据选择线宏定义
#define OLED_CD_H  (GPIOA->ODR |= 1 << 15)
#define OLED_CD_L  (GPIOA->ODR &= ~(1 << 15))//片选宏定义
#define OLED_CS_H  (GPIOB->ODR |= 1 <<7)
#define OLED_CS_L  (GPIOB->ODR &= ~(1 <<7))//复位管脚宏定义
#define OLED_RST_L  (GPIOB->ODR &= ~(1 << 13))
#define OLED_RST_H  (GPIOB->ODR |= 1 <<13)

SPI通信相关函数

SPI所用IO口的初始化函数
/***********************************************
*函数名    :spi1_init
*函数功能  :spi1控制器初始化配置
*函数参数  :无
*函数返回值:无
*函数描述  :SCK------PB3    SPI1_SCKMOSI----PB5     SPI1_MOSI         
************************************************/
void spi1_init(void)
{/*IO控制器配置*///端口时钟使能RCC->AHB1ENR |= (1<<1);//端口模式配置GPIOB->MODER &= ~((3<<6)|(3<<10));GPIOB->MODER |= ((2<<6)|(2<<10));//端口输出类型配置GPIOB->OTYPER &= ~((1<<3)|(1<<5));//端口输出速度配置GPIOB->OSPEEDR &= ~((3<<6)|(3<<10));GPIOB->OSPEEDR |= ((2<<6)|(2<<10));       //50M//端口上下拉配置GPIOB->PUPDR &= ~((3<<6)|(3<<10));//端口复用功能配置GPIOB->AFR[0] &= ~((0xf<<12)|(0xf<<20));GPIOB->AFR[0] |= ((5<<12)|(5<<20));/*SPI1控制器配置*///spi控制器时钟使能RCC->APB2ENR |= (1<<12);//CR1SPI1->CR1 &= ~(1<<15);         //双线单向模式  全双工SPI1->CR1 &= ~(1<<11);         //8位数据帧格式SPI1->CR1 &= ~(1<<10);         //全双工SPI1->CR1 |= (1<<9);           //选择软件从器件管理SPI1->CR1 |= (1<<8);           //内部NSS接口出现高电平,允许控制器通信SPI1->CR1 &= ~(1<<7);          //先发高位SPI1->CR1 &= ~(7<<3);          //42MHZSPI1->CR1 |=  (1<<2);          //主模式SPI1->CR1 &= ~(3<<0);          //0.0模式   时钟极性0   时钟相位0//CR2SPI1->CR2 &= ~(1<<4);          //MOT//spi控制器使能SPI1->CR1 |= (1<<6);
}
SPI发送一字节函数
/***********************************************
*函数名    :spi1_byte
*函数功能  :spi1传输一字节函数
*函数参数  :u8 data
*函数返回值:u8
*函数描述  :      
************************************************/
u8 spi1_byte(u8 data)
{u8 val;//等待之前数据发送完成while(!(SPI1->SR & (1<<1)));//将要发送的数据给到数据寄存器SPI1->DR = data;//等待接收数据完成while(!(SPI1->SR & (1<<0)));//将数据寄存器赋值给变量val = SPI1->DR;//返回变量return val;}

 

OLED屏幕相关函数

OLED所用到的IO初始化函数
/*****************************************************************************
*函数名    :OLED_IO_init
*函数功能  :OLED屏幕所用到的IO初始化配置
*函数参数  :无
*函数返回值:无
*函数描述  :	OLED_CS: OLED 片选信号。----------PB7    //通用输出OLED_RES:硬复位 OLED。 -----------PB13   //通用输出OLED_D/C:命令/数据标志(0,读写命令; 1,写数据)。-------PA15 //通用输出
******************************************************************************/
void OLED_IO_init(void)
{RCC->AHB1ENR |= (3<<0);//PA  PB//OLED_RES  	PB13GPIOB->MODER &= ~(3<<26);GPIOB->MODER |= (1<<26);GPIOB->OTYPER &= ~(1<<13);GPIOB->OSPEEDR &= ~(3<<26);GPIOB->OSPEEDR |= (2<<26);//OLED_DC 		PA15GPIOA->MODER &= ~(3<<30);GPIOA->MODER |= (1<<30);GPIOA->OTYPER &= ~(1<<15);GPIOA->OSPEEDR &= ~(3<<30);GPIOA->OSPEEDR |= (2<<30);//OLED_CS  		PB7GPIOB->MODER &= ~(3<<14);GPIOB->MODER |= (1<<14);GPIOB->OTYPER &= ~(1<<7);GPIOB->OSPEEDR &= ~(3<<14);GPIOB->OSPEEDR |= (2<<14);	GPIOB->ODR |= (1 << 7);       //片选拉高不选择OLED
}
对OLED复位函数
/****************************************************
*函数名    :OLED_RST
*函数功能  :OLED屏幕硬件复位函数
*函数参数  :无
*函数返回值:无
*函数描述  :			
****************************************************/
void OLED_RST(void)
{//拉低复位线OLED_RST_L;//延时100mstim11_delay_ms(100);//拉高复位线OLED_RST_H;
}
主控芯片发送数据/命令到OLED函数  
/******************************************************
*函数名    :OLED_writeByte
*函数功能  :主控芯片发送数据/命令到OLED
*函数参数  :u8 data,u8 cmd_data
*函数返回值:无
*函数描述  :要发送命令,cmd_data 传 0    OLED_CMD   DC线拉低->调用SPI发送一字节函数要发送数据,cmd_data 传 1    OLED_DAT  DC线拉高->调用SPI发送一字节函数
******************************************************/
void OLED_writeByte(u8 data,u8 cmd_data)
{//片选线拉低OLED_CS_L;(cmd_data)?(OLED_CD_H):(OLED_CD_L);spi1_byte(data);//片选线拉高OLED_CS_H;
}

根据底层标准设置驱动代码来确定函数的格式

清屏函数

说明:

每页的列编号会自动递增.

每页中的每列是8个像素点,需要8位数据(1byte)填充

每个像素点给1 就亮   给0就灭

分析:

一共有8页,每页都要做同样的事,所以,页编号可以设计一个循环结构

每页内有132列,要传入132次数据,所以列编号可以设计一个循环结构

/************************************************
*函数名    :OLED_clear
*函数功能  :OLED清屏函数
*函数参数  :无
*函数返回值:无
*函数描述  :list:  2  ~ 130     
**************************************************/
void OLED_clear(void)
{u8 page,list_cont;/*页循环*/for(page=0;page<8;page++){//确定页地址OLED_writeByte(0xB0+page,OLED_CMD);//每页设定列的起始地址  0号列  0x00OLED_writeByte(0x10,OLED_CMD);OLED_writeByte(0x00,OLED_CMD);/*每页中 根据 列数 传 数据字节数 的循环*/     //根据列数算出的传入数据的次数循环for(list_cont=0;list_cont<132;list_cont++){OLED_writeByte(0x00,OLED_DAT);}}
}
OLED屏幕初始化配置函数
/*******************************************************
*函数名    :OLED_init
*函数功能  :OLED屏幕初始化配置
*函数参数  :无
*函数返回值:无
*函数描述  :   
*********************************************************/
void OLED_init(void)
{//spi初始化spi1_init();//OLED屏幕所用到的IO初始化OLED_IO_init();//硬件复位OLED_RST();//底层标准设置驱动移植OLED_writeByte(0xAE,OLED_CMD);//--turn off oled panelOLED_writeByte(0x02,OLED_CMD);//---SET low column addressOLED_writeByte(0x10,OLED_CMD);//---SET high column addressOLED_writeByte(0x40,OLED_CMD);//--SET start line address  SET Mapping RAM Display Start Line (0x00~0x3F)OLED_writeByte(0x81,OLED_CMD);//--SET contrast control registerOLED_writeByte(0xFF,OLED_CMD); // SET SEG Output Current BrightnessOLED_writeByte(0xA1,OLED_CMD);//--SET SEG/Column Mapping     0xa0左右反置 0xa1正常OLED_writeByte(0xC8,OLED_CMD);//SET COM/Row Scan Direction   0xc0上下反置 0xc8正常OLED_writeByte(0xA6,OLED_CMD);//--SET normal displayOLED_writeByte(0xA8,OLED_CMD);//--SET multiplex ratio(1 to 64)OLED_writeByte(0x3f,OLED_CMD);//--1/64 dutyOLED_writeByte(0xD3,OLED_CMD);//-SET display offSET	Shift Mapping RAM Counter (0x00~0x3F)OLED_writeByte(0x00,OLED_CMD);//-not offSETOLED_writeByte(0xd5,OLED_CMD);//--SET display clock divide ratio/oscillator frequencyOLED_writeByte(0x80,OLED_CMD);//--SET divide ratio, SET Clock as 100 Frames/SecOLED_writeByte(0xD9,OLED_CMD);//--SET pre-charge periodOLED_writeByte(0xF1,OLED_CMD);//SET Pre-Charge as 15 Clocks & Discharge as 1 ClockOLED_writeByte(0xDA,OLED_CMD);//--SET com pins hardware configurationOLED_writeByte(0x12,OLED_CMD);OLED_writeByte(0xDB,OLED_CMD);//--SET vcomhOLED_writeByte(0x40,OLED_CMD);//SET VCOM Deselect LevelOLED_writeByte(0x20,OLED_CMD);//-SET Page Addressing Mode (0x00/0x01/0x02)OLED_writeByte(0x02,OLED_CMD);//OLED_writeByte(0x8D,OLED_CMD);//--SET Charge Pump enable/disableOLED_writeByte(0x14,OLED_CMD);//--SET(0x10) disableOLED_writeByte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)OLED_writeByte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_writeByte(0xAF,OLED_CMD);//--turn on oled panelOLED_writeByte(0xAF,OLED_CMD); /*display ON*///清屏函数OLED_clear();
}

4、OLED屏幕显示

①命令介绍

命令 0X81: 设置对比度。包含两个字节,第一个 0X81 为命令,随后发送的

一个字节为要设置的对比度的值。这个值设置得越大屏幕就越亮。

命令 0XAE/0XAF: 0XAE 为关闭显示命令; 0XAF 为开启显示命令。

命令 0XB0~B7: 用于设置页地址,其低三位的值对应着 GRAM 的页地址。

        此命令使用来确定页编号的  

        0xB0---------0号页

        0xB7---------7号页

        OLED_writeByte(0xB3,CMD)      //确定页编号是3号页

命令 0X00~0X0F 用于设置显示时的起始列地址低四位。  

命令 0X10~0X1F 用于设置显示时的起始列地址高四位。

        列:每一页有0~131列,

        例:0页30列 ①将30转为16进制--------0x1E

                              ②将高位给高位即1给0X1x------0X11

                              ③将低位给低位即E给0X0x------0X0E

②功能函数
确定显示位置函数

函数功能:

将起始页地址和列地址发送发送给OLED

方便了列地址的传入,可以直接传入十进制数据形式,函数会将列地址分为高位和低位发送出去

/*********************************************
*函数名    :OLED_setstart
*函数功能  :确定显示起始位置函数   哪页的哪列
*函数参数  :u8 page  页号    u8 list   列号
*函数返回值:无
*函数描述  :通过此函数能确定要显示的起始位置
*********************************************/
void OLED_setstart(u8 page,u8 list)
{OLED_writeByte(0xB0+page,OLED_CMD);        //页地址OLED_writeByte((list>>4)|0x10,OLED_CMD);   //列高位OLED_writeByte(list&0x0f,OLED_CMD);        //列低位     
}

显示可设定大小的字符函数

为什么要取模

        因为OLED屏幕显示是二进制显示方式,

        取模软件的作用就是将字符、汉子、图形转化成二进制形式

取模软件的使用

        设置:点阵格式:阴码

                  取模方式:列行式

                  取模走向:逆向(低位在前)

                  自定义格式: C51

                  把行前缀和行后缀的 {}  去掉

由下往上刷

显示16*16的字符

思路:

把所有可显示字符都取模放在一个数组中,我们可以通过ASCII码计算出要显示的字符与空格 字符的偏移量,因为16*16的字符每个字符的模数据是16个,通过偏移量*16能找到要显示的字 符的模数据在数组中元素的位置.

/************************************************
*函数名    :oled_dis_char16
*函数功能  :显示一个16*16的字符
*函数参数  :u8 page,u8 list,u8 ch
*函数返回值:无
*函数描述  :16*16  实际是 8*16   字高占用2页	page:0~7list:2~129
*************************************************/
void oled_dis_char16(u8 page,u8 list,u8 ch)
{u8 n;u8 i,j;/*计算要显示的字符与空格的偏移量*/n = ch - ' ';/*显示*///所用页数循环for(i=0;i<2;i++){//确定每页的起始显示位置OLED_setstart(page+i,list);//每页发送的数据字节数 取决字的宽度for(j=0;j<8;j++){OLED_writeByte(F16X16[n*16+i*8+j],OLED_DAT);//n*16 偏移到所要显示的字符  i*8 每页要显示的取模数据 j 每个取模数据的显示}}}

显示32*24的字符

说明:

实际是16*24的字符

字符占用3页,每页中的每列需要8位数据(1byte)填充

每页一共有16列,所以每页要传16个字节

每个字符字模数据一共有48个

思路:

把所有可显示字符都取模放在一个数组中,我们可以通过ASCII码计算出要显示的字符与空格字符的偏移量,因为16*24的字符每个字符的模数据是4448个,通过偏移量*48能找到要显示的字 符的模数据在数组中元素的位置.

/************************************************
*函数名    :oled_dis_char24
*函数功能  :显示一个32*24的字符
*函数参数  :u8 page,u8 list,u8 ch
*函数返回值:无
*函数描述  :32*24  实际是 16*24   字高占用3页	page:0~7list:2~129
*************************************************/
void oled_dis_char24(u8 page,u8 list,u8 ch)
{u8 n;u8 i,j;/*计算要显示的字符与空格的偏移量*/n = ch - ' ';/*显示*///所用页数循环for(i=0;i<3;i++){//确定每页的起始显示位置OLED_setstart(page+i,list);//每页发送的数据字节数 取决字的宽度for(j=0;j<16;j++){OLED_writeByte(F32X24[n*48+i*16+j],OLED_DAT);//n*16 偏移到所要显示的字符  i*16 每页要显示的取模数据 j 每个取模数据的显示}}}

优化程序:

显示一个可选择大小的字符函数

/************************************************
*函数名    :oled_dis_char
*函数功能  :显示一个字符
*函数参数  :u8 page,u8 list,u8 ch,u8 size
*函数返回值:无
*函数描述  :page:0~7list:2~12816*16  size:1632*24  size:24 
*************************************************/
void oled_dis_char(u8 page,u8 list,u8 ch,u8 size)
{u8 n;u8 i,j;/*计算要显示的字符与空格的偏移量*/n = ch - ' ';/*显示*///所用页数循环for(i=0;i<size/8;i++){//确定每页的起始显示位置OLED_setstart(page+i,list);if(size==16)//16号字符       {//每页发送的数据字节数 取决字的宽度for(j=0;j<8;j++){		OLED_writeByte(F16X16[n*16+i*8+j],OLED_DAT);}}else if(size==24)//24号字符 {//每页发送的数据字节数 取决字的宽度for(j=0;j<16;j++){OLED_writeByte(F32X24[n*48+i*16+j],OLED_DAT);}}	}}
显示可设定大小的汉字函数

说明:

一个汉字在数组中占两个元素的位置。

思路:

把所要显示的汉字存储到一维字库数组中

把所要显示的汉字按顺序分别取模16*16和32*32的字库数据存储到一维字模数组 中

通过传入想要打印的汉字在字库中查找,计算出所要显示的汉字与字库中的第一个 汉字的偏移量

需要避免所要找的汉字不是字库里的,并且如果不是字库里的,则需要退出程序

如果是字库里的,再选择大小

注意:

后期要添加新的字,一定要在字库的后面添加,然后取模也要放在模数据数组的后面


/************************************************
*函数名    :oled_dis_hz
*函数功能  :显示一个的汉字
*函数参数  :u8 page,u8 list,u8 *hz,u8 size
*函数返回值:无
*函数描述  :page:0~7list:2~12816*16  size:1624*24  size:24						
*************************************************/     
void oled_dis_hz(u8 page,u8 list,u8 *hz,u8 size)
{u8 n = 0;u8 i,j;/*计算要显示的汉字与字库数组中的首个汉字的偏移个数*/while(table[2*n] != '\0'){if(*hz==table[2*n]  && *(hz+1)==table[2*n+1]){break;}n++;}//判断n的值是否有效,无效就结束函数if(table[2*n] == '\0'){return;}//n值就是要显示的汉字与第一个汉字的偏移个数/*显示*/for(i=0;i<size/8;i++)     //页数循环{//确定每页的起始位置OLED_setstart(page+i,list);for(j=0;j<size;j++) //每页要传入的数据字节数循环   有字的宽度决定{if(size == 16){OLED_writeByte(hz16[n*32+16*i+j],OLED_DAT);}else if(size==24){OLED_writeByte(hz24[n*72+24*i+j],OLED_DAT);}}}}
显示可选大小的汉字和字符混合函数

思路:

接收字符串,通过指针偏移循环查找所显示的字符或汉字

判断字符-->调用显示字符函数,偏移到下一个元素(字符占一个字节),显示下一个字符(列+字符宽度)

否则是汉字-->调用显示汉字函数,偏移到下一个元素(汉字占两个字节),显示下一个汉字(列+汉字宽度)

问题:

如何判断遇到的是字符还是汉字?

不是字符就一定是汉字

如何判断是不是字符?

32~127

/************************************************
*函数名    :oled_dis_str
*函数功能  :显示可设置大小的字符和汉字混合形式
*函数参数  :u8 page,u8 list,u8 *str,u8 size
*函数返回值:无
*函数描述  :page:0~7list:2~12816*16      16*16      size:1632*24      24*24      size:24						
*************************************************/ 
void oled_dis_str(u8 page,u8 list,u8 *str,u8 size)
{while(*str != '\0'){//判断是否是字符if(*str >= 32 && *str <= 127){oled_dis_char(page,list%131,*str,size);str++;if(size == 16){list += 8;}else if(size == 24){list += 16;}}else{oled_dis_hz(page,list%131,str,size);str += 2;if(size == 16){list += 16;}else if(size == 24){list += 24;}}}
}
显示图片

说明:

在iconfont上下载PNG格式图标    

将PNG格式转换位bmp格式并修改像素大小(电脑的画图软件)

用取模软件修改丢失像素(鼠标左右键修补像素点)

生成字模(注意将每行的括号去掉--在设置里面)

显示原理:

        通过图形的高度知道要占的页数

        通过图形的宽度知道每页刷屏的列数

每页要刷的列数与要传入的数据字节数--->取决于图片的宽度

/************************************************
*函数名    :oled_dis_pic
*函数功能  :显示可设置大小的字符和汉字混合形式
*函数参数  :u8 page,u8 list,u8 w,u8 h,u8 *pic
*函数返回值:无
*函数描述  :w:指定要显示的图片的宽度h:指定要显示的图片的高度page:0~7list:2~128					
*************************************************/ 
void oled_dis_pic(u8 page,u8 list,u8 w,u8 h,const u8 *pic)
{u8 i,j;u8 p;//计算图形占的实际页数(h%8==0)?(p=h/8):(p=h/8+1);for(i=0;i<p;i++){//确定每页的起始位置OLED_setstart(page+i,list);for(j=0;j<w;j++){OLED_writeByte(pic[w*i+j],OLED_DAT);}}
}
显示动态图
多张照片来回切换形成动态图

利用指针数组存放每张图片的地址,再利用定时中断控制变量来寻找图片的地址空间,以显示在LCD屏幕上实现切换图片,形成动态图

        static u8 pic_n = 0;//动态图片切换const u8 *pics[] = {pic_0,pic_1,pic_2,pic_3,pic_4,pic_5,pic_6};if(timer_buff[4] >= 50){	 oled_dis_pic(0,1,64,64,pics[pic_n]); pic_n++;if(pic_n>6){pic_n=0;}				timer_buff[4] = 0;}
动态图取模

用软件生成模数据的.c文件,添加到工程中

利用定时中断控制变量来寻找图片的地址空间,以显示在LCD屏幕上

        if(timer_buff[4] >= 50){	 oled_dis_pic(0,1,64,64,tkr64x64[pic_n]); pic_n++;if(pic_n>=102){pic_n=0;}				timer_buff[4] = 0;}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词