找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6804|回复: 7
收起左侧

单片机DHT11温湿度设计 程序带详细注释

  [复制链接]
ID:237813 发表于 2017-10-8 16:00 | 显示全部楼层 |阅读模式
这是我的一个51单片机课程设计单片机型号STC89C52,采集模块是DHT11
谢谢!!!

Altium Designer画的原理图如下:(51hei附件中可下载工程文件)
0.png

单片机源程序如下(带有详细的注释):
  1. #include <reg52.h>                                   // 头文件包含
  2. #include <intrins.h>

  3. #define uchar unsigned char        // 以后unsigned char就可以用uchar代替
  4. #define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

  5. sfr ISP_DATA  = 0xe2;                        // 数据寄存器
  6. sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
  7. sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
  8. sfr ISP_CMD   = 0xe5;                        // 命令寄存器
  9. sfr ISP_TRIG  = 0xe6;                        // 命令触发寄存器
  10. sfr ISP_CONTR = 0xe7;                        // 命令寄存器

  11. sbit Buzzer_P  = P1^0;    // 蜂鸣器
  12. sbit DHT11_P   = P1^1;                 // 温湿度传感器DHT11数据接入
  13. sbit LcdRs_P   = P1^2;    // 1602液晶的RS管脚      
  14. sbit LcdRw_P   = P1^3;    // 1602液晶的RW管脚
  15. sbit LcdEn_P   = P1^4;    // 1602液晶的EN管脚
  16. sbit KeySet_P  = P1^5;                // “设置”按键的管脚
  17. sbit KeyDown_P = P1^6;                // “减”按键的管脚
  18. sbit KeyUp_P   = P1^7;                // “加”按键的管脚
  19. sbit LedTL_P   = P3^4;                // 温度过低报警指示灯
  20. sbit LedTH_P   = P3^5;                // 温度过高报警指示灯
  21. sbit LedHL_P   = P3^6;                // 湿度过低报警指示灯
  22. sbit LedHH_P   = P3^7;                // 湿度过高报警指示灯

  23. uchar temp;                                        // 保存温度
  24. uchar humi;                                        // 保存湿度

  25. uchar AlarmTL;                        // 温度下限报警值
  26. uchar AlarmTH;                        // 温度上限报警值
  27. uchar AlarmHL;                        // 湿度下限报警值
  28. uchar AlarmHH;                        // 湿度上限报警值



  29. /*********************************************************/
  30. // 单片机内部EEPROM不使能
  31. /*********************************************************/
  32. void ISP_Disable()
  33. {
  34.         ISP_CONTR = 0;
  35.         ISP_ADDRH = 0;
  36.         ISP_ADDRL = 0;
  37. }


  38. /*********************************************************/
  39. // 从单片机内部EEPROM读一个字节,从0x2000地址开始
  40. /*********************************************************/
  41. unsigned char EEPROM_Read(unsigned int add)
  42. {
  43.         ISP_DATA  = 0x00;
  44.         ISP_CONTR = 0x83;
  45.         ISP_CMD   = 0x01;
  46.         ISP_ADDRH = (unsigned char)(add>>8);
  47.         ISP_ADDRL = (unsigned char)(add&0xff);
  48.         // 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
  49.         ISP_TRIG  = 0x46;           
  50.         ISP_TRIG  = 0xB9;
  51.         _nop_();
  52.         ISP_Disable();
  53.         return (ISP_DATA);
  54. }


  55. /*********************************************************/
  56. // 往单片机内部EEPROM写一个字节,从0x2000地址开始
  57. /*********************************************************/
  58. void EEPROM_Write(unsigned int add,unsigned char ch)
  59. {
  60.         ISP_CONTR = 0x83;
  61.         ISP_CMD   = 0x02;
  62.         ISP_ADDRH = (unsigned char)(add>>8);
  63.         ISP_ADDRL = (unsigned char)(add&0xff);
  64.         ISP_DATA  = ch;
  65.         ISP_TRIG  = 0x46;
  66.         ISP_TRIG  = 0xB9;
  67.         _nop_();
  68.         ISP_Disable();
  69. }


  70. /*********************************************************/
  71. // 擦除单片机内部EEPROM的一个扇区
  72. // 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
  73. /*********************************************************/
  74. void Sector_Erase(unsigned int add)         
  75. {
  76.         ISP_CONTR = 0x83;
  77.         ISP_CMD   = 0x03;
  78.         ISP_ADDRH = (unsigned char)(add>>8);
  79.         ISP_ADDRL = (unsigned char)(add&0xff);
  80.         ISP_TRIG  = 0x46;
  81.         ISP_TRIG  = 0xB9;
  82.         _nop_();
  83.         ISP_Disable();
  84. }


  85. /*********************************************************/
  86. // 毫秒级的延时函数,time是要延时的毫秒数
  87. /*********************************************************/
  88. void DelayMs(uint time)
  89. {
  90.         uint i,j;
  91.         for(i=0;i<time;i++)
  92.                 for(j=0;j<112;j++);
  93. }


  94. /*********************************************************/
  95. // 1602液晶写命令函数,cmd就是要写入的命令
  96. /*********************************************************/
  97. void LcdWriteCmd(uchar cmd)
  98. {
  99.         LcdRs_P = 0;
  100.         LcdRw_P = 0;
  101.         LcdEn_P = 0;
  102.         P0=cmd;
  103.         DelayMs(2);
  104.         LcdEn_P = 1;   
  105.         DelayMs(2);
  106.         LcdEn_P = 0;        
  107. }


  108. /*********************************************************/
  109. // 1602液晶写数据函数,dat就是要写入的数据
  110. /*********************************************************/
  111. void LcdWriteData(uchar dat)
  112. {
  113.         LcdRs_P = 1;
  114.         LcdRw_P = 0;
  115.         LcdEn_P = 0;
  116.         P0=dat;
  117.         DelayMs(2);
  118.         LcdEn_P = 1;   
  119.         DelayMs(2);
  120.         LcdEn_P = 0;
  121. }


  122. /*********************************************************/
  123. // 1602液晶初始化函数
  124. /*********************************************************/
  125. void LcdInit()
  126. {
  127.         LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
  128.         LcdWriteCmd(0x0C);        // 开显示,不显示光标
  129.         LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
  130.         LcdWriteCmd(0x01);        // 清屏
  131. }


  132. /*********************************************************/
  133. // 液晶光标定位函数
  134. /*********************************************************/
  135. void LcdGotoXY(uchar line,uchar column)
  136. {
  137.         // 第一行
  138.         if(line==0)        
  139.                 LcdWriteCmd(0x80+column);
  140.         // 第二行
  141.         if(line==1)        
  142.                 LcdWriteCmd(0x80+0x40+column);
  143. }


  144. /*********************************************************/
  145. // 液晶输出字符串函数
  146. /*********************************************************/
  147. void LcdPrintStr(uchar *str)
  148. {
  149.         while(*str!='\0')                         // 判断是否到字符串的尽头了
  150.                 LcdWriteData(*str++);
  151. }


  152. /*********************************************************/
  153. // 液晶输出数字
  154. /*********************************************************/
  155. void LcdPrintNum(uchar num)
  156. {
  157.         LcdWriteData(num/10+48);        // 十位
  158.         LcdWriteData(num%10+48);         // 个位
  159. }


  160. /*********************************************************/
  161. // 液晶显示内容的初始化
  162. /*********************************************************/
  163. void LcdShowInit()
  164. {
  165.         LcdGotoXY(0,0);                                                                // 第0行的显示内容
  166.         LcdPrintStr("  DHT11 System  ");
  167.         LcdGotoXY(1,0);                                                           // 第1行的显示内容
  168.         LcdPrintStr("T:  30 C   H: 25 %RH");
  169.         LcdGotoXY(1,4);                                                                // 温度单位摄氏度上面的圆圈符号
  170.         LcdWriteData(0xdf);        
  171. }



  172. /*********************************************************/
  173. // 10us级延时程序
  174. /*********************************************************/
  175. void Delay10us()
  176. {
  177.         _nop_();        // 执行一条指令,延时1微秒
  178.         _nop_();
  179.         _nop_();
  180.         _nop_();
  181.         _nop_();
  182.         _nop_();
  183.         _nop_();
  184.         _nop_();
  185.         _nop_();
  186.         _nop_();
  187. }


  188. /*********************************************************/
  189. // 读取DHT11单总线上的一个字节
  190. /*********************************************************/
  191. uchar DhtReadByte(void)
  192. {   
  193.         bit bit_i;
  194.         uchar j;
  195.         uchar dat=0;

  196.         for(j=0;j<8;j++)   
  197.         {
  198.                 while(!DHT11_P);        // 等待低电平结束        
  199.                 Delay10us();                        // 延时
  200.                 Delay10us();
  201.                 Delay10us();
  202.                 if(DHT11_P==1)                // 判断数据线是高电平还是低电平
  203.                 {
  204.                         bit_i=1;
  205.                         while(DHT11_P);
  206.                 }
  207.                 else
  208.                 {
  209.                         bit_i=0;
  210.                 }
  211.                 dat<<=1;                                   // 将该位移位保存到dat变量中
  212.                 dat|=bit_i;   
  213.         }
  214.         return(dat);  
  215. }


  216. /*********************************************************/
  217. // 读取DHT11的一帧数据,湿高、湿低(0)、温高、温低(0)、校验码
  218. /*********************************************************/
  219. void ReadDhtData()
  220. {            
  221.         uchar HumiHig;                // 湿度高检测值
  222.         uchar HumiLow;                // 湿度低检测值
  223.         uchar TemHig;                        // 温度高检测值
  224.         uchar TemLow;                        // 温度低检测值
  225.         uchar check;                        // 校验字节
  226.         
  227.         DHT11_P=0;                                // 主机拉低
  228.         DelayMs(20);                        // 保持20毫秒
  229.         DHT11_P=1;                                // DATA总线由上拉电阻拉高

  230.         Delay10us();                         // 延时等待30us
  231.         Delay10us();
  232.         Delay10us();

  233.         while(!DHT11_P);        // 等待DHT的低电平结束
  234.         while(DHT11_P);                // 等待DHT的高电平结束

  235.         //进入数据接收状态
  236.         HumiHig = DhtReadByte();         // 湿度高8位
  237.         HumiLow = DhtReadByte();         // 湿度低8为,总为0
  238.         TemHig  = DhtReadByte();         // 温度高8位
  239.         TemLow  = DhtReadByte();         // 温度低8为,总为0
  240.         check   = DhtReadByte();        // 8位校验码,其值等于读出的四个字节相加之和的低8位

  241.         DHT11_P=1;                                // 拉高总线

  242.         if(check==HumiHig + HumiLow + TemHig + TemLow)                 // 如果收到的数据无误
  243.         {
  244.                 temp=TemHig;                         // 将温度的检测结果赋值给全局变量temp
  245.                 humi=HumiHig;                        // 将湿度的检测结果赋值给全局变量humi
  246.         }
  247. }


  248. /*********************************************************/
  249. // 是否需要报警判断
  250. /*********************************************************/
  251. void AlarmJudge(void)
  252. {
  253.         uchar i;

  254.         if(temp>AlarmTH)                                // 温度是否过高
  255.         {
  256.                 LedTH_P=0;
  257.                 LedTL_P=1;
  258.         }
  259.         else if(temp<AlarmTL)                // 温度是否过低
  260.         {
  261.                 LedTL_P=0;
  262.                 LedTH_P=1;
  263.         }
  264.         else                                                                                // 温度正常
  265.         {
  266.                 LedTH_P=1;
  267.                 LedTL_P=1;
  268.         }

  269.         if(humi>AlarmHH)                           // 湿度是否过高
  270.         {
  271.                 LedHH_P=0;
  272.           LedHL_P=1;
  273.         }
  274.         else if(humi<AlarmHL)                // 湿度是否过低
  275.         {
  276.                 LedHL_P=0;
  277.                 LedHH_P=1;
  278.         }
  279.         else                                                                           // 湿度正常
  280.         {
  281.                 LedHH_P=1;
  282.                 LedHL_P=1;
  283.         }

  284.         if((LedHH_P==0)||(LedHL_P==0)||(LedTH_P==0)||(LedTL_P==0))         // 蜂鸣器判断,只要至少1个报警灯亮,蜂鸣器就报警
  285.         {
  286.                 for(i=0;i<3;i++)
  287.                 {
  288.                         Buzzer_P=0;
  289.                         DelayMs(100);
  290.                         Buzzer_P=1;
  291.                         DelayMs(100);
  292.                 }
  293.         }
  294. }


  295. /*********************************************************/
  296. // 按键扫描,用于设置温湿度报警范围
  297. /*********************************************************/
  298. void KeyScanf()
  299. {
  300.         if(KeySet_P==0)                // 判断设置按键是否被按下
  301.         {
  302.                 /*将液晶显示改为设置页面的*******************************************************/

  303.                 LcdWriteCmd(0x01);                                // 设置界面的显示框架
  304.                 LcdGotoXY(0,0);
  305.                 LcdPrintStr("Temp: 20-40");
  306.                 LcdGotoXY(1,0);
  307.                 LcdPrintStr("Humi: 10-30");
  308.                
  309.                 LcdGotoXY(0,6);                                                 // 在液晶上填充温度的下限值        
  310.                 LcdPrintNum(AlarmTL);        
  311.                 LcdGotoXY(0,9);                                                 // 在液晶上填充温度的上限值
  312.                 LcdPrintNum(AlarmTH);

  313.                 LcdGotoXY(1,6);                                                 // 在液晶上填充湿度的下限值
  314.                 LcdPrintNum(AlarmHL);        
  315.                 LcdGotoXY(1,9);                                                  // 在液晶上填充湿度的上限值
  316.                 LcdPrintNum(AlarmHH);

  317.                 LcdGotoXY(0,7);                                                 // 光标定位到第0行第7列
  318.                 LcdWriteCmd(0x0F);                                // 光标闪烁
  319.                
  320.                 DelayMs(10);                                                  // 去除按键按下的抖动
  321.                 while(!KeySet_P);                                         // 等待按键释放
  322.                 DelayMs(10);                                                  // 去除按键松开的抖动

  323.                 /*设置温度的下限值****************************************************************/

  324.                 while(KeySet_P)                                                // “设置键”没有被按下,则一直处于温度下限的设置
  325.                 {
  326.                         if(KeyDown_P==0)                                // 判断 “减按键“ 是否被按下               
  327.                         {
  328.                                 if(AlarmTL>0)                                        // 只有当温度下限值大于0时,才能减1
  329.                                         AlarmTL--;
  330.                                 LcdGotoXY(0,6);                                 // 重新刷新显示更改后的温度下限值        
  331.                                 LcdPrintNum(AlarmTL);                  
  332.                                 LcdGotoXY(0,7);                                // 重新定位闪烁的光标位置
  333.                                 DelayMs(350);                                        // 延时
  334.                         }
  335.                         if(KeyUp_P==0)                                  // 判断 “加按键“ 是否被按下
  336.                         {
  337.                                 if(AlarmTL<99)                          // 只有当温度下限值小于99时,才能加1
  338.                                         AlarmTL++;
  339.                                 LcdGotoXY(0,6);                                  // 重新刷新显示更改后的温度下限值
  340.                                 LcdPrintNum(AlarmTL);
  341.                                 LcdGotoXY(0,7);                                // 重新定位闪烁的光标位置
  342.                                 DelayMs(350);                                        // 延时
  343.                         }        
  344.                 }

  345.                 LcdGotoXY(0,10);
  346.                 DelayMs(10);                                                  // 去除按键按下的抖动
  347.                 while(!KeySet_P);                                         // 等待按键释放
  348.                 DelayMs(10);                                                  // 去除按键松开的抖动

  349.                 /*设置温度的上限值****************************************************************/
  350.                                 
  351.                 while(KeySet_P)                                          // “设置键”没有被按下,则一直处于温度上限的设置
  352.                 {
  353.                         if(KeyDown_P==0)                                // 判断 “减按键“ 是否被按下
  354.                         {
  355.                                 if(AlarmTH>0)                                  // 只有当温度上限值大于0时,才能减1                        
  356.                                         AlarmTH--;
  357.                                 LcdGotoXY(0,9);                           // 重新刷新显示更改后的温度上限值
  358.                                 LcdPrintNum(AlarmTH);
  359.                                 LcdGotoXY(0,10);                        // 重新定位闪烁的光标位置
  360.                                 DelayMs(350);                                        // 延时
  361.                         }
  362.                         if(KeyUp_P==0)                                   // 判断 “加按键“ 是否被按下
  363.                         {
  364.                                 if(AlarmTH<99)                                 // 只有当温度上限值小于99时,才能加1
  365.                                         AlarmTH++;
  366.                                 LcdGotoXY(0,9);                                // 重新刷新显示更改后的温度上限值         
  367.                                 LcdPrintNum(AlarmTH);
  368.                                 LcdGotoXY(0,10);                        // 重新定位闪烁的光标位置
  369.                                 DelayMs(350);                                        // 延时
  370.                         }                                                                 
  371.                 }

  372.                 LcdGotoXY(1,7);
  373.                 DelayMs(10);                                                  // 去除按键按下的抖动
  374.                 while(!KeySet_P);                                         // 等待按键释放
  375.                 DelayMs(10);                                                  // 去除按键松开的抖动
  376.                
  377.                 /*设置湿度的下限值****************************************************************/

  378.                 while(KeySet_P)                                                 // “设置键”没有被按下,则一直处于湿度下限的设置
  379.                 {
  380.                         if(KeyDown_P==0)                                // 判断 “减按键“ 是否被按下
  381.                         {
  382.                                 if(AlarmHL>0)                                         // 只有当湿度下限值大于0时,才能减1
  383.                                         AlarmHL--;
  384.                                 LcdGotoXY(1,6);                                // 重新刷新显示更改后的湿度下限值         
  385.                                 LcdPrintNum(AlarmHL);
  386.                                 LcdGotoXY(1,7);                                // 重新定位闪烁的光标位置
  387.                                 DelayMs(350);
  388.                         }
  389.                         if(KeyUp_P==0)                                         // 判断 “加按键“ 是否被按下
  390.                         {
  391.                                 if(AlarmHL<99)                          // 只有当湿度下限值小于99时,才能加1
  392.                                         AlarmHL++;
  393.                                 LcdGotoXY(1,6);                                  // 重新刷新显示更改后的湿度下限值
  394.                                 LcdPrintNum(AlarmHL);
  395.                                 LcdGotoXY(1,7);                          // 重新定位闪烁的光标位置
  396.                                 DelayMs(350);                                        // 延时
  397.                         }        
  398.                 }

  399.                 LcdGotoXY(1,10);
  400.                 DelayMs(10);                                                  // 去除按键按下的抖动
  401.                 while(!KeySet_P);                                         // 等待按键释放
  402.                 DelayMs(10);                                                  // 去除按键松开的抖动
  403.                
  404.                 /*设置湿度的上限值****************************************************************/

  405.                 while(KeySet_P)                                                 // “设置键”没有被按下,则一直处于湿度上限的设置
  406.                 {
  407.                         if(KeyDown_P==0)                                 // 判断 “减按键“ 是否被按下
  408.                         {
  409.                                 if(AlarmHH>0)                                  // 只有当湿度上限值大于0时,才能减1
  410.                                         AlarmHH--;
  411.                                 LcdGotoXY(1,9);                                  // 重新刷新显示更改后的湿度上限值
  412.                                 LcdPrintNum(AlarmHH);
  413.                                 LcdGotoXY(1,10);                        // 重新定位闪烁的光标位置
  414.                                 DelayMs(350);
  415.                         }
  416.                         if(KeyUp_P==0)                                         // 判断 “加按键“ 是否被按下
  417.                         {
  418.                                 if(AlarmHH<99)                                // 只有当湿度上限值小于99时,才能加1
  419.                                         AlarmHH++;
  420.                                 LcdGotoXY(1,9);                                 // 重新刷新显示更改后的湿度上限值        
  421.                                 LcdPrintNum(AlarmHH);
  422.                                 LcdGotoXY(1,10);                         // 重新定位闪烁的光标位置
  423.                                 DelayMs(350);                                        // 延时
  424.                         }        
  425.                 }

  426.                 LcdWriteCmd(0x0C);                          // 取消光标闪烁
  427.                 LcdShowInit();                                                // 液晶显示为检测界面的

  428.                 DelayMs(10);                                                  // 去除按键按下的抖动
  429.                 while(!KeySet_P);                                         // 等待按键释放
  430.                 DelayMs(10);                                                  // 去除按键松开的抖动

  431.                 Sector_Erase(0x2000);                                                 // 存储之前必须先擦除
  432.                 EEPROM_Write(0x2000,AlarmTL);                // 把温度下限存入到EEPROM的0x2000这个地址
  433.                 EEPROM_Write(0x2001,AlarmTH);                // 把温度上限存入到EEPROM的0x2001这个地址
  434.                 EEPROM_Write(0x2002,AlarmHL);                // 把湿度下限存入到EEPROM的0x2002这个地址
  435.                 EEPROM_Write(0x2003,AlarmHH);                // 把湿度上限存入到EEPROM的0x2003这个地址
  436.         }        
  437. }


  438. /*********************************************************/
  439. // 主函数
  440. /*********************************************************/
  441. void main()
  442. {
  443.         uchar i;

  444.         LcdInit();                                                        // 液晶功能的初始化                        
  445.         LcdShowInit();                                         // 液晶显示的初始化

  446.         AlarmTL=EEPROM_Read(0x2000);        // 从EEPROM的0x2000这个地址读取温度的报警下限
  447.         AlarmTH=EEPROM_Read(0x2001);        // 从EEPROM的0x2001这个地址读取温度的报警上限
  448.         AlarmHL=EEPROM_Read(0x2002);        // 从EEPROM的0x2002这个地址读取湿度的报警下限        
  449.         AlarmHH=EEPROM_Read(0x2003);        // 从EEPROM的0x2003这个地址读取湿度的报警上限

  450.         if((AlarmTL==0)||(AlarmTL>100))        // 如果温度下限报警值读出来异常(等于0或大于100),则重新赋值
  451.                 AlarmTL=20;
  452.         if((AlarmTH==0)||(AlarmTH>100))        // 如果温度上限报警值读出来异常(等于0或大于100),则重新赋值
  453.                 AlarmTH=35;
  454.         if((AlarmHL==0)||(AlarmHL>100))        // 如果温度下限报警值读出来异常(等于0或大于100),则重新赋值
  455.                 AlarmHL=40;
  456.         if((AlarmHH==0)||(AlarmHH>100))        // 如果温度上限报警值读出来异常(等于0或大于100),则重新赋值
  457.                 AlarmHH=85;
  458.                
  459.         
  460.         while(1)
  461.         {
  462.                 ReadDhtData();                                 // 检测温湿度数据

  463.                 LcdGotoXY(1,2);                                 // 定位到要显示温度的地方
  464.                 LcdPrintNum(temp);                // 显示温度值
  465.                 LcdGotoXY(1,11);                        // 定位到要显示湿度的地方
  466.                 LcdPrintNum(humi);                // 显示湿度值
  467.                
  468.                 AlarmJudge();                                        // 判断并根据需要报警

  469.                 for(i=0;i<25;i++)
  470.                 {
  471.                         KeyScanf();                                        // 按键扫描
  472.                         DelayMs(20);                                // 延时        
  473.                 }
  474.         }

  475. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
0.png
所有资料51hei提供下载:
基于单片机的温湿度设计.rar (108.14 KB, 下载次数: 135)
回复

使用道具 举报

ID:146436 发表于 2017-10-12 15:53 | 显示全部楼层
谢谢,我已经下载,学习学习
回复

使用道具 举报

ID:89286 发表于 2017-10-12 20:19 | 显示全部楼层
Thanaks for sharing
回复

使用道具 举报

ID:231270 发表于 2017-10-13 08:18 来自手机 | 显示全部楼层
学习
回复

使用道具 举报

ID:436629 发表于 2018-11-30 16:24 来自手机 | 显示全部楼层
楼主大大,可以加个qq好友吗
回复

使用道具 举报

ID:252029 发表于 2018-12-3 17:34 | 显示全部楼层
谢谢你的程序 学习一下
回复

使用道具 举报

ID:39982 发表于 2019-4-12 13:16 | 显示全部楼层
学习学习,谢谢
回复

使用道具 举报

ID:510967 发表于 2019-4-13 11:04 | 显示全部楼层
感谢楼主,帮助很大。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表