HC32F460开发之rtthread+finsh组件的移植

HC32F460开发之rtthread+finsh组件的移植文章目录前言一、RT-Thread简介二、rtthread的移植1.裸机例程2.RT-Thread下载2.RT-Thread移植总结前言对于从事单片机的开发人员,操作系统可以说是绕不过的一个必修课程。在稍复杂的应用开发中,一个好的操作系统可以帮助我们将单片机的资源最大化的利用起来,而系统提供的各种API接口也可以可靠地帮我们实现各种应用逻辑功能。日常生活里,在各种各样的电子设备中,操作系统被广泛地应用,常见的有Linux,ucos,以及现在在各种物联网设备中被广泛应用的freertos,RT-Thre

大家好,又见面了,我是你们的朋友全栈君。


前言

对于从事单片机的开发人员,操作系统可以说是绕不过的一个必修课程。在稍复杂的应用开发中,一个好的操作系统可以帮助我们将单片机的资源最大化的利用起来,而系统提供的各种API接口也可以可靠地帮我们实现各种应用逻辑功能。日常生活里,在各种各样的电子设备中,操作系统被广泛地应用,常见的有Linux,ucos,以及现在在各种物联网设备中被广泛应用的freertos,RT-Thread等。本文主要从裸机工程开始,一步步介绍RT-Thread系统的移植。


一、RT-Thread简介

RT-Thread是一款开源的嵌入式实时操作系统,作为一款国产的操作系统,经过10余年的发展,RT-Thread逐渐得到了市场的认可,开始被广泛应用在智能家电,智能穿戴设备中。相对于其他的RTOS,RT-Thread最大的特点就是有着丰富的中间层组件的支持,我们可以根据产品功能的需要,移植各种组件,打造出自己需要的系统。
在这里插入图片描述
具体的介绍就不多说了,有兴趣了解的朋友可以自己去看官方介绍。
官方介绍

二、rtthread的移植

1.裸机例程

在移植RT-Thread前,我们需要一个能正常运行的裸机工程,同时为了方便后续的调试,我们还需要一个USART串口作为一个调试口。从开发板的原理图上我们可以知道,板子上有两路LED可供驱动,并且选择PB0和PB2作为调试串口。
在这里插入图片描述
在这里插入图片描述
参考开发板提供的例程,(例程可以到华大官网下载官方例程),完成对应的功能,代码如下:
LED驱动部分

/* LED0 Port/Pin definition */
#define LED0_PORT (PortE)
#define LED0_PIN (Pin06)

#define LED0_ON() (PORT_SetBits(LED0_PORT, LED0_PIN))
#define LED0_OFF() (PORT_ResetBits(LED0_PORT, LED0_PIN))
#define LED0_TOGGLE() (PORT_Toggle(LED0_PORT, LED0_PIN))

/* LED1 Port/Pin definition */
#define LED1_PORT (PortA)
#define LED1_PIN (Pin07)

#define LED1_ON() (PORT_SetBits(LED1_PORT, LED1_PIN))
#define LED1_OFF() (PORT_ResetBits(LED1_PORT, LED1_PIN))
#define LED1_TOGGLE() (PORT_Toggle(LED1_PORT, LED1_PIN))

void LedInit(void)
{ 
   
	stc_port_init_t stcPortInit;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcPortInit);

	stcPortInit.enPinMode = Pin_Mode_Out;
	/* LED0 Port/Pin initialization */
    LED0_OFF();
    PORT_Init(LED0_PORT, LED0_PIN, &stcPortInit);

	/* LED1 Port/Pin initialization */
    LED1_OFF();
    PORT_Init(LED1_PORT, LED1_PIN, &stcPortInit);
}

USART驱动部分

/* USART channel definition */
#define DEBUG_USART_CH (M4_USART1)
	
/* USART baudrate definition */
#define DEBUG_USART_BAUDRATE (115200ul)

/* USART RX Port/Pin definition */
#define DEBUG_USART_RX_PORT (PortB)
#define DEBUG_USART_RX_PIN (Pin02)
#define DEBUG_USART_RX_FUNC (Func_Usart1_Rx)
	
/* USART TX Port/Pin definition */
#define DEBUG_USART_TX_PORT (PortB)
#define DEBUG_USART_TX_PIN (Pin00)
#define DEBUG_USART_TX_FUNC (Func_Usart1_Tx)

void DebugUsartInit(void)
{ 
   
    en_result_t enRet = Ok;
    uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \
                             PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4;
    const stc_usart_uart_init_t stcInitCfg = { 
   
        UsartIntClkCkNoOutput,
        UsartClkDiv_1,
        UsartDataBits8,
        UsartDataLsbFirst,
        UsartOneStopBit,
        UsartParityNone,
        UsartSampleBit8,
        UsartStartBitFallEdge,
        UsartRtsEnable,
    };

    /* Enable peripheral clock */
    PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);

    /* Initialize USART IO */
    PORT_SetFunc(DEBUG_USART_RX_PORT, DEBUG_USART_RX_PIN, DEBUG_USART_RX_FUNC, Disable);
    PORT_SetFunc(DEBUG_USART_TX_PORT, DEBUG_USART_TX_PIN, DEBUG_USART_TX_FUNC, Disable);

    /* Initialize UART */
    enRet = USART_UART_Init(DEBUG_USART_CH, &stcInitCfg);
    if (enRet != Ok)
    { 
   
        while (1)
        { 
   
        }
    }

    /* Set baudrate */
    enRet = USART_SetBaudrate(DEBUG_USART_CH, DEBUG_USART_BAUDRATE);
    if (enRet != Ok)
    { 
   
        while (1)
        { 
   
        }
    }

    /*Enable RX && TX function*/
    USART_FuncCmd(DEBUG_USART_CH, UsartRx, Enable);
    USART_FuncCmd(DEBUG_USART_CH, UsartTx, Enable);
}

在PC上开发我们习惯使用C库中的printf做输出和调试,而将printf重定向为串口输出的方法,就是需要重新实现fputc()这个函数。在华大的驱动库中,我们可以看到官方已经帮我们实现了相关的功能(感兴趣的可以自行查看官方代码hc32f460_utility.c,这里不做讲解),而我们所需要做的,就是调用官方的API接口,注册对应的串口驱动,就可以在我们的工程中使用printf函数做输出和调试。最后代码如下:
main.c

/** * @brief BSP clock initialize. * Set board system clock to MPLL@200MHz * @param None * @retval None */
void BSP_CLK_Init(void)
{ 
   
    stc_clk_sysclk_cfg_t    stcSysClkCfg;
    stc_clk_xtal_cfg_t      stcXtalCfg;
    stc_clk_mpll_cfg_t      stcMpllCfg;
    stc_sram_config_t       stcSramConfig;

    MEM_ZERO_STRUCT(stcSysClkCfg);
    MEM_ZERO_STRUCT(stcXtalCfg);
    MEM_ZERO_STRUCT(stcMpllCfg);
    MEM_ZERO_STRUCT(stcSramConfig);

    /* Set bus clk div. */
    stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;
    stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
    stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
    stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
    stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
    stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
    stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;
    CLK_SysClkConfig(&stcSysClkCfg);

    /* Config Xtal and Enable Xtal */
    stcXtalCfg.enMode = ClkXtalModeOsc;
    stcXtalCfg.enDrv = ClkXtalLowDrv;
    stcXtalCfg.enFastStartup = Enable;
    CLK_XtalConfig(&stcXtalCfg);
    CLK_XtalCmd(Enable);

    /* sram init include read/write wait cycle setting */
    stcSramConfig.u8SramIdx = Sram12Idx | Sram3Idx | SramHsIdx | SramRetIdx;
    stcSramConfig.enSramRC = SramCycle2;
    stcSramConfig.enSramWC = SramCycle2;
    SRAM_Init(&stcSramConfig);

    /* flash read wait cycle setting */
    EFM_Unlock();
    EFM_SetLatency(EFM_LATENCY_5);
    EFM_Lock();

    /* MPLL config (XTAL / pllmDiv * plln / PllpDiv = 200M). */
    stcMpllCfg.pllmDiv = 1ul;
    stcMpllCfg.plln    = 50ul;
    stcMpllCfg.PllpDiv = 2ul;
    stcMpllCfg.PllqDiv = 2ul;
    stcMpllCfg.PllrDiv = 2ul;
    CLK_SetPllSource(ClkPllSrcXTAL);
    CLK_MpllConfig(&stcMpllCfg);

    /* Enable MPLL. */
    CLK_MpllCmd(Enable);
    /* Wait MPLL ready. */
    while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
    { 
   
        ;
    }
    /* Switch driver ability */
    PWC_HS2HP();
    /* Switch system clock source to MPLL. */
    CLK_SetSysClkSource(CLKSysSrcMPLL);
}

/** ******************************************************************************* ** \brief Main function of template project ** ** \param None ** ** \retval int32_t return value, if needed ** ******************************************************************************/
int32_t main(void)
{ 
   
    BSP_CLK_Init();	//系统时钟初始化
    DDL_PrintfInit(DEBUG_USART_CH, DEBUG_USART_BAUDRATE, DebugUsartInit);
    LedInit();
    DDL_Printf("hc32 example. \r\n");
    /* add your code here */
    while (1)
    { 
   
        LED0_TOGGLE();
        LED1_TOGGLE();
        Ddl_Delay1ms(500);
    }
}

运行,通过pc端可以看到串口有输出,同时LED灯也有闪烁。
在这里插入图片描述

2.RT-Thread下载

RT-Thread针对不同的应用场景,提供了三个主版本:RT-Thread 标准版RT-Thread NanoRT-Thread Smart
下载地址
这里根据项目需求,我们选择RT-Thread Nano(目前版本更新到3.1.5)。
下载后解压缩,目录结构如下:

在这里插入图片描述

3.RT-Thread移植

准备工作都已经做好了,接下来可以开始RT-Thread的移植了。
将rt-thread整个文件夹拷贝到我们的工程目录下,为了工程的精简,我们可以删掉一些我们不需要的文件。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将RT-Thread添加到我们的工程中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
添加头文件路径
在这里插入图片描述
移植RT-Thread,我们主要需要修改的是board.crtconfig.h这两个文件,board.c主要是配置系统时钟和OS_TICK(为操作系统提供心跳),而rtconfig.h则是可以根据需要配置系统的各项功能的。这里我们的配置如下(仅供参考):
rtconfig.h

/* RT-Thread config file */

#ifndef __RTTHREAD_CFG_H__
#define __RTTHREAD_CFG_H__

#include <rtthread.h>

#if defined(__CC_ARM) || defined(__CLANG_ARM)
//#include "RTE_Components.h"

#if defined(RTE_USING_FINSH)
#define RT_USING_FINSH
#endif //RTE_USING_FINSH

#endif //(__CC_ARM) || (__CLANG_ARM)

// <<< Use Configuration Wizard in Context Menu >>>
// <h>Basic Configuration
// <o>Maximal level of thread priority <8-256>
// <i>Default: 32
#define RT_THREAD_PRIORITY_MAX 8
// <o>OS tick per second
// <i>Default: 1000 (1ms)
#define RT_TICK_PER_SECOND 1000
// <o>Alignment size for CPU architecture data access
// <i>Default: 4
#define RT_ALIGN_SIZE 4
// <o>the max length of object name<2-16>
// <i>Default: 8
#define RT_NAME_MAX 8
// <c1>Using RT-Thread components initialization
// <i>Using RT-Thread components initialization
#define RT_USING_COMPONENTS_INIT
// </c>

#define RT_USING_USER_MAIN

// <o>the stack size of main thread<1-4086>
// <i>Default: 512
#define RT_MAIN_THREAD_STACK_SIZE 1024

// </h>

// <h>Debug Configuration
// <c1>enable kernel debug configuration
// <i>Default: enable kernel debug configuration
//#define RT_DEBUG
// </c>
// <o>enable components initialization debug configuration<0-1>
// <i>Default: 0
#define RT_DEBUG_INIT 0
// <c1>thread stack over flow detect
// <i> Diable Thread stack over flow detect
//#define RT_USING_OVERFLOW_CHECK
// </c>
// </h>

// <h>Hook Configuration
// <c1>using hook
// <i>using hook
//#define RT_USING_HOOK
// </c>
// <c1>using idle hook
// <i>using idle hook
//#define RT_USING_IDLE_HOOK
// </c>
// </h>

// <e>Software timers Configuration
// <i> Enables user timers
#define RT_USING_TIMER_SOFT 0
#if RT_USING_TIMER_SOFT == 0
    #undef RT_USING_TIMER_SOFT
#endif
// <o>The priority level of timer thread <0-31>
// <i>Default: 4
#define RT_TIMER_THREAD_PRIO 4
// <o>The stack size of timer thread <0-8192>
// <i>Default: 512
#define RT_TIMER_THREAD_STACK_SIZE 512
// </e>

// <h>IPC(Inter-process communication) Configuration
// <c1>Using Semaphore
// <i>Using Semaphore
#define RT_USING_SEMAPHORE
// </c>
// <c1>Using Mutex
// <i>Using Mutex
//#define RT_USING_MUTEX
// </c>
// <c1>Using Event
// <i>Using Event
//#define RT_USING_EVENT
// </c>
// <c1>Using MailBox
// <i>Using MailBox
#define RT_USING_MAILBOX
// </c>
// <c1>Using Message Queue
// <i>Using Message Queue
//#define RT_USING_MESSAGEQUEUE
// </c>
// </h>

// <h>Memory Management Configuration
// <c1>Dynamic Heap Management
// <i>Dynamic Heap Management
//#define RT_USING_HEAP
// </c>
// <c1>using small memory
// <i>using small memory
#define RT_USING_SMALL_MEM
// </c>
// <c1>using tiny size of memory
// <i>using tiny size of memory
//#define RT_USING_TINY_SIZE
// </c>
// </h>

// <h>Console Configuration
// <c1>Using console
// <i>Using console
#define RT_USING_CONSOLE
// </c>
// <o>the buffer size of console <1-1024>
// <i>the buffer size of console
// <i>Default: 128 (128Byte)
#define RT_CONSOLEBUF_SIZE 128
// </h>

#if defined(RT_USING_FINSH)
    #define FINSH_USING_MSH
    #define FINSH_USING_MSH_ONLY
    // <h>Finsh Configuration
    // <o>the priority of finsh thread <1-7>
    // <i>the priority of finsh thread
    // <i>Default: 6
    #define __FINSH_THREAD_PRIORITY 5
    #define FINSH_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 8 * __FINSH_THREAD_PRIORITY + 1)
    // <o>the stack of finsh thread <1-4096>
    // <i>the stack of finsh thread
    // <i>Default: 4096 (4096Byte)
    #define FINSH_THREAD_STACK_SIZE 512
    // <o>the history lines of finsh thread <1-32>
    // <i>the history lines of finsh thread
    // <i>Default: 5
    #define FINSH_HISTORY_LINES 1

    #define FINSH_USING_SYMTAB
    // </h>
#endif

// <<< end of configuration section >>>

#endif

board.c

/* * Copyright (c) 2006-2019, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2017-07-24 Tanek the first version * 2018-11-12 Ernest Chen modify copyright */
 
#include <stdint.h>
#include <rtthread.h>
#include "hc32_ddl.h"


static void sysTick_Init(void);
static void SysClkConfig(void);

static void SysClkConfig(void)
{ 
   
    stc_clk_xtal_cfg_t   stcXtalCfg;
    stc_clk_mpll_cfg_t   stcMpllCfg;
    en_clk_sys_source_t  enSysClkSrc;
    stc_clk_sysclk_cfg_t stcSysClkCfg;

    MEM_ZERO_STRUCT(enSysClkSrc);
    MEM_ZERO_STRUCT(stcSysClkCfg);
    MEM_ZERO_STRUCT(stcXtalCfg);
    MEM_ZERO_STRUCT(stcMpllCfg);

    /* Set bus clk div. */
    stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;
    stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
    stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
    stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
    stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
    stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
    stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;
    CLK_SysClkConfig(&stcSysClkCfg);

    /* Switch system clock source to MPLL. */
    /* Use Xtal as MPLL source. */
    stcXtalCfg.enMode = ClkXtalModeOsc;
    stcXtalCfg.enDrv = ClkXtalLowDrv;
    stcXtalCfg.enFastStartup = Enable;
    CLK_XtalConfig(&stcXtalCfg);
    CLK_XtalCmd(Enable);

    /* MPLL config. */
    stcMpllCfg.pllmDiv = 1u; /* XTAL 8M / 1 */
    stcMpllCfg.plln = 50u;   /* 8M*50 = 400M */
    stcMpllCfg.PllpDiv = 4u; /* MLLP = 100M */
    stcMpllCfg.PllqDiv = 4u; /* MLLQ = 100M */
    stcMpllCfg.PllrDiv = 4u; /* MLLR = 100M */
    CLK_SetPllSource(ClkPllSrcXTAL);
    CLK_MpllConfig(&stcMpllCfg);

    /* flash read wait cycle setting */
    EFM_Unlock();
    EFM_SetLatency(EFM_LATENCY_4);
    EFM_Lock();

    /* Enable MPLL. */
    CLK_MpllCmd(Enable);

    /* Wait MPLL ready. */
    while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
    { 
   
    }

    /* Switch system clock source to MPLL. */
    CLK_SetSysClkSource(CLKSysSrcMPLL);
}

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 4096
static uint32_t rt_heap[RT_HEAP_SIZE];     // heap default size: 4K(1024 * 4)
RT_WEAK void *rt_heap_begin_get(void)
{ 
   
    return rt_heap;
}

RT_WEAK void *rt_heap_end_get(void)
{ 
   
    return rt_heap + RT_HEAP_SIZE;
}
#endif

/** * This function will initial your board. */
void rt_hw_board_init()
{ 
   
    /* Call components board initial (use INIT_BOARD_EXPORT()) */
	SysClkConfig();
	sysTick_Init();

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif


#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}

void SysTick_Handler(void)
{ 
   
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}

static void sysTick_Init(void)
{ 
   
    stc_clk_freq_t stcClkFreq;

    /* configure structure initialization */

    MEM_ZERO_STRUCT(stcClkFreq);

    /* Config 1 sec trigger interrupt*/
    CLK_GetClockFreq(&stcClkFreq);
    SysTick_Config(stcClkFreq.sysclkFreq/RT_TICK_PER_SECOND);
}

更改完这两个文件后,我们可以尝试编译,会发现会报错(如下图),我们只需要在hc32f460_interrupts.c文件中删掉对应的函数,重新编译即可。
在这里插入图片描述
最后,编写代码简单测试下系统能否正常运行。

static struct rt_thread led_thread;
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_led_thread_stack[1024];
static void led_thread_entry(void * para);
static rt_uint8_t led_thread_priority = 6;

/** ******************************************************************************* ** \brief Main function of template project ** ** \param None ** ** \retval int32_t return value, if needed ** ******************************************************************************/
int32_t main(void)
{ 
   
    DDL_PrintfInit(DEBUG_USART_CH, DEBUG_USART_BAUDRATE, DebugUsartInit);
    LedInit();
    DDL_Printf("hc32 example. \r\n");

    	/* main thread */
	rt_thread_init(&led_thread,
					"led_thread",
					led_thread_entry,
					RT_NULL,
					&rt_led_thread_stack,
					sizeof(rt_led_thread_stack),
					led_thread_priority,
					1000);
	rt_thread_startup(&led_thread);
}


static void led_thread_entry(void * para)
{ 
   
    DDL_Printf("Entry %s. \r\n", __func__);
    while(1)
    { 
   
        LED0_TOGGLE();
        LED1_TOGGLE();
        rt_thread_delay(1000);
    }
}

正常运行
在这里插入图片描述

4.finsh组件移植

最后我们来讲一下RT-Thread FinSh组件的移植。Finsh是RT-Thread提供的一套命令行组件,在命令行下通过各种指令的调用,我们可以很轻松的获取到当前系统的运行状态,在项目开发中可以方便我们的调试。
添加源码
在这里插入图片描述
配置头文件路径
在这里插入图片描述

更改配置文件
rtconfig.h

#define RTE_USING_FINSH
#if defined(RTE_USING_FINSH)
#define RT_USING_FINSH
#endif //RTE_USING_FINSH

board.c

/** * This function will initial your board. */
void rt_hw_board_init()
{ 
   
    /* Call components board initial (use INIT_BOARD_EXPORT()) */
	SysClkConfig();
	sysTick_Init();

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif


#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif

	DDL_PrintfInit(DEBUG_USART_CH, DEBUG_USART_BAUDRATE, DebugUsartInit);
}

void rt_hw_console_output(const char *str)
{ 
   
	rt_size_t i = 0, size = 0;
	char a = '\r';

	size = rt_strlen(str);
	for (i = 0; i < size; i++)
	{ 
   
		if (*(str + i) == '\n')
		{ 
   
			DEBUG_USART_CH->DR = a;
		    while (0ul == DEBUG_USART_CH->SR_f.TC)
		    { 
   
		        ;
		    }
		}
		DEBUG_USART_CH->DR = *(str + i);
	    while (0ul == DEBUG_USART_CH->SR_f.TC)
	    { 
   
	        ;
	    }
	}
}

char rt_hw_console_getchar(void)
{ 
   
    int ch = -1;

	if (Set == USART_GetStatus(DEBUG_USART_CH, UsartRxNoEmpty))
	{ 
   
		ch = DEBUG_USART_CH->DR_f.RDR;
    }
    else
    { 
   
		if(Set == USART_GetStatus(DEBUG_USART_CH, UsartOverrunErr))
		{ 
   
            USART_ClearStatus(DEBUG_USART_CH, UsartOverrunErr);
        }
        rt_thread_mdelay(10);
    }
    return ch;
}

运行
在这里插入图片描述
最后附上源码链接:hc32f460petb_template.zip


总结

以上就是今天分享内容的全部,本文仅是简单的介绍了RT-Thread+FinSh组件的移植,若是有什么问题欢迎评论或私信提出。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143465.html原文链接:https://javaforall.net

(1)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JavaScript面向对象思想

    JavaScript面向对象思想javascript中的面向对象:ECMA标准定义JS中的对象:无序属性的集合,其属性可以包含基本值、对象或者函数。可以简单理解为JS的对象是一组无序的值,其中的属性或方法都有一个名字,根据这个名字可以访问相映射的值(值可以是基本值/对象/方法)面向对象三个基本特征是:封装、继承、多态封装:将对象运行所需的资源封装在程序对象中,基本上是方法和数据。对象是“公布其接口”。其他附加到这些接口上的对象不需要关心对象实现的方法即可使用这个对象。这个概念就是“不要告诉我你是怎么做的,只要做就可以了。”对象可

    2025年6月17日
    4
  • sqlserver中日期转字符串「建议收藏」

    sqlserver中日期转字符串「建议收藏」SelectCONVERT(varchar(100),GETDATE(),0):0516200610:57AMSelectCONVERT(varchar(100),GETDATE(),1):05/16/06SelectCONVERT(varchar(100),GETDATE(),2):06.05.16SelectCONVERT(varchar(100),GETDATE(),3):16/05/06SelectCONVERT(varchar(10.

    2022年10月8日
    3
  • 一气之下,我一行代码搞定了约瑟夫环问题,面试官懵了[通俗易懂]

    一气之下,我一行代码搞定了约瑟夫环问题,面试官懵了[通俗易懂]大家好,我是帅地。对于约瑟夫环问题估计大家都听说过,除非你刚刚读大一,因为在大一大部分学校的课本都会降到这个算法题。为了以防万一你没听过,我还是给下问题的描述问题描述:编号为1-N的N个士兵围坐在一起形成一个圆圈,从编号为1的士兵开始依次报数(1,2,3…这样依次报),数到m的士兵会被杀死出列,之后的士兵再从1开始报数。直到最后剩下一士兵,求这个士兵的编号。记得有一次,貌似是阿里的面试,面试官给了我一到原汁原味的约瑟夫好,好家伙,看我不把你秀一把。不过,作为一个有着几十场面

    2022年6月4日
    37
  • linux 解压分卷rar[通俗易懂]

    linux 解压分卷rar[通俗易懂]linux解压分卷rar其实很简单rarxxx.part001.rar执行解压之后系统会自动解压所有的part如果说解压过程当中解压有以存在文件的情况下选择never这样会省不少时间特别是接他大量文件的时候…

    2022年5月23日
    90
  • 彻底解决Intellij IDEA中文乱码问题(亲测成功)「建议收藏」

    关于JAVA IDE开发工具,Eclipse系列和Intelli IDEA是大部分公司的主要选择,从开发者的选择角度,Intellij IDEA似乎比Eclipse系列更受欢迎一些。当我们使用Intellij IDEA开发时,我们发现出现中文乱码问题,造成中…

    2022年3月13日
    2.9K
  • python py2exe_编写简单网页

    python py2exe_编写简单网页简介py2exe是 Python Distutils 的一个外部扩展,它可以把Python脚本转为可执行的Windows程序,无需安装Python即可运行.你可以在主页 SourceForge 得到更多资源. 说明py2exe可以把Python程序转为包,能够在其他没有安装Python 的电脑上运行。Pythonisneede

    2025年9月5日
    9

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号