【驱动篇】龙芯LS2K0300之spi设备驱动

实验介绍

GC9A01是一款小巧(1.28寸)、彩色(分辨率为 240 * 240 RGB)圆形TFT屏幕,它采用4线 SPI的控制方式,电源供电电压为3.3V,有7个控制引脚;本次实验将使用它来验证龙芯SOC的SPI通信流程,在用户态下移植和编写SPI设备驱动

模块连接

VCC接Pin2,GND接Pin1,SCL接Pin21,SDA接Pin27,DC接Pin16,CS接Pin23,RST接Pin18

在这里插入图片描述

SPI接口分布:SCLK -> GPIO64, CS -> GPIO67, MISO -> GPIO65, MOSI -> GPIO66

在这里插入图片描述

设备树

板载了2路SPI总线接口,SPI0是给norflash(QSPI)通信用的,只有SPI2是空闲的

&spi0{
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&spi0_6bit_f0>,<&spi0_6bit_f1>;

    norflash@0 {
       reg = <0>;
       spi-rx-bus-width = <4>;
       spi-max-frequency = <25000000>;
       #address-cells = <1>;
       #size-cells = <1>;
       partitions {
           compatible = "fixed-partitions";
           #address-cells = <1>;
           #size-cells = <1>;

           boot@0 {
               label = "boot";
               reg = <0x0000000 0x100000>;
               /*read-only;*/
           };

           kernel@100000 {
               label = "kernel";
               reg = <0x100000 0x600000>;
           };

           rootfs@700000 {
               label = "rootfs";
               reg = <0x700000 0x1000000>;
           };
       };

    };
};

&spi2{
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&spi2_pin>;
};

在/dev目录下可以查看到spi2总线对应的设备节点:spidev1.0

在这里插入图片描述

可以尝试短接SPI2的MOSI和MISO引脚进行自发自收测试,检查rx_dat是否接收到相同的数据

unsigned char tx_dat[] = {'h', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r', 'l', 'd'};
unsigned char rx_dat[sizeof(tx)] = {0};

struct spi_ioc_transfer tr = {
    .tx_buf = (unsigned long)tx_dat,
    .rx_buf = (unsigned long)rx_dat,
    .len = sizeof(tx_buf),
    .delay_usecs = 0,
    .speed_hz = 500000, 
    .bits_per_word = 8,
};
 
ioctl(fd, SPI_IOC_MESSAGE(1), &tr);

驱动代码

lcd_init.h

定义spi设备及lcd初始化的接口

#ifndef __LCD_INIT_H
#define __LCD_INIT_H

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>

#define USE_HORIZONTAL 0 
#define LCD_W 240
#define LCD_H 240

typedef unsigned int u32;
typedef  unsigned short u16;
typedef  unsigned char u8;

void LCD_Writ_Bus(u8 dat);
void LCD_WR_DATA8(u8 dat);
void LCD_WR_DATA(u16 dat);
void LCD_WR_REG(u8 dat);
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);
void LCD_Init(void);
void closeLCD();

#endif

lcd_init.c

spi设备及lcd初始化的代码实现

#include "lcd_init.h"

#define GPIO_PATH "/sys/class/gpio"
#define LCD_DC_Clr()   { write(dc_fd, "0", 1); } 
#define LCD_DC_Set()   { write(dc_fd, "1", 1); } 
#define LCD_RES_Clr()  { write(res_fd, "0", 1); } 
#define LCD_RES_Set()  { write(res_fd, "1", 1); } 

static int spi_fd = -1;
static int dc_fd = -1;
static int res_fd = -1;

int init_gpio(int gpio) 
{
    char path[64];
    int fd = -1;

	// export
    {
		sprintf(path, "%s/export", GPIO_PATH);
		fd = open(path, O_WRONLY);
		if (fd < 0) {
			perror("open export for writing");
			return -1;
		}
		write(fd, &gpio, sizeof(gpio));
		close(fd);
	}
 
    // direction
    {
		sprintf(path, "%s/gpio%d/direction", GPIO_PATH, gpio);
		fd = open(path, O_RDWR);
		if (fd < 0) {
			perror("open direction for reading and writing");
			return -1;
		}
		write(fd, "out", 3);
		close(fd);
	}
 
    // value
    {
		sprintf(path, "%s/gpio%d/value", GPIO_PATH, gpio);
		fd = open(path, O_RDWR);
		if (fd < 0) {
			perror("open value for reading and writing");
			return -1;
		}
		write(fd, "1", 1);
	}
 
    return fd;
}

void closeLCD()
{
	close(dc_fd);
	close(res_fd);
	close(spi_fd);
}

void LCD_Writ_Bus(u8 dat) 
{	
	int ret = 0;
    unsigned char tx[] = {dat};
    unsigned char rx[sizeof(tx)] = {0};
    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = sizeof(tx),
    };
 
    ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1) {
        perror("can't send spi message");
    }
}

void LCD_WR_DATA8(u8 dat)
{
	LCD_Writ_Bus(dat);
}

void LCD_WR_DATA(u16 dat)
{
	LCD_Writ_Bus(dat>>8);
	LCD_Writ_Bus(dat);
}

void LCD_WR_REG(u8 dat)
{
	LCD_DC_Clr();
	LCD_Writ_Bus(dat);
	LCD_DC_Set();
}

void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
	LCD_WR_REG(0x2a);
	LCD_WR_DATA(x1);
	LCD_WR_DATA(x2);
	LCD_WR_REG(0x2b);
	LCD_WR_DATA(y1);
	LCD_WR_DATA(y2);
	LCD_WR_REG(0x2c);
}

void delay_ms(int ms)
{
	usleep(ms * 1000);
}

void LCD_Init(void)
{
	int ret;

	// init pins
	{
		dc_fd = init_gpio(48);
		res_fd = init_gpio(49);
		spi_fd = open("/dev/spidev1.0", O_RDWR);
		if (spi_fd < 0) {
			perror("open");
			return ;
		}
	
		unsigned char mode = SPI_MODE_0;
		unsigned char bits = 8;
		unsigned int speed = 25000000; 
		ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode);
		ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
		ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
	}
	
	LCD_RES_Clr();
	delay_ms(100);
	LCD_RES_Set();
	delay_ms(100);
	
	LCD_WR_REG(0xEF);
	LCD_WR_REG(0xEB);
	LCD_WR_DATA8(0x14); 
	
  	LCD_WR_REG(0xFE);			 
	LCD_WR_REG(0xEF); 

	LCD_WR_REG(0xEB);	
	LCD_WR_DATA8(0x14); 

	LCD_WR_REG(0x84);			
	LCD_WR_DATA8(0x40); 

	LCD_WR_REG(0x85);			
	LCD_WR_DATA8(0xFF); 

	LCD_WR_REG(0x86);			
	LCD_WR_DATA8(0xFF); 

	LCD_WR_REG(0x87);			
	LCD_WR_DATA8(0xFF);

	LCD_WR_REG(0x88);			
	LCD_WR_DATA8(0x0A);

	LCD_WR_REG(0x89);			
	LCD_WR_DATA8(0x21); 

	LCD_WR_REG(0x8A);			
	LCD_WR_DATA8(0x00); 

	LCD_WR_REG(0x8B);			
	LCD_WR_DATA8(0x80); 

	LCD_WR_REG(0x8C);			
	LCD_WR_DATA8(0x01); 

	LCD_WR_REG(0x8D);			
	LCD_WR_DATA8(0x01); 

	LCD_WR_REG(0x8E);			
	LCD_WR_DATA8(0xFF); 

	LCD_WR_REG(0x8F);			
	LCD_WR_DATA8(0xFF); 


	LCD_WR_REG(0xB6);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x20);

	LCD_WR_REG(0x36);
	if(USE_HORIZONTAL==0)	LCD_WR_DATA8(0x08);
	else if(USE_HORIZONTAL==1)	LCD_WR_DATA8(0xC8);
	else if(USE_HORIZONTAL==2)	LCD_WR_DATA8(0x68);
	else	LCD_WR_DATA8(0xA8);

	LCD_WR_REG(0x3A);			
	LCD_WR_DATA8(0x05); 

	LCD_WR_REG(0x90);			
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08); 

	LCD_WR_REG(0xBD);			
	LCD_WR_DATA8(0x06);
	
	LCD_WR_REG(0xBC);			
	LCD_WR_DATA8(0x00);	

	LCD_WR_REG(0xFF);			
	LCD_WR_DATA8(0x60);
	LCD_WR_DATA8(0x01);
	LCD_WR_DATA8(0x04);

	LCD_WR_REG(0xC3);			
	LCD_WR_DATA8(0x13);
	LCD_WR_REG(0xC4);			
	LCD_WR_DATA8(0x13);

	LCD_WR_REG(0xC9);			
	LCD_WR_DATA8(0x22);

	LCD_WR_REG(0xBE);			
	LCD_WR_DATA8(0x11); 

	LCD_WR_REG(0xE1);			
	LCD_WR_DATA8(0x10);
	LCD_WR_DATA8(0x0E);

	LCD_WR_REG(0xDF);			
	LCD_WR_DATA8(0x21);
	LCD_WR_DATA8(0x0c);
	LCD_WR_DATA8(0x02);

	LCD_WR_REG(0xF0);   
	LCD_WR_DATA8(0x45);
	LCD_WR_DATA8(0x09);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x26);
 	LCD_WR_DATA8(0x2A);

 	LCD_WR_REG(0xF1);    
 	LCD_WR_DATA8(0x43);
 	LCD_WR_DATA8(0x70);
 	LCD_WR_DATA8(0x72);
 	LCD_WR_DATA8(0x36);
 	LCD_WR_DATA8(0x37);  
 	LCD_WR_DATA8(0x6F);


 	LCD_WR_REG(0xF2);   
 	LCD_WR_DATA8(0x45);
 	LCD_WR_DATA8(0x09);
 	LCD_WR_DATA8(0x08);
 	LCD_WR_DATA8(0x08);
 	LCD_WR_DATA8(0x26);
 	LCD_WR_DATA8(0x2A);

 	LCD_WR_REG(0xF3);   
 	LCD_WR_DATA8(0x43);
 	LCD_WR_DATA8(0x70);
 	LCD_WR_DATA8(0x72);
 	LCD_WR_DATA8(0x36);
 	LCD_WR_DATA8(0x37); 
 	LCD_WR_DATA8(0x6F);

	LCD_WR_REG(0xED);	
	LCD_WR_DATA8(0x1B); 
	LCD_WR_DATA8(0x0B); 

	LCD_WR_REG(0xAE);			
	LCD_WR_DATA8(0x77);
	
	LCD_WR_REG(0xCD);			
	LCD_WR_DATA8(0x63);		


	LCD_WR_REG(0x70);			
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x04);
	LCD_WR_DATA8(0x0E); 
	LCD_WR_DATA8(0x0F); 
	LCD_WR_DATA8(0x09);
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x03);

	LCD_WR_REG(0xE8);			
	LCD_WR_DATA8(0x34);

	LCD_WR_REG(0x62);			
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x0D);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xED);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x0F);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xEF);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);

	LCD_WR_REG(0x63);			
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x11);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xF1);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x13);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xF3);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);

	LCD_WR_REG(0x64);			
	LCD_WR_DATA8(0x28);
	LCD_WR_DATA8(0x29);
	LCD_WR_DATA8(0xF1);
	LCD_WR_DATA8(0x01);
	LCD_WR_DATA8(0xF1);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x07);

	LCD_WR_REG(0x66);			
	LCD_WR_DATA8(0x3C);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0xCD);
	LCD_WR_DATA8(0x67);
	LCD_WR_DATA8(0x45);
	LCD_WR_DATA8(0x45);
	LCD_WR_DATA8(0x10);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);

	LCD_WR_REG(0x67);			
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x3C);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x01);
	LCD_WR_DATA8(0x54);
	LCD_WR_DATA8(0x10);
	LCD_WR_DATA8(0x32);
	LCD_WR_DATA8(0x98);

	LCD_WR_REG(0x74);			
	LCD_WR_DATA8(0x10);	
	LCD_WR_DATA8(0x85);	
	LCD_WR_DATA8(0x80);
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x4E);
	LCD_WR_DATA8(0x00);					
	
  	LCD_WR_REG(0x98);			
	LCD_WR_DATA8(0x3e);
	LCD_WR_DATA8(0x07);

	LCD_WR_REG(0x35);	
	LCD_WR_REG(0x21);

	LCD_WR_REG(0x11);
	delay_ms(120);
	LCD_WR_REG(0x29);
	delay_ms(20);
} 

main.c

这里实现了一个圆形波纹的动画效果,代码根据GC9A01官方例程移植而来

#include <stdio.h>
#include "lcd_init.h"

void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{          
	u16 i,j; 
	LCD_Address_Set(xsta,ysta,xend-1,yend-1);
	for(i=ysta;i<yend;i++)
	{													   	 	
		for(j=xsta;j<xend;j++)
		{
			LCD_WR_DATA(color);
		}
	} 					  	    
}

void LCD_DrawPoint(u16 x,u16 y,u16 color)
{
	LCD_Address_Set(x,y,x,y);
	LCD_WR_DATA(color);
} 

void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
{
	int a,b;
	a=0;b=r;	  
	while(a<=b)
	{
		LCD_DrawPoint(x0-b,y0-a,color);                   
		LCD_DrawPoint(x0+b,y0-a,color);                     
		LCD_DrawPoint(x0-a,y0+b,color);                       
		LCD_DrawPoint(x0-a,y0-b,color);                  
		LCD_DrawPoint(x0+b,y0+a,color);                        
		LCD_DrawPoint(x0+a,y0-b,color);           
		LCD_DrawPoint(x0+a,y0+b,color);          
		LCD_DrawPoint(x0-b,y0+a,color);     
		a++;
		if((a*a+b*b)>(r*r))
		{
			b--;
		}
	}
}

int main()
{
    int j = 0;
    LCD_Init();
    LCD_Fill(0, 0, 240, 240, BLACK);

    while (1)
    {
        for(int i = 0; i < 240; i += 10) {
            Draw_Circle(120, 120, i, 400 * j);
        }
        if(j++ > 65536 / 400) {
            j = 0;
        }
        usleep(1000000);
    }
    closeLCD();
    return 0;
}

实验效果

圆形波纹动画

在这里插入图片描述

参考

GC9A01官方例程地址:https://gitee.com/meta-mcu/gc9a01-tft.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/793800.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

css实现图片渐变切换效果

一、效果 使用csskeyframes&#xff0c;实现5个图片渐变切换的效果。如下图&#xff1a; 二、代码 1.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"w…

头歌资源库(27)特别的数

一、 问题描述 编程输出一个特别的数&#xff0c;该数是一个由1~9组成的9位数&#xff0c;每个数字只能出现一次&#xff0c;且这个9位数由高位到低位前i位能被i整除。 二、算法思想 创建一个长度为9的数组&#xff0c;用于存放1~9这9个数字。使用回溯算法&#xff0c;从第…

(WRF-UCM)高精度城市化气象动力模拟技术

气候变化及应对是政府、科学界及商业界关注的焦点。气候是多个领域&#xff08;生态、水资源、风资源及碳中和等问题&#xff09;的主要驱动因素&#xff0c;合理认知气候变化有利于解释生态环境变化机理及过程&#xff0c;而了解现在、未来气候变化则是进行生态、环境及能源评…

IDEA中配置代理,解决Codearts Snap登陆不了的问题

问题描述&#xff1a;在mac电脑中的idea中安装了华为的codearts snap插件&#xff0c;一直登录不了&#xff0c;账号是没问题的&#xff0c;后来我怀疑是我的代理有问题&#xff0c;找到IDEA中的代理设置先是有这个问题“You have JVM property "https.proxyHost" se…

C++基础(一)

目录 1.不同版本的hello word&#xff01; 2.namespace和&#xff1a;&#xff1a;域作用限定符以及using 2.1 namespace 2.2&#xff1a;&#xff1a; 2.3using用于展开域 3.C输入和输出 4.缺省参数 5.重载 6.引用 6.1引用介绍 6.2 引用的特性 注意&#xff1a; 6.4 c…

C#绘制阻抗圆图初步

阻抗圆图&#xff0c;或者叫史密斯图&#xff0c;是无线电设计方面用的&#xff1b; 基本的阻抗圆图如下&#xff0c; 下面尝试用C#能不能画一下&#xff1b; 先在网上找一个画坐标的C#类&#xff0c;它的效果如下&#xff1b; 自己再增加一个函数&#xff0c;可以绘制中心在…

Redis的安装配置及IDEA中使用

目录 一、安装redis&#xff0c;配置redis.conf 1.安装gcc 2.将redis的压缩包放到指定位置解压 [如下面放在 /opt 目录下] 3.编译安装 4.配置redis.conf文件 5.开机自启 二、解决虚拟机本地可以连接redis但是主机不能连接redis 1.虚拟机网络适配器网络连接设置为桥接模式…

《昇思25天学习打卡营第16天|基于MindNLP+MusicGen生成自己的个性化音乐》

MindNLP 原理 MindNLP 是一个自然语言处理&#xff08;NLP&#xff09;框架&#xff0c;用于处理和分析文本数据。 文本预处理&#xff1a;包括去除噪声、分词、词性标注、命名实体识别等步骤&#xff0c;使文本数据格式化并准备好进行进一步分析。 特征提取&#xff1a;将文…

【嵌入式Linux】<知识点> GDB调试(更新中)

文章目录 前言 一、GDB调试预备工作 二、GDB的启动与退出 三、GDB中查看源代码 四、GDB断点操作 五、GDB调试指令 前言 在专栏【嵌入式Linux】应用开发篇_Linux打工仔的博客中&#xff0c;我们已经写了大量的源程序。但是在调试这些程序时我们都是通过printf大法和肉眼除…

异业联盟整合各大行业门店,共享资源

异业联盟系统是一种将不同行业的企业或商家整合在一起&#xff0c;通过资源共享、优势互补、合作推广等方式&#xff0c;实现共同发展和互利共赢的商业合作模式的数字化管理和运营系统。 其具有以下显著优势&#xff1a; 1.拓展客户群体&#xff1a;不同行业的企业联合起来&am…

Python骨架肌体运动学数学模型

&#x1f3af;要点 &#x1f3af;运动学矢量计算 | &#x1f3af;跳远的运动学计算 | &#x1f3af;关节肢体运动最小加加速度模型 | &#x1f3af;膝关节和踝关节角度二维运动学计算 | &#x1f3af;上下肢体关节连接运动链数学模型 | &#x1f3af;刚体连接点速度加速度计算…

PPTP、L2TP、IPSec、IPS 有什么区别?

随着互联网的发展&#xff0c;保护网络通信的安全越来越重要。PPTP、L2TP、IPSec、IPS是常见的网络安全协议和技术&#xff0c;在保护网络通信安全方面发挥着不同的作用和特点。下面介绍PPTP、L2TP、IPSec、IPS之间的区别。 点对点隧道协议&#xff08;PPTP&#xff09;是一种用…

Android列表控件的属性与用法

列表控件的属性与用法 列表控件有Spinner、ListView、RecyclerView、ViewPager等。列表控件的显示一般涉及3个部分&#xff1a;控件、适配器、数据&#xff0c;这三者之间的关系如图1所示。适配器是数据与列表之间的桥梁&#xff0c;适配器中需要将数据中需要显示的属性与列表…

Qt | 绘制直线与 QLineF 类

点击上方"蓝字"关注我们 01、绘制直线 02、Qline和QLineF 【1】QLine 是整型版本,成员函数较少,QLineF 是精度更高的浮点型版本,本文以 QLineF 类 进行讲解。 QLineF 类提供了一个二维向量,使用 QLineF 类绘制直线可以利用该类中的成员函数方便 的对线条的属…

调试的时候如何查看当前程序的变量信息

目录 调试前/后的调试窗口 ​编辑 调试窗口 --- 监视 调试窗口 --- 内存 调试窗口 --- 调用堆栈 调试前/后的调试窗口 调试前的调试窗口&#xff1a; 调试前的调试窗口是没有显示的&#xff0c;只有在调试的时候才会有相对应的调试窗口 调试后的调试窗口&#xff1a…

如何找工作 校招 | 社招 | 秋招 | 春招 | 提前批

马上又秋招了&#xff0c;作者想起以前读书的时候&#xff0c;秋招踩了很多坑&#xff0c;但是第一份工作其实挺重要的。这里写一篇文章&#xff0c;分享一些校招社招的心得。 现在大学的情况是&#xff0c;管就业的人&#xff0c;大都是没有就业的辅导员&#xff08;笔者见过…

开启新纪元!被AI驱动的游戏世界,提升游戏体验

随着人工智能的高速发展&#xff0c;人工智能逐渐应用到了生活中的方方面面&#xff0c;人工智能在游戏中也有诸多应用&#xff0c;在游戏里领域扮演了相当重要的角色。游戏AI是伴随着电子游戏而出现的&#xff0c;在早期的游戏中就出现了对抗类AI角色&#xff0c;后来逐渐出现…

SpringBoot新手快速入门系列教程十一:基于Docker Compose部署一个最简单分部署服务项目

如果您还对于Docker或者Docker Compose不甚了解&#xff0c;可以劳烦移步到我之前的教程&#xff1a; SpringBoot新手快速入门系列教程九&#xff1a;基于docker容器&#xff0c;部署一个简单的项目 SpringBoot新手快速入门系列教程十&#xff1a;基于Docker Compose&#xf…

职业教育人工智能实验实训室建设应用案例

随着人工智能技术的快速发展&#xff0c;其在职业教育领域的应用逐渐深入。唯众作为一家专注于教育技术领域的企业&#xff0c;积极响应国家关于人工智能教育的政策号召&#xff0c;通过建设人工智能实验实训室&#xff0c;为学生提供了一个实践操作与创新思维相结合的学习平台…

Axure-黑马

Axure-黑马 编辑时间2024/7/12 来源&#xff1a;B站黑马程序员 需求其他根据&#xff1a;visio&#xff0c;墨刀 Axure介绍 Axure RP是美国Axure Software Solution给公司出品的一款快速原型大的软件&#xff0c;一般来说使用者会称他为Axure 应用场景 拉投资使用 给项目团…