当前位置: 首页 > article >正文

龙芯1B开发板自检程序

  本代码为当时,参加嵌入式系统开发与应用赛项,训练时编写的自检程序,用于将程序烧录后,逐个演示板载模块功能是否正常,快速定位问题。这代码编写的时间为2023年,好像原代码是参考2023年官方案例来编写的。目前代码版本,和模块应该已经更新,所以参考价值不一定高。还有当时在编写时,是有些坑的,例如LCD方向定义有点问题,好像哪个库代码还少了部分之类的,总之有时候,有些功能给了接口,但是功能没有实装的,不过现在源代码迭代了些,应该修复了不少吧。

  • 软件:Embedded IDE for Loongson
  • 开发板,如下图

在这里插入图片描述

下述为main.c代码,完整项目放在末尾。


#include <stdio.h>

#include "ls1b.h"
#include "mips.h"

//-------------------------------------------------------------------------------------------------
// BSP
//-------------------------------------------------------------------------------------------------

#include "bsp.h"
#include "led_drv.h"
#include "key_drv.h"
#include "beep.h"
#include "uart.h"
#include "lkdGui.h"         // 显示库
#include "stdint.h"         // 显示相关
#include "ls1x_i2c_bus.h"   // i2C总线
#include "i2c/ads1015.h"    // ADC芯片
#include "i2c/mcp4725.h"    // ADC相关
#include "pwm_ic.h"         // PWM相关
#include "bh1750_iic.h"     // BH1750
#include "bh1750.h"         // BH1750
#include "libc/lwmem.h"     // LCD相关
#include "pic_flag.h"       // 图片存放
#include "i2c/gt1151.h"     // 触摸相关
#include "fan_resistance_control_drv.h" // 风扇控制
#include "lm35_drv.h"       // 温度测量
#include "ls1b_gpio.h"      // GPIO控制

#ifdef BSP_USE_FB
#include "ls1x_fb.h"
#ifdef XPT2046_DRV
char LCD_display_mode[] = LCD_800x480;
#elif defined(GT1151_DRV)
char LCD_display_mode[] = LCD_800x480;
#else
#error "在bsp.h中选择配置 XPT2046_DRV 或者 GT1151_DRV"
"XPT2046_DRV:  用于800*480 横屏的触摸屏."
"GT1151_DRV:   用于480*800 竖屏的触摸屏."
"如果都不选择, 注释掉本 error 信息, 然后自定义: LCD_display_mode[]"
#endif
#endif

/**** 辅助程序 ****/
unsigned int TaskTextRoll_Row = 0;          // 行索引
unsigned char TaskTextRoll_RowHigh = 35;    // 行高度
unsigned char JsMode_Num = 3;   // 计数模式的倒计时

char textBuf[50]= {0};
// 任务文本滚动
// str:字符串
// mode:模式选择  0.默认显示模式    1.计数等待模式    2.顺序例出文本且间隔比较大
void TaskTextRoll(uint8_t *str ,uint8_t mode)
{
    uint8_t i;

    switch(mode)
    {
        case 0:
            TaskTextRoll_Row += 1;  // 行数递增
            GuiRowText(30, 10+(TaskTextRoll_RowHigh * TaskTextRoll_Row) ,480, FONT_LEFT,str);
            printk(str);
            printk("\r\n");
            break;
        case 1:
            delay_ms(1000);
            for(i = 0; i < JsMode_Num; i++)
            {
                
                sprintf((char *)textBuf,"%d",JsMode_Num-i);
                GuiRowText(280+(i*50), 10+(TaskTextRoll_RowHigh * TaskTextRoll_Row) ,30, FONT_LEFT,textBuf);
                printk(textBuf);
                printk("  ");
                delay_ms(1000);
            }
            printk("\r\n");
            break;
        case 2:
            TaskTextRoll_Row += 1;  // 行数递增
            GuiRowText(60, 30+(TaskTextRoll_RowHigh * TaskTextRoll_Row) ,480, FONT_LEFT,str);
            printk(str);
            printk("\r\n");
            break;
        default:
            GuiRowText(30, (TaskTextRoll_RowHigh * TaskTextRoll_Row) ,480, FONT_LEFT,"显示错误!");
            break;
    }

}

unsigned char KEY_keyNum = 0;
unsigned char KEY_ExitKey = 4;
// 按键跳过程序
// 将该函数放置要循环的任务语句中
unsigned char KEY_SKipTask(void)
{
    KEY_keyNum = KEY_Scan();
    if(KEY_keyNum == KEY_ExitKey) return 0;
    return 1;
}

//-------------------------------------------------------------------------------------------------
// 主程序
//-------------------------------------------------------------------------------------------------
/***** 任务函数 *****/
//任务1现象--红绿蓝分别保持1秒
void Task1_LED(void)
{
    //printk("Task1_LED_start\r\n");
    LED_Init();
    while(KEY_SKipTask())
    {
        LED_RGBDemo();
    }
    //printk("Task1_LED_end\r\n");
}

//任务2现象--  S1-亮红灯  S2--亮绿灯 S3--亮蓝灯 S4--退出该任务
void Task2_KEY(void)
{
    unsigned char keyNum = 0;
    unsigned char status = 0;
    KEY_Init();
    //printk("Task2_KEY_start\r\n");
    while(1)
    {
        keyNum = KEY_Scan();
        status = 0;
        switch ( keyNum )
        {
            case 1:
                LED_On( LED1 );
                LED_Off( LED2 );
                LED_Off( LED3 );
                delay_ms(500);
                break;

            case 2:
                LED_On( LED2 );
                LED_Off( LED1 );
                LED_Off( LED3 );
                delay_ms(500);
                break;

            case 3:
                LED_On( LED3 );
                LED_Off( LED1 );
                LED_Off( LED2 );
                delay_ms(500);
                break;
            case 4:
                status = 1;
                break;

            default:
                LED_Off( LED1 );
                LED_Off( LED2 );
                LED_Off( LED3 );
                break;
        }
        if(status == 1) break;
    }
    //printk("Task2_KEY_end\r\n");
}

//任务3现象--蜂鸣器响起
void Task3_BEEP(void)
{
    //printk("Task3_BEEP_start\r\n");
    BEEP_Init();
    BEEP_On();
    delay_ms(500);
    BEEP_Off();
    delay_ms(500);
    BEEP_On();
    delay_ms(500);
    BEEP_Off();
    delay_ms(500);
    BEEP_On();
    delay_ms(500);
    BEEP_Off();
    delay_ms(500);
    //printk("Task3_BEEP_end\r\n");
}

//任务4现象--UART交互(波特率115200)
void Task4_UART(void)
{
    //printk("Task4_UART_start\r\n");
    UART5_Config_Init();
    LED_Off(LED1);
    //串口控制函数
    while(UART5_Test())
    {
        if(!(KEY_SKipTask())) break;
    }
    //printk("Task4_UART_end\r\n");
}

extern float temp;
double lm35_temp_data;
char str[100];
//任务5现象--风扇与加热
void Task5_FAN_HOT(void)
{
    unsigned char i = 0;
    unsigned int i_5S = 0;
    unsigned char Tempfirst = 0;    // 记录初始温度
    unsigned char TempEnd = 0;      // 记录最后温度
    
    fan_resistance_io_Config();

    gpio_write(38,1);//加热电阻打开
    gpio_write(36,1);//风扇开关打开

    Fan_Control(100);//风扇控制PWM最大
    
    ls1x_i2c_initialize(busI2C0);
    ls1x_ads1015_ioctl(busI2C0,IOCTL_ADS1015_DISP_CONFIG_REG,NULL);
    
    GuiRowText(50, 550,400, FONT_MID, "加热30S电阻测温度");
    //GuiRowText(50, 590,480, FONT_LEFT, "加热模式");
    //GuiRowText(50, 590,480, FONT_LEFT, "        ");
    // 进入时测量(5S)
    GuiRowText(50, 590,480, FONT_LEFT, "测量模式: 进行中");
    GuiRowText(50, 630,400, FONT_LEFT, "当前温度:");
    while(i_5S < 25)
    {
        lm35_get_temp();
        GuiRowText(220, 630,480, FONT_LEFT, "      ");
        sprintf(str,"%.01f℃",temp);
        GuiRowText(220, 630,400, FONT_LEFT, str);
        delay_ms(200);
        i_5S++;
    }
    Tempfirst = temp;
    
    // 加热30S
    GuiRowText(50, 590,480, FONT_LEFT, "加热模式: ");
    for(i=0;i<30;i++)
    {
        GuiRowText(220, 590,480, FONT_LEFT, "      ");
        sprintf(str,"%d S",30-i);
        GuiRowText(220, 590,480, FONT_LEFT, str);
        delay_ms(1000);
    }
    gpio_write(38,0);//加热电阻关闭
    gpio_write(36,0);//风扇开关关闭
    GuiRowText(50, 590,480, FONT_LEFT, "                ");
    GuiRowText(50, 590,480, FONT_LEFT, "测量模式: 进行中");
    GuiRowText(50, 630,400, FONT_LEFT, "当前温度:");
    while(KEY_SKipTask())
    {
        lm35_get_temp();
        GuiRowText(220, 630,480, FONT_LEFT, "      ");
        sprintf(str,"%.01f℃",temp);
        GuiRowText(220, 630,400, FONT_LEFT, str);
        delay_ms(200);
        
        TempEnd = temp;
        GuiRowText(220, 670,480, FONT_LEFT, "             ");
        sprintf(str,"初始温度:%d",Tempfirst);
        GuiRowText(50, 670,400, FONT_LEFT, str);
        GuiRowText(220, 710,480, FONT_LEFT, "                           ");
        sprintf(str,"温度差值:%d",(TempEnd-Tempfirst)>0?TempEnd-Tempfirst:(TempEnd-Tempfirst)*(-1));
        GuiRowText(50, 710,400, FONT_LEFT, str);
    }
    // 清除
    fb_fillrect(0, 0, 350, 480, cidxBLACK);
}

//任务6现象--语音模块交互
void Task6_VOICE(void)
{
    
    //printk("Task6_VOICE_start\r\n");

    //printk("Task6_VOICE_end\r\n");
}

//任务数码管验证
void Task7_SMG(void)
{
    //printk("Task7_SMG_start\r\n");
    int num;
    SMG_Init();
    while(KEY_SKipTask())
    {
        num = 9999;
        while(1)
        {
            SMG_SeleNumDyn(num,1000);
            num -= 1111;
            if(num == 0) break;
        }
    }
    //printk("Task7_SMG_end\r\n");
}

char tbuf1[50]= {0},tbuf2[50]= {0},tbuf3[50]= {0},tbuf4[50]= {0},sbuf1[50]= {0},sbuf2[50]= {0},sbuf3[50]= {0},sbuf4[50]= {0},rt;
unsigned short dac=0, adc1=0, adc2=0, adc3=0, adc4=0;
float out_v,in_v1,in_v2,in_v3,in_v4;

void Task8_I2C_ADC(void)
{
    unsigned char quitNum = 0;
    unsigned int RowAdjust = 550;   // Y 轴显示高度补偿
    ls1x_ads1015_ioctl(busI2C0,IOCTL_ADS1015_DISP_CONFIG_REG,NULL);
    while(KEY_SKipTask())
    {
        adc1 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_0);
        adc2 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_1);
        adc3 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_2);
        adc4 = get_ads1015_adc(busI2C0, ADS1015_REG_CONFIG_MUX_SINGLE_3);
        in_v1 = 4.096*2*adc1/4096;//采集电压的转换公式
        in_v2 = 4.096*2*adc2/4096;//采集电压的转换公式
        in_v3 = 4.096*2*adc3/4096;//采集电压的转换公式
        in_v4 = 4.096*2*adc4/4096;//采集电压的转换公式
        sprintf((char *)sbuf1,"CH 1 = %f V",in_v1);
        sprintf((char *)sbuf2,"CH 2 = %f V",in_v2);
        sprintf((char *)sbuf3,"CH 3 = %f V",in_v3);
        sprintf((char *)sbuf4,"CH 4 = %f V",in_v4);

        GuiRowText(30, 30+RowAdjust,400, FONT_LEFT, "ADS1015 ADC GET");
        GuiRowText(30, 60+RowAdjust,400, FONT_LEFT,sbuf1);
        GuiRowText(30, 90+RowAdjust,400, FONT_LEFT,sbuf2);
        GuiRowText(30, 120+RowAdjust,400, FONT_LEFT,sbuf3);
        GuiRowText(30, 150+RowAdjust,400, FONT_LEFT,sbuf4);
        //fb_textout(10, 60, "ADS1015 ADC GET");
        delay_ms(500);
        quitNum ++;
        //if(quitNum>10) break;
    }
    
    fb_fillrect(0, 0, 350, 480, cidxBLACK);
    
}


char  data[20];
unsigned int frequency = 5000;
unsigned int x_i=0; //X轴绘图前进
void Task9_PWM(void)
{
    unsigned int i = 0;
    unsigned char isDown = 0;
    GuiRowText(50, 550,400, FONT_LEFT, "PWM输出");
    GuiRowText(50, 580,400, FONT_LEFT, "PWM输出占空比为:");
    // 容器化(统一宽高)
    // xy轴画线
    GuiRLine(50,650,750,cidxRED);
    GuiHLine(50,750,400,cidxRED);
    //Set_PWM(500); // 20KMz

    // 触顶低反弹
    for(i = 0; isDown?i>=0:i<101 ; isDown?i--:i++)
    {
        sprintf(data,"%d ",i);
        GuiRowText(320, 580,400, FONT_LEFT, data);
        x_i++;  // 递进数
        GuiPoint(50+x_i,750-i,cidxGREEN);   //绘制波形
        // 设置PWM函数(我也不知道为啥这么设,只是验证后现象没问题)
        // 数值越大越慢
        Set_PWM(i*50);
        delay_ms(100);

        // 触顶低反弹逻辑
        if(i == 0)
        {
            i=1 ;
            isDown = 0;
        }
        else if(i == 100)
        {
            i=99 ;
            isDown = 1;
        }
        // 退出逻辑
        if(50 + x_i > 400)
        {
            break;
        }
    }
    while(KEY_SKipTask());
    fb_fillrect(0, 0, 350, 480, cidxBLACK);
}

unsigned int task10_ContY = 550;
void Task10_BH1750(void)
{
    unsigned char buf[20] = {0};
    unsigned int lx = 0;
    BH1750_Init();			 //光照强度传感器初始化
    GuiRowText(50, 30+task10_ContY, 400, FONT_LEFT, "BH1750光照度传感器测量");
    GuiRowText(50, 70+task10_ContY, 400, FONT_LEFT, "光照传感器");
    GuiRowText(50, 110+task10_ContY, 400, FONT_LEFT, "当前光照强度:");

    while(KEY_SKipTask())
    {
        // 循环检测部分
        sprintf((char *)buf,"%d lux", BH1750_reData());
        GuiRowText(280, 110+task10_ContY, 400, FONT_LEFT, buf);
    }
    fb_fillrect(0, 0, 350, 480, cidxBLACK);
}



void Task11_LCD(void)
{
    //初始化内存堆
    //lwmem_initialize(0);
    delay_ms(500);
    fb_cons_clear();//清屏
    //while(KEY_SKipTask())
    //{
        // 颜色充填演示
        fb_fillrect(0, 0, 800, 480, cidxRED);
        delay_ms(1500);
        fb_fillrect(0, 0, 800, 480, cidxYELLOW);
        delay_ms(1500);
        fb_fillrect(0, 0, 800, 480, cidxBLUE);
        delay_ms(1500);
        fb_fillrect(0, 0, 800, 480, cidxBLACK);
        delay_ms(1500);
        // 图片演示
        display_pic(50,50,400,400,gImage_img);  //显示图片
        delay_ms(1500);
    //}
}

void Task12_Toush(void)
{
    //GT1151_Init();
    //GT1151_Test();
}

// 自检任务演示--综合
void TaskDemo_AND(void)
{
    // 综合演示模式
    while(1)
    {
        GuiRowText(0, 0,480, FONT_MID,"龙芯1B自检程序");
        TaskTextRoll("Task1_LED",0);
        TaskTextRoll("0",1);
        Task1_LED();
        delay_ms(1000);
        TaskTextRoll("Task2_KEY",0);
        TaskTextRoll("0",1);
        Task2_KEY();
        delay_ms(1000);
        TaskTextRoll("Task3_BEEP",0);
        TaskTextRoll("0",1);
        Task3_BEEP();
        delay_ms(1000);
        TaskTextRoll("Task4_UART",0);
        TaskTextRoll("0",1);
        Task4_UART();
        delay_ms(1000);
        TaskTextRoll("Task5_FAN_HOT",0);
        TaskTextRoll("0",1);
        Task5_FAN_HOT();
        delay_ms(1000);
        TaskTextRoll("Task6_VOICE",0);
        TaskTextRoll("0",1);
        Task6_VOICE();
        delay_ms(1000);
        TaskTextRoll("Task7_SMG",0);
        TaskTextRoll("0",1);
        Task7_SMG();
        delay_ms(1000);
        TaskTextRoll("Task8_I2C_ADC",0);
        TaskTextRoll("0",1);
        Task8_I2C_ADC();
        delay_ms(1000);
        TaskTextRoll("Task9_PWM",0);
        TaskTextRoll("0",1);
        Task9_PWM();
        delay_ms(1000);
        TaskTextRoll("Task10_BH1750",0);
        TaskTextRoll("0",1);
        Task10_BH1750();
        delay_ms(1000);
        TaskTextRoll("Task11_LCD",0);
        TaskTextRoll("0",1);
        Task11_LCD();
        delay_ms(1000);
        //TaskTextRoll("Task12_Toush",0);
        //TaskTextRoll("0",1);
        //Task12_Toush();
        //delay_ms(1000);
        break;
    }
}

// 自检任务演示--单独
void TaskDemo_ONE(void)
{
    int taskNum = 1;    // 选择的任务数(1~11)
    unsigned char keyNum = 0;   // 1.-  2.确定  3.+   4.退出
    // 清光标
    fb_fillrect(0, 0, 800, 60, cidxBLACK);
    // 任务列表显示
    TaskTextRoll("Task1_LED",2);
    TaskTextRoll("Task2_KEY",2);
    TaskTextRoll("Task3_BEEP",2);
    TaskTextRoll("Task4_UART",2);
    TaskTextRoll("Task5_FAN_HOT",2);
    TaskTextRoll("Task6_VOICE",2);
    TaskTextRoll("Task7_SMG",2);
    TaskTextRoll("Task8_I2C_ADC",2);
    TaskTextRoll("Task9_PWM",2);
    TaskTextRoll("Task10_BH1750",2);
    TaskTextRoll("Task11_LCD",2);
    
    char* data[10];
    // 单独演示模式
    while(1)
    {
        sprintf(data,"%d ",taskNum);
        GuiRowText(0, 0 ,40, FONT_LEFT,data);
        keyNum = KEY_Scan();
        switch(keyNum)
        {
            case 1: // 减
                if(taskNum-1>0) 
                {
                    taskNum-=1;
                    // 清光标
                    //fb_fillrect(0, 0, 800, 60, cidxBLACK);
                    // 光标(任务数选择)
                    //GuiFillRect(0,0+20*(taskNum),20,20+20*(taskNum),cidxWHITE);
                }
                break;
            case 4: // 确定
                switch(taskNum)
                {
                    case 1:
                        Task1_LED();
                        break;
                    case 2:
                        Task2_KEY();
                        break;
                    case 3:
                        Task3_BEEP();
                        break;
                    case 4:
                        Task4_UART();
                        break;
                    case 5:
                        Task5_FAN_HOT();
                        break;
                    case 6:
                        Task6_VOICE();
                        break;
                    case 7:
                         Task7_SMG();
                        break;
                    case 8:
                        Task8_I2C_ADC();
                        break;
                    case 9:
                        Task9_PWM();
                        break;
                    case 10:
                        Task10_BH1750();
                        break;
                    case 11:
                        Task11_LCD();
                        break;
                }
                break;
            case 3: //  加
                if(taskNum+1<12)
                {
                    taskNum+=1;
                    // 清光标
                    fb_fillrect(0, 0, 800, 60, cidxBLACK);
                    // 光标(任务数选择)
                    //GuiFillRect(0,0+20*(taskNum),20,20+30*(taskNum),cidxWHITE);
                }
                break;
        }
    }
}

int DemoMode = 1;   // 演示模式  1.综合演示模式  2.单独演示模式
// 自检任务
void TaskDemo(void)
{
    unsigned char keyNum = 0;   // 健值
    
    // 屏幕显示初始化
    fb_open();              //打开LCD显示
    delay_ms(500);
    fb_cons_clear();        //清屏
    defaultFontInit();      /* 字库初始化 */
    GuiUpdateDisplayAll();  /* 更新屏幕-清屏 */
    
    // 开机介绍
    GuiRowText(0, 240,480, FONT_MID,"龙芯1B自检程序介绍");
    GuiRowText(0, 290,480, FONT_LEFT,"    任务会按顺序依次演示,大多");
    GuiRowText(0, 330,480, FONT_LEFT,"数任务是存在循环演示,可以按S4");
    GuiRowText(0, 370,480, FONT_LEFT,"按键跳转到下个任务。现在就可以");
    GuiRowText(0, 410,480, FONT_LEFT,"按下S4按键开始自检程序。");
    while(KEY_SKipTask());
    fb_fillrect(0, 0, 800, 480, cidxBLACK);
    delay_ms(1000);
    
    // 演示模式选择
    KEY_Init();
    GuiRowText(0, 340,480, FONT_MID,"->综合演示模式");
    GuiRowText(0, 400,480, FONT_MID,"  单独演示模式");
    while(KEY_SKipTask())
    {
        keyNum = KEY_Scan();
        switch(keyNum)
        {
            case 1: // 1.综合演示模式  
                DemoMode = 1;
                GuiRowText(0, 340,480, FONT_MID,"->综合演示模式");
                GuiRowText(0, 400,480, FONT_MID,"  单独演示模式");
            break;
            case 2: // 2.单独演示模式
                DemoMode = 2;
                GuiRowText(0, 340,480, FONT_MID,"  综合演示模式");
                GuiRowText(0, 400,480, FONT_MID,"->单独演示模式");
            break;
        }
    }
    fb_fillrect(0, 0, 800, 480, cidxBLACK);
    
    // 进入模式
    switch(DemoMode)
    {
        case 1:
            TaskDemo_AND();
        break;
        case 2:
            TaskDemo_ONE();
        break;
    }
    

}

int main(void)
{
    printk("\r\nmain() function.\r\n");

    ls1x_drv_init();            		/* Initialize device drivers */

    install_3th_libraries();      		/* Install 3th libraies */

    // 屏幕显示初始化
    fb_open();              //打开LCD显示
    delay_ms(500);
    fb_cons_clear();        //清屏
    defaultFontInit();      /* 字库初始化 */
    GuiUpdateDisplayAll();  /* 更新屏幕-清屏 */
    KEY_Init();

    // 自检程序
    TaskDemo();

    /*
     * 裸机主循环
     */
    for (;;)
    {

        //unsigned int tickcount = get_clock_ticks();
        //printk("tick count = %i\r\n", tickcount);
        //BH1750_Test();
        //delay_ms(500);
    }

    /*
     * Never goto here!
     */
    return 0;
}

/*
 * @@ End
 */

完整工程链接,希望能帮助到大家!

龙芯1B开发板自检程序
链接:https://pan.baidu.com/s/1dyx5YroQxsvu4-pEHARj3Q  提取码:di6t


http://www.kler.cn/news/329815.html

相关文章:

  • 828华为云征文|部署在线论坛网站 Flarum
  • 【STM32单片机_(HAL库)】4-3-1【定时器TIM】串口打印功能打开
  • MongoDB mongoose 的 save、insert 和 create 方法的比较
  • 算力共享系统中数据平面和控制平面
  • 富格林:正确指引远离欺诈黑幕
  • JAVASE总结
  • 学习threejs,添加环境光和点光源
  • 工具介绍---效率高+实用
  • 优化Mysql
  • [C++] 剖析AVL树功能的实现原理
  • 滚雪球学MySQL[11.2讲]:MySQL未来学习方向:大数据、云计算与迁移路径
  • [极客大挑战 2019]RCE ME1
  • Spring Security中自定义cors配置
  • 【算法篇】回溯算法类(1)(笔记)
  • 虚拟机U盘启动
  • 使用 Git 帮助文档
  • 养老院管理系统(含源码+sql+视频导入教程+文档)
  • 图解C#高级教程(四):协变、逆变
  • JSR303微服务校验
  • docker-compose 快速部署clickhouse集群
  • Springboot项目在win系统开发部署到linux服务器出现上传文件编码问题
  • 如何改善网站的核心网络生命力
  • TypeScript 封装 Axios 1.7.7
  • 软件测试面试八股文(含答案+文档)
  • 【yolov8】模型导出----pytorch导出为onnx模型
  • windows美化终端
  • go结构体默认值和校验器(go-defaults、go-validator)
  • 【Redis】主从复制(下)--主从复制原理和流程
  • 【数据分享】2001-2023年我国省市县镇四级的逐月平均气温数据(免费获取/Shp/Excel格式)
  • ubuntu 安装kvm 创建windos虚拟机