【正点原子Linux连载】第二十三章 Linux PWM驱动实验 摘自【正点原子】ATK-DLRK3568嵌入式Linux驱动开发指南

news2024/11/27 14:52:07

1)实验平台:正点原子ATK-DLRK3568开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=731866264428
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban

第二十三章 Linux PWM驱动实验

PWM是很常用到功能,我们可以通过PWM来控制电机速度,也可以使用PWM来控制LCD的背光亮度。本章我们就来学习一下如何在Linux下进行PWM驱动开发。

23.1 PWM驱动简析
PWM全称是Pulse Width Modulation,也就是脉冲宽度调制,PWM信号如图23.1.1所示:
在这里插入图片描述

图23.1.1 PWM信号
PWM信号有两个关键的术语:频率和占空比,频率就是开关速度,把一次开关算作一个周期,那么频率就是1秒内进行了多少次开关。占空比就是一个周期内高电平时间和低电平时间的比例,一个周期内高电平时间越长占空比就越大,反之占空比就越小。占空比用百分之表示,如果一个周期内全是低电平那么占空比就是0%,如果一个周期内全是高电平那么占空比就是100%。
我们给LCD的背光引脚输入一个PWM信号,这样就可以通过调整占空比的方式来调整LCD背光亮度了。提高占空比就会提高背光亮度,降低占空比就会降低背光亮度,重点就在于PWM信号的产生和占空比的控制。
23.1.1 设备树下的PWM控制器节点
1、PWM通道与引脚
RK3568有4个PWM模块,每个PWM模块有4个通道,因此一共有16路PWM:PWM0~PWM15,PWM模块与PWM通道以及对应的引脚关系如表23.1.1.1所示:
在这里插入图片描述

图23.1.1.1 RK3568 PWM通道与引脚
其中PWM3,PWM7,PWM11和PWM15可用用于IR。
2、PWM简介
RK3568有4个PWM模块,每个PWM模块的功能基本相同,这些PWM通道的特性如下:
①、每个PWM模块有4个通道。
②、支持捕获模式:
—测量输入波形高低电平的有效周期。
—输入波形极性变化的时候产生中断信号。
—32位高电平捕获寄存器。
—32位低电平捕获寄存器。
—32位当前值寄存器。
—捕获结果可以保存到FIFO中,FIFO深度为8,FIFO中的数据可以通过CPU或DMA读取。
③、支持连续以及单次模式:
— 32位的周期计数寄存器。
— 32位的占空比寄存器。
— 32位当前值寄存器。
— 输出PWM极性以及占空比可调。
— 可配置中央对齐或左对齐模式。
3、PWM设备节点
接下来看一下PWM的设备树,RK3568的PWM设备树绑定信息文档为:Documentation/devicetree/bindings/pwm/pwm-rockchip.txt,我们简单总结一下PWM节点信息。
①、必须的参数:
compatible:必须是“rockchip,-pwm”形式的,比如:rockchip,rk3288-pwm、rockchip,rk3568-pwm等。对于RK3568而言,有效的是rockchip,rk3288-pwm。
reg:PWM控制器物理寄存器基地址,比如对于PWM0来说,这个地址为0XFDD70000,这个可以在RK3568的数据手册上找到。
clocks:时钟源。
#pwm-cells:瑞芯微的芯片必须是2或者3,对于RK3568来说是3。
了解完PWM的绑定文档以后,我们来看一下RK3568实际的定时器节点,打开rk3568.dtsi,找到名为“pwm15”的设备节点,内容如下:
示例代码23.1.1.1 PWM15节点

1 pwm15: pwm@fe700030 {
2         compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm";
3         reg = <0x0 0xfe700030 0x0 0x10>;
4         interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
5                      <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
6         #pwm-cells = <3>;
7         pinctrl-names = "active";
8         pinctrl-0 = <&pwm15m0_pins>;
9         clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
10        clock-names = "pwm", "pclk";
11        status = "disabled";
12};
RK3568的PWM节点的compatible属性为“rockchip,rk3568-pwm”和“”rockchip,rk3328-pwm,我们可以在linux内核源码中搜索这两个字符串就可以找到PWM驱动文件,这个文件为:drivers/pwm/pwm-rockchip.c。

23.1.2 PWM子系统
Linux内核提供了个PWM子系统框架,编写PWM驱动的时候一定要符合这个框架。PWM子系统的核心是pwm_chip结构体,定义在文件include/linux/pwm.h中,定义如下:

示例代码23.1.2.1 pwm_chip结构体
1  struct pwm_chip {
2  		struct device       	*dev;
3   	struct list_head    	list;
4   	const struct pwm_ops 	*ops;
5   	int         			base;
6   	unsigned int        	npwm;
7  
8   	struct pwm_device   	*pwms;
9  
10  	struct pwm_device * (*of_xlate)(struct pwm_chip *pc,
11                      const struct of_phandle_args *args);
12  	unsigned int        	of_pwm_n_cells;
13  	bool            		can_sleep;
14 };

第4行,pwm_ops结构体就是PWM外设的各种操作函数集合,编写PWM外设驱动的时候需要开发人员实现。pwm_ops结构体也定义在pwm.h头文件中,定义如下:
示例代码23.1.2.2 pwm_ops结构体

1  struct pwm_ops {
2   	int (*request)(struct pwm_chip *chip,	//请求PWM
3                      struct pwm_device *pwm);
4   	void (*free)(struct pwm_chip *chip, 	//释放PWM
5                   struct pwm_device *pwm);
6   	int (*config)(struct pwm_chip *chip, 	//配置PWM周期和占空比
7                     struct pwm_device *pwm,
8                     int duty_ns, int period_ns);
9   	int (*set_polarity)(struct pwm_chip *chip, //设置PWM极性
10                    struct pwm_device *pwm,
11                    enum pwm_polarity polarity);
12  	int  (*enable)(struct pwm_chip *chip, 		//使能PWM
13                    struct pwm_device *pwm);
14  	void (*disable)(struct pwm_chip *chip, 	//关闭PWM
15                     struct pwm_device *pwm);
16 #ifdef CONFIG_DEBUG_FS
17  	void (*dbg_show)(struct pwm_chip *chip,
18                      struct seq_file *s);
19 #endif
20  	struct module       *owner;
21 };

pwm_ops中的这些函数不一定全部实现,但是像config、enable和disable这些肯定是需要实现的,否则的话打开/关闭PWM,设置PWM的占空比这些就没操作了。
PWM子系统驱动的核心初始化pwm_chip结构体,然后向内核注册初始化完成以后的pwm_chip。这里就要用到pwmchip_add函数,此函数定义在drivers/pwm/core.c文件中,函数原型如下:
int pwmchip_add(struct pwm_chip *chip)
函数参数和返回值含义如下:
chip:要向内核注册的pwm_chip。
返回值:0 成功;负数 失败。
卸载PWM驱动的时候需要将前面注册的pwm_chip从内核移除掉,这里要用到pwmchip_remove函数,函数原型如下:
int pwmchip_remove(struct pwm_chip *chip)
函数参数和返回值含义如下:
chip:要移除的pwm_chip。
返回值:0 成功;负数 失败。
23.1.3 PWM驱动源码分析
我们简单分析一下Linux内核自带的RK3568 PWM驱动,驱动文件前面都说了,是pwm-rockchip.c这个文件。打开这个文件,可以看到,这是一个标准的平台设备驱动文件,有如下所示:
示例代码23.1.3.1 RK3568 PWM平台驱动

1  static const struct of_device_id rockchip_pwm_dt_ids[] = {
2   	{ .compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1},
3   	{ .compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2},
4   	{ .compatible = "rockchip,vop-pwm", .data = &pwm_data_vop},
5   	{ /* sentinel */ }
6  };
7  ......
8  static struct platform_driver rockchip_pwm_driver = {
9   	.driver = {
10      	.name = "rockchip-pwm",
11      	.of_match_table = rockchip_pwm_dt_ids,
12  	},
13  	.probe = rockchip_pwm_probe,
14  	.remove = rockchip_pwm_remove,
15 };
16 module_platform_driver(rockchip_pwm_driver);

第2~4行,当设备树PWM节点的compatible属性值为“rockchip,rk2928-pwm”、“rockchip,rk3288-pwm”和“rockchip,vop-pwm”中的某一个的话就会匹配此驱动。
第13行,当设备树节点和驱动匹配以后rockchip_pwm_probe函数就会执行。
在看rockchip_pwm_probe函数之前先来看下rockchip_pwm_chip stm32_pwm结构体,这个结构体是瑞芯微官方创建的针对瑞芯微芯片的PWM结构体,这个结构体会贯穿整个PWM驱动,起到灵魂的作用。rockchip_pwm_chip结构体内容如下:
示例代码23.1.3.2 rockchip_pwm_chip结构体

1 struct rockchip_pwm_chip {
2   	struct pwm_chip chip;
3   	struct clk *clk;
4   	const struct rockchip_pwm_data *data;
5   	void __iomem *base;
6 };
重点看一下第2行,这是一个pwm_chip结构体成员变量chip,前面说了,PWM子系统的核心就是pwm_chip。

rockchip_pwm_probe函数如下(有缩减):
示例代码23.1.3.3 rockchip_pwm_probe函数

1  static int rockchip_pwm_probe(struct platform_device *pdev)
2  {
3   const struct of_device_id *id;
4   struct rockchip_pwm_chip *pc;
5   struct resource *r;
6   int ret;
7  
8   id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
9   if (!id)
10      return -EINVAL;
11 
12  pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
13  if (!pc)
14      return -ENOMEM;
15 
16  r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
17  pc->base = devm_ioremap_resource(&pdev->dev, r);
18  if (IS_ERR(pc->base))
19      return PTR_ERR(pc->base);
20 
21  pc->clk = devm_clk_get(&pdev->dev, NULL);
22  if (IS_ERR(pc->clk))
23      return PTR_ERR(pc->clk);
24 
25  ret = clk_prepare(pc->clk);
26  if (ret)
27      return ret;
28 
29  platform_set_drvdata(pdev, pc);
30 
31  pc->data = id->data;
32  pc->chip.dev = &pdev->dev;
33  pc->chip.ops = pc->data->ops;
34  pc->chip.base = -1;
35  pc->chip.npwm = 1;
36 
37  if (pc->data->ops->set_polarity) {
38      pc->chip.of_xlate = of_pwm_xlate_with_flags;
39      pc->chip.of_pwm_n_cells = 3;
40  }
41 
42  ret = pwmchip_add(&pc->chip);
43  if (ret < 0) {
44      clk_unprepare(pc->clk);
45      dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
46  }
47 
48  return ret;
49 }

第12行,pc是一个rockchip_pwm_chip类型的结构体指针变量,这里为其申请内存。rockchip_pwm_chip结构体有个重要的成员变量chip,chip是pwm_chip类型的。所以这一行就引出了PWM子系统核心部件pwm_chip,稍后的重点就是初始化chip。
第32~35行,初始化pc的chip成员变量,也就是初始化pwm_chip!第33行设置pwm_chip的ops操作集为pc->data->ops。根据示例代码23.1.3.1中的compatible属性可以,RK3568对应的data是pwm_data_v2,因此pwm_data_v2源码如下:
示例代码23.1.3.4 pwm_data_v2源码

1  static const struct rockchip_pwm_data pwm_data_v2 = {
2   	.regs = {
3       		.duty = 0x08,
4       		.period = 0x04,
5       		.cntr = 0x00,
6       		.ctrl = 0x0c,
7   	},
8   	.prescaler = 1,
9   	.ops = &rockchip_pwm_ops_v2,
10  	.set_enable = rockchip_pwm_set_enable_v2,
11 };
第9行,rockchip_pwm_ops_v2就是pwm_chip的ops函数,也就是RK3568的ops函数。
继续回到示例代码23.1.3.3中,第49行使用pwmchip_add函数向内核添加pwm_chip,这个就是rockchip_pwm_probe函数的主要工作。
我们重点来看一下rockchip_pwm_ops_v2,定义如下:

示例代码23.1.3.5 rockchip_pwm_ops_v2操作集合

1 static const struct pwm_ops rockchip_pwm_ops_v2 = {
2   	.config = rockchip_pwm_config,
3   	.set_polarity = rockchip_pwm_set_polarity,
4   	.enable = rockchip_pwm_enable,
5   	.disable = rockchip_pwm_disable,
6   	.owner = THIS_MODULE,
7 };
第2行rockchip_pwm_config就是最终的PWM设置函数,我们在应用中设置的PWM频率和占空比最终就是由rockchip_pwm_config函数来完成的,此函数会最终操作RK3568相关的寄存器。
rockchip_pwm_config函数源码如下:

示例代码23.1.3.6 rockchip_pwm_config函数

1  static int rockchip_pwm_config(struct pwm_chip *chip, 
2             struct pwm_device *pwm,int duty_ns, int period_ns)
3  {
4   struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
5   unsigned long period, duty;
6   u64 clk_rate, div;
7   int ret;
8  
9   clk_rate = clk_get_rate(pc->clk);
10 
11  /*
12   * Since period and duty cycle registers have a width of 32
13   * bits, every possible input period can be obtained using the
14   * default prescaler value for all practical clock rate values.
15   */
16  div = clk_rate * period_ns;
17  do_div(div, pc->data->prescaler * NSEC_PER_SEC);
18  period = div;
19 
20  div = clk_rate * duty_ns;
21  do_div(div, pc->data->prescaler * NSEC_PER_SEC);
22  duty = div;
23 
24  ret = clk_enable(pc->clk);
25  if (ret)
26      return ret;
27 
28  writel(period, pc->base + pc->data->regs.period);
29  writel(duty, pc->base + pc->data->regs.duty);
30  writel(0, pc->base + pc->data->regs.cntr);
31 
32  clk_disable(pc->clk);
33 
34  return 0;
35 }
第16~18行,根据设置的频率,计算出RK3568 PWM的PERIOD寄存器。
第20~22行,根据设置的占空比,计算出DUTY寄存器的值。
第28~30行,设置PWM外设的PERIOD、DUTY和CNT寄存器。
至此,RK3568的PWM驱动基本分析到这里。

23.2 PWM驱动编写
23.2.1 修改设备树
PWM驱动就不需要我们再编写了,瑞芯微已经写好了,前面我们也已经详细的分析过这个驱动源码了。我们在实际使用的时候只需要修改设备树即可,ATK-DLRK3568开发板上的JP11排针引出了GPIO3_C5这个引脚,这个引脚可以用作PWM15_IR_M0,如图23.2.1.1所示:
在这里插入图片描述

图23.2.1.1 GPIO3_C5引脚
GPIO3_C5可以作为PWM3的通道3的PWM输出引脚,也就是PWM15_IR_M0,所以我们需要在设备树里面添加GPIO3_C5的引脚信息以及PWM15外设信息。
1、添加GPIO3_C5引脚信息
PWM的引脚配置瑞芯微已经帮我们做好了,打开rk3568-pinctrl.dtsi文件,找到如下所示内容:
示例代码23.2.1.1 TIM1 PWM引脚信息

1 pwm15 {
2         /omit-if-no-ref/
3         pwm15m0_pins: pwm15m0-pins {
4                 rockchip,pins =
5                         /* pwm15_irm0 */
6                         <3 RK_PC5 1 &pcfg_pull_down>;
7         };
8 
9         /omit-if-no-ref/
10        pwm15m1_pins: pwm15m1-pins {
11                rockchip,pins =
12                        /* pwm15_irm1 */
13                        <4 RK_PC3 1 &pcfg_pull_none>;
14        };
15};
可以看出瑞芯微官方对GPIO3_C5写了两个配置,第6行是把GPIO3_C5配置为PWM15_IR_M0引脚,但是默认没有上下拉!大家根据实际情况修改为上下拉配置即可。本章实验,我们选择pcfg_pull_down,也就是将GPIO3_C5配置为PWM15_IR_M0,默认下拉。
2、向pwm15节点追加信息
前面已经讲过了,rk3568.dtsi文件中已经有了“pwm15”节点,但是这个节点默认是disable的,还不能直接使用,所以需要在rk3568-atk-evb1-ddr4-v10.dtsi文件中向打开pwm15节点。

示例代码23.2.1.3 向timers1添加的内容

1&pwm15 {
2        status = "okay";
3}
第2行,status改为okay,也就是使能PWM15。

23.2.2 使能PWM驱动
瑞芯微官方的Linux内核已经默认使能了PWM驱动,所以不需要我们修改,但是为了学习,我们还是需要知道怎么使能。打开Linux内核配置界面,按照如下路径找到配置项:
-> Device Drivers │
-> Pulse-Width Modulation (PWM) Support (PWM [=y])
-> <*> Rockchip PWM support //选中
配置如图23.2.2.1所示:
在这里插入图片描述

图23.2.2.1 PWM配置项
23.3 PWM驱动测试
1、确定PWM15对应的pwmchipX文件
使用新的设备树启动系统,然后将开发板上的GPIO3_C5引脚连接到示波器上,通过示波器来查看PWM波形图。我们可以直接在用户层来配置PWM,进入目录/sys/class/pwm中,如图23.3.1所示:
在这里插入图片描述

图23.3.1 当前系统下的PWM外设
注意!图23.3.1中有个pwmchip0~ pwmchip3,但是我们并不知道哪个是PWM15的。我们可以通过查看pwmchip0~pwmchip3的外设基地址哪个和PWM15一样,那么哪个就是PWM15的。
ls -l
进入到pwm执行上面的ls -l指令,以后会打印出其链接的路径,如图23.3.2所示:
在这里插入图片描述

图23.3.2 pwmchip1路径名称
从图23.3.2可以看出pwmchip3对应的定时器寄存器起始地址为0XFE700030,根据示例代码23.1.1.1中的pwm15节点,可以知道PWM15这个定时器的寄存器起始地址就是0XFE700030。因此,pwmchip1就是PWM15对应的文件。
为什么要用这么复杂的方式来确定定时器对应的pwmchip文件呢?因为当RK3568开启多个PWM以后,其pwmchip文件就会变!
2、调出pwmchip15的pwm0子目录
输入如下命令打开pwmchip15的pwm0子目录
echo 0 > /sys/class/pwm/pwmchip3/export
执行完成会在pwmchip3目录下生成一个名为“pwm0”的子目录,如图23.3.3所示:
在这里插入图片描述

图23.3.3 新生成的pwm0子目录
2、设置PWM的频率
注意,这里设置的是周期值,单位为ns,比如20KHz频率的周期就是50000ns,输入如下命令:
echo 50000 > /sys/class/pwm/pwmchip3/pwm0/period
3、设置PWM的占空比
这里不能直接设置占空比,而是设置的一个周期的ON时间,也就是高电平时间,比如20KHz频率下20%占空比的ON时间就是10000,输入如下命令:
echo 10000 > /sys/class/pwm/pwmchip3/pwm0/duty_cycle
4、设置PWM极性
设置一下PWM波形的极性,输入如下命令:
echo normal > /sys/class/pwm/pwmchip3/pwm0/polarity
极性设置为normal,也就是duty_cycle为高电平时间。如果要将极性反过来,可以设置为inversed。
5、使能PWM
一定要先设置频率和波特率,最后在开启PWM,否则会提示参数错误!输入如下命令使能PWM:
echo 1 > /sys/class/pwm/pwmchip3/pwm0/enable
设置完成使用示波器查看波形是否正确,正确的话如图23.3.4所示:
在这里插入图片描述

图23.3.4 PWM波形图
从图23.3.4可以看出,此时PWM频率为20KHz,占空比为20%,与我们设置的一致。如果要修改频率或者占空比的话一定要注意这两者时间值,比如20KHz频率的周期值为50000ns,那么你在调整占空比的时候ON时间就不能设置大于50000,否则就会提示你参数无效。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Rust 02.控制、引用、切片Slice、智能指针

1.控制流 //rust通过所有权机制来管理内存&#xff0c;编译器在编译就会根据所有权规则对内存的使用进行 //堆和栈 //编译的时候数据的类型大小是固定的&#xff0c;就是分配在栈上的 //编译的时候数据类型大小不固定&#xff0c;就是分配堆上的 fn main() {let x: i32 1;{le…

AOP的实现方式一(Spring学习笔记十)

1、什么是AOP 全称是 Aspect Oriented Programming 即&#xff1a;面向切面编程。是OOP&#xff08;面向对象编程&#xff09;的延续&#xff0c;也是Spring框架中的一个重要内容&#xff0c;是函数式编程的一种衍生泛型。简单的说他就是把我们程序重复的代码抽取出来&#xf…

【网站项目】泉文化管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

面试题:JVM的垃圾回收

一、GC概念 为了让程序员更专注于代码的实现&#xff0c;而不用过多的考虑内存释放的问题&#xff0c;所以&#xff0c;在Java语言中&#xff0c;有了自动的垃圾回收机制&#xff0c;也就是我们熟悉的GC(Garbage Collection)。 有了垃圾回收机制后&#xff0c;程序员只需要关…

java调用c++,使用clion进行JNI开发,ddl包生成以及so包生成

java调用c&#xff0c;使用clion进行JNI开发&#xff0c;ddl包生成以及so包生成 java基础代码生成C头部文件使用clion写C实现代码cmke打包构建使用java调用C执行linux环境下产生CPP的so包 java基础代码 先写好对应的基础代码&#xff0c;先不管static加载的ddl文件&#xff0c…

【JavaScript】数组 ③ ( JavaScript 数组长度 | 修改数组长度 | 数组案例 )

文章目录 一、JavaScript 数组长度1、数组长度2、修改数组长度 二、数组案例1、求数组元素平均值2、求数组元素最大值 一、JavaScript 数组长度 1、数组长度 在 JavaScript 中 , 数组长度 可以通过 数组变量的 length 属性 获取 , 该属性 返回 数组中的元素数量 , 也就是 数组长…

软件速成书:一夜成神的传说,还是现实的泡影?

嗨&#xff0c;各位小伙伴&#xff01; &#x1f431;‍&#x1f4bb; 我是【行走的程序喵】&#xff01;一个兼具Web前端和Java后端技能的技术宅&#xff01; &#x1f31f; 我的博客上分享最新的Web前端和Java后端技术文章&#xff0c;从基础入门到进阶应用&#xff0c;应有…

Linux系统----------探索mysql数据库MHA高可用

目录 一、MHA概述 1.1 什么是 MHA 1.2MHA 的组成 1.2.1MHA Node&#xff08;数据节点&#xff09; 1.2.2MHA Manager&#xff08;管理节点&#xff09; 1.3MHA 的特点 1.4MHA工作原理 1.5数据同步的方式 1.5.1同步复制 1.5.2异步复制 1.5.3半同步复制 二、搭建 MySQ…

夜神模拟器录制脚本录制键盘操作方法

很多用户们在使用夜神模拟器的时候&#xff0c;有个操作助手的功能非常的好用&#xff0c;用户们在录制自己的操作以后&#xff0c;就能够进行全自动的操作等&#xff0c;使用起来还是非常方便的&#xff0c;想要知道的用户们快来查看详细的教程吧~ 夜神模拟器录制脚本怎样录制…

5-规范设计(下):commit信息风格迥异、难以阅读,如何规范?

我们在做代码开发时&#xff0c;经常需要提交代码&#xff0c;提交代码时需要填写 Commit Message&#xff08;提交说明&#xff09;&#xff0c;否则就不允许提交。 所以在 Go 项目开发时&#xff0c;一个好的 Commit Message 至关重要&#xff1a; 可以使自己或者其他开发人…

3.26学习总结java初步实现学生管理系统

(该项目通过视频讲解过程中完成,其中将一些操作进行了修改和完善,其目的是为了巩固前面学习java的一些用法,熟悉写项目的过程) 一.项目要求 学生类: 属性:id、姓名、年龄、家庭住址 添加功能: 键盘录入每一个学生信息并添加&#xff0c;需要满足以下要求: ID唯一 删除功能…

Qt源码调试步骤记录

1.源码&#xff1a; 两种方式&#xff0c;要么安装qt时选择source&#xff0c;要么从官网下载源码&#xff0c;然后在qt creator中设置路径。二选一即可。我选的第二种。 1.1.第一种&#xff0c;安装时选择source&#xff1a; 1.2.第二种&#xff0c;下载源码设置路径&#x…

Linux中安装JDK17.X

1、总体概述&#xff1f; 该操作方式适合centos或red hat环境 2.1、在线下载JDK安装包&#xff1f; 通过wget命令下载JDK17.X包 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 如果提示&#xff1a;没有wget命令就安装wget yum install w…

Qt 富文本处理 (字体颜色大小加粗等)

Qt中支持HTML的控件有textEdit 、label 、textBrowser 。 接口&#xff1a;setHtml("Qt"); toHtml(). 文本样式设置 : 可分字设置 &#xff0c;主要使用QTextCharFormat类进行文本样式设置。 示例&#xff1a; QTextCharFormat fmt; //粗体 fmt.setFontWeight…

wps没保存关闭了恢复数据教程

有时候我们因为电脑问题会忘记保存就关闭wps导致数据丢失&#xff0c;不知道wps没保存关闭了怎么恢复数据&#xff0c;其实数据是无法恢复的。 wps没保存关闭了怎么恢复数据 1、wps没有数据恢复功能&#xff0c;不过可以开启自动备份。 2、我们可以先点击wps左上角的“文件”…

Vtk裁剪功能之平面裁剪vtkClipClosedSurface(vtk小记)

1.原理分析 对你的三维图形&#xff0c;使用一个平面切下去&#xff0c;然后保留一半。 确定一个平面&#xff1a;使用法向量和一个三维坐标点可以确定一个平面 原始图像 切一刀 切两刀&#xff0c;又一半 切三刀&#xff0c;又一半 源代码 #include <vtkActor.h> #i…

Linux 学习之路 -- 工具篇 -- gcc / g++

在 Linux 系统中&#xff0c;gcc 和 g 是两个常用的编译工具&#xff0c;分别用于编译 C 和 C 代码。下面我将介绍gcc、g的一些基本用法 目录 一、简单的认识 二、简单了解一下编译的过程 <1> 预处理阶段 <2>编译 <3>汇编 <4>链接…

SQLite数据库成为内存中数据库(三)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite使用的临时文件&#xff08;二&#xff09; 下一篇&#xff1a;SQLite中的原子提交&#xff08;四) ​​ SQLite数据库通常存储在单个普通磁盘中文件。但是&#xff0c;在某些情况下&#xff0c;数据库可能…

python爬虫基础------函数

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

打工人神器! Raccoon 代码小浣熊

继这三个之后&#xff0c;今天又来了一个 [ Raccoon代码小浣熊 ] 核心精要与产品特点 全面支持多种编程语言和IDE&#xff1a;「代码小浣熊」支持超过90种主流编程语言&#xff0c;包括但不限于Python、Java、JavaScript、C、Go和SQL等。同时&#xff0c;它集成了市面上主流的…