找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6048|回复: 3
打印 上一主题 下一主题
收起左侧

STC单片机ISP-Demo-使用Y-Modem协议源码与库函数分享

  [复制链接]
跳转到指定楼层
楼主


MCU的ISP程序完全用C语言编写,接收Ymodem协议时忽略CRC16 校验,用户可以向己加上。当然,用户可以完全自己定义协议,更改接收程序来获得自己独一无二的下载协议。关于Ymodem协议的相关知识,用户可以向己上网搜索,资料很多。
原则上,用户程序不需要知道具体ISP程序的实际地址,满足一定条件时复位到用户入口即可。但是用户程序的长度不可以超过ISP占用的部分。 本例程,ISP定位在0xE400用户程序可以写到57K-3字节。0xE3FD、0xE30xE3FF这3个字节,被ISP存放用户程序的入口指令。用超级终端下载时, 如果用户程序超过0xE3FC, ISP会停止执行下载。
本文以宏晶科技的IAP12C5A60S2和IAP15F2K61S2为例,详细说明使用宏晶科技的IAP单片机开发用户自己的ISP程序的方法,并给出了基于keil的汇编和c源代码


FLASH空间中,从地址0000H开始的连续57K-3字节的空间为用户程序区。当满足特定的下载条件时,需要用户将MCU复位到用户如成入口,执行IAP_CONTR=0x20即可,此时可对用户程序区进行擦除和改写,以达到更新用户程序的目的。

三.下位机固件程序说明

下位机固件程序包括两部分:ISP(ISP代码)和AP(用户代码)*ISP代码向成一体,用户不需要调用ISP,软件复位总会先运行ISP。两种方式进入ISP:
1、超级终端,键盘为小写状态,按下字母d键,给MCU上电,MCU检测到10个字母(1,就会进入ISP。
2、用户程序中,串口连续接收到字母d,超过10个就执行IAP_CONTR=0x20复位到ISP。

*用户代码

用户代码可以使用C或者汇编语言编写,但对于汇编代码需要注意一点:位于0000H的复位入口地址处的指令必须是一个长跳转语句(类似LJMP START)。在用户代码中,需要设置好串口,并在串口连续接收到字母d,超过10个就执行IAP_CONTR=0x20复位到ISP。具体细节请参考附件中的代码。


ISP程序在编译时,要设置一下,见下阁:




STC_IAP_ISP监控程序
  1. #define MAIN_Fosc                22118400L        //定义主时钟
  2. #define Baudrate0                115200UL        //串口0波特率600~115200

  3. #include        "STC15Fxxxx.H"
  4. #include        "ymodem.h"


  5. #define        WDT_Enable        0                        //1: 允许内部看门狗,        0: 禁止
  6. #define D_BRT0_1T_8bit                (256 - MAIN_Fosc / 32 / Baudrate0)        //计算波特率        1T  8bit



  7. #define        ISP_ADDRESS                0xE400                                //ISP开始地址, 高地址必须是偶数, 注意要预留ISP空间,本例程留3K
  8. #define        UserflashLenth         (ISP_ADDRESS-3)                //用户FLASH长度, 保留个字节存放用户地址程序的跳转地址


  9. /*************        本地变量声明        **************/

  10. typedef                void (*pFunction)(void);
  11. pFunction        Jump_To_Application;
  12. u16                        JumpAddress;

  13. u16                FileLength;
  14. u16                Y_TimeOut,WaitTime;
  15. u8                packets_received, session_begin;
  16. u8                idata file_name[FILE_NAME_LENGTH];
  17. u8                idata file_size[FILE_SIZE_LENGTH];
  18. u8                StartCode[3];
  19. u16                FlashDestination;
  20. u16                RxCnt;
  21. u8                HandCnt;
  22. u8        xdata        RxBuff[1024];
  23. u8        idata        RxBuff_10[10];

  24. u32                DownCheckSum,FlashCheckSum;

  25. /*************        本地函数声明        **************/
  26. u8                Hex2Ascii(u8 dat);
  27. u8                UART_Download(void);
  28. u16                Str2Int(u8 *inputstr);
  29. void        ISP_WriteByte(u16 addr, u8 dat);
  30. void        ISP_EraseSector(u16 addr);
  31. u8        ISP_ReadByte(u16 addr);




  32. //========================================================================
  33. // 函数: void        TX1_write2buff(u8 dat)
  34. // 描述: 串口发送一个字节.
  35. // 参数: dat: 要发送的字节.
  36. // 返回: none.
  37. // 版本: V1.0, 2013-4-29
  38. //========================================================================
  39. void        TX1_write2buff(u8 dat)
  40. {
  41.         TI = 0;
  42.         SBUF = dat;
  43.         while(!TI);
  44. }

  45. //========================================================================
  46. // 函数: void        PrintString1(u8 *p)
  47. // 描述: 串口发送一个字符串.
  48. // 参数: *p: 要发送的字符串指针.
  49. // 返回: none.
  50. // 版本: V1.0, 2013-4-29
  51. //========================================================================
  52. void        PrintString1(u8 *p)
  53. {
  54.         for(; *p > 0; p++)        TX1_write2buff(*p);
  55. }

  56. //========================================================================
  57. // 函数: void        Tx_DEC_U16(u16 j)
  58. // 描述: 把一个16位整型数转成十进制送串口发送.
  59. // 参数: j: 要处理的16位整型数.
  60. // 返回: none.
  61. // 版本: V1.0, 2013-4-29
  62. //========================================================================
  63. void        Tx_DEC_U16(u16 j)
  64. {
  65.         u8        i;
  66.         u8        tmp[10];
  67.         for(i=4; i<5; i--)        tmp[i] = j % 10 + '0',        j = j / 10;
  68.         for(i=0; i<4; i++)
  69.         {
  70.                 if(tmp[i] != '0')        break;
  71.                 tmp[i] = ' ';
  72.         }
  73.         for(i=0; i<5; i++)        TX1_write2buff(tmp[i]);
  74. }

  75. //========================================================================
  76. // 函数: void        Tx_HEX_U32(u32 j)
  77. // 描述: 把一个32位长整型数转成十进制送串口发送.
  78. // 参数: j: 要处理的32位整型数.
  79. // 返回: none.
  80. // 版本: V1.0, 2013-4-29
  81. //========================================================================
  82. void        Tx_HEX_U32(u32 j)
  83. {
  84.         u8        i,k;
  85.         u8        tmp[10];
  86.         for(i=8; i>0; i--)
  87.         {
  88.                 k = ((u8)j) & 0x0f;
  89.                 if(k <= 9)        tmp[i] = k+'0';
  90.                 else                tmp[i] = k-10+'A';
  91.                 j >>= 4;
  92.         }
  93.         for(i=1; i<9; i++)        TX1_write2buff(tmp[i]);
  94. }


  95. //========================================================================
  96. // 函数: void        ReturnNameAndLength(void)
  97. // 描述: 返回程序的文件名和长度, 和累加校验和.
  98. // 参数: none.
  99. // 返回: none.
  100. // 版本: V1.0, 2013-4-29
  101. //========================================================================
  102. void        ReturnNameAndLength(void)
  103. {
  104.         u16        i;
  105.         PrintString1("================================\r\n File name:     ");
  106.         for(i=0; i<FILE_NAME_LENGTH; i++)       
  107.         {
  108.                 if(file_name[i] == 0)        break;
  109.                 TX1_write2buff(file_name[i]);
  110.         }
  111.         PrintString1("\r\n File length:   ");
  112.         Tx_DEC_U16(FileLength);
  113.         PrintString1(" Bytes\r\n DownChexkSum:  ");
  114.         Tx_HEX_U32(DownCheckSum);
  115.         PrintString1("\r\n ISP Versiom:   2013-4-30 by Coody");
  116.         PrintString1("\r\n================================\r\n\r\n");
  117. }

  118. //========================================================================
  119. // 函数: void        UART1_RxPackage(void)
  120. // 描述: 串口接收一个数据块.
  121. // 参数: none.
  122. // 返回: none.
  123. // 版本: V1.0, 2013-4-29
  124. //========================================================================
  125. void        UART1_RxPackage(void)
  126. {
  127.         u16        j;        //5ms超时
  128. //        RI = 0;
  129.         RxCnt = 0;
  130.         for(j = 0;        j < 5000; j++)        //最后收到一个字节5ms后,超时退出
  131.         {
  132.                 if(RI)
  133.                 {
  134.                         RI = 0;
  135.                         if(RxCnt < 1024)        RxBuff[RxCnt] = SBUF;
  136.                         else
  137.                         {
  138.                                 RxBuff_10[RxCnt-1024] = SBUF;
  139.                         }
  140.                         if(++RxCnt >= 1034)        RxCnt = 1033;
  141.                         j = 0;        //重新定时5ms
  142.                 }
  143.         }
  144.         #if (WDT_Enable > 0)
  145.                 WDT_reset(D_WDT_SCALE_256);
  146.         #endif
  147. }

  148. //========================================================================
  149. // 函数: void        main(void)
  150. // 描述: 主函数.
  151. // 参数: none.
  152. // 返回: none.
  153. // 版本: V1.0, 2013-4-29
  154. //========================================================================
  155. void        main(void)
  156. {
  157.         u8        i;

  158.         EA = 0;
  159.         Timer0_Stop();
  160.         Timer1_Stop();
  161.         #if (WDT_Enable > 0)
  162.                 WDT_reset(D_WDT_SCALE_256);
  163.         #endif

  164.         S1_8bit();
  165.         S1_RX_Enable();
  166.         S1_BRT_UseTimer1();
  167.         Timer1_AsTimer();
  168.         Timer1_1T();
  169.         Timer1_8bitAutoReload();
  170.         Timer1_InterruptDisable();
  171.         TH1 = D_BRT0_1T_8bit;
  172.         Timer1_Run();

  173. //        PrintString1("\r\n STC ISP Demo\r\n");
  174.        
  175.         while(1)
  176.         {
  177.         //        TX1_write2buff('A');
  178.                 HandCnt = 0;
  179.                 for(WaitTime = 0; WaitTime < 300; WaitTime++)                //1.5秒超时
  180.                 {
  181.                         UART1_RxPackage();
  182.                         if((RxCnt == 1) && (RxBuff[0] == 'd'))
  183.                         {
  184.                                 if(++HandCnt >= 10)
  185.                                 {
  186.                                         i = UART_Download();
  187.                                         WaitTime = 250;
  188.                                         if(i == 1)                        PrintString1("\r\n User abort!\r\n");
  189.                                         else if(i == 2)                PrintString1("\r\n PC Cancel!\r\n");
  190.                                         else if(i == 4)                PrintString1("\r\n Programming Error!\r\n");
  191.                                         else if(i == 0)
  192.                                         {
  193.                                                 PrintString1("\r\n\r\n Programming Completed Successfully!\r\n");
  194.                                                 ReturnNameAndLength();
  195.                                         }
  196.                                 }
  197.                         }
  198.                 //        else        HandCnt = 0;
  199.                 }

  200.                 if(ISP_ReadByte(ISP_ADDRESS-3) == 0x02)
  201.                 {
  202.             SCON = 0;
  203.                         AUXR = 0;
  204.             TMOD = 0;
  205.             TL0 = 0;
  206.             TH0 = 0;
  207.             TH1 = 0;
  208.             TL1 = 0;
  209.             TCON = 0;
  210.                         IAP_CMD = 0;

  211.                         JumpAddress = ISP_ReadByte(ISP_ADDRESS-2);
  212.                         JumpAddress = (JumpAddress << 8) | ISP_ReadByte(ISP_ADDRESS-1);        //Jump to user application
  213.                         Jump_To_Application = (pFunction) JumpAddress;
  214.                         Jump_To_Application();
  215.                 }
  216.                 PrintString1(" No AP\r\n");
  217.         }
  218. }



  219. //========================================================================
  220. // 函数: u16 Str2Int(u8 *inputstr)
  221. // 描述: 字符串转整型.
  222. // 参数: *inputstr: 字符串指针.
  223. // 返回: 16位整型数.
  224. // 版本: V1.0, 2013-4-29
  225. //========================================================================
  226. u16 Str2Int(u8 *inputstr)
  227. {
  228.         u16        val;
  229.         u8        i;
  230.        
  231.         val = 0;
  232.         for (i = 0; i < 5; i++)
  233.         {
  234.                 if((inputstr[i] < '0') || (inputstr[i] > '9'))        break;
  235.                 val = val * 10 + inputstr[i] - '0';
  236.         }
  237.         return val;
  238. }

  239. //========================================================================
  240. // 函数: void        ISP_WriteByte(u16 addr, u8 dat)
  241. // 描述: 对一个地址写FLASH一个字节.
  242. // 参数: addr: 16位FLASH地址.
  243. //       dat:  要写入的一字节数据.
  244. // 返回: none.
  245. // 版本: V1.0, 2013-4-29
  246. //========================================================================
  247. void        ISP_WriteByte(u16 addr, u8 dat)
  248. {
  249.         IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //使能IAP功能
  250.         ISP_WRITE();                        //编程命令
  251.         IAP_ADDRL = addr;
  252.         IAP_ADDRH = addr >> 8;
  253.         IAP_DATA  = dat;                //将当前数据送IAP数据寄存器
  254.         ISP_TRIG();                                //触发ISP命令
  255. }

  256. //========================================================================
  257. // 函数: u8        ISP_ReadByte(u16 addr)
  258. // 描述: 从一个地址读FLASH一个字节.
  259. // 参数: addr: 16位FLASH地址.
  260. // 返回: 读出的一字节数据.
  261. // 版本: V1.0, 2013-4-29
  262. //========================================================================
  263. u8        ISP_ReadByte(u16 addr)
  264. {
  265.         IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //使能IAP功能
  266.         ISP_READ();                        //编程命令
  267.         IAP_ADDRL = addr;
  268.         IAP_ADDRH = addr >> 8;
  269.         ISP_TRIG();                                //触发ISP命令
  270.         return(IAP_DATA);
  271. }

  272. //========================================================================
  273. // 函数: void        ISP_EraseSector(u16 addr)
  274. // 描述: 对FLASH擦除一个扇区.
  275. // 参数: addr: 16位FLASH地址.
  276. // 返回: none.
  277. // 版本: V1.0, 2013-4-29
  278. //========================================================================
  279. void        ISP_EraseSector(u16 addr)
  280. {
  281.         IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);                //使能IAP功能
  282.         ISP_ERASE();                                //擦除命令
  283.         IAP_ADDRL = addr;
  284.         IAP_ADDRH = addr >> 8;
  285.         ISP_TRIG();                                //触发ISP命令
  286. }

  287. //========================================================================
  288. // 函数: u8        UART_Download(void)
  289. // 描述: 按Ymodem接收文件数据并写入用户FLASH.
  290. // 参数: none.
  291. // 返回: none.
  292. // 版本: V1.0, 2013-4-29
  293. //========================================================================
  294. u8        UART_Download(void)
  295. {
  296.         u16        i;
  297.         u8        j;

  298.         PrintString1("\r\n\r\n Waiting for the file to be sent ... (press 'a' to abort)\r\n");
  299.        
  300.         Y_TimeOut = 0;
  301.         packets_received = 0;
  302.         session_begin = 0;
  303.         WaitTime = 40;
  304.         DownCheckSum = 0;
  305.        
  306.         while(WaitTime > 0)
  307.         {
  308.                 if(Y_TimeOut == 0)
  309.                 {
  310.                         TX1_write2buff(CRC16);
  311.                         Y_TimeOut = 300;
  312.                         if(WaitTime > 0) WaitTime--;
  313.                 }

  314.                 while(Y_TimeOut > 0)
  315.                 {
  316.                         UART1_RxPackage();
  317.                         if(RxCnt == 0)        Y_TimeOut--;
  318.                         else
  319.                         {
  320.                                 if(RxCnt == 1)
  321.                                 {
  322.                                         if(RxBuff[0] == EOT)
  323.                                         {
  324.                                                 TX1_write2buff(ACK);
  325.                                                 Y_TimeOut = 40;
  326.                                         }
  327.                                         else if((RxBuff[0] == ABORT1) || (RxBuff[0] == ABORT2))
  328.                                         {
  329.                                                 return 1;
  330.                                         }
  331.                                 }
  332.                                 else if(RxCnt <= 5)
  333.                                 {
  334.                                         if((RxBuff[0] == CANCEL) && (RxBuff[1] == CANCEL))
  335.                                         {
  336.                                                 return 2;
  337.                                         }
  338.                                 }
  339.                                 else if((RxCnt == 133) || (RxCnt == 1029))
  340.                                 {
  341.                                         if (RxBuff[PACKET_SEQNO_INDEX] != (RxBuff[PACKET_SEQNO_COMP_INDEX] ^ 0xff))
  342.                                         {
  343.                                                 TX1_write2buff(NAK);        //错误, 请求重发
  344.                                                 Y_TimeOut = 300;
  345.                                         }
  346.                                         else
  347.                                         {
  348.                                                 WaitTime = 5;
  349.                                                 if (packets_received == 0)        //发送序号为0, 为文件名数据包
  350.                                                 {
  351.                                                         if (RxBuff[PACKET_HEADER] != 0)  //文件名不为空
  352.                                                         {
  353.                                                                 for (i = 0; i < FILE_NAME_LENGTH; i++)        file_name[i] = 0;
  354.                                                                 for (i = 0; i < FILE_SIZE_LENGTH; i++)        file_size[i] = 0;
  355.                                                                 j = PACKET_HEADER;
  356.                                                                 for (i = 0; (i < FILE_NAME_LENGTH) && (RxBuff[j] != 0); i++)
  357.                                                                         file_name[i] = RxBuff[j++];                //保存文件名

  358.                                                                 for (i=0, j++; (RxBuff[j] != ' ') && (i < FILE_SIZE_LENGTH); i++)
  359.                                                                         file_size[i] = RxBuff[j++];        //保存文件长度
  360.                                                                 FileLength = Str2Int(file_size);        //文件长度由字符串转成十六进制数据

  361.                                                                 if (FileLength >= UserflashLenth)        //长度过长错误
  362.                                                                 {
  363.                                                                         TX1_write2buff(CANCEL);        //错误返回2个 CA
  364.                                                                         TX1_write2buff(CANCEL);
  365.                                                                         return 3;                //长度过长
  366.                                                                 }
  367.                                                                
  368.                                                                 StartCode[0] = ISP_ReadByte(0);        //保存ISP跳转地址
  369.                                                                 StartCode[1] = ISP_ReadByte(1);
  370.                                                                 StartCode[2] = ISP_ReadByte(2);
  371.                                                                 ISP_EraseSector(0);
  372.                                                                 ISP_WriteByte(0,StartCode[0]);        //回写ISP跳转地址
  373.                                                                 ISP_WriteByte(1,StartCode[1]);
  374.                                                                 ISP_WriteByte(2,StartCode[2]);
  375.                                                                 for(i=0x200; i < UserflashLenth; i+=0x200)        //擦除N页
  376.                                                                         ISP_EraseSector(i);
  377.                                                        
  378.                                                                 TX1_write2buff(ACK);        //擦除完成, 返回应答
  379.                                                                 Y_TimeOut = 40;
  380.                                                                 packets_received ++;
  381.                                                                 session_begin = 1;
  382.                                                                 FlashDestination = 0;
  383.                                                                 DownCheckSum = 0;
  384.                                                         }
  385.                                                 }

  386.                                                 else if(session_begin == 1)        //收过文件名
  387.                                                 {
  388.                                                         if(RxBuff[PACKET_SEQNO_INDEX] == 0)        //全0数据帧
  389.                                                         {
  390.                                                                 ISP_WriteByte(ISP_ADDRESS-3,StartCode[0]);        //全部下载结束,最后写用户入口地址
  391.                                                                 ISP_WriteByte(ISP_ADDRESS-2,StartCode[1]);
  392.                                                                 ISP_WriteByte(ISP_ADDRESS-1,StartCode[2]);
  393.                                                                 TX1_write2buff(ACK);
  394.                                                                
  395.                                                                 FlashCheckSum  = ISP_ReadByte(ISP_ADDRESS-3);
  396.                                                                 FlashCheckSum += ISP_ReadByte(ISP_ADDRESS-2);
  397.                                                                 FlashCheckSum += ISP_ReadByte(ISP_ADDRESS-1);
  398.                                                                 for(i = 3;        i < FileLength; i++)        FlashCheckSum += ISP_ReadByte(i);        //计算FLASH累加和
  399.                                                                 if(FlashCheckSum == DownCheckSum)        return 0;        //正确
  400.                                                                 else
  401.                                                                 {
  402.                                                                         ISP_EraseSector(ISP_ADDRESS-0x200);
  403.                                                                         return 4;        //写入错误
  404.                                                                 }
  405.                                                         }
  406.                                                         else        //数据帧
  407.                                                         {
  408.                                                                 for(i=0; i<1024; i++)        RxBuff[i] = RxBuff[i+3];
  409.                                                                 RxBuff[1021] = RxBuff_10[0];
  410.                                                                 RxBuff[1022] = RxBuff_10[1];
  411.                                                                 RxBuff[1023] = RxBuff_10[2];
  412.                                                                 RxCnt -= 5;
  413.                                                                 for(i = 0; (i < RxCnt) && (FlashDestination < FileLength); i++)
  414.                                                                 {
  415.                                                                         if(FlashDestination == 0)
  416.                                                                         {
  417.                                                                                 StartCode[0] = RxBuff[0];
  418.                                                                                 StartCode[1] = RxBuff[1];
  419.                                                                                 StartCode[2] = RxBuff[2];
  420.                                                                                 FlashDestination = 3;
  421.                                                                                 i += 3;
  422.                                                                                 DownCheckSum += RxBuff[0]; DownCheckSum += RxBuff[1]; DownCheckSum += RxBuff[2];
  423.                                                                         }
  424.                                                                         ISP_WriteByte(FlashDestination,RxBuff[i]);
  425.                                                                         DownCheckSum += RxBuff[i];
  426.                                                                         FlashDestination ++;
  427.                                                                 }
  428.                                                                 TX1_write2buff(ACK);        //保存完成, 返回应答
  429.                                                                 Y_TimeOut = 300;
  430.                                                                 packets_received ++;
  431.                                                         }
  432.                                                 }
  433.                                         }
  434.                                 }
  435.                         }
  436.                 }
  437.         }
  438.         return 100;        //其他错误
  439. }
复制代码


用户实际代码范例
  1. /*------------------------------------------------------------------*/
  2. /* --- STC MCU International Limited -------------------------------*/
  3. /* --- STC IAP 系列单片机实现用户ISP 演示程序 ----------------------*/
  4. /* 如果要在程序中使用或者在文章中引用该程序,请在程序中或文章中注明  */
  5. /* 使用了宏晶科技的资料或程序                                       */
  6. /*------------------------------------------------------------------*/

  7. #include "reg51.h"

  8. #define FOSC 22118400L                  //系统时钟频率
  9. #define BAUD (256 - FOSC/32/115200)     //定义串口波特率                要与IAP里的相同


  10. /* 定义串口相关SFR */
  11. sfr AUXR = 0x8E;                        //波特率发生器控制寄存器
  12. sfr ISP_CONTR = 0xC7;
  13. sfr PCON2     = 0x97;   //for IAP15F2K61S2
  14. sfr P_SW1     = 0xA2;   //for IAP15F2K61S2

  15. char HandCnt;                             //Isp_Check内部使用的变量

  16. void uart() interrupt 4         //串口中断服务程序
  17. {
  18.     if (TI) TI = 0;                     //发送完成中断
  19.     if (RI)                             //接收完成中断
  20.     {
  21.         if (SBUF == 'd')
  22.         {
  23.             HandCnt++;
  24.             if (HandCnt >= 16)
  25.             {
  26.                 ISP_CONTR = 0x20;           //复位到AP入口
  27.             }
  28.         }
  29.         else        HandCnt = 0;
  30.         RI = 0;                         //清接收完成标志
  31.     }
  32. }

  33. void main()
  34. {
  35.     SCON = 0x50;                        //定义串口模式为8bit可变,无校验位
  36.     AUXR = 0x40;                        //波特率发生器12倍速,并启动波特率发生器定时器
  37.     TMOD = 0x20;                         //初始化波特率发生器定时器的定时初值

  38. //对于IAP15F2K61S2, 增加这两句,串口1可以切换P30,P31
  39.            P_SW1 &= ~0xc0;                //S1_USE_P30P31();
  40.         PCON2 &= ~(1<<4);        //S1_TXD_RXD_OPEN();

  41.     TH1 = BAUD;
  42.         TR1 = 1;
  43.         ES = 1;                             //使能串口中断
  44.     EA = 1;                             //打开全局中断开关

  45.     while (1)
  46.     {
  47.         P1++;
  48.     }
  49. }
复制代码




全部资料51hei下载地址:

STC库函数使用参考.pdf (152.17 KB, 下载次数: 41) STC库函数使用参考

库函数.zip (24.14 KB, 下载次数: 32) 库函数

例程.zip (1.96 MB, 下载次数: 48) 例程

ISP-Demo-使用Y-Modem协议.zip (275.68 KB, 下载次数: 78) ISP-Demo-使用Y-Modem协议


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:449599 发表于 2019-12-11 20:53 来自手机 | 只看该作者
留个记号,这几天要用
回复

使用道具 举报

板凳
ID:655329 发表于 2019-12-11 21:13 | 只看该作者
挺好的
回复

使用道具 举报

地板
ID:135723 发表于 2023-2-6 00:35 | 只看该作者
有一定的参考意义。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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