• CH559L单片机ADC多通道采样数据串口打印案例


    CH559L单片机ADC介绍以及ADC采样案例


    • ✨本案例基于Keil环境下开发。
    • 📌案例来源WCH官网地址:https://www.wch.cn/products/CH559.html
      在这里插入图片描述
    根据ADC采样通道的选择分为:单通道采样和多通道采样,根据ADC数据的转换处理分:DMA方式自动AD采样和手动方式AD采样。

    📑CH559 ADC简介

    CH559 芯片提供 10 位或 11 可选的逐次逼近型模拟数字转换器。该转换器具有 8 个模拟信号输入通道,可以分时采集。ADC 主要特性:

    1. 可选 10 位或 11 位分辨率;
    2. ADC 模拟输入电压范围:0 到 VDD33;
    3. 最高 1MSPS 采样速率;
    4. 支持自动交替通道模式,用于在两个输入通道之间进行自动交替转换;
    5. 内置 2 级 FIFO,支持自动采样和 DMA。

    ADC 相关寄存器介绍

    • P1_IE: P1 端口输入使能寄存器 。
      在这里插入图片描述

    该寄存器为0-7bit设置位,P1.x 引脚输入使能,该位为 0 则引脚用于 ADC 模拟输入,禁止数字输入;该位为 1 则使能数字输入 。

    • ADC_EX_SW:ADC 扩展模拟开关控制寄存器
      在这里插入图片描述

    • ADC_SETUP:ADC 设置寄存器
      在这里插入图片描述

    • ADC_CHANN :ADC 通道选择寄存器
      在这里插入图片描述

    • ADC_CTRL:ADC 控制寄存器
      在这里插入图片描述

    • ADC_STAT :ADC 状态寄存器
      在这里插入图片描述

    • ADC_CK_SE:ADC 时钟分频设置寄存器
      在这里插入图片描述

    • ADC_DMA_CN:DMA 剩余计数寄存器,

    当前 DMA 剩余计数,可预置初值,DMA 操作后自动减少。

    • ADC_DMA :ADC_DMA_AL 和 ADC_DMA_AH 组成 16 位 SFR
      在这里插入图片描述

    📝ADC 采样模式配置步骤:

    1. 设置 ADC 设置寄存器 ADC_SETUP 中的 bADC_POWER_EN 位为 1,开启 ADC 模块。
    2. 设置时钟分频设置寄存器 ADC_CK_SE,选择时钟频率,频率最高 12MHz,建议不低于 1MHz。
    3. 清空 FIFO 中的已有数据;如果需要用到中断或者 DMA,那么在此处进行相关设置。
    4. 对于自动采样模式,那么应该先设置 ADC 通道选择寄存器 ADC_CHANN。
    5. 设置 ADC 控制寄存器 ADC_CTRL 中的 bADC_SAMPLE 和 MASK_ADC_CYCLE,如果 MASK_ADC_CYCLE
      设置为 0,则为手动采样模式;如果 MASK_ADC_CYCLE 设置为非 0 值,则为自动采样模式,此
      时 MASK_ADC_CYCLE 就是连续不断自动采样的时钟周期。
    6. 对于手工采样模式,设置 ADC 通道选择寄存器 ADC_CHANN,选择 ADC 模拟信号输入通道。
    7. 如果是手动采样模式,那么需要通过设置 bADC_SAMPLE 位为 1 并延时至少一个 ADC 时钟周期后
      再清 0,完成一次模拟信号采样并启动一次 ADC 转换。
    8. 等待 ADC 状态寄存器 ADC_STAT 的 bADC_IF_ACT 位为 1,表示 ADC 转换结束,可通过 ADC_FIFO
      读取结果数据。
    9. 或读取 ADC 状态寄存器 ADC_STAT 的 MASK_ADC_FIFO_CNT 获得 FIFO 计数,再通过 ADC_FIFO 读
      取若干数据,建议丢弃第一个 ADC 结果数据,因为有可能采样不完全。
    10. 如需 DMA 步骤:设置 ADC_DMA 为用户定义的数据缓冲区的起始地址值,设置 ADC_DMA_CN 为用
      户定义的 DMA 剩余计数,并设置 ADC_SETUP 中的 bADC_DMA_EN 位为 1,即开启 DMA 功能。
    11. ADC 结果数据共 12 位,其中位 0~位 10 为 ADC 数值,位 11 是标志位,位 12~位 15 始终为 0。
      对于手工选择通道模式,位 11 始终为 0;对于自动交替通道模式,位 11 表示该 ADC 数值的通
      道识别标志,参考 bADC_CHANN_ID 说明。

    ⛳DMA方式自动ADC采样案例测试

    • 官方所给的示例代码如下:

    来自:ADCAUTODMA.C文件

    
    /********************************** (C) COPYRIGHT *******************************
    * File Name          : ADCAutoDMA.C
    * Author             : WCH
    * Version            : V1.3
    * Date               : 2016/6/24
    * Description        : CH559的ADC自动DMA方式采样操作,设置采样通道为0和1轮测,采样位数设置为11位               				   
    *******************************************************************************/
    #include "..\DEBUG.C"                                                          //调试信息打印
    #include "..\DEBUG.H"
    
    #define ADCCount 30
    UINT16X	ADCbuf[ ADCCount ];// _at_ 0x0040 ;  //不选择存入xdata存储区,ADC采样数据
    UINT8 Flag;
    
    #pragma  NOAREGS
    
    /*******************************************************************************
    * Function Name  : InitADCInterrupt()
    * Description    : ADC中断初始化
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void InitADCInterrupt()
    {
    //  ADC_SETUP |= bADC_IE_FIFO_OV;                                             //使能FIFO溢出中断
    //  ADC_SETUP |= bADC_IE_AIN7_LOW;                                            //使能AIN7低电平中断
    //  ADC_SETUP |= bADC_IE_ACT;                                                 //ADC完成中断
        IE_ADC = 1;                                                               //使能ADC中断
    }
    
    /*******************************************************************************
    * Function Name  : InitADCAuto()
    * Description    : ADC自动采样初始化
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void InitADCAuto()
    {
    	 //P10-P17对应AIN0~AIN7:8 通道 ADC 模拟信号输入。
    	
        P1_IE = 0x00; //关闭P1口其他数据功能,如果只用部分通道,可根据需要设定,否则影响IO正常使用
        ADC_SETUP |= bADC_POWER_EN;  //ADC电源使能
        ADC_CK_SE |= (MASK_ADC_CK_SE & 0x0C);//设置12分频
        ADC_CTRL &= ~MASK_ADC_CYCLE;
        ADC_CTRL |= 0x0C;  //设置ADC自动采样周期
    	//ADC channel control mode
        ADC_CTRL &= ~bADC_CHANN_MOD1; //1101 1111                              
        ADC_CTRL |= bADC_CHANN_MOD0;  //0001 0000  自动通道选择通道0和通道1
    
        ADC_EX_SW |= bADC_RESOLUTION;//采样位数11bit
    //	ADC_EX_SW &= ~bADC_RESOLUTION; //采样位数10bit
        mDelayuS(100);  //确保ADC正常启动	
    }
    
    /*******************************************************************************
    * Function Name  : InitADCDMA(UINT16 addr,UINT8 num)
    * Description    : ADC的DMA初始化
    * Input          : UINT16 addr,DMA起始地址
                       UINT8 num,DMA剩余计数
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void InitADCDMA( )
    {
        ADC_DMA = ADCbuf;                                                         //设置DMA起始地址
        ADC_DMA_CN = ADCCount;                                                    //设置DMA剩余计数
        ADC_SETUP |= bADC_DMA_EN;                                                 //使能DMA和中断
    }
    
    /*******************************************************************************
    * Function Name  : ADCInterrupt(void)
    * Description    : ADC 中断服务程序
    *******************************************************************************/
    void ADCInterrupt( void ) interrupt INT_NO_ADC using 1                        //ADC中断服务程序,使用寄存器组1
    {
    	printf("%02u  ",(UINT16)ADC_STAT);//ADC 状态寄存器 :11111000 
        if(ADC_STAT & bADC_IF_DMA_END)                                            //DMA完成中断
        {
        	Flag = 1;
        	ADC_STAT |= bADC_IF_DMA_END;                                          //清中断
        }
        if(ADC_STAT & bADC_IF_FIFO_OV)                                            //ADC的FIFO溢出中断
        {
        	ADC_STAT |= bADC_IF_FIFO_OV;                                          //清中断
        }
        if(ADC_STAT & bADC_IF_AIN7_LOW)                                           //AIN7低电平中断
        {
        	ADC_STAT |= bADC_IF_AIN7_LOW;                                         //清中断
        }
        if(ADC_STAT & bADC_IF_ACT)                                                //ADC完成中断
        {
        	ADC_STAT |= bADC_IF_ACT;                                              //清中断
        }
    }
    
    void main( ) 
    {
        UINT8 i;
        mDelaymS(30);  //上电延时,等待内部晶振稳定,必加 
      CfgFsys( ); //CH559时钟选择配置
        mInitSTDIO( ); //串口0,可以用于调试
        printf("CH559L start ...\n"); 
        Flag = 0;
    //ADC采样有8个通道,在P1口,通道n 分别ADC_CHANN对应 (0x01 << n) ,如通道0是0x01,通道1是0x02依次类推	
    //	ADC_CHANN =0x01 << 5;
    	InitADCInterrupt();  //ADC自动采样初始化
        InitADCAuto();//ADC中断初始化
        InitADCDMA();
    
        EA = 1; //开启全局中断
        while(1)
        { 
          if(Flag)
    	    {
    	    	for(i=1;i<29;i++)
    	    	{
    	    	    printf("%04u  ",ADCbuf[i]); //初次采样值建议丢弃
    	    	}
    	    	Flag = 0;
    				mDelaymS(1000); 
    	    }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 串口打印的结果:
      在这里插入图片描述

    DMA方式自动AD采样通道选择说明

    • 自动通道选择,配置方法如下:
    • 自动交替通道模式,在 AIN0 和 AIN1 之间自动交替切换
        ADC_CTRL &= ~bADC_CHANN_MOD1;   //1101 1111                                    
       ADC_CTRL |= bADC_CHANN_MOD0; //0001 0000自动通道选择:通道0和通道1
    
    
    • 1
    • 2
    • 3
    • 自动交替通道模式,在 AIN6 和 AIN4 之间自动交替切换
        ADC_CTRL |= bADC_CHANN_MOD1;   //0001 0000                                    
       ADC_CTRL &= ~bADC_CHANN_MOD0; //1101 1111自动通道选择:通道6和通道4
    
    • 1
    • 2
    • 自动交替通道模式,在 AIN6 和 AIN7 之间自动交替切换
        ADC_CTRL |= bADC_CHANN_MOD1;   //0001 0000                                    
       ADC_CTRL |= bADC_CHANN_MOD0; //0010 0000 自动通道选择:通道6和通道7
    
    • 1
    • 2
    • 手工选择通道,配置方法如下:
    	ADC_CTRL &= ~bADC_CHANN_MOD0; //	手工选择通道
    	//ADC采样有8个通道,在P1口,通道n 分别ADC_CHANN对应 (0x01 << n) ,如通道0是0x01,通道1是0x02依次类推	
    	ADC_CHANN =0x01 << 1;//手工指定通道1
    //ADC_CHANN = 0x02;	//同上
    
    • 1
    • 2
    • 3
    • 4
    并未实现DMA自动采样并连续打印的效果,只有在复位后重启后才打印一次采用的数据。上面的打印数据是烧录官方所提供的Hex文件,打印的结果。本想自己来找出bug来补上,看了半天的CH559手册上的ADC寄存器真的很难看懂, 以前吐槽STC单片机手册都是1000+页的资料难翻阅,现在看到了WCH的73页的数据手册,感觉不够看,关键是有些看不懂。感叹STC单片机手册详细,STM32的描述的明白。目前还没有找到清标志位的地方。

    ⛳DMA多次采样注意事项

    • 在官方所给出的DMA采样案例中,采样的30次的10/11位ADC模数转换的数据存进16位地址线的xdata 区域,直接进行存储是不对的,打印出来的数值是16位的数值,最大值为65536,而CH559L单片机8个通道只支持10/11位的ADC模数转换,如果选择10位的采样方式,那么最大采样值:1024,如果选择11位采样方式,最大采样值:2048,不是不可以这样存储,是需要在存储前需要对该存储地址位进行清零操作,否则读取的数据就不对了。
    UINT16X	ADCbuf[ ADCCount ];// _at_ 0x0040 ; //存储ADC采样数据
        while(1)
        { 
          if(Flag)
    	    {
    				ADC_SETUP &= ~bADC_DMA_EN;//关闭DMA和中断
    	    	for(i=1;i<5;i++)
    	    	{
    
    	    	    printf("%hu  ",ADCbuf[i]);//初次和最后一次采样值建议丢弃	
    					total +=ADCbuf[i];					
    	    	}
    				total =total/4;
    				printf("ADC_value=:%lu  \n",total);//初次和最后一次采样值建议丢弃				
    //				memset(ADCbuf, 0, sizeof(ADCbuf));//清空数组
    				total=0;
    	    	Flag = 0;
    				ADC_DMA = ADCbuf; //设置DMA起始地址
    				ADC_DMA_CN=ADCCount;
    				ADC_SETUP |= bADC_DMA_EN;//使能DMA和中断
    //				InitADCDMA( );
    	    }
    			 mDelaymS(1000);			
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    🎯手动采样案例

    
    /********************************** (C) COPYRIGHT *******************************
    * File Name          : ADCManual.C
    * Author             : WCH
    * Version            : V1.3
    * Date               : 2016/6/24
    * Description        : CH559的手动采样ADC操作,支持通道切换
    *******************************************************************************/
    
    #include "..\DEBUG.C"                                                          //调试信息打印
    #include "..\DEBUG.H"
    
    UINT8 ADCChannel[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};               //ADC通道1-8
    
    // #define _INT_  1 //ADC中断方式
    
    
    //#define mul_channel  //启用代表0-8个通道一起采集,不启用则单通道采集
    
    #define Single_channel 2 //如果选择单通道数据采集,指定单通道号:0-7
    
    #pragma  NOAREGS
    
    
    /*******************************************************************************
    * Function Name  : InitADCManual()
    * Description    : ADC手动采用初始化
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void InitADCManual()
    {
        P1_IE = 0x00;                                                              //关闭P1口其他数据功能,如果只用到部分采样通道,其余置1,否则影响IO功能
        ADC_SETUP |= bADC_POWER_EN;                                                //ADC电源使能
        ADC_CK_SE = 0x02;                                                          //设置分频
        ADC_CTRL &= ~MASK_ADC_CYCLE;                                               //选择手动采样
        ADC_CTRL &= ~(bADC_CHANN_MOD1 | bADC_CHANN_MOD0);                          //手动选择通道
        ADC_CHANN = ADCChannel[0];                                                 //选通通道1
        ADC_EX_SW |= bADC_RESOLUTION;                                              //采样位数11bit
    //	ADC_EX_SW &= ~bADC_RESOLUTION;                                             //采样位数10bit
        mDelayuS(100);                                                             //确保ADC正常启动
    }
    
    /*******************************************************************************
    * Function Name  : ADCChanelChange()
    * Description    : ADC通道切换
    * Input          : UINT8 Chanel
    * Output         : None
    * Return         : UINT16 ADCValue
    *******************************************************************************/
    UINT16 ADCChanelChange(UINT8 Chanel)
    {
      UINT16 ADCValue = 0;
    	ADC_CHANN = Chanel;                                                          //切换ADC通道
    // 	ADC_EX_SW |= bADC_RESOLUTION;                                              //ADC采集位数
    	mDelayuS(10);                                                                //可选,等待通道切换成功
    	ADC_CTRL |= bADC_SAMPLE;                                                     //手动产生采样脉冲
    	mDelayuS(5);
    	ADC_CTRL &= ~bADC_SAMPLE;	
    	while((ADC_STAT & bADC_IF_ACT) == 0);                                        //非中断方式,等待采集完成
    	ADC_STAT |= bADC_IF_ACT;
    	ADCValue = ADC_FIFO;
      return ADCValue;                                                             //返回采样值
    }
    
    #ifdef _INT_
    /*******************************************************************************
    * Function Name  : InitADCInterrupt()
    * Description    : ADC中断初始化
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void InitADCInterrupt()
    {
        ADC_SETUP |= bADC_IE_FIFO_OV;                                              //使能FIFO溢出中断
    //	ADC_SETUP |= bADC_IE_AIN7_LOW;                                             //使能AIN7低电平中断
        ADC_SETUP |= bADC_IE_ACT;                                                  //ADC完成中断
        IE_ADC = 1;                                                                //使能ADC中断
    }
    
    /*******************************************************************************
    * Function Name  : ADCInterrupt(void)
    * Description    : ADC 中断服务程序
    *******************************************************************************/
    void	ADCInterrupt( void ) interrupt INT_NO_ADC using 1                       //ADC中断服务程序,使用寄存器组1
    { 
        UINT16 ADCValue = 0;
        if(ADC_STAT & bADC_IF_ACT)                                                //ADC完成中断
        {  
        	ADC_STAT |= bADC_IF_ACT;                                                //清中断                                         
        }
        ADCValue = ADC_FIFO;
    	  printf("FIFOCnt:%02u  ADC_DATA:%04u  \n",(UINT16)(ADC_STAT&3),(UINT16)ADC_FIFO);
    /* 如果需要继续采样,则使能下面程序,产生手工采样脉冲 */
    #if 1
        ADC_CTRL |= bADC_SAMPLE;                                                  //手动产生采样脉冲
        mDelayuS(2);
        ADC_CTRL &= ~bADC_SAMPLE;	
    #endif
    }
    #endif
    
    void main( ) 
    {
        UINT16 ADCDat;
        UINT8 i = 0;
      CfgFsys( );                                                                //CH559时钟选择配置 
        mDelaymS(5);                                                               //等待内部晶振稳定
        
        mInitSTDIO( );                                                             //串口0,可以用于调试
        printf("start ...\n"); 
    //ADC采样有8个通道,在P1口,通道n 分别ADC_CHANN对应 (0x01 << n) ,如通道0是0x01,通道1是0x02依次类推		
        InitADCManual();                                                           //ADC手动采样初始化
    		ADCDat=ADC_FIFO;                                                           //ADC开启后,FIFO中有一个无效的采样值,取出丢弃
    	  printf("FIFOCnt:%02u  InvalidADC_DATA:%04u  \n",(UINT16)(ADC_STAT&3),(UINT16)ADCDat);	
    #ifdef _INT_
        InitADCInterrupt();                                                        //ADC中断初始化
        EA = 1;                                                                    //开启全局中断
    	
        ADC_CTRL |= bADC_SAMPLE;                                                   //手动产生采样脉冲
        mDelayuS(2);
        ADC_CTRL &= ~bADC_SAMPLE;	
    #endif	
        while(1)                                                                   //可以如果不用中断方式,可以查询bADC_IF_ACT位,为1代表手动采样成功
        {
    #ifndef _INT_
    		    ADC_SETUP|=bADC_POWER_EN;  			//开启ADC电源
    #ifdef mul_channel			
            for(i=0;i<8;i++){
              ADCDat = ADCChanelChange(ADCChannel[i]);                             //通道i采样
    	        printf("FIFOCnt:%02u  ADC_DATA_P1%u:%04u  \n",(UINT16)(ADC_STAT&3),(UINT16)i,(UINT16)ADCDat);			
            }
    #else
       ADCDat = ADCChanelChange(ADCChannel[Single_channel]);  
    				printf("FIFOCnt:%02u  ADC_DATA_P1%u:%04u  \n",(UINT16)(ADC_STAT&3),(UINT16)1,(UINT16)ADCDat);	
    #endif			
    	      ADC_SETUP&=~bADC_POWER_EN;                                             //关闭ADC电源
            printf("-----我是分隔符------\n");
            mDelaymS(1000);				
    //如果同时采样多个通道,可以在采样完成后通过bADC_CHANN_ID区分采样值所属的通道
    #endif
        }                                                                 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 指定单通道P1_2采样数据串口数据打印的结果
      在这里插入图片描述
    • 将上面的代码改成多通道一起采用并打印;

    启用和注释对应的宏定义即可

    #define mul_channel  //启用代表0-8个通道一起采集,不启用则启用下面的单通道采集
    //#define Single_channel 2 //如果选择单通道数据采集,指定单通道号:0-7
    
    • 1
    • 2

    在这里插入图片描述

    在这里源码就不提供了,根据上面提供的官方的参考源码以及上面附的代码修改对应内容即可验证。

  • 相关阅读:
    腾讯待办是不是停了?怎么用其它提醒软件查看导出的ics文件
    Java Servlet生成html页面
    MySQL该使用哪种CPU架构服务器?
    vue3 setup(基础版)
    SpringBoot+vue+elementui实现前后端分离的化妆品销售商城网站
    Linux - 内核 - 安全机制 - 内存页表安全
    惯导标定国内外研究现状小结(删减版)
    windows不能修改hosts?有这篇文章就够了
    房贷计算器微信小程序原生语言
    liunx 基础命令应用
  • 原文地址:https://blog.csdn.net/weixin_42880082/article/details/127129591