![单片机开源项目之按键可调时电子钟矩阵按键红外遥控按键进行调时_第1页](http://file3.renrendoc.com/fileroot_temp3/2022-1/11/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb0/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb01.gif)
![单片机开源项目之按键可调时电子钟矩阵按键红外遥控按键进行调时_第2页](http://file3.renrendoc.com/fileroot_temp3/2022-1/11/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb0/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb02.gif)
![单片机开源项目之按键可调时电子钟矩阵按键红外遥控按键进行调时_第3页](http://file3.renrendoc.com/fileroot_temp3/2022-1/11/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb0/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb03.gif)
![单片机开源项目之按键可调时电子钟矩阵按键红外遥控按键进行调时_第4页](http://file3.renrendoc.com/fileroot_temp3/2022-1/11/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb0/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb04.gif)
![单片机开源项目之按键可调时电子钟矩阵按键红外遥控按键进行调时_第5页](http://file3.renrendoc.com/fileroot_temp3/2022-1/11/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb0/827ebc1c-3c5a-4a86-bb3b-42c1d2f6cdb05.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、单片机开源项目之按键可调时电子钟 ( 矩 阵按键 +红外遥控按键进行调时 )此程序是基于 51hei 单片机开发板上面写的,如需 要移植到自己的电路上,修改相应的端口即可,开发板 完整的电路图下载 : 点这里(注意:只需要看相关部分即 可如矩阵键盘 数码管 红外等,其他部分可以忽略)/* filemain.c* author :xr* date2014 年 4 月 21 日 22:23:12 - 2014年 4 月 26 日21:22:29* version :V1.2.3brief按键可调时电子钟 ( 矩阵按键 +红外遥控按键进行调 时)单片机 STC89C52RC MC晶振 11.0592
2、MHZ*/#include ;#include "main.h"/*定义结构体来封装从 DS1302中读取的时间和日期和设置到 DS 1 302中的时间和日期 */ struct Time unsigned char year; /DS1302中只存放的是年的低两位字节unsigned char month; unsigned char day;unsigned char hour;unsigned char min;unsigned char sec;unsigned char week;/* 定义结构体时间变量来保存时间和日期 */struct Time timeBuf
3、; / 此处必须用结构体变量 , 不能用 结构体指针否则写入失败 !unsigned char setTimeIndex = 0; / 设置时间状态及设 置光标位置及设置时间位置的索引值 (0 时正常运 行 ,1-12 为设置时间状态 ,1-12 是设置的位置 ) bit flag200ms = 0;unsigned char thr0, tlr0;/红外通信解码的键码和标准PC机编码映射表unsigned char code IrdCodeMap = 0x45, 0x46, 0x47, / 开关 ,Mode, 静音0x44, 0x40, 0x43, /播放 / 暂停 快退 , 快进0x07,
4、 0x15, 0x09, /EQ,减 , 加0x16, 0x19, 0x0D, /0,返回 , U/SD0x0C, 0x18, 0x5E, /1, 2, 30x08, 0x1C, 0x5A, /4, 5, 60x42, 0x52, 0x4A;/7, 8, 9 / 外部变量声明extern bit flagIrd; / 红外数据码值接收完毕标志位extern unsigned char irdCode4; /保存 NEC协议解码的四个字节的数据码 (用户码+用户反码 ,键码+键码反 码)extern void InitLCD1602();extern void LcdShowStr(unsign
5、ed char x, unsignedchar y, unsigned char * str);extern void LcdSetCoursor(unsigned char x, unsigned char y);extern void LcdOpenCoursor();extern void InitDS1302();extern void GetTimeFromDS1302(struct Time * time);extern void SetTimeToDS1302(struct Time * time);extern void KeyDriver();extern void KeyS
6、can();extern void LcdCoursorRight();extern void LcdCoursorLeft();void ConfgiTimer0(unsigned int xms);void RefreshLcdShowTime();extern void ConfigIrdByTimer1();void IrdDrive();void IrdKeyAction();extern void SetTimeBcdByte(unsigned char keyNum);/* 主程序 main()*/void main()unsigned char psec = 0xFF;/ 用于
7、检测 sec 秒是否 变化 , 若变化则刷新时间显示ConfgiTimer0(1); /定时 1msConfigIrdByTimer1();/ 配置红外通信InitLCD1602();InitDS1302();/* 液晶初始化显示 */LcdShowStr(1, 0, "*");LcdShowStr(2, 0, "20 - - ");LcdShowStr(12, 0, "*");LcdShowStr(14, 0, "-");LcdShowStr(0, 1, "time: -:-:-");whil
8、e (1)KeyDriver();/检测按键动作if (flagIrd)flagIrd = 0;IrdKeyAction();/ 检测红外按键动作if (flag200ms = 1 & (setTimeIndex = 0) /每 200ms 且 setTimeIndex=0 处于非设定时间状态时刷新 一次时间显示flag200ms = 0;GetTimeFromDS1302(&timeBuf);/ 从 DS1302中获取时间到 timeBuf 结构体指针变量的成员中if (timeBuf.sec != psec) /当前秒值和上一次的秒值不相等RefreshLcdShowTime();/ 刷新
9、时间显示psec = timeBuf.sec;/ 备份当前的秒值 ( 秒寄存器值 )/* 定时器 T0 配置 */void ConfgiTimer0(unsigned int xms)unsigned long tmp;tmp = 11059200/12;/ 周期频率tmp = (tmp * xms) / 1000;/ 定时 xms 需要的计数 值tmp = 65536-tmp;/ 定时装入的初值thr0 = (unsigned char)(tmp ; 8);tlr0 = (unsigned char)tmp;TMOD &= 0xF0;/ 清零 T0 控制位TMOD |= 0x01;/T0 方
10、式 1,16 位可设定时模式TH0 = thr0;TL0 = tlr0;TR0 = 1;ET0 = 1;EA = 1;/*将一个BCD码字节数据分解显示到LCD1602的(x, y)坐标上 */void LcdShowBCDByte(unsigned char x, unsigned char y, unsigned char bcdbyte)unsigned char str4;数字 +1 和 -1*取BCD码的第显示年显示星*以下函数功能是 BCD码字节的高位和低位四位字节str1 = (bcdbyte & 0x0F) + 0;/ 四位字节str2 = 0;LcdShowStr(x, y,
11、 str);/*刷新时间显示到 LCD1602液晶上*/void RefreshLcdShowTime()LcdShowBCDByte(4, 0, timeBuf.year); /LcdShowBCDByte(7, 0, timeBuf.month);LcdShowBCDByte(10, 0, timeBuf.day);LcdShowBCDByte(6, 1, timeBuf.hour);LcdShowBCDByte(9, 1, timeBuf.min);LcdShowBCDByte(12, 1, timeBuf.sec);LcdShowBCDByte(14, 0, timeBuf.week)
12、; / 期/*递增BCD码的高位数字*/ unsigned char IncrementBCDByteHigh(unsigned char bcdbyte)if (bedbyte & OxFO) ; 0)/1取 BCD码字节的高四位字节bedbyte -= 0x10; /高四位字节数字 -1else/ 到 0 归 9bedbyte |= 0x90; / 或 bedbyte &= 0x9Freturn (bedbyte);/*递减BCD码数据字节的低字节数字 */unsigned char DescBCDByteLow(unsigned char bcdbyte) if (bcdbyte & 0
13、x0F) ; 0)bcdbyte -= 0x01;/ 低位数字 -1else/ 到 0 归 9bcdbyte |= 0x09;return (bcdbyte);/* 根据 setTimeIndex 的值来设置光标闪烁的位置 */ void LcdRefreshSetCoursor()switch (setTimeIndex)十位数字case 2: LcdSetCoursor(5, 0); break;case 3: LcdSetCoursor(7, 0); break;case 4: LcdSetCoursor(8, 0); break;case 5: LcdSetCoursor(10, 0)
14、; break;case 6: LcdSetCoursor(11, 0); break;case 7: LcdSetCoursor(6, 1); break;case 8: LcdSetCoursor(7, 1); break;case 9: LcdSetCoursor(9, 1); break;case 10: LcdSetCoursor(10, 1); break;case 11: LcdSetCoursor(12, 1); break;case 12: LcdSetCoursor(13, 1); break;default: break;LcdOpenCoursor();/* 递增光标闪
15、烁位置的时间值 */void IncTimeBysetTimeIndex()switch (setTimeIndex)case 1: timeBuf.year =IncrementBCDByteHigh(timeBuf.year);break;/year10+ 年的十位数字 +case 2: timeBuf.year =IncrementBCDByteLow(timeBuf.year);break;/ 年的个位数字 +case 3: timeBuf.month =月十月个IncrementBCDByteHigh(timeBuf.month); break;/ 位+case 4: timeBuf
16、.month =IncrementBCDByteLow(timeBuf.month); break;/ 位+case 5: timeBuf.day= IncrementBCDByteHigh(timeBuf.day);break;case 6: timeBuf.day= IncrementBCDByteLow(timeBuf.day);break;case 7: timeBuf.hour =IncrementBCDByteHigh(timeBuf.hour); break;break;case 8: timeBuf.hour =IncrementBCDByteLow(timeBuf.hour)
17、;case 9: timeBuf.min= IncrementBCDByteHigh(timeBuf.min);break;case 10: timeBuf.min= IncrementBCDByteLow(timeBuf.min);break;case 11: timeBuf.sec= IncrementBCDByteHigh(timeBuf.sec);break;case 12: timeBuf.sec= IncrementBCDByteLow(timeBuf.sec);break;default: break;刷新光标闪烁显示RefreshLcdShowTime();/ 刷新时间显示Lc
18、dRefreshSetCoursor();/* 递减光标位置的时间值 */void DecTimeBySetTimeIndex()switch (setTimeIndex)case 1: timeBuf.year =年十位数字DescBCDByteHigh(timeBuf.year); break;/ 递减case 2: timeBuf.year = DescBCDByteLow(timeBuf.year);break;/ 年个位数字递减case 3: timeBuf.month = DescBCDByteHigh(timeBuf.month); break;case 4: timeBuf.m
19、onth = DescBCDByteLow(timeBuf.month); break;break;case 6: timeBuf.day= DescBCDByteLow(timeBuf.day); break;case 7: timeBuf.hour =DescBCDByteHigh(timeBuf.hour); break;case 8: timeBuf.hour =DescBCDByteLow(timeBuf.hour);break;case 9: timeBuf.min= DescBCDByteHigh(timeBuf.min); break;case 10: timeBuf.min=
20、 DescBCDByteLow(timeBuf.min); break;case 11: timeBuf.sec= DescBCDByteHigh(timeBuf.sec);break;case 12: timeBuf.sec= DescBCDByteLow(timeBuf.sec);break;default: break;/* 先刷新时间显示 , 再刷新光标闪烁显示 */RefreshLcdShowTime();LcdRefreshSetCoursor();/* 红外按键动作函数 */void IrdKeyAction()if (irdCode2 = 0x44) / ;|if (setTi
21、meIndex = 0) /正常运行状态setTimeIndex = 1;LcdRefreshSetCoursor();/ 刷新光标设置显示elseSetTimeToDS1302(&timeBuf); / 将时间写入到DS1302中setTimeIndex = 0;RefreshLcdShowTime();else if (irdCode2 = 0x40) /|;|if (setTimeIndex != 0)LcdCoursorRight();else if (irdCode2 = 0x15) /-DecTimeBySetTimeIndex();else if (irdCode2 = 0x09
22、) /+IncTimeBysetTimeIndex();else if (irdCode2 = 0x19) /EQsetTimeIndex = 0;RefreshLcdShowTime();else if (irdCode2 = 0x16) /SetTimeBcdByte(0);else if (irdCode2 = 0x0C) /SetTimeBcdByte(1);else if (irdCode2 = 0x18) /SetTimeBcdByte(2);数字键 0数字键 1数字键 2else if (irdCode2 = 0x5E)SetTimeBcdByte(3);else if (ird
23、Code2 = 0x08)SetTimeBcdByte(4);else if (irdCode2 = 0x1C)SetTimeBcdByte(5);else if (irdCode2 = 0x5A)SetTimeBcdByte(6);else if (irdCode2 = 0x42)SetTimeBcdByte(7);else if (irdCode2 = 0x52)SetTimeBcdByte(8);else if (irdCode2 = 0x4A)SetTimeBcdByte(9);else/*T0 中断服务 */void Timer0_ISP() interrupt 1static un
24、signed char counter = 0;TH0 = thr0;TL0 = tlr0; /1mscounter+;KeyScan();/ 按键扫描if (counter ;= 200) counter = 0;flag200ms = 1;/200ms #ifndef _MAIN_H_ #define _MAIN_H_sbit ADDRO = P1A0;sbit ADDR1 = PM1;sbit ADDR2 = P1A2;sbit ADDR3 = P1A3;sbit ENLED = P1A4; #endif /_MAIN_H_*fileLcd1602.c author : xrdate20
25、14 年 4 月 21 日 22:23:12* version :V1.2.3* briefLCD1602 底层驱动单片机 STC89C52RC MC晶振 11.0592MHZ*/#include ;/LCD1602sbit LCD1602_RS = P1A0;sbit LCD1602_RW = PM1;sbit LCD1602_EN = P1A5;#define LCD1602_DB P0/*LCD1602 忙碌等待 */void LCD1602Wait()unsigned char sta; 读取 LCD1602状态字/* 读取液晶状态字之前必须将 P0 口全部拉高 */LCD1602_D
26、B = 0xFF;LCD1602_RS = 0;LCD1602_RW = 1;LCD1602_EN = 0;doLCD1602_EN = 1;sta = LCD1602_DB;/ 读状态字LCD1602_EN = 0; while (sta & 0x80); / 检测最高位是否为 1,1 忙碌,0 空闲/*LCD1602 写命令 */void LCD1602WriteCmd(unsigned char cmd)/ 读写前要进行液晶的忙碌等待LCD1602Wait();LCD1602_RS = 0;LCD1602_RW = 0;LCD1602_EN = 0;LCD1602_DB = cmd;LC
27、D1602_EN = 1;/ 高脉冲LCD1602_EN = 0;/ 关闭液晶输出/*LCD1602 写数据 */void LCD1602WriteData(unsigned char dat)LCD1602Wait();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_EN = 0;LCD1602_DB = dat;/ 送入数据LCD1602_EN = 1;/ 高脉冲LCD1602_EN = 0;/ 关闭液晶输出/* 液晶初始化 */void InitLCD1602()LCD1602WriteCmd(0x38); /LCD1602WriteCmd(0x0C); /L
28、CD1602WriteCmd(0x06); /标 +LCD1602WriteCmd(0x01); /* 在 LCD1602的坐标(x, y)写指令 38H开显示不显示光标写入字符时字符指针 +且光显示清屏位置显示 str*/void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str)unsigned char addr;if (y = 0)addr = 0x00 + x; /elseaddr = 0x40 + x; /第一行的 x 位置显示第二行 x 的位置显示LCD1602WriteCmd(addr + 0x80
29、);while (*str != 0)LCD1602WriteData(*str+);/* 设置光标的位置为 (x, y)*/void LcdSetCoursor(unsigned char x, unsigned char y) unsigned char addr;if (y = 0)addr = 0x00 + x;elseaddr = 0x40 + x;LCD1602WriteCmd(addr | 0x80); / 写入光标闪烁地 址/* 打开光标显示 */void LcdOpenCoursor()LCD1602WriteCmd(0x0F); / 显示光标病使光标闪烁/* 关闭光标显示
30、*/void LcdCloseCoursor()LCD1602WriteCmd(0x0C); / 开显示但不显示光标 /* * fileDs1302.c* author :xr* date2014 年 4 月 21 日 22:23:12* version :V1.2.3briefDS1302 底层驱动单片机 STC89C52RC MC晶振 11.0592MHZ*/#include ;/DS1302sbit DS1302_SIO = P3A4;/数据 IOsbit DS1302_SCK =卩3八5; 时钟线sbit DS1302_CE = P1A7;/ 片选使能/* 使用外部数据类型时必须在这个
31、文件中再一次声明 */ struct Time unsigned char year;/ 年在DS1302中只存放的是低两位 这里用 unsigned char 型unsigned char month;unsigned char day;unsigned char hour;unsigned char min;unsigned char sec;unsigned char week;/*向SIO发送一个字节数据*/void DS1302WriteByte(unsigned char byte) unsigned char mask = 0x01;/ 低位在前 , 逐位发送/*初始化DS130
32、2时,将SIO和SCK引脚拉低,空闲*/for (mask = 0x01; mask != 0; mask ;year = buff6;/ 将年寄存器中的 bcd 码取出来存入结构体 time-;year 中time-;month = buff4;time-;week = buff5;time-;day= buff3;time-;hour = buff2;time-;min= buff1;time-;sec= buff0;/*设置时间,将当前修改后的时间值设置到DS1302中*/void SetTimeToDS1302(struct Time * time)unsigned char buff
33、8; / 保存当前修改后的 time 结构 体成员的值buff0 = time-;sec; / 将秒寄存器中的值存入 buff0 buff1 = time-;min;buff2 = time-;hour;buff3 = time-;day;buff4 = time-;month;buff5 = time-;week;buff6 = time-;year;buff7 = 0x00;/WP 写保护寄存器DS1302BurstWrite(buff); /将 buff 中的值以Burst模式写入 DS1302中/* 初始化 DS1302*/void InitDS1302()struct Time co
34、de InitTime= 0x14, 0x04, 0x22, 0x23,0x59, 0x59, 0x02; /2014年4月22日23:59:59unsigned char psec; /检测DS1302的停止位CH/* 初始化DS1302的通信引脚*/DS1302_SCK = 0;DS1302_CE = 0;psec = DS1302ReadSingleByte(0x00); /0x00;/ 红外通信引脚sbit IRD = P3A3;/红外通信引脚,外部中断1弓I脚bit flagIrd = 0; /红外数据码值接收完毕标志位unsigned char irdCode4; / 保存 NEC
35、协议解码的四个 字节的数据码 (用户码+用户反码 ,键码+键码反码 )/* 红外通信 - 定时器 T1 计数进行红外接收数据判定的时 间获取 */void ConfigIrdByTimer1()TMOD &= 0x0F;/ 清零 T1 控制位TMOD |= 0x10;/ 使用 T1 方式 1,16 位可设定模式TH1 = 0;TL1 = 0;/开始时没有红外信号 , 清零 T1 计数TR1 = 0;/开始时关闭 T1 计数ET1 = 0;/关闭T1中断,只用T1计数功能/* 外部中断 1 配置 */IE1 = 0;/外部中断 1 标志位清零IT1 = 1;/设置外部中断 1 为下降沿触发EX1
36、 = 1;/开启外部中断EA = 1;/ 开总中断/*获取IRD引脚即红外引脚高电平T1计数值*/unsigned int GetHighTimers()IRD =1;/在检测红外引脚之前,要先将IRD引脚拉高释放TH1= 0;TL1 =0;/先清零上一次的 T1 计数值TR1= 1;/开启 T1 计数while (IRD) / 高电平 T1 进行计数if (TH1 ; 0x40) /0x40 * 256 * (12/11059200) 1000 = 17.7msbreak; / 当时间 ;17.7ms 时我们认为是误码 , 强制退出TR1 = 0; / 关闭 T1 计数return (TH1
37、 * 256 + TL1); /返回 IRD 引脚高电平时 T1 的计数值/* 获得低电平载波时间 */ unsigned int GetLowTimers()IRD = 1;/在检测红外引脚之前 , 要先将 IRD 引脚释放TH1 = 0;TL1 =0; /清零 T1 计数值TR1= 1; /开启 T1 计数while (!IRD)/ 超时判断if (TH1 ; 0x40) /超出 17.7ms 就退出break;TR1 = 0;/ 关闭 T1 计数return (TH1 * 256 + TL1);/ 返回 T1 计数值/*外部中断1服务,判定红外并接收红外NEC解码*/void EXINT
38、1_ISP() interrupt 2 /EXINT1 中断标号为 2unsigned char byte = 0;/unsigned int time = 0;/ 的时间unsigned char i, j;接收解码数据接收引导码和空闲与载波time = GetLowTimers();/载波 引导码 (9ms 的载波+4.5ms 的空闲 ) :范围 (8.5ms-9.5ms)if (time ; 8755) / 计数周期 =12/11059200 计数 时间 =(TH1*256+TL1)*12/11059200/ 误码, 清零中断标志并退出中断IE1 = 0;return;time = Ge
39、tHighTimers();/ 空闲 4.5ms 的空闲:范 围: 4ms-5msif (time ; 4608) /判断时必须加上 ()/ 不符合IE1 = 0;/外部中断标志位return; /退出中断函数/ 引导码正确 , 开始循环接收用户码和键码for (i = 0; i ; 700)/ 误码IE1 = 0;/ 清零外部中断标志return;time = GetHighTimers();/ 空闲低位在先 ,先右if (time ; 313) & (time ;= 1;/ 逐位接收,将数据位右移到低位else if (time ; 1271) & (time ;= 1;/ 移一位 , 将
40、这一位移到 byte 的最高位else/ 接收的是误码IE1 = 0;/ 清零外部中断 1 标志位return;/ 退出中断函数irdCodei = byte;/ 接收码值flagIrd = 1;/ 接收完成标志置 1IE1 = 0;/ 清零外部中断标志byte |= 0x80;/再将这一位置 1/*fileKeyboard.c* author :xr* date2014 年 4 月 21 日 22:23:12* version :V1.2.3* brief按键底层驱动单片机 STC89C52RC MC晶振 11.0592MHZ*/#include ;/KEY sbit KEY_IN_1 = P2A4;sbit KEY_IN_2 =卩2八5;sbit KEY_IN_3 = P2A6;sbit KEY_IN_4 = P2A7;sbit KEY_OUT_1 = P2A3;sbit KEY_OUT_2 = P2A2;sbit KEY_OUT_3 = P2A1;sbit KEY_OU
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 个人房屋租赁合同简易模板
- 上海市建设工程合同示范文本:汽车4S店建设
- 专利研发合同
- 专业家教服务合同(五)
- 个人和单位的购货合同
- 二手房买卖委托代理合同示例
- 中小企业融资借款合同
- 个人汽车股权合作合同
- 个人购车分期付款合同范本
- KTV战略合作合同协议书
- 《携程旅行营销环境及营销策略研究》10000字(论文)
- 餐饮行业优化食品供应链管理计划
- cnc加工岗前培训
- 2024年海南省公务员录用考试《行测》真题卷及答案解析
- 2025年中国汽车车灯行业市场现状、前景分析研究报告(智研咨询发布)
- 2024夏季广东广州期货交易所招聘高频难、易错点500题模拟试题附带答案详解
- 浙江省2024年高考化学模拟试题(含答案)2
- 2024新人教七年级英语上册 Unit 2 Were Family!(大单元教学设计)
- (部编版)统编版小学语文教材目录(一至六年级上册下册齐全)
- 材料力学之材料疲劳分析算法:S-N曲线法:疲劳分析案例研究与项目实践.Tex.header
- 天津2024年天津市规划和自然资源局所属事业单位招聘笔试历年典型考题及考点附答案解析
评论
0/150
提交评论