• STC32G 单片机EEPROM 操作实例


    一  STC32G 单片机EEPROM简介

    STC32G系列单片机内部集成了大量的EEPROM,特别是STC32G12K128集成多达128K EEPROM。

    STC32G内部EEPROM可擦写10万次,分若干扇区,每个扇区512字节。EEPROM的写操作只能将1写为0。要将0写为1,必须擦除扇区。EEPROM的读写是以字节为单位,擦除是以扇区为单位进行,要修改扇区内容,需要先将整个扇区内容读入内存,然后擦除整个扇区,然后再将内容写入扇区。STC32G的EEPROM操作时间与系统频率相关,设置好IAP_TPS寄存器值后,操作所需时间由硬件自动控制,IAP_TPS寄存器值 = 系统频率 / 1000000,如系统频率是30MHz,IAP_TPS寄存器值设为30.

    与EEPROM相关的寄存器如下:

     STC32G12K128的数据寄存器,仅IAP_DATA有效。

    操作EEPROM的命令如下:

     STC32G系列单片机仅支持命令CMD0~CMD3.

    要操作STC32G EEPROM必须将IAP_CONTR寄存器的IAPEN设为1.在设置完操作地址与操心命令后必须分别向IAP_TRIG分别写入0x5A、0xA5,才能使命令生效。

    二 与STC32G 单片机EEPROM 操作相关库函数的编写

    EEPROM 的操作离不开操作与EEPROM相关的寄存器,如果不写相关的库函数,每次都直接去写操作寄存器的代码,非常麻烦,且工作量大,我们先写好库函数,后面要用时,调用即可,就会省去很多麻烦,提高效率。下面是我写的库函数。先看下头文件。

    1. /*STC32G_EEPROM.h
    2. Designed by Bill Liu
    3. Version 0.0
    4. Modified last by Bill Liu on 07/18/2022
    5. //macro function/
    6. IAP_STANDBY(); //idle,no operation command
    7. IAP_READ(); //read command
    8. IAP_WRITE(); //write command
    9. IAP_ERASE(); //erase section command
    10. IAP_ENABLE(); //IAP operation enable
    11. IAP_DISABLE(); //IAP operation disable
    12. //Function
    13. EEPROM_Disable(); //Set eeprom operating disable, return void
    14. EEPROM_Trig(); //set INT state,then send eeprom operating trigger signal, resore INT state,return void
    15. EEPROM_SectorErase(u32 EE_address); //erase EEPROM section, return void
    16. EEPROM_Read_nChar(ui32 EE_address,ui8* destData, u16 number); //read n char from eeprom begine from EE_address,return void
    17. EEPROM_Write_nChar(u32 EE_address,ui8* sourceData,u16 number); //write n char to eeprom begine from EE_address, return void
    18. EEPROM_Write_Integer(u32 EE_address,i16 sourceData); //write integer to eeprom begine from EE_address, return void
    19. EEPROM_Write_Long(u32 EE_address,i32 sourceData); //write long to eeprom begine from EE_address, return void
    20. EEPROM_Write_Float(u32 EE_address,f32 sourceData); //write float to eeprom begine from EE_address,return void
    21. EEPROM_Write_Double(u32 EE_address,f64 sourceData); //write double to eeprom begine from EE_address,return void
    22. EEPROM_Write_String(u32 EE_address,char* sourceStr); //read string from eeprom begine from EE_address, return void
    23. EEPROM_Read_Integer(u32 EE_address,i16* destData); //read integer from eeprom begine from EE_address,return i16
    24. EEPROM_Read_Long(u32 EE_address,i32* destData); //read long from eeprom begine from EE_address, return i32
    25. EEPROM_Read_Float(u32 EE_address,f32* destData); //ead float from eeprom begine from EE_address,return f32
    26. EEPROM_Read_Double(u32 EE_address,f64* destData); //read double from eeprom begine from EE_address, return f64
    27. EEPROM_Read_String(u32 EE_address,char* str); //read string from eeprom begine from EE_address,return void
    28. EEPROM_Read_StringnChar(u32 EE_address,char* str, ui16 number); //read string n char from eeprom begine from EE_address, return void
    29. */
    30. #ifndef __STC32G_EEPROM_H
    31. #define __STC32G_EEPROM_H
    32. #include "config.h"
    33. #include "mtype.h"
    34. #include <STC32G.h>
    35. #define IAP_STANDBY() {IAP_CMD = 0x00;} //idle,no operation command
    36. #define IAP_READ() {IAP_CMD = 0x01;} //read command
    37. #define IAP_WRITE() {IAP_CMD = 0x02;} //write command
    38. #define IAP_ERASE() {IAP_CMD = 0x03;} //erase section command
    39. #define IAP_ENABLE() {IAPEN = 1; IAP_TPS = FOSC / 1000000;} //FOSC defined in config.h
    40. #define IAP_DISABLE() {IAP_CONTR = 0; IAP_CMD = 0; IAP_TRIG = 0; IAP_ADDRH = 0xFF; IAP_ADDRL = 0xFF;}
    41. /*********************************************************
    42. Function: EEPROM_Disable();
    43. Return value: void
    44. Discription: Set eeprom operating disable
    45. Example:
    46. EEPROM_Disable();
    47. *********************************************************/
    48. void EEPROM_Disable();
    49. /****************************************************************
    50. Function: EEPROM_Trig();
    51. Return value: void
    52. Discription: set INT state,then send eeprom operating trigger signal, resore INT state
    53. Example:
    54. EEPROM_Trig();
    55. ****************************************************************/
    56. void EEPROM_Trig();
    57. /*********************************************************
    58. Function: EEPROM_SectorErase(u32 EE_address);
    59. Return value: void
    60. EE_address: eeprom address
    61. Discription: erase EE_address eeprom section
    62. Example:
    63. EEPROM_SectorErase(0x90F);
    64. *********************************************************/
    65. void EEPROM_SectorErase(u32 EE_address);
    66. /*********************************************************
    67. Function: EEPROM_Write_nChar(u32 EE_address,ui8* sourceData,u16 number);
    68. Return value: void
    69. EE_address: eeprom address
    70. sourceData: char arry name to write to eeprom
    71. Discription: write n char to eeprom begine from EE_address
    72. Example:
    73. EEPROM_Write_nChar(0x90F,mCharArray, 30);
    74. *********************************************************/
    75. void EEPROM_Write_nChar(u32 EE_address,ui8* sourceData,u16 number);
    76. /*********************************************************
    77. Function: EEPROM_Read_nChar(ui32 EE_address,ui8* destData, u16 number);
    78. Return value: void
    79. EE_address: eeprom address
    80. destData: char arry name to store read data
    81. Discription: read n char from eeprom begine from EE_address
    82. Example:
    83. EEPROM_Read_nChar(0x90F,mCharArray, 30);
    84. *********************************************************/
    85. void EEPROM_Read_nChar(ui32 EE_address,ui8* destData, u16 number);
    86. /*********************************************************
    87. Function: EEPROM_Write_Integer(u32 EE_address,i16 sourceData);
    88. Return value: void
    89. EE_address: eeprom address
    90. sourceData: data to write to eeprom
    91. Discription: write integer to eeprom begine from EE_address
    92. Example:
    93. EEPROM_Write_Integer(0x90F,1600);
    94. *********************************************************/
    95. void EEPROM_Write_Integer(u32 EE_address,i16 sourceData);
    96. /*********************************************************
    97. Function: EEPROM_Write_Long(u32 EE_address,i32 sourceData);
    98. Return value: void
    99. EE_address: eeprom address
    100. sourceData: data to write to eeprom
    101. Discription: write long to eeprom begine from EE_address
    102. Example:
    103. EEPROM_Write_Long(0x90F,1600);
    104. *********************************************************/
    105. void EEPROM_Write_Long(u32 EE_address,i32 sourceData);
    106. /*********************************************************
    107. Function: EEPROM_Write_Float(u32 EE_address,f32 sourceData);
    108. Return value: void
    109. EE_address: eeprom address
    110. sourceData: data to write to eeprom
    111. Discription: write float to eeprom begine from EE_address
    112. Example:
    113. EEPROM_Write_Long(0x90F,1600.53);
    114. *********************************************************/
    115. void EEPROM_Write_Float(u32 EE_address,f32 sourceData);
    116. /*********************************************************
    117. Function: EEPROM_Write_Double(u32 EE_address,f64 sourceData);
    118. Return value: void
    119. EE_address: eeprom address
    120. sourceData: data to write to eeprom
    121. Discription: write double to eeprom begine from EE_address
    122. Example:
    123. EEPROM_Write_Double(0x90F,1600.53);
    124. *********************************************************/
    125. void EEPROM_Write_Double(u32 EE_address,f64 sourceData);
    126. /*********************************************************
    127. Function: EEPROM_Write_String(u32 EE_address,char* sourceStr);
    128. Return value: void
    129. EE_address: eeprom address
    130. sourceStr: string to write to eeprom
    131. Discription: write string to eeprom begine from EE_address
    132. Example:
    133. EEPROM_Write_String(0x90F,"Hello world");
    134. *********************************************************/
    135. void EEPROM_Write_String(u32 EE_address,char* sourceStr);
    136. /*********************************************************
    137. Function: EEPROM_Read_Integer(u32 EE_address,i16* destData);
    138. Return value: i16
    139. EE_address: eeprom address
    140. destData: addess to store data to read
    141. Discription: read integer from eeprom begine from EE_address
    142. Example:
    143. i16 tem;
    144. EEPROM_Read_Integer(0x90F,&tem);
    145. *********************************************************/
    146. i16 EEPROM_Read_Integer(u32 EE_address,i16* destData);
    147. /*********************************************************
    148. Function: EEPROM_Read_Long(u32 EE_address,i32* destData);
    149. Return value: i32
    150. EE_address: eeprom address
    151. destData: addess to store data to read
    152. Discription: read long from eeprom begine from EE_address
    153. Example:
    154. i32 tem;
    155. EEPROM_Read_Long(0x90F,&tem);
    156. *********************************************************/
    157. i32 EEPROM_Read_Long(u32 EE_address,i32* destData);
    158. /*********************************************************
    159. Function: EEPROM_Read_Float(u32 EE_address,f32* destData);
    160. Return value: f32
    161. EE_address: eeprom address
    162. destData: addess to store data to read
    163. Discription: read float from eeprom begine from EE_address
    164. Example:
    165. f32 tem;
    166. EEPROM_Read_Float(0x90F,&tem);
    167. *********************************************************/
    168. f32 EEPROM_Read_Float(u32 EE_address,f32* destData);
    169. /*********************************************************
    170. Function: EEPROM_Read_Double(u32 EE_address,f64* destData);
    171. Return value: f64
    172. EE_address: eeprom address
    173. destData: addess to store data to read
    174. Discription: read double from eeprom begine from EE_address
    175. Example:
    176. f64 tem;
    177. EEPROM_Read_Double(0x90F,&tem);
    178. *********************************************************/
    179. f64 EEPROM_Read_Double(u32 EE_address,f64* destData);
    180. /*********************************************************
    181. Function: EEPROM_Read_String(u32 EE_address,char* str);
    182. Return value: void
    183. EE_address: eeprom address
    184. str: addess to store data to read
    185. Discription: read string from eeprom begine from EE_address
    186. Example:
    187. char str[20];
    188. EEPROM_Read_String(0x90F,str);
    189. *********************************************************/
    190. void EEPROM_Read_String(u32 EE_address,char* str);
    191. /*********************************************************
    192. Function: EEPROM_Read_StringnChar(u32 EE_address,char* str);
    193. Return value: void
    194. EE_address: eeprom address
    195. str: addess to store read data
    196. number: number of char to read
    197. Discription: read string n char from eeprom begine from EE_address
    198. Example:
    199. char str[20];
    200. EEPROM_Read_StringnChar(0x90F,str, 10);
    201. *********************************************************/
    202. void EEPROM_Read_StringnChar(u32 EE_address,char* str, ui16 number);
    203. #endif

    头文件的开头注释部分列出了定义的宏函数与函数,编程使用是直接复制粘贴,替换参数即可:

    再看下库函数的源码:

    1. /*STC32G_EEPROM.h
    2. Designed by Bill Liu
    3. Version 0.0
    4. Modified last by Bill Liu on 07/18/2022
    5. */
    6. #include "STC32G_EEPROM.h"
    7. //****************************************************************
    8. void EEPROM_Disable()
    9. {
    10. IAP_CONTR = 0;
    11. IAP_CMD = 0;
    12. IAP_TRIG = 0;
    13. IAP_ADDRE = 0xff; //set a disable operate addr
    14. IAP_ADDRH = 0xff; //set a disable operate addr
    15. IAP_ADDRL = 0xff; //set a disable operate addr
    16. }
    17. //End of EEPROM_Disable(void)
    18. //****************************************************************
    19. void EEPROM_Trig()
    20. {
    21. F0 = EA; //save EA state
    22. EA = 0; //INT disable
    23. IAP_TRIG = 0x5A;
    24. IAP_TRIG = 0xA5;
    25. _nop_();
    26. _nop_();
    27. _nop_();
    28. _nop_();
    29. EA = F0; //restore EA
    30. }
    31. //End of EEPROM_Disable()
    32. //****************************************************************
    33. void EEPROM_SectorErase(u32 EE_address)
    34. {
    35. IAP_ENABLE();
    36. IAP_ERASE();
    37. IAP_ADDRL = (u8)EE_address;
    38. IAP_ADDRH = (u8)(EE_address >> 8);
    39. IAP_ADDRE = (u8)(EE_address >> 16);
    40. EEPROM_Trig();
    41. EEPROM_Disable();
    42. }
    43. //End of EEPROM_SectorErase(u32 EE_address)
    44. //****************************************************************
    45. void EEPROM_Write_nChar(u32 EE_address,ui8* sourceData,u16 number)
    46. {
    47. IAP_ENABLE();
    48. IAP_WRITE();
    49. do
    50. {
    51. IAP_ADDRL = (u8)EE_address;
    52. IAP_ADDRH = (u8)(EE_address >> 8);
    53. IAP_ADDRE = (u8)(EE_address >> 16);
    54. IAP_DATA = *sourceData;
    55. EEPROM_Trig();
    56. EE_address++;
    57. sourceData++;
    58. }while(--number);
    59. EEPROM_Disable();
    60. }
    61. //End of EEPROM_Write_nChar(u32 EE_address,ui8* sourceData,u16 number)
    62. //****************************************************************
    63. void EEPROM_Read_nChar(ui32 EE_address,ui8* destData, u16 number)
    64. {
    65. IAP_ENABLE();
    66. IAP_READ();
    67. do
    68. {
    69. IAP_ADDRL = (u8)EE_address;
    70. IAP_ADDRH = (u8)(EE_address >> 8);
    71. IAP_ADDRE = (u8)(EE_address >> 16);
    72. EEPROM_Trig();
    73. *destData = IAP_DATA;
    74. EE_address++;
    75. destData++;
    76. }while(--number);
    77. EEPROM_Disable();
    78. }
    79. //End of EEPROM_Read_nChar(ui32 EE_address,ui8* destData, u16 number)
    80. //****************************************************************
    81. void EEPROM_Write_Integer(u32 EE_address,i16 sourceData)
    82. {
    83. typedef union
    84. {
    85. i16 mData;
    86. char arry[2];
    87. }mySoure;
    88. mySoure source;
    89. source.mData = sourceData;
    90. EEPROM_Write_nChar(EE_address,source.arry,2);
    91. }
    92. //End of EEPROM_Write_Integer(u32 EE_address,i16 sourceData)
    93. //****************************************************************
    94. void EEPROM_Write_Long(u32 EE_address,i32 sourceData)
    95. {
    96. typedef union
    97. {
    98. i32 mData;
    99. char arry[4];
    100. }mySoure;
    101. mySoure source;
    102. source.mData = sourceData;
    103. EEPROM_Write_nChar(EE_address,source.arry,4);
    104. }
    105. //End of EEPROM_Write_Long(u32 EE_address,i32 sourceData)
    106. //*************************************************************
    107. void EEPROM_Write_Float(u32 EE_address,f32 sourceData)
    108. {
    109. typedef union
    110. {
    111. f32 mData;
    112. char arry[4];
    113. }mySoure;
    114. mySoure source;
    115. source.mData = sourceData;
    116. EEPROM_Write_nChar(EE_address,source.arry,4);
    117. }
    118. //End of EEPROM_Write_Float(u32 EE_address,f32 sourceData)
    119. //************************************************************
    120. void EEPROM_Write_Double(u32 EE_address,f64 sourceData)
    121. {
    122. typedef union
    123. {
    124. f32 mData;
    125. char arry[8];
    126. }mySoure;
    127. mySoure source;
    128. source.mData = sourceData;
    129. EEPROM_Write_nChar(EE_address,source.arry,8);
    130. }
    131. //End of EEPROM_Write_Double(u32 EE_address,f64 sourceData)
    132. //***********************************************************
    133. void EEPROM_Write_String(u32 EE_address,char* sourceStr)
    134. {
    135. EEPROM_Write_nChar(EE_address,sourceStr,strlen(sourceStr));
    136. EEPROM_Write_nChar(EE_address+strlen(sourceStr),0,1);
    137. }
    138. //End of EEPROM_Write_String(u32 EE_address,char* sourceStr)
    139. //***********************************************************************
    140. i16 EEPROM_Read_Integer(u32 EE_address,i16* destData)
    141. {
    142. typedef union
    143. {
    144. i16 mData;
    145. char arry[2];
    146. }myDest;
    147. myDest dest;
    148. EEPROM_Read_nChar(EE_address,dest.arry, 2);
    149. *destData = dest.mData;
    150. return *destData;
    151. }
    152. //End of EEPROM_Read_Integer(u32 EE_address,i16* destData)
    153. //***********************************************************************
    154. i32 EEPROM_Read_Long(u32 EE_address,i32* destData)
    155. {
    156. typedef union
    157. {
    158. i32 mData;
    159. char arry[4];
    160. }myDest;
    161. myDest dest;
    162. EEPROM_Read_nChar(EE_address,dest.arry, 4);
    163. *destData = dest.mData;
    164. return *destData;
    165. }
    166. //End of EEPROM_Read_Long(u32 EE_address,i32* destData)
    167. //***********************************************************************
    168. f32 EEPROM_Read_Float(u32 EE_address,f32* destData)
    169. {
    170. typedef union
    171. {
    172. f32 mData;
    173. char arry[4];
    174. }myDest;
    175. myDest dest;
    176. EEPROM_Read_nChar(EE_address,dest.arry, 4);
    177. *destData = dest.mData;
    178. return *destData;
    179. }
    180. //End of EEPROM_Read_Float(u32 EE_address,f32* destData)
    181. //***********************************************************************
    182. f64 EEPROM_Read_Double(u32 EE_address,f64* destData)
    183. {
    184. typedef union
    185. {
    186. f64 mData;
    187. char arry[8];
    188. }myDest;
    189. myDest dest;
    190. EEPROM_Read_nChar(EE_address,dest.arry, 8);
    191. *destData = dest.mData;
    192. return *destData;
    193. }
    194. //End of EEPROM_Read_Double(u32 EE_address,f64* destData)
    195. //***********************************************************************
    196. void EEPROM_Read_String(u32 EE_address,char* str)
    197. {
    198. ui8 tem = 0xFF;
    199. memset(str,0, strlen(str));
    200. while(tem != 0)
    201. {
    202. EEPROM_Read_nChar(EE_address,&tem, 1);
    203. *str = tem;
    204. str++;
    205. EE_address++;
    206. }
    207. }
    208. //End of EEPROM_Read_String(u32 EE_address,char* str)
    209. //***********************************************************************
    210. void EEPROM_Read_StringnChar(u32 EE_address,char* str, ui16 number)
    211. {
    212. memset(str,0, strlen(str));
    213. EEPROM_Read_nChar(EE_address, str, number);
    214. }
    215. //End of EEPROM_Read_nString(u32 EE_address,char* str, ui16 number)

    三  调试验证

    下面写一个程序,调用库函数,先将数据写入EEPROM,然后再读出,将读出的数据通过串口发送到串口助手,显示出来从而确定其正确性。

    maim.h代码:

    1. /*main.h
    2. Designed by Bill Liu
    3. Version 0.0
    4. Modified last by Bill Liu on 06/22/2022
    5. */
    6. #ifndef __MAIN_H__
    7. #define __MAIN_H__
    8. //#include "myport.h"
    9. #include "STC32G_GPIO.h"
    10. //#include "STC32G_PWM.h"
    11. #include "STC32G_UART.h"
    12. //#include "STC32G_UART.h"
    13. //#include "STC32G_ADC.h"
    14. #include "STC32G_EEPROM.H"
    15. #endif

    config.h代码:

    1. ifndef __CONFIG_H__
    2. #define __CONFIG_H__
    3. #define PRINTF_SEGLED //printfÊä³öÖض¨Ïòµ½ISPÏÂÔØÈí¼þÖеÄ7¶ÎÊýÂë¹Ü
    4. //#define PRINTF_HID //printfÊä³öÖ±½ÓÖض¨Ïòµ½USB HID½Ó¿Ú
    5. #define FOSC 30000000UL
    6. //#define F11_0592MHz
    7. //#define F12MHz
    8. //#define F18_432MHz //18.432MHz
    9. //#define F20MHz
    10. //#defimne F22_1184MHz //22.1184MHz
    11. //#define F24MHz
    12. //#define F27MHz
    13. #define F30MHz
    14. //#define F33MHz
    15. //#define F33_1776MHz //33.1776MHz
    16. //#define F35MHz
    17. //********************************************************
    18. void SysInit(); //init System speed fastest
    19. #endif

    config.c代码:

    1. /*config.c
    2. Designed by Bill Liu
    3. Version 0.0
    4. Modified last by Bill Liu on 06/22/2022
    5. */
    6. #include <STC32G.h>
    7. #include "config.h"
    8. //********************************************************
    9. void SysInit() //init System speed fastest
    10. {
    11. EAXFR = 1; //visit XFR enable
    12. CKCON = 0x00; //set outer data bus speed fastest
    13. WTST = 0x00; //CPU wait 0 to run program
    14. }
    15. //End of SysInit()

    main.c代码:

    1. /*main.c
    2. Designed by Bill Liu
    3. Version 0.0
    4. Modified last by Bill Liu on 11/26/2022
    5. */
    6. #include "main.h"
    7. //#include "config.h"
    8. //#include "STC32G_Timer.h"
    9. #include "STC32G_Delay.h"
    10. //#include "STC32G_comparator.h"
    11. ui8 t1 = 250;
    12. ui16 t2 = 65533;
    13. i32 t3 = -165533;
    14. f32 t4 = 51.25;
    15. f64 t5 = -3.14;
    16. ui8 t6 = 0;
    17. ui16 t7 = 0;
    18. i32 t8 = 0;
    19. f32 t9 = 0;
    20. f64 t10 = 0;
    21. ui8 str[20] = {0};
    22. ui8 str1[20] = "Hello World";
    23. void main()
    24. {
    25. SysInit();
    26. Uart1_Init(VBAUD_8BITS,G1, 0, 9600);
    27. EEPROM_SectorErase(0x00);
    28. EEPROM_Write_nChar(0x00,&t1,1);
    29. EEPROM_Write_Integer(0x01,t2);
    30. EEPROM_Write_Long(0x03,t3);
    31. EEPROM_Write_Float(0x07,t4);
    32. EEPROM_Write_Double(0x0B,t5);
    33. EEPROM_Write_String(0x13,str1);
    34. while(1)
    35. {
    36. EEPROM_Read_nChar(0x00,&t6,1);
    37. LongToString(t6,str);
    38. Uart1_SendString(str);
    39. Uart1_SendString("\r\n");
    40. EEPROM_Read_Integer(0x01,&t7);
    41. LongToString(t7,str);
    42. Uart1_SendString(str);
    43. Uart1_SendString("\r\n");
    44. EEPROM_Read_Long(0x03,&t8);
    45. LongToString(t8,str);
    46. Uart1_SendString(str);
    47. Uart1_SendString("\r\n");
    48. EEPROM_Read_Float(0x07,&t9);
    49. FloatString(t9,str,2);
    50. Uart1_SendString(str);
    51. Uart1_SendString("\r\n");
    52. EEPROM_Read_Double(0x0B,&t10);
    53. FloatString(t10,str,2);
    54. Uart1_SendString(str);
    55. Uart1_SendString("\r\n");
    56. EEPROM_Read_String(0x13,str);
    57. Uart1_SendString(str);
    58. Uart1_SendString("\r\n");
    59. Uart1_SendString("\r\n");
    60. Delayxms(1000);
    61. }
    62. }
    63. //End of main()

    编译结果:

     下载到单片机的设置如下:

    打开串口,串口助手中的结果如下:

     

     可以看出数据写入与读出正确,其中3.14变成了3.15并非写入与读出错误,而是单片机处理浮点数的不足。

  • 相关阅读:
    Android系统的特性
    C++_抽象类
    Springboot整合shiro安全框架+swagger
    技术团队:给代码评审发起者的4个建议
    C语言之文件操作
    java计算机毕业设计竞赛信息发布及组队系统源码+数据库+lw文档+系统
    [附源码]Python计算机毕业设计Django基于vue的软件谷公共信息平台
    Ansible的脚本 --- playbook 剧本
    使用socket对http站点的访问
    【JavaScript】DOM查询(子节点、父节点、兄弟节点)源码详解
  • 原文地址:https://blog.csdn.net/billliu66/article/details/128053591