网站首页 > 资源文章 正文
1.ui界面(注意:中文在这里不能显示) 以下源代码仅供学习交流!!!
关注我 可获得源代码
#include "ui.h" #include "stm32f10x.h" #include <stdio.h> extern u8 RTCItSecStatus; extern u8 Time6ItStatus; int Min=0,Sec=0,CentiSec=0; //í?D?????????£??ù?Y±?á??μ???¨??ê????????? u8 UICnt=0; extern void Delay(u32 Cnt); u16 Get_TouchKey( void ) { u16 KeyTemp; strType_XPT2046_Coordinate Coordinate; if ( ucXPT2046_TouchFlag == 1 ) //è?1?′¥?tá??á?? { if( UICnt==0 ) //UI00′¥?á?üê?±e { if ( XPT2046_Get_TouchedPoint ( & Coordinate, & strXPT2046_TouchPara ) ) //??è?′¥?tμ?μ?×?±ê { if( Coordinate.x>0 && Coordinate.x<80 && Coordinate.y>0 && Coordinate.y<36 ) KeyTemp = 101; else if( Coordinate.x>80 && Coordinate.x<160 && Coordinate.y>0 && Coordinate.y<36 ) KeyTemp = 102; else if( Coordinate.x>160 && Coordinate.x<240 && Coordinate.y>0 && Coordinate.y<36 ) KeyTemp = 103; else if( Coordinate.x>0 && Coordinate.x<240 && Coordinate.y>290 && Coordinate.y<320 ) KeyTemp = 104; else KeyTemp = 0; } } else if( UICnt==1 ) //UI01′¥?á?üê?±e { if ( XPT2046_Get_TouchedPoint ( & Coordinate, & strXPT2046_TouchPara ) ) //??è?′¥?tμ?μ?×?±ê { if( Coordinate.x>0 && Coordinate.x<80 && Coordinate.y>0 && Coordinate.y<36 ) KeyTemp = 201; else if( Coordinate.x>80 && Coordinate.x<160 && Coordinate.y>0 && Coordinate.y<36 ) KeyTemp = 202; else if( Coordinate.x>160 && Coordinate.x<240 && Coordinate.y>0 && Coordinate.y<36 ) KeyTemp = 203; else if( Coordinate.x>0 && Coordinate.x<120 && Coordinate.y>290 && Coordinate.y<320 ) KeyTemp = 204; else if( Coordinate.x>120 && Coordinate.x<240 && Coordinate.y>290 && Coordinate.y<320 ) KeyTemp = 205; else KeyTemp = 0; } } else if( UICnt==2 ) //UI02′¥?á?üê?±e { if ( XPT2046_Get_TouchedPoint ( & Coordinate, & strXPT2046_TouchPara ) ) //??è?′¥?tμ?μ?×?±ê { if( Coordinate.x>0 && Coordinate.x<=239 && Coordinate.y>0 && Coordinate.y<=320 ) KeyTemp = 121; //... } } else if( UICnt==3 ) //UI03′¥?á?üê?±e { if ( XPT2046_Get_TouchedPoint ( & Coordinate, & strXPT2046_TouchPara ) ) //??è?′¥?tμ?μ?×?±ê { if( Coordinate.x>0 && Coordinate.x<=239 && Coordinate.y>0 && Coordinate.y<=320 ) KeyTemp = 131; //... } } //... } else KeyTemp = 0; return KeyTemp; } //light: 0~999 void SetLedRed( u16 light ) { TIM3->CCR2 = light; } void SetLedGreen( u16 light ) { TIM3->CCR3 = light; } void SetLedBlue( u16 light ) { TIM3->CCR4 = light; } //UI00 ?aê????? void UI00( void ) { char cStr[20]; u16 R=0,G=0,B=0; u16 BackColor=0,RBackColor=0,GBackColor=0,BBackColor=0; strType_XPT2046_Coordinate Coordinate; SetLedRed( R ); SetLedGreen( G ); SetLedBlue( B ); //1. ????í?D????? ILI9341_Clear( 0,0,macILI9341_Default_Max_Width,macILI9341_Default_Max_Heigth,macBLACK ); ILI9341_DrawRectangle( 0,115,240,30,RBackColor,1 ); ILI9341_DispString_EN( 12,122,"Red:",RBackColor,macWHITE ); sprintf( cStr,"%03d",(int)R ); ILI9341_DispString_EN( 138,122,cStr,RBackColor,macWHITE ); ILI9341_DrawRectangle( 0,145,240,30,GBackColor,1 ); ILI9341_DispString_EN( 12,152,"Green:",GBackColor,macWHITE ); sprintf( cStr,"%03d",(int)G ); ILI9341_DispString_EN( 138,152,cStr,GBackColor,macWHITE ); ILI9341_DrawRectangle( 0,175,240,30,BBackColor,1 ); ILI9341_DispString_EN( 12,182,"Blue:",BBackColor,macWHITE ); sprintf( cStr,"%03d",(int)B ); ILI9341_DispString_EN( 138,182,cStr,BBackColor,macWHITE ); //2. ′¥?á2ù×÷ while(1) { if ( ucXPT2046_TouchFlag == 1 ) //è?1?óD′¥?t { SetLedRed( 500 ); if ( XPT2046_Get_TouchedPoint ( & Coordinate, & strXPT2046_TouchPara ) ) //??è?′¥?tμ?μ?×?±ê { SetLedGreen( 500 ); if( Coordinate.y>=115 && Coordinate.y<145 ) { R = Coordinate.x * 25 / 6; RBackColor = (Coordinate.x*2/15)<<11; BackColor = RBackColor | GBackColor | BBackColor; SetLedRed( R ); ILI9341_DrawRectangle( 0,115,240,30,RBackColor,1 ); ILI9341_DispString_EN( 12,122,"Red:",RBackColor,macWHITE ); sprintf( cStr,"%03d",(int)R ); ILI9341_DispString_EN( 138,122,cStr,RBackColor,macWHITE ); ILI9341_DrawRectangle( 0,0,240,115,BackColor,1 ); ILI9341_DrawRectangle( 0,205,240,115,BackColor,1 ); } else if( Coordinate.y>=145 && Coordinate.y<175 ) { G = Coordinate.x * 25 / 6; GBackColor = (Coordinate.x*4/15)<<5; BackColor = RBackColor | GBackColor | BBackColor; SetLedGreen( G ); ILI9341_DrawRectangle( 0,145,240,30,GBackColor,1 ); ILI9341_DispString_EN( 12,152,"Green:",GBackColor,macWHITE ); sprintf( cStr,"%03d",(int)G ); ILI9341_DispString_EN( 138,152,cStr,GBackColor,macWHITE ); ILI9341_DrawRectangle( 0,0,240,115,BackColor,1 ); ILI9341_DrawRectangle( 0,205,240,115,BackColor,1 ); } else if( Coordinate.y>=175 && Coordinate.y<205 ) { B = Coordinate.x * 25 / 6; BBackColor = Coordinate.x*2/15; BackColor = RBackColor | GBackColor | BBackColor; SetLedBlue( B ); ILI9341_DrawRectangle( 0,175,240,30,BBackColor,1 ); ILI9341_DispString_EN( 12,182,"Blue:",BBackColor,macWHITE ); sprintf( cStr,"%03d",(int)B ); ILI9341_DispString_EN( 138,182,cStr,BBackColor,macWHITE ); ILI9341_DrawRectangle( 0,0,240,115,BackColor,1 ); ILI9341_DrawRectangle( 0,205,240,115,BackColor,1 ); } } Delay(100000); } } } u8 IsYunNian( int Years ) { if((Years%4==0&&Years%100!=0)||Years%400==0) { return 1; } else { return 0; } } void settime(int nian,int yue,int ri,int shi,int feng,int miao) { int MaxDay[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int count=0; int countn=0; int county=0; int countr=0; int counts=0; int countf=0; int countm=0; int i=1970; int k=1; if(nian>=1970 && nian<=2099) { while(i<nian) { if(IsYunNian(i)==1) { countn=countn+31622400; i++; } else { countn=countn+31536000; i++; } } if(IsYunNian(nian)==1) { MaxDay[2]=29; } else { MaxDay[2]=28; } while(k<yue) { county=county+(MaxDay[k])*86400; k=k+1; } countr=countr+(ri-1)*86400; counts=counts+shi*3600; countf=countf+feng*60; countm=countm+miao*1; } count=count+countn+county+countr+counts+countf+countm; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); RTC_SetCounter(count); } void UI01( void ) { // char cstr[20]; char buff[20]; char buff_1[20]; char buff_2[20]; char buff_3[20]; char buff_4[20]; char buff_5[20]; char buff_6[20]; int counter=0; char dd='/'; int Year,Month,Date,Hour=0,Min=0,Sec=0,Days; int MaxDays[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; settime(2018,9,8,7,8,9); //???????? //3ìDò1|?ü while(1) { counter = RTC_GetCounter(); // sprintf(buff_6,"%d",counter); // ILI9341_DispString_EN_48(0,0, buff_6,macWHITE,macBLACK); // if(RTCItSecStatus) // counter = RTC_GetCounter(); Year = 1970; Month = 1; Date = 1; Days = counter/86400; if(Days>=1) { while(Days>=365) { if(IsYunNian(Year)==1) { if(Days>=366) { Days-=366; Year++; } } else { Days-=365; Year++; } } if(IsYunNian(Year)==1) { MaxDays[2]=29; } else { MaxDays[2]=28; } while(Days>=MaxDays[Month]) { // if(IsYunNian(Year)==1) // { // if(Month==2) // { // Days-=29; // Month++; // } // Days-=MaxDays[Month]; // Month++; // } Days-=MaxDays[Month]; Month=Month+1; } Date=Days+1; // Days=0; Hour=counter%86400/3600; Min=counter%86400%3600/60; Sec=counter%86400%3600%60; } else { Date=1; Hour=counter%86400/3600; Min=counter%86400%3600/60; Sec=counter%86400%3600%60; } // ret=IsYunNian(Year); // sprintf(cstr,"%d",ret); // ILI9341_DispString_EN_48(0,250, cstr,macWHITE,macBLACK); sprintf(buff,"%d",Year); sprintf(buff_6,"%c",dd); ILI9341_DispString_EN_48(0,70, buff,macWHITE,macBLACK); ILI9341_DispString_EN_48(100,70, buff_6,macWHITE,macBLACK); sprintf(buff_1,"%0.2d",Month); ILI9341_DispString_EN_48(120,70, buff_1,macWHITE,macBLACK); ILI9341_DispString_EN_48(165,70, buff_6,macWHITE,macBLACK); sprintf(buff_2,"%0.2d",Date); ILI9341_DispString_EN_48(185,70, buff_2,macWHITE,macBLACK); sprintf(buff_3,"%0.2d",Hour); ILI9341_DispString_EN_48(20,120, buff_3,macWHITE,macBLACK); ILI9341_DispString_EN_48(65,120, buff_6,macWHITE,macBLACK); sprintf(buff_4,"%0.2d",Min); ILI9341_DispString_EN_48(90,120, buff_4,macWHITE,macBLACK); ILI9341_DispString_EN_48(135,120, buff_6,macWHITE,macBLACK); sprintf(buff_5,"%0.2d",Sec); ILI9341_DispString_EN_48(160,120, buff_5,macWHITE,macBLACK); } }
2.main 主程序
#include "stm32f10x.h" #include "bsp_lcd.h" #include "fatfs_flash_spi.h" #include "bsp_usart1.h" #include "pic.h" #include <stdio.h> #include "screendirection.h" #include "ui.h" #define LEDBLUE_ON GPIO_ResetBits(GPIOB, GPIO_Pin_1) #define LEDBLUE_OFF GPIO_SetBits(GPIOB, GPIO_Pin_1) #define LEDGREEN_ON GPIO_ResetBits(GPIOB, GPIO_Pin_0) #define LEDGREEN_OFF GPIO_SetBits(GPIOB, GPIO_Pin_0) #define LEDRED_ON GPIO_ResetBits(GPIOB, GPIO_Pin_5) #define LEDRED_OFF GPIO_SetBits(GPIOB, GPIO_Pin_5) extern u8 UICnt; void Delay(u32 Cnt) { while(--Cnt); } void GPIO_Configration() { GPIO_InitTypeDef GPIO_InitStructure; //±?D??è?a??ê±?ó?ù????òy?? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC ,ENABLE); // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_5; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOC, &GPIO_InitStructure); // LEDBLUE_OFF;LEDGREEN_OFF;LEDRED_OFF; } u8 KeyScan() { u8 key; if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) && (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1)) key = 3; else if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0) && (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1)) key = 2; else if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) && (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==0)) key = 1; else key = 0; return key; } // /** // * @brief LCD′¥?t?áD£×??ò′óía2?flash?áè?D£×??μêy // * @param ?T // * @retval ?T // */ // void Flash_TouchCalibrate ( void ) // { // uint8_t ucStoreFlag,FlagWord; //LCD′¥?t?áD£×??μêy′?′¢±ê?? // // #if ScreenDirection==1 // FlagWord = 0x53; // #elif ScreenDirection==2 // FlagWord = 0x54; // #endif // // // SPI_FLASH_ReadDeviceID(); // Get SPI Flash Device ID */ // // SPI_FLASH_BufferRead ( & ucStoreFlag, 0, 1 ); //′óía2?flash?á3?LCD′¥?t?áD£×??μêy′?′¢±ê?? // // if ( ucStoreFlag == FlagWord ) //ò?′?′¢1yLCD′¥?t?áD£×??μêy // SPI_FLASH_BufferRead ( ( void * ) & strXPT2046_TouchPara, 1, sizeof ( strXPT2046_TouchPara ) ); //?ìD??áè?LCD′¥?t?áD£×??μêy // // else //éD?′′?′¢1yLCD′¥?t?áD£×??μêy // { // while( ! XPT2046_Touch_Calibrate () ); //μè′y′¥?t?áD£?yíê±? // /* ′?′¢LCD′¥?t?áD£×??μêyoí±ê?? */ // ucStoreFlag = FlagWord; // SPI_FLASH_SectorErase ( 0 ); // SPI_FLASH_BufferWrite ( & ucStoreFlag, 0, 1 ); // SPI_FLASH_BufferWrite ( ( void * ) & strXPT2046_TouchPara, 1, sizeof ( strXPT2046_TouchPara ) ); // } // // } void TIM3_Configuration( void ) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; GPIO_InitTypeDef GPIO_InitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // ê?3?±è??í¨μà GPIO 3?ê??ˉ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); //??ó3é?PB5?aTIM3_CH2òy?? //μ±??óD??ó3é?ê±£?TIM3μ?????í¨μàCH1£?CH2£?CH3£?CH4·?±e??ó|PA6£?PA7,PB0,PB1 //μ±2?·???ó3é?ê±£?TIM3μ?????í¨μàCH1£?CH2£?CH3£?CH4·?±e??ó|PB4£?PB5,PB0,PB1 //μ±íêè???ó3é?ê±£?TIM3μ?????í¨μàCH1£?CH2£?CH3£?CH4·?±e??ó|PC6£?PC7,PC8,PC9 // GPIO_AFIODeInit(); GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3 ,ENABLE ); RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3 , ENABLE ); // ?ù±??¨ê±?÷????£??ü?ú1ms£???êy?ü?ú1000 TIM_TimeBaseStructure.TIM_Period = 999; TIM_TimeBaseStructure.TIM_Prescaler = 71; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;// ê±?ó·??μòò×ó TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;// ??êy?÷??êy?£ê?£?éè???a?òé???êy TIM_TimeBaseInit( TIM3 , &TIM_TimeBaseStructure); // ?????aPWM?£ê? TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // D?óú???TóDD§ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // ê1?üê?3? TIM_OCInitStructure.TIM_Pulse = 0; // éè??????±è′óD? TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // óDD§μ????aμí TIM_OC2Init( TIM3 , &TIM_OCInitStructure ); TIM_OC3Init( TIM3 , &TIM_OCInitStructure ); TIM_OC4Init( TIM3 , &TIM_OCInitStructure ); //ê1?üTIM3 ?ú CCR2,3,4 é?μ??¤×°????′??÷ TIM_OC2PreloadConfig( TIM3 , TIM_OCPreload_Enable ); TIM_OC3PreloadConfig( TIM3 , TIM_OCPreload_Enable ); TIM_OC4PreloadConfig( TIM3 , TIM_OCPreload_Enable ); // ê1?ü??êy?÷ TIM_Cmd( TIM3 , ENABLE ); } void TIM6_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //ê1?üê±?ó RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //???′3?ê?éè?? TIM_DeInit(TIM6); //?¨ê±?÷éè?? TIM_TimeBaseStructure.TIM_Prescaler = 7199; TIM_TimeBaseStructure.TIM_Period = 99; TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); //ê1?ü?D?? TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); //ê1?ü?¨ê±?÷ // TIM_Cmd(TIM6, ENABLE); } void NVIC_Configuration(void) //??ì×?òá??D???????÷???? { NVIC_InitTypeDef NVIC_InitStructure; //????ó??è??×é±e 1???à??ó??è?? 3??×óó??è?? NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //éè??TIM6?D?? //1???à??ê?ó??è??,0???±ó??è??,ê1?ü?D?? NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //éè??RTC?D?? //1???à??ê?ó??è??,0???±ó??è??,ê1?ü?D?? NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void RTC_Configuration(void) { RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); BKP_DeInit(); RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); RTC_WaitForSynchro(); RTC_WaitForLastTask(); RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_WaitForLastTask(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); PWR_BackupAccessCmd(DISABLE); } int main(void) { GPIO_Configration(); LCD_Init(); ILI9341_Clear( 0,0,macILI9341_Default_Max_Width,macILI9341_Default_Max_Heigth,macWHITE ); FLASH_SPI_initialize(); // Flash_TouchCalibrate(); TIM6_Configuration(); TIM3_Configuration(); RTC_Configuration(); NVIC_Configuration(); UICnt = 1; while(1) { switch(UICnt) { case 0: UI00();break; case 1: UI01();break; default: break; } } }
猜你喜欢
- 2024-09-16 手机“满血复活”时间从数小时到几分钟 技术进步让大众告别充电焦虑
- 2024-09-16 51单片机AD模数转换,使用SPI通信方式
- 2024-09-16 正点原子STM32F4/F7水星开发板资料连载第三十五章 触摸屏实验
- 2024-09-16 正点原子开拓者 Nios II资料连载第十二章MCU TFT-LCD画板实验
- 2024-09-16 正点原子开拓者NiosII资料连载第二十七章GUI综合实验
- 2024-09-16 「正点原子STM32Mini板资料连载」第二十六章 触摸屏实验
- 2024-09-16 串行交互程序设计基于STM32103VET6
- 2024-09-16 Labview实验二十:触摸屏实验(labview自动触发按键)
- 2024-09-16 探索者 STM32F407 开发板资料连载第三十三章 触摸屏实验
- 2024-09-16 基于STM32设计的数码相册(stm32电子相册毕业设计论文)
你 发表评论:
欢迎- 05-21外贸人必备8个效率外贸工具合集
- 05-21Dify实战:解除Dify知识库上传文件15MB限制的
- 05-21腾讯云国际站:怎样优化TCP传输效率?
- 05-21电脑文件怎么压缩
- 05-21手机扩容新方案,搭配腾隐P2000移动固态硬盘,还可以在再战几年
- 05-21如何安全的传输文件(2)
- 05-21前端大文件秒传黑科技!程序员集体沸腾
- 05-21128GB内存8060S最强核显!极摩客EVO-X2 Max+ 395开箱
- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)