Linux学习笔记————C 语言版 LED 灯实验

news/2024/7/26 11:28:29/文章来源:https://blog.csdn.net/wozhihecha/article/details/137288646

这里写目录标题

  • 一、实验程序编写
  • 二、 汇编部分实验程序编写
  • 三、C 语言部分实验程序编写
  • 四、编译下载验证

汇编 LED 灯实验中,我们讲解了如何使用汇编来编写 LED 灯驱动,实际工作中是很少用到汇编去写嵌入式驱动的,毕竟汇编太难,而且写出来也不好理解,大部分情况下都是使用 C 语言去编写的。只是在开始部分用汇编来初始化一下 C 语言环境,比如初始化 DDR、设置堆栈指针 SP 等等,当这些工作都做完以后就可以进入 C 语言环境,也就是运行 C 语言代码,一般都是进入 main 函数。所以我们有两部分文件要做:
①、汇编文件
汇编文件只是用来完成 C 语言环境搭建。
②、C 语言文件
C 语言文件就是完成我们的业务层代码的,其实就是我们实际例程要完成的功能。

一、实验程序编写

新建 VScode 工程,工程名字为“ledc”,新建三个文件:start.S、main.c 和 main.h。其中 start.S是汇编文件,main.c 和 main.h 是 C 语言相关文件

二、 汇编部分实验程序编写

示例代码  start.s 文件代码
描述 : I.MX6U-ALPHA/I.MX6ULL 开发板启动文件,完成 C 环境初始化,C 环境初始化完成以后跳转到 C 代码。
**************************************************************/
1 .global _start /* 全局标号 */
2 
3 /*
4 * 描述: _start 函数,程序从此函数开始执行,此函数主要功能是设置 C 5 * 运行环境。
6 */
7 _start: 
8
9 /* 进入 SVC 模式 */
10 mrs r0, cpsr
11 bic r0, r0, #0x1f /* 将 r0 的低 5 位清零,也就是 cpsr 的 M0~M4 */
12 orr r0, r0, #0x13 /* r0 或上 0x13,表示使用 SVC 模式 */
13 msr cpsr, r0 /* 将 r0 的数据写入到 cpsr_c 中 */
14
15 ldr sp, =0X80200000 /* 设置栈指针 */
16 b main /* 跳转到 main 函数 */

第 1 行定义了一个全局标号_start

第 7 行就是标号_start 开始的地方,相当于是一个_start 函数,这个_start 就是第一行代码。

第 10~ 13 行就是设置处理器进入 SVC 模式, Cortex-A 有九个运行模型,这里我们设置处理器运行在 SVC 模式下。处理器模式的设置是通过修改 CPSR(程序状态)寄存器来完成的, CPSR 寄存器中 M[4:0](CPSR 的 bit[4:0])就是设置处理器运行模式的,如果要将处理器设置为 SVC 模式,那么 M[4:0]就要等于 0X13。11~13 行代码就是先使用指令 MRS 将 CPSR寄存器的值读取到 R0 中,然后修改 R0 中的值,设置 R0 的 bit[4:0]为 0X13,然后再使用指令MSR 将修改后的 R0 重新写入到 CPSR 中。

第 15 行通过 ldr 指令设置 SVC 模式下的 SP 指针=0X80200000,因为 I.MX6U-ALPHA 开发板上的 DDR3 地址范围是 0X80000000~ 0XA0000000(512MB) 或 者0X80000000~ 0X90000000(256MB),不管是 512MB 版本还是 256MB 版本的,其 DDR3 起始地址都是 0X80000000。由于 Cortex-A7 的堆栈是向下增长的,所以将 SP 指针设置为 0X80200000,因此 SVC 模式的栈大小 0X80200000-0X80000000=0X200000=2MB,2MB 的栈空间已经很大了,如果做裸机开发的话绰绰有余。

第 16 行就是跳转到 main 函数,main 函数就是 C 语言代码了。

至此汇编部分程序执行完成,就几行代码,用来设置处理器运行到 SVC 模式下、然后初始化 SP 指针、最终跳转到 C 文件的 main 函数中。如果有玩过三星的 S3C2440 或者 S5PV210 的话会知道我们在使用 SDRAM 或者 DDR 之前必须先初始化 SDRAM 或者 DDR。所以 S3C2440或者 S5PV210 的汇编文件里面是一定会有 SDRAM 或者 DDR 初始化代码的。我们上面编写的start.s 文件中却没有初始化 DDR3 的代码,但是却将 SVC 模式下的 SP 指针设置到了 DDR3 的地址范围中,这不会出问题吗?肯定不会的,DDR3 肯定是要初始化的,但是不需要在 start.s 文件中完成。在分析 DCD 数据的时候就已经讲过了,DCD 数据包含了 DDR 配置参数,I.MX6U 内部的 Boot ROM 会读取 DCD 数据中的 DDR 配置参数然后完成 DDR 初始化的。

三、C 语言部分实验程序编写

C 语言部分有两个文件 main.c 和 main.h,main.h 里面主要是定义的寄存器地址,在 main.h里面输入代码:

示例代码 main.h 文件代码
#ifndef __MAIN_H
#define __MAIN_H
/******************************************************************
描述 : 时钟 GPIO1_IO03 相关寄存器地址定义。
其他 : 无
*****************************************************************/
1 /* 
2 * CCM 相关寄存器地址
3 */
4 #define CCM_CCGR0 *((volatile unsigned int *)0X020C4068)
5 #define CCM_CCGR1 *((volatile unsigned int *)0X020C406C) 
6 #define CCM_CCGR2 *((volatile unsigned int *)0X020C4070) 
7 #define CCM_CCGR3 *((volatile unsigned int *)0X020C4074) 
8 #define CCM_CCGR4 *((volatile unsigned int *)0X020C4078) 
9 #define CCM_CCGR5 *((volatile unsigned int *)0X020C407C)
10 #define CCM_CCGR6 *((volatile unsigned int *)0X020C4080)
11
12 /* 
13 * IOMUX 相关寄存器地址
14 */
15 #define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068) 
16 #define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02F4) 
17
18 /* 
19 * GPIO1 相关寄存器地址
20 */
21 #define GPIO1_DR *((volatile unsigned int *)0X0209C000)
22 #define GPIO1_GDIR *((volatile unsigned int *)0X0209C004)
23 #define GPIO1_PSR *((volatile unsigned int *)0X0209C008)
24 #define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C)
25 #define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010)
26 #define GPIO1_IMR *((volatile unsigned int *)0X0209C014)
27 #define GPIO1_ISR *((volatile unsigned int *)0X0209C018)
28 #define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C)
29
30 #endif

在 main.h 中我们以宏定义的形式定义了要使用到的所有寄存器,后面的数字就是其地址,比如 CCM_CCGR0 寄存器的地址就是 0X020C4068,这个很简单,很好理解。

接下看一下 main.c 文件,在 main.c 里面输入如下所示代码:

示例代码 main.c 文件代码
/**************************************************************
描述 : I.MX6U 开发板裸机实验 2 C 语言点灯
使用 C 语言来点亮开发板上的 LED 灯,学习和掌握如何用 C 语言来完成对 I.MX6U 处理器的 GPIO 初始化和控制。
**************************************************************/
1 #include "main.h"
2 
3 /*
4 * @description : 使能 I.MX6U 所有外设时钟
5 * @param : 无 
6 * @return : 无 
7 */
8 void clk_enable(void) 
9 {
10 CCM_CCGR0 = 0xffffffff;
11 CCM_CCGR1 = 0xffffffff;
12 CCM_CCGR2 = 0xffffffff;
13 CCM_CCGR3 = 0xffffffff;
14 CCM_CCGR4 = 0xffffffff;
15 CCM_CCGR5 = 0xffffffff;
16 CCM_CCGR6 = 0xffffffff;
17 }
18
19 /*
20 * @description : 初始化 LED 对应的 GPIO
21 * @param : 无
22 * @return : 无
23 */
24 void led_init(void)
25 {
26 /* 1、初始化 IO 复用, 复用为 GPIO1_IO03 */
27 SW_MUX_GPIO1_IO03 = 0x5; 
28 
29 /* 2、配置 GPIO1_IO03 的 IO 属性 
30 *bit [16]:0 HYS 关闭
31 *bit [15:14]: 00 默认下拉
32 *bit [13]: 0 kepper 功能
33 *bit [12]: 1 pull/keeper 使能
34 *bit [11]: 0 关闭开路输出
35 *bit [7:6]: 10 速度 100Mhz
36 *bit [5:3]: 110 R0/6 驱动能力
37 *bit [0]: 0 低转换率
38 */
39 SW_PAD_GPIO1_IO03 = 0X10B0; 
40
41 /* 3、初始化 GPIO, GPIO1_IO03 设置为输出 */
42 GPIO1_GDIR = 0X0000008;
43 
44 /* 4、设置 GPIO1_IO03 输出低电平,打开 LED0 */
45 GPIO1_DR = 0X0;
46 }
48 /*
49 * @description : 打开 LED 灯
50 * @param : 无
51 * @return : 无
52 */
53 void led_on(void)
54 {
55 /* 
56 * 将 GPIO1_DR 的 bit3 清零 
57 */
58 GPIO1_DR &= ~(1<<3);
59 }
60 
61 /*
62 * @description : 关闭 LED 灯
63 * @param : 无
64 * @return : 无
65 */
66 void led_off(void)
67 {
68 /* 
69 * 将 GPIO1_DR 的 bit3 置 1
70 */
71 GPIO1_DR |= (1<<3);
72 }
73 
74 /*
75 * @description : 短时间延时函数
76 * @param - n : 要延时循环次数(空操作循环次数,模式延时)
77 * @return : 无
78 */
79 void delay_short(volatile unsigned int n)
80 {
81 while(n--){}
82 }
83 
84 /*
85 * @description : 延时函数,在 396Mhz 的主频下延时时间大约为 1ms
86 * @param - n : 要延时的 ms 数
87 * @return : 无
88 */
89 void delay(volatile unsigned int n)
90 {
91 while(n--)
92 {
93 delay_short(0x7ff);
94 }
95 }
96 
97 /*
98 * @description : main 函数
99 * @param : 无
100 * @return : 无
101 */
102 int main(void)
103 {
104 clk_enable(); /* 使能所有的时钟 */
105 led_init(); /* 初始化 led */
106
107 while(1) /* 死循环 */
108 { 
109 led_off(); /* 关闭 LED */
110 delay(500); /* 延时大约 500ms */
111
112 led_on(); /* 打开 LED */
113 delay(500); /* 延时大约 500ms */
114 }
115
116 return 0;
117 }

main.c 文件里面一共有 7 个函数,这 7 个函数都很简单。clk_enable 函数是使能CCGR0~CCGR6 所控制的所有外设时钟。led_init 函数是初始化 LED 灯所使用的 IO,包括设置IO 的复用功能、IO 的属性配置和 GPIO 功能,最终控制 GPIO 输出低电平来打开 LED 灯。led_on 和 led_off 这两个函数看名字就知道,用来控制 LED 灯的亮灭的。delay_short()和 delay()这两个函数是延时函数,delay_short()函数是靠空循环来实现延时的,delay()是对 delay_short()的 简单封 装, 在 I.MX6U 工 作在 396MHz(Boot ROM 设置 的 396MHz) 的主 频的时 候
delay_short(0x7ff)基本能够实现大约 1ms 的延时,所以 delay()函数我们可以用来完成 ms 延时。main 函数就是我们的主函数了,在 main 函数中先调用函数 clk_enable()和 led_init()来完成时钟使能和 LED 初始化,最终在 while(1)循环中实现 LED 循环亮灭,亮灭时间大约是 500ms。

本实验的程序部分就是这些了,接下来即使编译和测试了。

四、编译下载验证

4.1 编写 Makefile
新建 Makefile 文件,在 Makefile 文件里面输入如下内容:

示例代码 10.3.2.2 main.c 文件代码
1 objs := start.o main.o
2 
3 ledc.bin:$(objs)
4 arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^
5 arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
6 arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
7 
8 %.o:%.s
9 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
10 
11 %.o:%.S
12 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
13 
14 %.o:%.c
15 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
16 
17 clean:
18 rm -rf *.o ledc.bin ledc.elf ledc.dis

第 1 行定义了一个变量 objs,objs 包含着要生成 ledc.bin 所需的材料:start.o 和 main.o,也就是当前工程下的 start.s 和 main.c 这两个文件编译后的.o 文件。这里要注意 start.o 一定要放到最前面!因为在后面链接的时候 start.o 要在最前面,因为 start.o 是最先要执行的文件!

第 3 行就是默认目标,目的是生成最终的可执行文件 ledc.bin,ledc.bin 依赖 start.o 和 main.o如果当前工程没有 start.o 和 main.o 的时候就会找到相应的规则去生成 start.o 和 main.o。比如start.o 是 start.s 文件编译生成的,因此会执行第 8 行的规则。

第 4 行是使用 arm-linux-gnueabihf-ld 进行链接,链接起始地址是 0X87800000,但是这一行用到了自动变量“ ” ,“ ^”,“ ^”的意思是所有依赖文件的集合,在这里就是 objs 这个变量的值:start.o 和 main.o。链接的时候 start.o 要链接到最前面,因为第一行代码就是 start.o 里面的,因此这一行就相当于:
在这里插入图片描述
第 5 行使用 arm-linux-gnueabihf-objcopy 来将 ledc.elf 文件转为 ledc.bin,本行也用到了自动变量“ @ ”,“ @”,“ @”@”的意思是目标集合,在这里就是“ledc.bin”,那么本行就相当于:
在这里插入图片描述
第 6 行使用 arm-linux-gnueabihf-objdump 来反汇编,生成 ledc.dis 文件。

第 8~15 行就是针对不同的文件类型将其编译成对应的.o 文件,其实就是汇编.s(.S)和.c 文件,比如 start.s 就会使用第 8 行的规则来生成对应的 start.o 文件。第 9 行就是具体的命令,这行也用到了自动变量“ @ ”和“ @”和“ @”<”,其中“$<”的意思是依赖目标集合的第一个文件。比如start.s 要编译成 start.o 的话第 8 行和第 9 行就相当于:
在这里插入图片描述
第 17 行就是工程清理规则,通过命令“make clean”就可以清理工程。Makefile 文件就讲到这里,我们可以将整个工程拿到 Ubuntu 下去编译,编译完成以后可以使用软件 imxdownload 将其下载到 SD 卡中,命令如下:
在这里插入图片描述
4.2 链接脚本
在上面的 Makefile 中我们链接代码的时候使用如下语句:
在这里插入图片描述
上面语句中我们是通过“-Ttext”来指定链接地址是 0X87800000 的,这样的话所有的文件都会链接到以 0X87800000 为起始地址的区域。但是有时候我们很多文件需要链接到指定的区域,或者叫做段里面,比如在 Linux 里面初始化函数就会放到 init 段里面。因此我们需要能够自定义一些段,这些段的起始地址我们可以自由指定,同样的我们也可以指定一个文件或者函数应该存放到哪个段里面去。要完成这个功能我们就需要使用到链接脚本,看名字就知道链接脚本主要用于链接的,用于描述文件应该如何被链接在一起形成最终的可执行文件。其主要目的是描述输入文件中的段如何被映射到输出文件中,并且控制输出文件中的内存排布。比如我们编译生成的文件一般都包含 text 段、data段等等。

链接脚本的语法很简单,就是编写一系列的命令,这些命令组成了链接脚本,每个命令是一个带有参数的关键字或者一个对符号的赋值,可以使用分号分隔命令。像文件名之类的字符串可以直接键入,也可以使用通配符“*”。最简单的链接脚本可以只包含一个命令“SECTIONS”,
我们可以在这一个“SECTIONS”里面来描述输出文件的内存布局。我们一般编译出来的代码都包含在 text、data、bss 和 rodata 这四个段内,假设现在的代码要被链接到 0X10000000 这个地址,数据要被链接到 0X30000000 这个地方,下面就是完成此功能的最简单的链接脚本:

示例代码链接脚本演示代码
1 SECTIONS{ 
2 . = 0X10000000; 
3 .text : {*(.text)}
4 . = 0X30000000; 
5 .data ALIGN(4) : { *(.data) } 
6 .bss ALIGN(4) : { *(.bss) } 
7 }

第 1 行我们先写了一个关键字“SECTIONS”,后面跟了一个大括号,这个大括号和第 7 行的大括号是一对,这是必须的。看起来就跟 C 语言里面的函数一样

第 2 行对一个特殊符号“.”进行赋值,“.”在链接脚本里面叫做定位计数器,默认的定位计数器为 0。我们要求代码链接到以 0X10000000 为起始地址的地方,因此这一行给“.”赋值0X10000000,表示以 0X10000000 开始,后面的文件或者段都会以 0X10000000 为起始地址开
始链接。

第 3 行的“.text”是段名,后面的冒号是语法要求,冒号后面的大括号里面可以填上要链接到“.text”这个段里面的所有文件,“(.text)”中的“”是通配符,表示所有输入文件的.text段都放到“.text”中。

第 4 行,我们的要求是数据放到 0X30000000 开始的地方,所以我们需要重新设置定位计数器“.”,将其改为 0X30000000。如果不重新设置的话会怎么样?假设“.text”段大小为 0X10000,那么接下来的.data 段开始地址就是 0X10000000+0X10000=0X10010000,这明显不符合我们的要求。所以我们必须调整定位计数器为 0X30000000。

第 5 行跟第 3 行一样,定义了一个名为“.data”的段,然后所有文件的“.data”段都放到这里面。但是这一行多了一个“ALIGN(4)”,这是什么意思呢?这是用来对“.data”这个段的起始地址做字节对齐的,ALIGN(4)表示 4 字节对齐。也就是说段“.data”的起始地址要能被 4 整除,一般常见的都是 ALIGN(4)或者 ALIGN(8),也就是 4 字节或者 8 字节对齐。

第 6 行定义了一个“.bss”段,所有文件中的“.bss”数据都会被放到这个里面,“.bss”数据就是那些定义了但是没有被初始化的变量。

上面就是链接脚本最基本的语法格式,我们接下来就按照这个基本的语法格式来编写我们本试验的链接脚本,我们本试验的链接脚本要求如下:
①、链接起始地址为 0X87800000。
②、start.o 要被链接到最开始的地方,因为 start.o 里面包含这第一个要执行的命令。
根据要求,在 Makefile 同目录下新建一个名为“imx6ul.lds”的文件,然后在此文件里面输入如下所示代码:

示例代码  imx6ul.lds 链接脚本代码
1 SECTIONS{ 2 . = 0X87800000; 3 .text : 4 { 5 start.o 
6 main.o 
7 *(.text) 8 } 9 .rodata ALIGN(4) : {*(.rodata*)} 
10 .data ALIGN(4) : { *(.data) } 
11 __bss_start = .; 
12 .bss ALIGN(4) : { *(.bss) *(COMMON) } 
13 __bss_end = .;
14 }

第 2 行设置定位计数器为0X87800000,因为我们的链接地址就是0X87800000。第5行设置链接到开始位置的文件为start.o,因为 start.o 里面包含着第一个要执行的指令,所以一定要链接到最开始的地方。第 6 行是 main.o这个文件,其实可以不用写出来,因为 main.o 的位置就无所谓了,可以由编译器自行决定链接位置。在第 11、13 行有“__bss_start”和“__bss_end”这两个东西?这个是什么呢?“__bss_start”和“__bss_end”是符号,第 11、13 这两行其实就是对这两个符号进行赋值,其值为定位符“.”,这两个符号用来保存.bss 段的起始地址和结束地址。前面说了.bss 段是定义了但是没有被初始化的变量,我们需要手动对.bss 段的变量清零的,因此我们需要知道.bss 段的起始和结束地址,这样我们直接对这段内存赋 0 即可完成清零。通过第 11、13 行代码,.bss 段的起始地址和结束地址就保存在了“__bss_start”和“__bss_end”中,我们就可以直接在汇编或者 C 文件里面使用这两个符号。

4.3 修改 Makefile
在上一小节中我们已经编写好了链接脚本文件:imx6ul.lds,我们肯定是要使用这个链接脚本文件的,将 Makefile 中的如下一行代码:
在这里插入图片描述
改为:
在这里插入图片描述
其实就是将-T 后面的 0X87800000 改为 imx6ul.lds,表示使用 imx6ul.lds 这个链接脚本文件。修改完成以后使用新的 Makefile 和链接脚本文件重新编译工程,编译成功以后就可以烧写到 SD 卡中验证了。

4.4 下载验证
使用软件 imxdownload 将编译出来的 ledc.bin 烧写到 SD 卡中,命令如下:
在这里插入图片描述
烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板,如果代码运行正常的话 LED0 就会以 500ms 的时间间隔亮灭。

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

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

相关文章

linux设置Nacos自启动

前提&#xff1a;已经安装好nacos应用 可参考&#xff1a;Nacos单机版安装-CSDN博客 1. 创建nacos.service 1.1 在 /lib/systemd/system 目录底下&#xff0c;新建nacos.service文件 [Unit] Descriptionnacos Afternetwork.target[Service]Typeforking# 单机启动方式&#…

OmniGraffle Pro for mac 出色的图形设计软件

OmniGraffle Pro是一款非常出色的图形设计软件&#xff0c;它主要适用于Mac和iPad平台&#xff0c;可以用来轻松绘制各种精美的图表、示意图和界面设计。 软件下载&#xff1a;OmniGraffle Pro for mac中文注册激活版 以下是OmniGraffle Pro的一些主要特点和功能&#xff1a; 界…

Java就近原则和this关键字

Java 中的就近原则和 this 关键字有着密切的关系&#xff0c;特别是在处理成员变量与方法参数同名的情况下。就近原则指的是在同一作用域下&#xff0c;优先使用最近声明的变量或参数。 在 Java 中&#xff0c;如果一个方法的参数与类的成员变量同名&#xff0c;为了明确指示要…

HTX Ventures:为什么BounceBit可能成为新的BTC生态解决方案?

随着BTC现货ETF的通过&#xff0c;全球各大机构和个人都在不断加码对BTC的持仓&#xff0c;BTC价格也随之上升&#xff0c;目前已上升至全球市值排名前十的资产。在本轮市场周期中&#xff0c;BTC铭文和BTC扩容是两个被市场高度关注的细分赛道。BTC生态资产的多元化收益探索正在…

HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程

HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程 &#x1f4cd;相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》 ✨stm32使用硬件I2C去读取角度数据&#xff0c;通过STM32CubeMX工具配置工程&#xff0c;读取角度数据&#xff0c;只需要调用一个函数&#xf…

如何使用VNC+Cpolar实现Windows电脑公网远程控制Ubuntu系统桌面

文章目录 前言1. VisualSVN安装与配置2. VisualSVN Server管理界面配置3. 安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4. 固定公网地址访问 前言 SVN 是 subversion 的缩写&#xff0c;是一个开放源代码的版本控制系统…

复变函数导数求解(包含矢量、矩阵形式)

文章目录 目录 文章目录 前言 一、复变函数导数 1.1 导数定义 1.2 求导法则 1.3 存在条件 二、常用求导结论 2.1 标量函数对标量的导数 2.2 标量函数对矢量的导数 2.3 标量函数对矩阵的导数 总结 前言 本文将从信号处理的角度简单阐明复变函数理论的重要性&#xff…

Ansys Zemax | 如何将光栅数据从Lumerical导入至OpticStudio(上)

附件下载 联系工作人员获取附件 本文介绍了一种使用Ansys Zemax OpticStudio和Lumerical RCWA在整个光学系统中精确仿真1D/2D光栅的静态工作流程。将首先简要介绍方法。然后解释有关如何建立系统的详细信息。 本篇内容将分为上下两部分&#xff0c;上部将首先简要介绍方法工…

工业边缘计算网关在工业中的应用以及其为工业生产带来的效益-天拓四方

随着信息技术的不断发展&#xff0c;工业领域对数据处理和分析的需求日益增长。工业边缘计算网关作为一种新型技术&#xff0c;正逐渐成为工业数字化转型的关键驱动力。本文将通过一个具体案例阐述工业边缘计算网关在工业中的应用&#xff0c;以及其为工业生产带来的显著效益。…

Stable Diffusion 模型下载:epiCPhotoGasm(真实、照片)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八下载地址模型介绍

【QT入门】 QListWidget各种常见用法详解之列表模式

往期回顾 【QT入门】 Qt代码创建布局之setLayout使用-CSDN博客 【QT入门】 Qt代码创建布局之多重布局变换与布局删除技巧-CSDN博客 【QT入门】 QTabWidget各种常见用法详解-CSDN博客 【QT入门】 QListWidget各种常见用法详解之列表模式 QListWidget有列表和图标两种显示模式&a…

基于ssm汽车养护管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本汽车养护管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

啥是MCU,MCU科普

啥是MCU&#xff0c;MCU科普 附赠自动驾驶学习资料和量产经验&#xff1a;链接 MCU是Microcontroller Unit 的简称&#xff0c;中文叫微控制器&#xff0c;俗称单片机&#xff0c;是把CPU的频率与规格做适当缩减&#xff0c;并将内存、计数器、USB、A/D转换、UART、PLC、DMA等…

YARN集群 和 MapReduce 原理及应用

YARN集群模式 本文内容需要基于 Hadoop 集群搭建完成的基础上来实现 如果没有搭建&#xff0c;请先按上一篇: <Linux 系统 CentOS7 上搭建 Hadoop HDFS集群详细步骤> 搭建&#xff1a;https://mp.weixin.qq.com/s/zPYsUexHKsdFax2XeyRdnA 配置hadoop安装目录下的 etc…

Netty学习——源码篇10 Netty内存分配ByteBuf基础

1 初始ByteBuf ByteBuf是Netty整个结构中最为底层的模块&#xff0c;主要负责把数据从底层I/O读取到ByteBuf&#xff0c;然后传递给应用程序&#xff0c;应用程序处理完成后再把数据封装成ByteBuf写回I/O。所以&#xff0c;ByteBuf是直接与底层打交道的一层抽象。 2 ByteBuf的…

蓝桥杯物联网竞赛_STM32L071_15_ADC/脉冲模块

ADC模块用的是RP1不用多说了&#xff0c;主要是脉冲模块&#xff0c;这个模块没考过 这个脉冲模块放出脉冲&#xff0c;主要能用TIM捕获到这个脉冲的高电平持续时间即可 CubMx配置&#xff1a; 脉冲模块的引脚与PB0相连&#xff0c;所以用PB0读取上升沿记的数和下降沿记的数&am…

JavaScript基础代码练习之表单提交

一、这段代码是一个简单的HTML页面&#xff0c;其中包含一个密码输入框和一个用于显示提示消息的段落。当密码输入框失去焦点时&#xff08;即用户输入完成后点击其他地方&#xff09;&#xff0c;会触发事件处理函数。该函数会检查密码的长度是否在6到16位之间&#xff0c;如果…

非关系型数据库之Redis配置与优化

一、关系数据库与非关系型数据库 1.1关系型数据库 关系型数据库是一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上一般面向于记录。SQL语句&#xff08;标准数据查询语言&#xff09;就是一种基于关系型数据库的语言&#xff0c;用…

Python实现【贪吃蛇大作战】+源码

文章目录 前言&#xff1a;一、游戏概述1.游戏玩法2.游戏特色 二、游戏规则三、工具选择四、主要技术pygame 库numpy 库cocos2d 五、源码分享六、项目地址 前言&#xff1a; 今天的GitHub小游戏分享&#xff0c;我们将聚焦于一个经典而又极富趣味性的游戏——贪吃蛇大作战。这…

部署云原生边缘计算平台kubeedge

文章目录 1、kubeedge架构2、基础服务提供 负载均衡器 metallb2.1、开启ipvc模式中的strictARP2.2、部署metalb2.2.1、创建IP地址池2.2.2、开启二层转发&#xff0c;实现在k8s集群节点外访问2.2.3、测试 3、部署cloudcore3.1、部署cloudcore3.2、修改cloudcore的网络类型 4、部…