5.2.16.静态映射操作LED3

5.2.16.静态映射操作LED3
5.2.16.1、添加驱动中的写函数
(1)先定义好应用和驱动之间的控制接口,这个是由自己来定义的。譬如定义为:应用向驱动写"on"则驱动让LED亮,应用向驱动写"off",驱动就让LED灭

 1. 驱动文件 module_test.c

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>      //copy_from_user
#include <linux/errno.h>  // 错误码
#include <mach/regs-gpio.h>//arch/arm/mach-s5pv210/include/mach/regs-gpio.h  这两个顺序不能放错,c语言基础
#include <mach/gpio-bank.h> //arch/arm/mach-s5pv210/include/mach/gpio-bank.h
#include <linux/string.h>//包含 内核的 memset  、strcmp#define MYMAJOR 200  /* 定义 register_chrdev 注册设备的 主设备号 */#define MYNAME  "test_char" /* 定义 register_chrdev 注册设备的 设备名字 */#define GPJ0CON	  S5PV210_GPJ0CON	   // FD500240 虚拟地址	
#define GPJ0DAT	  S5PV210_GPJ0DAT	   // FD500244#define rGPJ0CON	*((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT	*((volatile unsigned int *)GPJ0DAT)int mymajor; /* 定义 register_chrdev 注册设备号*/char kbuf[100];/* 内核空间的 buf*//* NOTE  自己定义函数指针  test_chrdev_open  */
static int test_chrdev_open(struct inode *inode, struct file *file)
{/* 这个函数中真正应该 放置 打开这个硬件设备的 操作代码 ,我们先 printk 代替一下 */printk(KERN_INFO "test_chrdev_open module_test.c->test_chrdev_open \n");  /* 在应用app.c 执行open 时,就会执行 LED亮 */rGPJ0CON = 0x11111111;//rGPJ0DAT = ((0<<3)|(0<<4)|(0<<5));  //LED亮return 0;} /* test_chrdev_open() *//* NOTE  自己定义函数指针 test_chrdev_release ,   release对应的就是 close  */
static int test_chrdev_release(struct inode *inode, struct file *file)
{printk(KERN_INFO "test_chrdev_release module_test.c->test_chrdev_release \n");/* 在应用app.c 执行close 时,就会执行 LED灭 */rGPJ0DAT = ((1<<3)|(1<<4)|(1<<5)); //LED灭return 0;
}static ssize_t test_chrdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos)
{int ret = -1;printk(KERN_INFO "test_chrdev_release module_test.c->test_chrdev_read \n");/* 从内核 的 kbuf, 复制到用户的 ubuf  */ret = copy_to_user(ubuf,kbuf,size);    /* 成功后 就会拷贝到用户 ubuf */if(ret)  /* 如果 不成功复制则返回尚未成功复制剩下的字节数, 这里 就不做 纠错 机制了 */{printk(KERN_ERR "copy_to_user  fail \n"); return -EINVAL;}printk(KERN_INFO "copy_to_user  OK!!! module_test.c->test_chrdev_write\n");return 0;
}// 写函数的本质:将应用层 传递过来的数据先 复制到 内核中,然后将之正确的方式写入硬件完成的操作!(数据从应用层到驱动层的复制,)
// 内核有一个 虚拟地址空间,应用层有一个 虚拟地址空间
static ssize_t test_chrdev_write(struct file *file, const char __user *user_buf,size_t count, loff_t *ppos)
{int ret = -1;printk(KERN_INFO "test_chrdev_release module_test.c->test_chrdev_write\n");memset(kbuf,0,sizeof(kbuf)); /*清除kbuf *///使用改函数将: 应用层传过来的 ubuf 中的内容 拷贝到驱动空间中的 一个 kbuf 中/* 不能用memcpy(kbuf,buf); 因为 2 个 不在一个地址空间中,不能 比较 霍元甲和成龙 谁更厉害 ,不在一个年龄段*/ret = copy_from_user(kbuf,user_buf,count);    /*  成功后 就会 放到 kbuf 中 */if(ret)  /* 如果 不成功复制则返回尚未成功复制剩下的字节数, 这里 就不做 纠错 机制了 */{printk(KERN_ERR "copy_from_user fail \n"); return -EINVAL;}printk(KERN_INFO "copy_from_user OK!!! module_test.c->test_chrdev_write\n");/* 真正的 驱动的 数据从 应用层 复制 到 驱动中后,我们就要根据这个数据去写硬件的操作,所以下面就应该操作硬件 */if (!strcmp(kbuf,"on"))  /*strcmp相等的话应该是 0 */{rGPJ0DAT = ((0<<3)|(0<<4)|(0<<5));  //LED亮}else if(!strcmp(kbuf,"off")) {rGPJ0DAT = ((1<<3)|(1<<4)|(1<<5)); //LED灭}return 0;	
}//自定义  file_operations 结构体 及其元素填充
/* NOTE  定义 register_chrdev 注册设备的 设备结构体 test_fops */
static const struct file_operations test_fops = {.owner		= THIS_MODULE,                    /* 所有的驱动 代码这一行不需要动,所有的都是这样,不是函数指针, 惯例直接写即可 */.open		= test_chrdev_open,  /* 将来应用 open 打开这个设备时实际 调用的就是这个 .open  函数指针*/.release	= test_chrdev_release,         /* release对应的就是 close    函数指针 */.write		= test_chrdev_write, .read		= test_chrdev_read, 
};// 模块安装函数
static int __init chrdev_init(void)
{	//int ret = -1;  /* 定义 register_chrdev 的返回值  */printk(KERN_INFO "chrdev_init helloworld init\n");// 在 module_init 宏 调用函数中去注册字符串 设备驱动mymajor = register_chrdev(0, "test_char", &test_fops);   /* major设成0,内核帮我们自动分配空白的设备号,分配的值会 做返回值 ,负数还是返回失败  */if(mymajor < 0){printk(KERN_ERR "registe_chrdev fail \n");return -EINVAL;  /* 返回一个错误码 需要加 ’-‘负号*/}printk(KERN_INFO "自动分配 register_chrdev success....mymajor = %d \n",mymajor);
#if 0	/* 现在把 硬件操作放到这里,不用操作app.c 就可以操作硬件 */rGPJ0CON = 0x11111111;rGPJ0DAT = ((0<<3)|(0<<4)|(0<<5));  //LED亮printk(KERN_INFO "S5PV210_GPJ0CON = %p \n",S5PV210_GPJ0CON);printk(KERN_INFO "S5PV210_GPJ0DAT = %p \n",S5PV210_GPJ0DAT );
#endif return 0;
}// 模块卸载函数
static void __exit chrdev_exit(void)
{printk(KERN_INFO "chrdev_exit helloworld exit\n");// 在 module_exit宏 调用函数中去注销 字符串 设备驱动unregister_chrdev(mymajor, "test_char");  /* 这里不判断返回值 了,一般不会出错 */
#if 0		// 模块卸载 LED灭rGPJ0DAT = ((1<<3)|(1<<4)|(1<<5)); //LED灭
#endif
}module_init(chrdev_init);
module_exit(chrdev_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息/***********************************************************
如果 KERN_DEBUG 打印不出来,更改打印级别 或者  	
printk(KERN_DEBUG "chrdev_init helloworld init\n"); [root@liang_x210 driver_test]# cat /proc/sys/kernel/printk
7       4       1       7
[root@liang_x210 driver_test]# echo 8 > /proc/sys/kernel/printk
[root@liang_x210 driver_test]# cat /proc/sys/kernel/printk
8       4       1       7************************************************************/

2. app.c(Mkfile无更改)

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define FILE  "/dev/test"   // 刚才mknod创建的设备文件 名,必须保持一致char buf[100];int main(void)
{int fd = -1;fd = open(FILE, O_RDWR);if(fd < 0){printf("open %s error \n",FILE);return -1;}printf("open %s success..\n",FILE);//读写文件write(fd,"on",2);sleep(2);write(fd,"off",3);sleep(2);write(fd,"on",2);sleep(2);write(fd,"off",3);sleep(2);//关闭文件close(fd);return 0;
}

运行效果:

上面的代码可以正常运行,但是实际开发中,一般驱动中只要可以实现简单功能,更多的功能代码都放到 app.c 看下面的示例:

(2)应用和驱动的接口定义做的尽量简单,譬如用1个字目来表示。譬如定义为:应用写"1"(字符串)表示灯亮,写"0"表示让灯灭。

5.2.16.2、写应用来测试写函数
5.2.16.3、驱动和应用中来添加读功能

 1. 驱动文件 module_test.c

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>      //copy_from_user
#include <linux/errno.h>  // 错误码
#include <mach/regs-gpio.h>//arch/arm/mach-s5pv210/include/mach/regs-gpio.h  这两个顺序不能放错,c语言基础
#include <mach/gpio-bank.h> //arch/arm/mach-s5pv210/include/mach/gpio-bank.h
#include <linux/string.h>//包含 内核的 memset  、strcmp#define MYMAJOR 200  /* 定义 register_chrdev 注册设备的 主设备号 */#define MYNAME  "test_char" /* 定义 register_chrdev 注册设备的 设备名字 */#define GPJ0CON	  S5PV210_GPJ0CON	   // FD500240 虚拟地址	
#define GPJ0DAT	  S5PV210_GPJ0DAT	   // FD500244#define rGPJ0CON	*((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT	*((volatile unsigned int *)GPJ0DAT)int mymajor; /* 定义 register_chrdev 注册设备号*/char kbuf[100];/* 内核空间的 buf*//* NOTE  自己定义函数指针  test_chrdev_open  */
static int test_chrdev_open(struct inode *inode, struct file *file)
{/* 这个函数中真正应该 放置 打开这个硬件设备的 操作代码 ,我们先 printk 代替一下 */printk(KERN_INFO "test_chrdev_open module_test.c->test_chrdev_open \n");  /* 在应用app.c 执行open 时,就会执行 LED */rGPJ0CON = 0x11111111;//rGPJ0DAT = ((0<<3)|(0<<4)|(0<<5));  //LED亮return 0;} /* test_chrdev_open() *//* NOTE  自己定义函数指针 test_chrdev_release ,   release对应的就是 close  */
static int test_chrdev_release(struct inode *inode, struct file *file)
{printk(KERN_INFO "test_chrdev_release module_test.c->test_chrdev_release \n");/* 在应用app.c 执行close 时,就会执行 LED灭 */rGPJ0DAT = ((1<<3)|(1<<4)|(1<<5)); //LED灭return 0;
}static ssize_t test_chrdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos)
{int ret = -1;printk(KERN_INFO "test_chrdev_release module_test.c->test_chrdev_read \n");/* 从内核 的 kbuf, 复制到用户的 ubuf  */ret = copy_to_user(ubuf,kbuf,size);    /* 成功后 就会拷贝到用户 ubuf */if(ret)  /* 如果 不成功复制则返回尚未成功复制剩下的字节数, 这里 就不做 纠错 机制了 */{printk(KERN_ERR "copy_to_user  fail \n"); return -EINVAL;}printk(KERN_INFO "copy_to_user  OK!!! module_test.c->test_chrdev_write\n");return 0;
}// 写函数的本质:将应用层 传递过来的数据先 复制到 内核中,然后将之正确的方式写入硬件完成的操作!(数据从应用层到驱动层的复制,)
// 内核有一个 虚拟地址空间,应用层有一个 虚拟地址空间
static ssize_t test_chrdev_write(struct file *file, const char __user *user_buf,size_t count, loff_t *ppos)
{int ret = -1;printk(KERN_INFO "test_chrdev_release module_test.c->test_chrdev_write\n");memset(kbuf,0,sizeof(kbuf)); /*清除kbuf *///使用改函数将: 应用层传过来的 ubuf 中的内容 拷贝到驱动空间中的 一个 kbuf 中/* 不能用memcpy(kbuf,buf); 因为 2 个 不在一个地址空间中,不能 比较 霍元甲和成龙 谁更厉害 ,不在一个年龄段*/ret = copy_from_user(kbuf,user_buf,count);    /*  成功后 就会 放到 kbuf 中 */if(ret)  /* 如果 不成功复制则返回尚未成功复制剩下的字节数, 这里 就不做 纠错 机制了 */{printk(KERN_ERR "copy_from_user fail \n"); return -EINVAL;}printk(KERN_INFO "copy_from_user OK!!! module_test.c->test_chrdev_write\n");/* 真正的 驱动的 数据从 应用层 复制 到 驱动中后,我们就要根据这个数据去写硬件的操作,所以下面就应该操作硬件 */if(kbuf[0] == '1'){rGPJ0DAT = ((0<<3)|(0<<4)|(0<<5));  //LED亮}else if (kbuf[0]=='0'){rGPJ0DAT = ((1<<3)|(1<<4)|(1<<5)); //LED灭}return 0;
}//自定义  file_operations 结构体 及其元素填充
/* NOTE  定义 register_chrdev 注册设备的 设备结构体 test_fops */
static const struct file_operations test_fops = {.owner		= THIS_MODULE,                    /* 所有的驱动 代码这一行不需要动,所有的都是这样,不是函数指针, 惯例直接写即可 */.open		= test_chrdev_open,  /* 将来应用 open 打开这个设备时实际 调用的就是这个 .open  函数指针*/.release	= test_chrdev_release,         /* release对应的就是 close    函数指针 */.write		= test_chrdev_write, .read		= test_chrdev_read, 
};// 模块安装函数
static int __init chrdev_init(void)
{	//int ret = -1;  /* 定义 register_chrdev 的返回值  */printk(KERN_INFO "chrdev_init helloworld init\n");// 在 module_init 宏 调用函数中去注册字符串 设备驱动mymajor = register_chrdev(0, "test_char", &test_fops);   /* major设成0,内核帮我们自动分配空白的设备号,分配的值会 做返回值 ,负数还是返回失败  */if(mymajor < 0){printk(KERN_ERR "registe_chrdev fail \n");return -EINVAL;  /* 返回一个错误码 需要加 ’-‘负号*/}printk(KERN_INFO "自动分配 register_chrdev success....mymajor = %d \n",mymajor);
#if 0	/* 现在把 硬件操作放到这里,不用操作app.c 就可以操作硬件 */rGPJ0CON = 0x11111111;rGPJ0DAT = ((0<<3)|(0<<4)|(0<<5));  //LED亮printk(KERN_INFO "S5PV210_GPJ0CON = %p \n",S5PV210_GPJ0CON);printk(KERN_INFO "S5PV210_GPJ0DAT = %p \n",S5PV210_GPJ0DAT );
#endif return 0;
}// 模块卸载函数
static void __exit chrdev_exit(void)
{printk(KERN_INFO "chrdev_exit helloworld exit\n");// 在 module_exit宏 调用函数中去注销 字符串 设备驱动unregister_chrdev(mymajor, "test_char");  /* 这里不判断返回值 了,一般不会出错 */
#if 0		// 模块卸载 LED灭rGPJ0DAT = ((1<<3)|(1<<4)|(1<<5)); //LED灭
#endif
}module_init(chrdev_init);
module_exit(chrdev_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息/***********************************************************
如果 KERN_DEBUG 打印不出来,更改打印级别 或者  	
printk(KERN_DEBUG "chrdev_init helloworld init\n"); [root@liang_x210 driver_test]# cat /proc/sys/kernel/printk
7       4       1       7
[root@liang_x210 driver_test]# echo 8 > /proc/sys/kernel/printk
[root@liang_x210 driver_test]# cat /proc/sys/kernel/printk
8       4       1       7************************************************************/

 2. app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>#define FILE  "/dev/test"   // 刚才mknod创建的设备文件 名,必须保持一致char buf[100];int main(void)
{int fd = -1;int i= 0;fd = open(FILE, O_RDWR);if(fd < 0){printf("open %s error \n",FILE);return -1;}printf("open %s success..\n",FILE);
#if 0//璇诲啓鏂囦欢write(fd, "1",1);//亮sleep(2);write(fd, "0",1);//灭sleep(2);write(fd, "1",1);sleep(2);
#endifwhile(1){memset(buf, 0, sizeof(buf));printf("请输入 on|off \n\n");scanf("%s",buf);if (!strcmp(buf,"on")){write(fd, "1",1);//亮}else if (!strcmp(buf,"off"))	{write(fd, "0",1);//灭}	else if (!strcmp(buf,"flash"))	{	for(i=0;i<3;i++){write(fd, "1",1);//亮sleep(2);write(fd, "0",1);//灭sleep(2);}}else if (!strcmp(buf,"quit"))	{break;}}//鍏抽棴鏂囦欢close(fd);return 0;
}

3.(Mkfile无更改)

#ubuntu的内核源码树,如果要编译在ubuntu中安装的模块就打开这2个
#KERN_VER = $(shell uname -r)
#KERN_DIR = /lib/modules/$(KERN_VER)/build	# 开发板的linux内核的源码树目录  
KERN_DIR = /root/driver/kernelobj-m	+= module_test.oall:make -C $(KERN_DIR) M=`pwd` modules # app 是在 开发板运行 所以 arm-linux-gcc arm-linux-gcc app.c -o app
cp:cp *.ko app /root/rootfs/rootfs/driver_test#cp app  /root/rootfs/rootfs/driver_test	.PHONY: clean	
clean:rm -rf  app make -C $(KERN_DIR) M=`pwd` modules clean

运行效果:

 

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

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

相关文章

计算机网络(2) --- 网络套接字

计算机网络&#xff08;1&#xff09; --- 网络介绍_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131967378?spm1001.2014.3001.5501 目录 1.端口号 2.TCP与UDP协议 1.TCP协议介绍 1.TCP协议 2.UDP协议 3.理解 2.网络字节序 发送逻辑…

Go 下载安装教程

1. 下载地址&#xff1a;The Go Programming Language (google.cn) 2. 下载安装包 3. 安装 &#xff08;1&#xff09;下一步 &#xff08;2&#xff09;同意 &#xff08;3&#xff09;修改安装路径&#xff0c;如果不修改&#xff0c;直接下一步 更改后&#xff0c;点击下一…

代码随想录算法训练营第三十天 | 单调栈系列复习

单调栈系列复习 每日温度未看解答自己编写的青春版重点题解的代码日后再次复习重新写 下一个更大元素 I未看解答自己编写的青春版重点题解的代码日后再次复习重新写 下一个更大元素II未看解答自己编写的青春版重点题解的代码日后再次复习重新写 接雨水未看解答自己编写的青春版…

计算机毕设 深度学习卫星遥感图像检测与识别 -opencv python 目标检测

文章目录 0 前言1 课题背景2 实现效果3 Yolov5算法4 数据处理和训练5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长…

《数据同步-NIFI系列》Nifi配置DBCPConnectionPool连接SQL Server数据库

Nifi配置DBCPConnectionPool连接SQL Server数据库 一、新增DBCPConnectionPool 在配置中新增DBCPConnectionPool&#xff0c;然后配置数据库相关信息 二、配置DBCPConnectionPool 2.1 DBCPConnectionPool介绍 主要介绍以下五个必填参数 Database Connection URL&#xff1…

iOS开发-实现自定义Tabbar及tabbar按钮动画效果

iOS开发-实现自定义Tabbar及tabbar按钮动画效果 之前整理了一个继承UITabbarController的Tabbar效果 查看 https://blog.csdn.net/gloryFlow/article/details/132012628 这里是继承与UIViewController的INSysTabbarViewController实现及点击tabbar按钮动画效果。 一、INSysT…

qt源码--事件系统之QAbstractEventDispatcher

1、QAbstractEventDispatcher内容较少&#xff0c;其主要是定义了一些注册接口&#xff0c;如定时器事件、socket事件、注册本地事件、自定义事件等等。其源码如下&#xff1a; 其主要定义了大量的纯虚函数&#xff0c;具体的实现会根据不同的系统平台&#xff0c;实现对应的方…

软件测试员的非技术必备技能

成为软件测试人员所需的技能 非技术技能 以下技能对于成为优秀的软件测试人员至关重要。 将您的技能组合与以下清单进行比较&#xff0c;以确定软件测试是否适合您 - 分析技能&#xff1a;优秀的软件测试人员应具备敏锐的分析能力。 分析技能将有助于将复杂的软件系统分解为…

LeetCode每日一题Day1——买卖股票的最佳时机

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇&#xff08;C\C版&#xff09; &#x1f353;专栏&#xff1a;算法修炼之筑基篇&#xff08;C\C版&#xff09; &#x1f433;专栏&#xff1a;算法修炼之练气篇&#xff08;Python版&#xff09; ✨…

Ribbon源码

学了feign源码之后感觉&#xff0c;这部分还是按运行流程分块学合适。核心组件什么的&#xff0c;当专业术语学妥了。序章&#xff1a;认识真正のRibbon 但只用认识一点点 之前我们学习Ribbon的简单使用时&#xff0c;都是集成了Eureka-client或者Feign等组件&#xff0c;甚至在…

开发一个RISC-V上的操作系统(五)—— 协作式多任务

目录 往期文章传送门 一、什么是多任务 二、代码实现 三、测试 往期文章传送门 开发一个RISC-V上的操作系统&#xff08;一&#xff09;—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客 开发一个RISC-V上的操作系统&#xff08;二&#xff09;—— 系统引导程序&a…

Mac下certificate verify failed: unable to get local issuer certificate

出现这个问题&#xff0c;可以安装证书 在finder中查找 Install Certificates.command找到后双击&#xff0c;或者使用其他终端打开 安装完即可

【机器学习】Cost Function

Cost Function 1、计算 cost2、cost 函数的直观理解3、cost 可视化总结附录 首先&#xff0c;导入所需的库&#xff1a; import numpy as np %matplotlib widget import matplotlib.pyplot as plt from lab_utils_uni import plt_intuition, plt_stationary, plt_update_onclic…

【Github】自动监测 SSL 证书过期的轻量级监控方案 - Domain Admin

在现代的企业网络中&#xff0c;网站安全和可靠性是至关重要的。一个不注意的SSL证书过期可能导致网站出现问题&#xff0c;给公司业务带来严重的影响。针对这个问题&#xff0c;手动检测每个域名和机器的证书状态需要花费大量的时间和精力。为了解决这个问题&#xff0c;我想向…

【bar堆叠图形绘制】

绘制条形图示例 在数据可视化中&#xff0c;条形图是一种常用的图表类型&#xff0c;用于比较不同类别的数据值。Python的matplotlib库为我们提供了方便易用的功能来绘制条形图。 1. 基本条形图 首先&#xff0c;我们展示如何绘制基本的条形图。假设我们有一个包含十个类别的…

VS附加到进程调试

操作&#xff1a; 要附加到进程中调试外部可执行文件&#xff0c;您需要使用Visual Studio的“调试附加”功能。以下是附加到进程中调试外部可执行文件的步骤&#xff1a; 打开您要调试的源代码文件或可执行文件。打开Visual Studio。选择“调试”菜单&#xff0c;然后选择“…

轮趣科技教育版ros小车键盘控制运动

我之前买的ros小车是单独买的底板&#xff0c;以为随便一个树莓派就可以&#xff0c;因为我以前有一个树莓派3B&#xff0c;后来买了单独的小车之后&#xff0c;发现只能使用树莓派4B&#xff0c;然后又单独买了一个树莓派4B&#xff0c;给装上镜像&#xff0c;安装ros-melodic…

kotlin 编写一个简单的天气预报app(二)增加搜索城市功能

增加界面显示openweathermap返回的信息。 在activity_main.xml里增加输入框来输入城市&#xff0c;在输入款旁边增加搜索按钮来进行查询。 然后原来显示helloworld的TextView用来显示结果。 1. 增加输入城市名字的EditText <EditTextandroid:id"id/editTextCity"…

用于永磁同步电机驱动器的自适应SDRE非线性无传感器速度控制(MatlabSimulink实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码&Simulink仿真实现 &#x1f4a5;1 概述 本文方法基于状态依赖的里卡蒂方程&#xff08;SDRE&#xff09;控制技术及其梯度型神经网络的实时计算方法&#xff0c;允许…

理解构建LLM驱动的聊天机器人时的向量数据库检索的局限性 - (第1/3部分)

本博客是一系列文章中的第一篇&#xff0c;解释了为什么使用大型语言模型&#xff08;LLM&#xff09;部署专用领域聊天机器人的主流管道成本太高且效率低下。在第一篇文章中&#xff0c;我们将讨论为什么矢量数据库尽管最近流行起来&#xff0c;但在实际生产管道中部署时从根本…