51单片机写 红外程序,由外部中断0 INT0下降沿进入红外程序,那么我想问在什么时候或是是什么引起

51单片机写 红外程序,由外部中断0 INT0下降沿进入红外程序,那么我想问在什么时候或是是什么引起,第1张

这个看你的电路了,你的外部接的什么传感器?光电的还是霍尔的?也就是接到单片机INT0(p32)引脚的那个信号。

那中断信号就来自红外接收的二极管,比如下面这个电路,收到信号后通过三极管产生一个低电平(下降沿)送到单片机中。

给你一个PIC写的接收红外遥控器的程序。

//

//mcu: PIC16F883

//author:

//data:

//ver: 10

//

#include <pich>

#include <pic16f887h>

#include "mainh"

// 函数声明部份

void interrupt IRQ_TEST(void);

void fun_intset(void);

void set_port(void);

void fun_timerset(void);

void delay_10us(void);

void delay_130us(void);

void test_remote(void);

// 主函数

void main()

{

set_port();

fun_timerset();

fun_intset();

delay_10ms();

ram_ini();

GIE=1;

while(1)

{

asm("clrwd");

test_remote();

}

}

//端口I/O定义子程序

void set_port()

{

ANSEL =0X00; //porta io port

ANSELH=0X00; //portb io port

//TRISX BIT=1, PORTX AS INPUT

TRISA = 0x0F; //RA0-RA3 INPUT ,RA4-RA5 OUTPUT

TRISB = 0x07; //RB0 PASS0, RB1-RB2 INPUT ,RB3-RB6 OUTPUT

TRISC = 0x0F;

// TRISC = 0x03; //RC0-RC1 INPUT,RC5-RC6 OUTPUT , RC3 RC4 EEPROM SCL SDA

PORTC=0;

PORTA=0XFF;

// WPUB=0XFF;

PORTB=0X07;

}

//中断子程序

void interrupt IRQ_TEST(void)

{

if(T0IF) //Timer0中断服务子程序

{

TMR0=0xce;

T0IF=0;

timer_100us++; //100us

}

if(INTF==1)

{

INTF=0;

timer_rec=timer_100us;

timer_100us=0;

flag_rec_remote=1;

}

}

//定时器0初始化设置子程序

void fun_timerset()

{

//Timer0初始化设置

PSA=0;//Timer0 使用预分频器

//Timer0选择分频率为1:2

PS0=0;PS1=0;PS2=0;

//内部时钟定时方式,定时时间:200uS,误差:0uS

T0CS=0;

// TMR0=0x9b;

TMR0=0xce; //100us

}

/

//定时器2初始化设置子程序

void fun_timer2set()

{

//Timer2初始化设置

//timer2使用预分频率1:1

T2CKPS0=0;T2CKPS1=0;

//timer2使用后分频率1:1

TOUTPS0=0;

TOUTPS1=0;

TOUTPS2=0;

TOUTPS3=0;

//定时器2定时时间为:200uS,误差:0uS

TMR2=0x38;

TMR2ON=1;

}

/

//中断允许设置子程序

void fun_intset()

{

T0IE=1;//Tiemr0中断允许

INTEDG=0; //RB0 FALLAGE INTERRUPT

INTE=1;

INTF=0;

}

void ram_ini(void)

{

}

//------------------------------------------------------------

//

void delay_10us(void)

{

NOP;

NOP;

NOP;

NOP;

NOP;

NOP;

}

void delay_130us(void)

{

uchar i;

for(i=0;i<13;i++)

{

NOP;

NOP;

NOP;

}

}

void delay_10ms(void)

{

unsigned int i;

for(i=0;i<1000;i++)

{

NOP;

NOP;

NOP;

NOP;

NOP;

}

}

void test_remote(void)

{

uchar rec_ok,i;

if(flag_rec_remote==1)

{

flag_rec_remote=0;

// remote_buf[rec_byte]=timer_rec; //test use

// rec_byte++; //test use

// return; //test use

if(flag_rec_head==0)

{

if(timer_rec>=90&&timer_rec<=140) //135

{

flag_rec_head=1;

rec_byte=0;

rec_bit=0;

rec_buf=0;

return;

}

}

else

{

if(timer_rec>=8&&timer_rec<=12) //112

{

rec_buf=(rec_buf>>1);

rec_buf=rec_buf&0x7f;

}

else if(timer_rec>=18&&timer_rec<=22) //22

{

rec_buf=(rec_buf>>1);

rec_buf=rec_buf|0x80;

}

else if(timer_rec>=90&&timer_rec<=140)

{

flag_rec_head=1;

rec_byte=0;

rec_bit=0;

rec_buf=0;

return;

}

else

{

flag_rec_head=0;

rec_byte=0;

rec_bit=0;

rec_buf=0;

return;

}

}

if(flag_rec_head==1)

{

rec_bit++;

if(rec_bit==8)

{

remote_buf[rec_byte]=rec_buf;

rec_byte++;

rec_bit=0;

if(rec_byte==4)

{

NOP;

NOP;

NOP;

NOP;

rec_byte=0;

rec_bit=0;

rec_buf=0;

flag_rec_head=0;

}

}

}

}

}

#include<reg52h> //包含单片机寄存器的头文件

#include<intrinsh> //包含_nop_()函数定义的头文件

sbit IR=P3^2; //将IR位定义为P32引脚

sbit RS=P2^0; //寄存器选择位,将RS位定义为P20引脚

sbit RW=P2^1; //读写选择位,将RW位定义为P21引脚

sbit E=P2^2; //使能信号位,将E位定义为P22引脚

sbit BF=P0^7; //忙碌标志位,,将BF位定义为P07引脚

sbit BEEP = P3^6; //蜂鸣器控制端口P36

unsigned char flag;

unsigned char code string[ ]= {"1602IR-CODE TEST"};

unsigned char a[4]; //储存用户码、用户反码与键数据码、键数据反码

unsigned int LowTime,HighTime; //储存高、低电平的宽度

/

函数功能:延时1ms

/

void delay1ms()

{

unsigned char i,j;

for(i=0;i<10;i++)

for(j=0;j<33;j++)

;

}

/

函数功能:延时若干毫秒

入口参数:n

/

void delay(unsigned char n)

{

unsigned char i;

for(i=0;i<n;i++)

delay1ms();

}

//

void beep() //蜂鸣器响一声函数

{

unsigned char i;

for (i=0;i<100;i++)

{

delay1ms();

BEEP=!BEEP; //BEEP取反

}

BEEP=1; //关闭蜂鸣器

delay(250); //延时

}

/

函数功能:判断液晶模块的忙碌状态

返回值:result。result=1,忙碌;result=0,不忙

/

unsigned char BusyTest(void)

{

bit result;

RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态

RW=1;

E=1; //E=1,才允许读写

_nop_(); //空 *** 作

_nop_();

_nop_();

_nop_(); //空 *** 作四个机器周期,给硬件反应时间

result=BF; //将忙碌标志电平赋给result

E=0;

return result;

}

/

函数功能:将模式设置指令或显示地址写入液晶模块

入口参数:dictate

/

void WriteInstruction (unsigned char dictate)

{

while(BusyTest()==1); //如果忙就等待

RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令

RW=0;

E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E从0到1发生正跳变,所以应先置"0"

_nop_();

_nop_(); //空 *** 作两个机器周期,给硬件反应时间

P0=dictate; //将数据送入P0口,即写入指令或地址

_nop_();

_nop_();

_nop_();

_nop_(); //空 *** 作四个机器周期,给硬件反应时间

E=1; //E置高电平

_nop_();

_nop_();

_nop_();

_nop_(); //空 *** 作四个机器周期,给硬件反应时间

E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令

}

/

函数功能:指定字符显示的实际地址

入口参数:x

/

void WriteAddress(unsigned char x)

{

WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"

}

/

函数功能:将数据(字符的标准ASCII码)写入液晶模块

入口参数:y(为字符常量)

/

void WriteData(unsigned char y)

{

while(BusyTest()==1);

RS=1; //RS为高电平,RW为低电平时,可以写入数据

RW=0;

E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E从0到1发生正跳变,所以应先置"0"

P0=y; //将数据送入P0口,即将数据写入液晶模块

_nop_();

_nop_();

_nop_();

_nop_(); //空 *** 作四个机器周期,给硬件反应时间

E=1; //E置高电平

_nop_();

_nop_();

_nop_();

_nop_(); //空 *** 作四个机器周期,给硬件反应时间

E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令

}

/

函数功能:对LCD的显示模式进行初始化设置

/

void LcdInitiate(void)

{

delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间

WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口

delay(5); //延时5ms 

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x0C); //显示模式设置:显示开,有光标,光标闪烁

delay(5);

WriteInstruction(0x06); //显示模式设置:光标右移,字符不移

delay(5);

WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除

delay(5);

}

/

函数功能:对4个字节的用户码和键数据码进行解码

说明:解码正确,返回1,否则返回0

出口参数:dat

/

bit DeCode(void)

{

unsigned char i,j;

unsigned char temp; //储存解码出的数据

for(i=0;i<4;i++) //连续读取4个用户码和键数据码

{

for(j=0;j<8;j++) //每个码有8位数字

{

temp=temp>>1; //temp中的各数据位右移一位,因为先读出的是高位数据

TH0=0; //定时器清0

TL0=0; //定时器清0

TR0=1; //开启定时器T0

while(IR==0) //如果是低电平就等待

; //低电平计时

TR0=0; //关闭定时器T0

LowTime=TH0256+TL0; //保存低电平宽度

TH0=0; //定时器清0

TL0=0; //定时器清0

TR0=1; //开启定时器T0

while(IR==1) //如果是高电平就等待

;

TR0=0; //关闭定时器T0

HighTime=TH0256+TL0; //保存高电平宽度

if((LowTime<370)||(LowTime>640))

return 0; //如果低电平长度不在合理范围,则认为出错,停止解码

if((HighTime>420)&&(HighTime<620)) //如果高电平时间在560微秒左右,即计数560/1085=516次

temp=temp&0x7f; //(520-100=420, 520+100=620),则该位是0

if((HighTime>1300)&&(HighTime<1800)) //如果高电平时间在1680微秒左右,即计数1680/1085=1548次

temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是1

}

a[i]=temp; //将解码出的字节值储存在a[i]

}

if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码

return 1; //解码正确,返回1

}

/------------------二进制码转换为压缩型BCD码,并显示---------------/

void two_2_bcd(unsigned char date)

{

unsigned char temp;

temp=date;

date&=0xf0;

date>>=4; //右移四位得到高四位码

date&=0x0f; //与0x0f想与确保高四位为0

if(date<=0x09)

{

WriteData(0x30+date); //lcd显示键值高四位

}

else

{

date=date-0x09;

WriteData(0x40+date);

}

date=temp;

date&=0x0f;

if(date<=0x09)

{

WriteData(0x30+date); //lcd显示低四位值

}

else

{

date=date-0x09;

WriteData(0x40+date);

}

WriteData(0x48); //显示字符'H'

}

/

函数功能:1602LCD显示

/

void Disp(void)

{

WriteAddress(0x40); // 设置显示位置为第一行的第1个字

two_2_bcd(a[0]);

WriteData(0x20);

two_2_bcd(a[1]);

WriteData(0x20);

two_2_bcd(a[2]);

WriteData(0x20);

two_2_bcd(a[3]);

}

/

函数功能:主函数

/

void main()

{

unsigned char i;

LcdInitiate(); //调用LCD初始化函数

delay(10);

WriteInstruction(0x01);//清显示:清屏幕指令

WriteAddress(0x00); // 设置显示位置为第一行的第1个字

i = 0;

while(string[i] != '\0') //'\0'是数组结束标志

{ // 显示字符 >

#include<reg52h>

#include<intrinsh>

#define uchar unsigned char

#define uint unsigned int

sbit lcden = P2^7;

sbit lcdrs = P2^6;

sbit lcdwr = P2^5;

sbit IR = P3^2;

uchar IRCOM[6];//数组,用于存储红外编码

uchar code table1[] = "remote control";

uchar code table2[] = "CODE:";

void delayms(uchar x)// 延时x014ms

{

uchar i;

while(x--)

for(i=0;i<13;i++){}

}

void delay(uchar x) //延时xms

{

uchar i,j;

for(i=x;i>0;i--)

for(j=110;j>0;j--);

}

/LCD部分/

void write_com(uchar com)

{

lcden = 0;

lcdrs = 0;

lcdwr = 0;

P0 = com;

delay(5);

lcden = 1;

delay(5);

lcden = 0; //别忘了lcden拉低

}

void write_date(uchar date)

{

lcden = 0;

lcdrs = 1;

lcdwr = 0;

P0 = date;

delay(5);

lcden = 1;

delay(5);

lcden = 0;

}

void lcd_init(void)

{

lcden = 0;

lcdrs = 0;

lcdwr = 0;

delay(5);

write_com(0x38);

write_com(0x0c);

write_com(0x06);

write_com(0x01);

}

/main()/

void main(void)

{

uchar count=0;

IR = 1;

lcd_init();

write_com(0x80);

while(table1[count]!='\0')

{

write_date(table1[count]);

count++;

delay(5);

}

count = 0;

write_com(0x80+0x40);

while(table2[count]!='\0')

{

write_date(table2[count]);

count++;

delay(5);

}

IE = 0x81; //开中断

TCON = 0x01;//脉冲负边沿触发

while(1);

}

/红外中断/

void IR_time() interrupt 0

{

uchar i,j,TimeNum=0;//TimeNum用来计IR高电平次数 从而判断是0还是1

EX0 = 0; //关闭中断

delayms(5);

if(1 == IR)

{

EX0 = 1;

return;

}

while(!IR) //跳过9ms前导低电平

delayms(1);

for(i=0;i<4;i++)

{

for(j=0;j<8;j++)

{

while(IR) //跳过45ms的前导高电平

delayms(1);

while(!IR) //跳过056ms的低电平

delayms(1);

while(IR)

{

TimeNum++; //计时高电平时间从而判断读取的是0还是1

delayms(1);

}

if(TimeNum>=30)//按键按下时间过长 跳过

{

EX0 = 1;

return;

}

IRCOM[i] = IRCOM[i]>>1;

if(TimeNum >= 8) //8014ms 这时读取的是1;

{

IRCOM[i] = IRCOM[i]|0x80;

}

TimeNum = 0;

}

}

if(IRCOM[2]!=~IRCOM[3])//判断八位数据和八位数据反码是否相等

{

EX0 = 1;

return;

}

IRCOM[4] = IRCOM[2]&0x0f;//取低四位

IRCOM[5] = IRCOM[2]>>4; //IRCOM[5]取IRCOM[2]高四位

if(IRCOM[4] > 9) //转换成字符

{

IRCOM[4] = IRCOM[4] + 0x37;

}

else

IRCOM[4] = IRCOM[4] + 0x30;

if(IRCOM[5] > 9)

{

IRCOM[5] = IRCOM[5] + 0x37;

}

else

IRCOM[5] = IRCOM[5] + 0x30;

delay(5);

write_com(0x80 + 0x40 + 5);

write_date(IRCOM[5]);

write_date(IRCOM[4]);

EX0 = 1; //重新开启外部中断

}

#include<reg51h>

#include <intrinsh>

#define uchar unsigned char

#define uint unsigned int

#define ulong unsigned long

#define Nop() {_nop_(); _nop_(); _nop_(); _nop_(); _nop_();}

volatile ulong IRcode=0x00000000; //32位的键代码

volatile ulong Irdcode=0x00000000;

volatile uint customcode=0x0000; //16位用户码

volatile uint time_us=0x0000; //两个下降沿之间的时间

volatile uchar timeH,timeL; //保存TH1 TL的值

uchar Lcustomcode; //低8用户码

uchar Hcustomcode; //高8

uchar datacode; //8位键数据码

uchar mycode;

uchar Rdatacode; //8位键数据反码

uchar uc1ms;

uchar uc10ms;

uchar uc3ms;

uchar ucDispTime;

uchar ucDispOrder;

uchar ucDispCon;

uchar ucSpeakerTime;

unsigned char code LedData[16] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

unsigned char code LedCon[2] = {0x8f,0x4f};

unsigned char ucDispData[2]; // 存放显示数据

sbit led1 = P3^7;

sbit led2 = P3^6;

sbit power=P1^0; //电源开关

sbit BEEP= P2^1;

bit NewIRcode=0; //指示当处理完了32位码后,就有了新的遥控码

bit DataRight=0; //为1时读取数据正确

bit bSampleOk;

bit bSampling;

bit b10msInt;

bit b1msInt;

bit bKeySound;

bit b1msMain;

bit IR_E; //表示有新的遥控键控下就更新扫描数据

bit b3msint;

void SendDataToDispDevice();

void Ir_process();

void display();

void beeping();

/ 晶振为12 MHZ/

/定时器1,12 MHZ最大定时为6553ms/

//------------------------------------------------------------------------------

void init()

{

IP=0x09; //定时器1,外部中断0优先级高

TMOD=0x11; //定时器0,工作方式1 ; 定时器1,工作方式1

TCON=0x01; //外中断0下降沿触发,(包括TR1=0,TR0=0)

TH0=0xff; //初始化定时器0,定时02ms

TL0=0x47;

TH1=0x00; //初始化定时器1

TL1=0x00;

EA=1; //开全中断

ET0=1; //开放T0中断

ET1=1; //开放T1中断

EX0=1; //开放INT0

TR1=0;

TR0=1;

}

//--------------------------------------

void TimeProg(void)

{

b1msMain = b1msInt;

b1msMain=0;

b10msInt = 0;

if(b1msInt == 1)

{

b1msMain=1;

if(++uc10ms == 10)

{

uc10ms = 0;

b10msInt = 1;

if(bKeySound==1)

{ beeping();

bKeySound=0;

}

}

}

}//void TimeProg(void)

//-------------------------------------interrupt0-------------------------------------

void IR_ISR() interrupt 0 using 1 //遥控器中断处理函数

{

static uchar cn;

TR1=0;

timeH=TH1;

timeL=TL1;

TH1=0;

TL1=0;

TR1=1; //开定时器中断1

time_us=(unsigned int)timeH;

time_us=time_us<<8;

time_us=time_us|timeL;

if(time_us>12200&&time_us<13000) {cn=1;IRcode=0;} //遇到引导码,就把cn清0,IRcode清0

//引导码的时间长度为9ms+45ms

if(cn<34)

{

if(time_us>950&&time_us<1120) //0

{

IRcode=IRcode|0x00000000;

if(cn<33) IRcode=IRcode>>1;

}

else if(time_us>1920&&time_us<2120) //1t > 1950 && t < 2150

{

IRcode=IRcode|0x80000000;

if(cn<33) IRcode=IRcode>>1;

}

//else if(time_us>10000&&time_us<11000) {Irdcode=IRcode;cn=34; } //遇到重复码

//cn用于记录接收到的数据位

}

cn++;

if(cn==34)

{ NewIRcode=1;

TR1=0;

Irdcode= IRcode; cn=0;

} //读完32位码,则有新码产生

}

//--------------------------------------timer_ISR------------------------------

void Timer0_ISR() interrupt 1 using 2 //定时器0中断函数

{

TR0=0;

TH0=0xff; //初始化定时器0,定时02ms 晶振为110592 MHZ

TL0=0x47;

TR0=1;

if(++uc1ms == 5)

{

uc1ms = 0;

b1msInt=1;

if(++uc3ms==8)

{

uc3ms=0;

b3msint=1;

SendDataToDispDevice(); //n ms送一次显示

}

}

}//void Timer0IntProg() interrupt 1 using 1

void Timer1_ISR() interrupt 3 using 3 //定时器1中断函数

{

TR1=0;

TH1=0x00; //初始化定时器1

TL1=0x00;

TR1=1;

}

//--------------------SendDataToDispDevice----------

void SendDataToDispDevice()

{

unsigned char n;

//watchdog();

if(++ucDispOrder >= 2) ucDispOrder = 0; // 下一显示巡回

// 下面为发送控制数据 位控

if(ucDispOrder==0)

{led1=0;

led2=1;

Nop();

Nop();

}

if(b3msint==1)

{if(ucDispOrder==1)

{led2=0;

led1=1;

Nop();

Nop();

}

}

// 下面为发送显示数据

n = LedData[ucDispData[ucDispOrder]];

P0=n;

} //void SendDataToDispDevice()

//------------------------------------main()----------------------------------------------

void main()

{

init();

beeping();

while(1)

{

TimeProg();

Ir_process();

display();

}

}

void Ir_process()

{

if(NewIRcode==1) //如果有新的遥控码就读

{

NewIRcode=0; //读完之后清零,表示新码已读

customcode=(Irdcode>>16); //取红外码中的按码键

//取低8位用户码

Lcustomcode=customcode>>8;//取低8位按码键

datacode=(unsigned char)(customcode&0x00ff); //取高8位按码键

Rdatacode=Lcustomcode; //取低8位按码键的反码

if(~Rdatacode!=datacode)

{ DataRight=0;

Irdcode=0;

datacode=Rdatacode=0;

} //校验用户码,反码

else

{ DataRight=1;

IR_E=1;

mycode=datacode;}

if(DataRight==1) { bKeySound = 1;DataRight=0; }

}

}

void display()

{

/ unsigned char a[2];

a[0] = mycode & 0x0f;

mycode = mycode >> 4;

a[1] = mycode & 0x0f;

ET0 = 0;

ucDispData[0] = a[0];

ucDispData[1] = a[1];

ET0 = 1;/

if(IR_E==1)

{

ET0 = 0;

ucDispData[0] = mycode & 0x0f;

mycode = mycode >> 4;

ucDispData[1] = mycode & 0x0f;

IR_E=0;

ET0 = 1;

}

}

//

void delay(unsigned char x) //x014MS

{

unsigned char a;

while(x--)

{

for (a = 0; a<13; a++) {;}

}

}

//

void beeping()

{

unsigned char i;

for (i=0;i<100;i++)

{

delay(4);

BEEP=!BEEP; //BEEP取反

}

BEEP=1;

//关闭蜂鸣器

}

这个问题不难解决,在I/O口紧张的情况下,这个方法不失为一个取巧的方式,赞一个。

如果红外信号要进行解码的话这个问题就更好解决了,首先红外码是有规律的按照协议发送的,在程序中也有相应的解码程序。红外信号发送的时间一般都很短,比如nec32位的前导码占用9ms低电平+45ms高电平,32bit码值最大宽度为32(056+225)ms,这样一个发射码大约100ms就完成了,值得注意的是低电平最大的维持时间为9ms左右。如果按键的话,一般按下的时间都会超过10ms的。

编程思路,中断后进入解码程序,如果接收到的是IR信号,正确解码;如果是按键,解码程序解码失败退出转入按键判定,例如维持10ms以上的低电平就可以认为是按键了,连消抖程序都可免了。

我给个思路吧,直接给程序学不到东西的:

1、用NE555设计一个38K——40K的振荡器来驱动红外管,接收端可以用成品红外接收头送给MCU的外中断一个输入口。目的:搞干扰,可以直接用成品接收头。

2、发令q响的同时启动定时器开始计时,在外中断时停止计时即可

当然,这只是简单的单赛道的做法,多赛道要考虑很多问题。

以上就是关于51单片机写 红外程序,由外部中断0 INT0下降沿进入红外程序,那么我想问在什么时候或是是什么引起全部的内容,包括:51单片机写 红外程序,由外部中断0 INT0下降沿进入红外程序,那么我想问在什么时候或是是什么引起、单片机控制红外程序、基于51单片机的红外接收模块的c编程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/10165659.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存