基于tiny6410的led驱动程序

2023-11-09

今天弄了一个晚上了 终于弄懂了第一个简单的linux驱动感觉很多人编写的第一个驱动也是拿led开刀的吧。本文的led驱动是基于tiny6410的四个led驱动,用字符设备的驱动模块,而不是混杂设备驱动模块来编写,本人在使用混杂设备方法编写的时候led灯第二个始终无法实现控制开和关现在还在纠结中。

一下图片是开发板手册关于四个用户led的硬件介绍。


下面是s3c6410关于gpio的寄存器说明。





编写字符驱动程序的流程为:

1.要先驱动模块加载函数。在改函数中要实现将本驱动模块添加到系统中用到函数register_chrdev(),同时还要对gpio控制寄存器与状态寄存器进行初始化。

2.要编写file_operatins 结构体的实现函数比如read()、write()、open()、release()、ioctl()等函数的具体实现。

3模块卸载函数 dev_exit(),用到unregister_chrdev(),向系统注销本驱动模块。

可能跟书本说的有点不一样比如没用到 设备结构体  struct  xxx_dev_t   与向系统注册模块的函数不是 register_chrdev_region(xxx_dev_no,1,DEV_NAME) 和alloc_chrdev_region(&xxx_dev_no,1,DEV_NAME) 这两个函数是为获取字符设备号,而注册设备用到函数cdev_add(&xxx_dev.cdev,xxx_dev_no,1)。在注销驱动模块的卸载函数为unregister_chrdev_region(xxx_dev_no,1)用于释放占用的设备号,cdev_del(&xxx_dev.cdev)用于注销设备。以上的都没用到这些函数和结构体,请高手指教。

一下是具体实现代码。

led_driver.c

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<asm/uaccess.h>
#include<linux/pci.h>
#include<linux/pci.h>
#include<mach/map.h>
#include<mach/regs-gpio.h>
#include<mach/gpio-bank-k.h>
#include<mach/hardware.h>
#include<linux/cdev.h>
#include<asm/atomic.h>


#define LED_MAJOR 243


static ssize_t led_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
return count;
}


static ssize_t led_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos)
{
char nbuf[10];
unsigned tmp;

if(copy_from_user(nbuf,buf,count))
return -EINVAL;

switch(nbuf[0])
{
case 0: /* 四个led全亮 */
tmp=readl(S3C64XX_GPKDAT);
tmp&=0x0f;
writel(tmp, S3C64XX_GPKDAT);  
break;

case 1 :/* 四个led全灭 */
tmp  = readl(S3C64XX_GPKDAT);       
                        tmp |= (0xf0);       
            writel(tmp, S3C64XX_GPKDAT);  
break;

case 2:/* 第一个led亮 */
tmp=readl(S3C64XX_GPKDAT);
tmp&=0xef;
writel(tmp, S3C64XX_GPKDAT);  
break;

case 3:/* 第一个led灭 */
tmp = readl(S3C64XX_GPKDAT);       
            tmp |= (0x10);       
            writel(tmp, S3C64XX_GPKDAT);   
break;

case 4:/* 第二个led亮 */
tmp=readl(S3C64XX_GPKDAT);
tmp&=0xdf;
writel(tmp, S3C64XX_GPKDAT);  
break;

case 5:/* 第二个led灭 */
tmp = readl(S3C64XX_GPKDAT);       
            tmp |= (0x20);       
            writel(tmp, S3C64XX_GPKDAT);    
break;

case 6:/* 第三个led亮 */
tmp=readl(S3C64XX_GPKDAT);
tmp&=0xbf;
writel(tmp, S3C64XX_GPKDAT);  
break;

case 7:/* 第三个led灭 */
tmp = readl(S3C64XX_GPKDAT);       
            tmp |= (0x40);       
            writel(tmp, S3C64XX_GPKDAT);  
break;

case 8:/* 第四个led亮 */
tmp=readl(S3C64XX_GPKDAT);
tmp&=0x7f;
writel(tmp, S3C64XX_GPKDAT);  
break;

case 9:/* 第四个led灭 */
tmp = readl(S3C64XX_GPKDAT);       
            tmp |= (0x80);       
            writel(tmp, S3C64XX_GPKDAT); 
break;

default :    
                break;
}
return 0;
}


struct file_operations led_fops = {
.owner = THIS_MODULE,
.read  = led_read,
.write = led_write,
};


static int __init dev_init(void)
{
int ret;
unsigned tmp;
   
printk ("Test led dev\n");    
ret = register_chrdev(LED_MAJOR,"led",&led_fops);      
if (ret <0){    
printk ("register %s char dev error\n","led");    
return -1;    
}  

/* 设置为GPK4-GPK7为输出方式*/
tmp = readl(S3C64XX_GPKCON);      
        tmp = (tmp&0x0000ffff)|0x1111ffff; 
        writel(tmp, S3C64XX_GPKCON);
        
        /* GPKDAT[7:4]=1 灯灭 */
tmp=readl(S3C64XX_GPKDAT);
tmp |=(0xF<<4);
writel(tmp,S3C64XX_GPKDAT);

/* 禁止上拉下拉   */
tmp=readl(S3C64XX_GPKPUD);
tmp &=(0x00<<8);
writel(tmp,S3C64XX_GPKPUD);

printk ("module install ok!\n");    

return 0;
}




static void __exit dev_exit (void)    
{    
    unregister_chrdev(LED_MAJOR,"led");    
    printk ("module exit\n");    
    return ;    
}    
    
module_init(dev_init);    
module_exit(dev_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("GAN WEIWANG");


Makefile函数

ifneq ($(KERNELRELEASE),)
obj-m := led_driver.o 
else
KDIR :=/home/part4/linux-2.6.38
PWD  :=$(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules


clean:
rm -f *.ko *.o *.mod.o *mod.c *.symvers
endif


测试程序

#include <stdio.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
#include <stdlib.h>  
   
int main (int argc,char **argv)    
{     
    int  fd;    

    int buf;
    if(argc!=2||sscanf(argv[1],"%d",&buf)!=1||buf<0||buf>9)
    {
    fprintf(stderr,"Usage:leds 0~9\n");
exit(1);
    }
    fd = open("/dev/led",O_RDWR);    
    if (fd < 0)    
    {    
        printf ("Open /dev/led file error\n");    
        return -1;    
    }       
 
    write(fd,&buf,1);   
    close (fd);    
    return 0;    
    
}

上述编译没有问题,就可以下到板子测试了。


加载驱动          insmod  led_driver.ko

创建设备文件    mknod /dev/led c 243 0  其中243要跟驱动文件中的设备号一致

运行测试文件    ./test_led

完成。


参考资料:


#include <linux/module.h>/*它定义了模块的 API、类型和宏(MODULE_LICENSE、MODULE_AUTHOR等等),所有的内核模块都必须包含这个头文件。/
#include <linux/kernel.h>/*使用内核信息优先级时要包含这个文件,一般在使用printk函数时使用到优先级信息*/
#include <linux/init.h>//头文件:module_init、module_exit等宏定义。
#include <linux/fs.h>struct file_operations
#include <asm/irq.h>
#include <mach/regs-gpio.h>// S3C2410 GPIO寄存器定义
#include <mach/hardware.h>// s3c2410_gpio_setpin, s3c2410_gpio_cfgpin等
#include <linux/device.h>//class_create device_create(注意,有些2.6.27以前是的可能是class_device_create,如果出现implicate 错误时,看一下这个头问题里边是哪一个),udev,自动在/dev下创建设备节点
#include <linux/cdev.h>//字符设备节点注册,函数有cdev_init,cdev_add,cdev_del等早期的办法是register_chrdev,unregister_chrdev这种方法应避免使用。
#define DEVICE_NAME "leds" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
#define LED_MAJOR 231 /* 主设备号 */
/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
#define IOCTL_LED_ON 1
#define IOCTL_LED_OFF 0
/* 用来指定LED所用的GPIO引脚 */
static unsigned long led_table [] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
/* 用来指定GPIO引脚的功能:输出 */
static unsigned int led_cfg_table [] =
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
struct leds_type
{
struct cdev cdev;
};
struct leds_type *my_leds_dev;
/* 应用程序对设备文件/dev/EmbedSky-leds执行open(...)时,
* 就会调用EmbedSky_leds_open函数
*/
static int EmbedSky_leds_open(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < 4; i++)
{
// 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
}
return 0;
}
/* 应用程序对设备文件/dev/EmbedSky-leds执行ioclt(...)时,
* 就会调用EmbedSky_leds_ioctl函数
*/
static int EmbedSky_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
if (arg > 4)
{
return -EINVAL;
}
switch(cmd)
{
case IOCTL_LED_ON:
// 设置指定引脚的输出电平为0
s3c2410_gpio_setpin(led_table[arg], 0);
return 0;
case IOCTL_LED_OFF:
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(led_table[arg], 1);
return 0;
default:
return -EINVAL;
}
}
/* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中指定的对应函数
*/
static struct file_operations EmbedSky_leds_fops =
{
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = EmbedSky_leds_open, 
.ioctl = EmbedSky_leds_ioctl,
};
static char __initdata banner[] = "TQ2440/SKY2440 LEDS, (c) 2008,2009 www.embedsky.net/n";
static struct class *led_class;
/*
* 执行“insmod EmbedSky_leds.ko”命令时就会调用这个函数
*/
static int __init EmbedSky_leds_init(void)
{
int ret;
dev_t devno=MKDEV(LED_MAJOR,0);
printk("init led/n");
printk(banner);
/* 注册字符设备驱动程序
* 参数为主设备号、设备名字、file_operations结构;
* 这样,主设备号就和具体的file_operations结构联系起来了,
* 操作主设备为LED_MAJOR的设备文件时,就会调用EmbedSky_leds_fops中的相关成员函数
ret = register_chrdev_region(devno, 1,DEVICE_NAME);//获得设备编号
my_leds_dev=kmalloc(sizeof(struct leds_type),GFP_KERNEL);
/*这个必须有不然会在加载模块时出现Unable to handle kernel NULL pointer dereference at virtual addres 00000000 错误,这是由于在这里my_leds_dev仅仅是个指针,没有相应大小的分配内存,所以使用时会出错,,,寻找这个错误是比较麻烦的*/
if(!my_leds_dev)
{
ret=-ENOMEM;
goto fail_malloc;
}
memset(my_leds_dev,0,sizeof(struct leds_type));
cdev_init(&(my_leds_dev->cdev),&EmbedSky_leds_fops);
ret=cdev_add(&(my_leds_dev->cdev),devno,1);
/*注意:与早期的设备注册方法不同,早期的直接register_chrdev()就可以,*/
if(ret)printk(KERN_NOTICE"ERROR %d",ret); 
//注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
led_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(led_class))
{
printk("Err: failed in EmbedSky-leds class. /n");
return -1;
}
//创建一个设备节点,节点名为DEVICE_NAME
device_create(led_class, NULL, MKDEV(LED_MAJOR, 0), NULL, DEVICE_NAME);
printk(DEVICE_NAME " initialized/n");
return 0;
fail_malloc: unregister_chrdev_region(devno,1);
return ret;
}
/*
* 执行”rmmod EmbedSky_leds.ko”命令时就会调用这个函数
*/
static void __exit EmbedSky_leds_exit(void)
{
/* 卸载驱动程序 */
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
device_destroy(led_class, MKDEV(LED_MAJOR, 0)); //删掉设备节点
class_destroy(led_class); //注销类
}
/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(EmbedSky_leds_init);
module_exit(EmbedSky_leds_exit);
/* 描述驱动程序的一些信息,不是必须的 */
MODULE_AUTHOR("http://www.embedsky.net"); // 驱动程序的作者
MODULE_DESCRIPTION("TQ2440/SKY2440 LED Driver"); // 一些描述信息
MODULE_LICENSE("GPL"); // 遵循的协议
上面代码中,led_table数组相当于对应了GPB的四个IO口的索引,通过这四个值,对这四个IO口进行相关操作。例如:
S3C2410_GPB5 = S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)
= S3C2410_GPIO_BANKB + 5
= 32*1 + 5
在s3c2410_gpio_setpin(S3C2410_GPB5,0)中,该函数首先通过S3C2410_GPB5获得GPB的虚拟地址和偏移地址,再对GPB5的GPBDAT寄存器进行操作,具体
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);//读取GPIO的DAT数据到dat
dat &= ~(1 << offs); //先将要设置的IO口拉低
dat |= to << offs; //再将形参的to值赋给dat
__raw_writel(dat, base + 0x04);//最后将DAT值写进GPIO的DAT
local_irq_restore(flags);
}

上面的 函数调用了两个子函数,具体定义如下

#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
其中S3C24XX_VA_GPIO定义如下:

#define S3C24XX_VA_GPIO S3C2410_ADDR(0x00E00000)
#define S3C2410_ADDR(x) (0xF0000000 + (x))
这里S3C2410_ADDR的基地址为0xF0000000(??),也即2440所有寄存器的虚拟地址的基地址。0x00E00000表示2440的GPIO的偏移地址,也就是说其GPIO的虚拟地址首地址为0xF0E00000。

再看看S3C2410_GPIO_BASE(pin)的定义,我们不仿把S3C2410_GPB5的值放进去计算,可以得到(S3C2410_GPB5&~31)=32。其目的就是去掉GPB的偏移值,然后再右移一位,和GPIO的虚拟地址首地址相加。因此,S3C2410_GPIO_BASE(pin)只代表了对应GPIO组的虚拟地址,如GPB的虚拟地址为10000(B)+0xF0E00000=0xF0E00010。依此类推,可以得到所有GPIO的偏移地址,具体如下表:


BANK
(pin&~31)
(pin&~31)>>1
S3C2410_GPIO_BASE(pin)

GPA
32*0
0000,0000
0x00
0xF0E00000

GPB
32*1
0010,0000
0x10
0xF0E00010

GPC
32*2
0100,0000
0x20
0xF0E00020

GPD
32*3
0110,0000
0x30
0xF0E00030

GPE
32*4
1000,0000
0x40
0xF0E00040

GPF
32*5
1010,0000
0x50
0xF0E00050

GPG
32*6
1100,0000
0x60
0xF0E00060

GPH
32*7
1110,0000
0x70
0xF0E00070


S3C2410_GPIO_OFFSET用于获得具体GPIO的偏移地址。如GPB5,则S3C2410_GPIO_OFFSET(pin) = (pin)&31 = (32*1 + 5) & 31 = 5。有了*base和off,就可以操作具体的寄存器了。
函数s3c2410_gpio_cfgpin()用于配置GPCON寄存器。具体代码
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long mask;
unsigned long con;
unsigned long flags;
if (pin < S3C2410_GPIO_BANKB)
{
mask = 1 << S3C2410_GPIO_OFFSET(pin);//GPA的寄存器只占一位
}
else 
{
mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;//非GPA的寄存器占两位
}
local_irq_save(flags);
con = __raw_readl(base + 0x00);//先保留GPCON的值
con &= ~mask; //再将要设置的管脚的CON值清零
con |= function; //然后将形参传进来的配置赋给CON
__raw_writel(con, base + 0x00); //最后将CON值写进GPCON寄存器
local_irq_restore(flags);
}
上面的LED驱动程序中,led_cfg_table数组给出了GPB相应管脚的属性设置,调用上面的函数后即设置为Output。

到此为止,整个S3C2440的IO口操作,应该就一目了然了

#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v)) 
# define __chk_io_ptr(x) (void)0

__chk_io_ptr()是编译器为了更细致地检查参数的属性,用于调试,正常编译时没有作用。 
volatile为了防止Compiler优化。

内核中,对所有的地址都是通过虚拟地址进行访问的.因此,不能直接访问0x56000010的物理地址,如果要对0x56000010的物理地址进行访问(一般是外设寄存器),那么需要把0x56000010的物理地址映射为虚拟地址,然后对该虚拟地址进行访问就是对实际的物理地址进行访问了。 
需要注意的是:在进行映射时,该虚拟地址需要disable cache和Write Buffer, 否则就是加了volatile也是没有用的

这个IOREMAP的实现过程中 
/* 
* figure out the physical address offset in a page size 
* PAGE_MASK = (1 << 10) 
*/ 
offset = phys_addr &~ PAGE_MASK; 
/* 
* figure out physical address with page align 
*/ 
phys_addrs &= PAGE_MASK; 
/* 
* get the real size with page align 
*/ 
size = PAGE_ALIGN(last_addr) - phys_addrs; 
下面是通过vmlist中查找以size大小的空闲块,所以从这里可以看出,已经做过了页的对齐,只以映射的大小

杂项设备(misc device)

杂项设备也是在嵌入式系统中用得比较多的一种设备驱动。在 Linux 内核的include/linux目录下有Miscdevice.h文件,要把自己定义的misc device从设备定义在这里。其实是因为这些字符设备不符合预先确定的字符设备范畴,所有这些设备采用主编号10 ,一起归于misc device,其实misc_register就是用主标号10调用register_chrdev()的。 

也就是说,misc设备其实也就是特殊的字符设备。 

字符设备(char device) 

使用register_chrdev(LED_MAJOR,DEVICE_NAME,&dev_fops)注册字符设备驱动程序时,如果有多个设备使用该函数注册驱动程序,LED_MAJOR不能相同,否则几个设备都无法注册(我已验证)。如果模块使用该方式注册并且 LED_MAJOR为0(自动分配主设备号 ),使用insmod命令加载模块时会在终端显示分配的主设备号和次设备号,在/dev目录下建立该节点,比如设备leds,如果加载该模块时分配的主设备号和次设备号为253和0,则建立节点:mknod leds c 253 0。使用register_chrdev (LED_MAJOR,DEVICE_NAME,&dev_fops)注册字符设备驱动程序时都要手动建立节点 ,否则在应用程序无法打开该设备。

__raw_readl和__raw_writel

Linux对I/O的操作都定义在asm/io.h中,相应的在arm平台下,就在asm-arm/io.h中。

#define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v))

#define __raw_writew(v,a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))

#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))在include/linux/compiler.h中:

#ifdef __CHECKER__……
extern void __chk_io_ptr(void __iomem *);
#else……
# define __chk_io_ptr(x) (void)0……
#endif

__raw_readl(a)展开是:((void)0, *(volatile unsigned int _force *)(a))。在定义了__CHECKER__的时候先调用__chk_io_ptr检查该地址,否则__chk_io_ptr什么也不做,*(volatile unsigned int _force *)(a)就是返回地址为a处的值。(void)xx的做法有时候是有用的,例如编译器打开了检查未使用的参数的时候需要将没有用到的参数这么弄一下才能编译通过。

CPU对I/O的物理地址的编程方式有两种:一种是I/O映射,一种是内存映射。__raw_readl和__raw_writel等是原始的操作I/O的方法,由此派生出来的操作方法有:inb、outb、_memcpy_fromio、readb、writeb、ioread8、iowrite8等。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于tiny6410的led驱动程序 的相关文章

  • Java 导入excel 两个sheet

    import java io File import java io FileInputStream import java io IOException import org apache poi ss usermodel Cell im
  • nexus仓库有jar但是maven 拉取不到jar问题解决

    eclipse在工程上右键 maven gt select maven profile 然后选择profile就好了 方式二 直接使用命令行拉取 mvn f pom xml dependency copy dependencies
  • mac显示文件路径

    在 Mac 上 可以使用 显示文件路径 功能来查看文件的路径 这个功能可以让你看到文件所在文件夹的完整路径 以及文件名 要查看文件路径 你可以在 Finder 中打开文件所在的文件夹 然后按下 Command Shift G 键 输入文件名
  • CCP协议学习

    一 CCP协议基础知识 a CCP CAN Calibration Protocol 中文名为CAN标定协议 是基于CAN总线的一种应用层协议 b CCP可以读取RAM PORTS ROM FLASH 写RAM PORTS FLASH c
  • signalr 控制台做服务端

    服务端 一 新建控制台应用程序 net framework 4 8 SignalRSelfHost 二 引入NuGet包 install package Microsoft AspNet SignalR Core install packa
  • Centos安装配置git

    最简单的安装方式直接使用yaml命令 yum install git all 服务器回应 其实除了安装git之外 也会安装其他需要的依赖文件 yum 安装的git默认是 git version 1 8 3 1 git官网下载压缩包 本地配置
  • JPA快速开发之查询接口Repository

    什么是JPA SpringData是Spring提供的一个数据操作框架 而SpringData JPA则是该框架下基于JPA标准进行数据操作的模块 SpringData JPA简化了持久层代码的操作 只需编写接口即可实现 JPA 全称Jav
  • Python全栈开发【基础-10】流程控制之for循环

    专栏介绍 本专栏为Python全栈开发系列文章 技术包括Python基础 函数 文件 面向对象 网络编程 并发编程 MySQL数据库 HTML JavaScript CSS JQuery bootstrap WSGI Django Flas
  • JetBrains产品教育版申请

    JetBrains产品教育版申请 Pycharm和IntelliJ都是申请的JetBarins官方edu版 功能上应该和professional一样 虽然咱不一定能用得到pro 以下内容以申请Pycharm为例 事实上 只要能认证成功 所有
  • 蓝牙DA14580学习教程(附开源可编程手环/手表全套学习资料下载地址)

    DA14580学习 DA14580用来干什么 1 超长待机的智能手环 手表和其他智能穿戴设备 2 智能鼠标 键盘 遥控器 触控板 语音和手势识别控制板等 3 计步 如小米手环 活动和睡眠监测器 血压血糖心率监测器 4 多感测器运动电脑平台
  • 数据处理的关键组件:编程与数据加工

    编程是计算机科学中至关重要的一环 它涉及到对数据进行加工与处理的过程 通过编程 我们可以创建算法和程序来操作和转换数据 使其具有意义和价值 在本文中 我们将探讨编程在数据处理中的作用 并提供一些使用中文编写的源代码示例 编程语言是用来编写程
  • spring boot2 与dubbo整合经验

    开始接触spring boot2整合dubbo时 参考了好多文章 都不太完全 导致整合屡次失败 坚信降低门槛才会普及大众 否则技术再好束之高阁也白搭 dubbo配置文件分好几种 xml类 properties类 api配置类 注解类 另外注
  • 目标跟踪算法研究整理

    最近项目有用到目标跟踪的算法 用的还是传统opencv 整理一下 1 基础框架 目标跟踪基础认识 视频图像跟踪算法综述 opencv实现目标跟踪的八种算法 2 CSRT追踪器 CSRT追踪器 官方描述 在具有通道和空间可靠性的判别相关滤波器
  • JSX初探

    需求 动态的创建HTML页面 假设有一个布尔变量 editable 为true时创建A界面 为false时创建B界面 A界面 div class div B界面 div class div 现有的实现思路有两个 一 JS动态创建HTML标签
  • Unity3D物体上下左右旋转(不受物体自身坐标轴影响【万向锁问题解决】)

    直接将代码挂载到需要旋转的物体上 按上下左右键旋转即可 using UnityEngine using System Collections public class SpinObject MonoBehaviour public Game
  • FineReport.10 一(帆软)(报表基础练习)

    文章目录 一 FineReport 1 报表 2 安装 二 安装目录 2 1 设计器相关目录 2 2 工程相关文件夹 2 3 缓存文件 2 3 1 FineReportEnv xml 三 初始练习 四 遇见的问题记录 1 初始数据库出问题需
  • Python基础入门(五)——关于一个Number类型的小实例

    Number类型数据是我们在python当中经常要用到的数据类型 先上一些小知识点 再上实例 相关知识点 Number类型 Number类型 Number类型的定义和删除 一句话 赋值就是定义 删除要用DEL 定义 var1 1 var2
  • 大语言模型的演进

    大语言模型的演进 借着上次科技树剪枝的话题 大语言模型为人工智能科技树再次剪枝 让我们再来看看大语言模型这个分枝是如何生长的 也是经历6年的Google和OpenAI两家公司几次大战后的结果 第一回合 2017年6月 Google的6500
  • 从代码生成到问题解答,InsCode AI助你成为编程及写作高手

    目录 前言 InsCode AI写作助手 创造更好的写作体验 InsCode AI 创作助手 如何帮助创作者高效创作文章 结论 个人感受 一 你平时会使用这类AI工具吗 你对这类型的工具有什么看法 二 你可以花几分钟体验一下InsCode

随机推荐

  • 新的刷脸支付方式掘起手机支付将会終结

    手机支付将会終结 新的支付方式掘起 新的支付方式对很多人还是很陌生的 这就要很好的推广和布置 现在推出了二代的蜻蜓刷脸设备 向商户销售出了舒缓的二代蜻蜓刷脸支付设备 超市 快餐厅 自动贩卖机都已经实现商业直播 相信很快在每个城市 都会发现这
  • 重载new/delete(C++中的new/delete与operator new/operator delete)

    转 http blog csdn net zhangxiao93 article details 50768025 原文 http www cnblogs com luxiaoxun archive 2012 08 10 2631812 h
  • k8s的dashboard日常操作

    k8s的dashboard日常操作 一 k8s的dashboard介绍 1 dashboard介绍 2 dashboard的功能 集群管理 工作负载 服务发现和负载均衡 存储 配置 日志视图 三 查看集群的所有角色 四 查看集群的命令空间
  • Python数据结构-----递归实现快速排序

    目录 前言 快速排序 1 概念 2 示例 Python代码实现 递归实现快速排序 前言 今天我们就来一起学习快速排序的思想方法 然后通过Python语言来实现快速排序的功能 下面我们就开始今天的学习吧 快速排序 1 概念 快速排序其实是冒泡
  • 使用ggplot2包绘制分组带状图实战

    使用ggplot2包绘制分组带状图实战 在数据可视化中 分组带状图是一种常用的图表类型 可以直观地展示多个组别之间的差异和变化趋势 而R语言中的ggplot2包提供了丰富的绘图函数 其中geom jitter函数可以用来创建分组带状图 下面
  • SpringBoot + Websocket 实现实时聊天

    SpringBoot WebSocket 实现实时聊天 最近有点小时间 上个项目正好用到了websocket实现广播消息来着 现在来整理一下之前的一些代码 分享给大家 WebSocket协议是基于TCP的一种新的网络协议 它实现了浏览器与服
  • ctfshow-web10 with rollup 绕过

    0x00 前言 CTF 加解密合集 CTF Web合集 网络安全知识库 文中工具皆可关注 皓月当空w 公众号 发送关键字 工具 获取 0x01 题目 0x02 Write Up 基本方法 到处点一点 点到取消的时候 突然发现 可以下载一个文
  • C语言中signed和unsigned怎么理解?C语言unsigned long、long long 取值范围???

    C语言中signed和unsigned signed意思为有符号的 也就是第一个位代表正负 剩余的代表大小 例如 signed int 大小区间为 128 127 unsigned意思为无符号的 所有的位都为大小 没有负数 例如 unsig
  • java实现下载excel读取与生成超详细

    背景 没啥背景 就是要做这个功能 创建ExcelUtil工具类 具体导入导出方法如下 excel导入 param inputStream 导入的excel文件 return public static List
  • 酱香咖啡喝了没?用数据分析揭秘瑞幸咖啡的7500万用户增长策略

    瑞幸 X 茅台 这波联名赢麻了 不仅狂卖 542 万杯 甚至带动茅台市值飙升200亿 瑞幸这几年联名搞了不少 又是线条小狗的爱情故事 又是椰树 维密 周大福 足球的 下面老李就从数据分析角度 带大家来看一下近几年 瑞幸咖啡的用户增长策略 是
  • 数据结构笔记之链式栈的基本操作

    include stdio h include stdlib h include io h include math h include time h define OK 1 define ERROR 0 define TRUE 1 def
  • VMWare安装

    1 1 VMWare简介 VMWare是一个虚拟技术的合集 它提供了众多的相关软件 类似于Parallels VMWare是商业应用 而且价格非常的贵 所以 通常我们使用的是网上别人破解的版本 而不是使用官方的正版 VMWare官网 VMw
  • 【UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xd3 in position 0: invalid continuation byte】

    UnicodeDecodeError utf 8 codec can t decode byte 0xd3 in position 0 invalid continuation byte F jupyter work dir MMLAB m
  • 有一个公网IP,在内网如何架设多台服务器?

    进行内网ip到外网ip的映射 也就是pat 这个工作现在多半由防火墙来完成 不过如果没有防火墙 用路由器也可以完成 只不过会在高峰时加重路由器的负担 思科2600路由可以独立完成各种nat pat但是因为这款产品本身属于低端产品 所以能够担
  • Java8学习记录(一)——Lambda表达式

    这两天看了 Java8实战 做一下记录 目录 一 行为参数化 1 什么是行为参数化 二 函数式接口 1 概念 三 Lambda表达式 四 方法引用 注意点 1 静态方法引用 2 实例方法引用 重点来了 任意类型的实例方法引用 现有对象的实例
  • 【深度学习】树莓派Zero w深度学习模型Python推理

    在机器学习开发过程中 当模型训练好后 接下来就要进行模型推理了 根据部署环境可分为三类场景 边缘计算 一般指手机 嵌入式设备 直接在数据生成的设备上进行推理 因为能避免将采集到的数据上传到云端 所以实时性非常好 端计算 介于云和边缘设备之间
  • Spring Boot 集成Mybatis实现多数据源

    总体来说多数据源配置有两种方式 一种是静态的 一种是动态的 静态的方式 我们以两套配置方式为例 在项目中有两套配置文件 两套mapper 两套SqlSessionFactory 各自处理各自的业务 这个两套mapper都可以进行增删改查的操
  • GPU版本安装Pytorch教程最新方法

    目录 步骤 第一步 安装 Anaconda 和 Pycharm 软件 第二步 下载安装CUDA11 3 1 首先查看自己电脑GPU版本 方式一 搜索框输入nvidia 打开nvidia控制面板 方式二 win R打开cmd 输入nvidia
  • ubuntu的FTP服务器搭建

    1 安装服务器 sudo apt get install vsftpd 如果有错误 先执行 apt update 2 创建用户 Linux下的用户 创建专用目录 mkdir home ftp 命令添加ftp用户 sudo useradd d
  • 基于tiny6410的led驱动程序

    今天弄了一个晚上了 终于弄懂了第一个简单的linux驱动感觉很多人编写的第一个驱动也是拿led开刀的吧 本文的led驱动是基于tiny6410的四个led驱动 用字符设备的驱动模块 而不是混杂设备驱动模块来编写 本人在使用混杂设备方法编写的