【驱动篇】龙芯LS2K0300之单总线驱动

news2025/2/25 9:55:59

实验过程

实验目的: 在龙芯开发板上面使用单总线驱动DS18B20温度传感器

① 根据原理图连接DS18B20模块

② 将i2c0引脚的功能复用为GPIO

③ 注册字符设备,按照DS18B20的读写时序编写读写驱动接口

④ 编写测试用例解析传感器的数值

原理图

将板子上面的GPIO48连接传感器的DAT引脚,其余引脚连接如下

在这里插入图片描述

然后记得在设备树中把i2c0部分代码注释掉,将PIN16复用为GPIO48

驱动代码

定义相关传感器设备结构体

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/errno.h>

#define DS18B20_DEV_NUM			1		  
#define DS18B20_DEV		        "ds18b20"	
#define DS18B20_GPIO            48
#define DS18B20_DQ_OUT(x)       gpio_direction_output(ds18b20.gpio, x)
#define DS18B20_DQ_IN           ds18b20_get_io()

struct ds18b20_dev {
    dev_t dev_id;		
	struct cdev cdev;	
	struct class *class;	
	struct device *device;	
	int major;			
	int minor;	
    int gpio;				
    unsigned char data[2]; 
	struct timer_list timer;	
    struct work_struct work;
};

struct ds18b20_dev ds18b20;

传感器数据读写交互

static int ds18b20_get_io(void)
{
    gpio_direction_input(ds18b20.gpio);
    return gpio_get_value(ds18b20.gpio); 
}

static void ds18b20_reset(void)
{
    DS18B20_DQ_OUT(0);  /* 拉低DQ,复位 */
    udelay(750);      /* 拉低750us */
    DS18B20_DQ_OUT(1);  /* DQ=1, 释放复位 */
    udelay(15);       /* 延迟15US */
}

uint8_t ds18b20_check(void)
{
    uint8_t retry = 0;
    uint8_t rval = 0;

    while (DS18B20_DQ_IN && retry < 200)    /* 等待DQ变低, 等待200us */
    {
        retry++;
        udelay(1);
    }

    if (retry >= 200)
    {
        rval = 1;
    }
    else
    {
        retry = 0;

        while (!DS18B20_DQ_IN && retry < 240)   /* 等待DQ变高, 等待240us */
        {
            retry++;
            udelay(1);
        }

        if (retry >= 240) rval = 1;
    }

    return rval;
}

static uint8_t ds18b20_read_bit(void)
{
    uint8_t data = 0;
    DS18B20_DQ_OUT(0);
    udelay(2);
    DS18B20_DQ_OUT(1);
    udelay(12);

    if (DS18B20_DQ_IN)
    {
        data = 1;
    }

    udelay(50);
    return data;
}

static uint8_t ds18b20_read_byte(void)
{
    uint8_t i, b, data = 0;

    for (i = 0; i < 8; i++)
    {
        b = ds18b20_read_bit(); /* DS18B20先输出低位数据 ,高位数据后输出 */

        data |= b << i;         /* 填充data的每一位 */
    }

    return data;
}

static void ds18b20_write_byte(uint8_t data)
{
    uint8_t j;
    for (j = 1; j <= 8; j++)
    {
        if (data & 0x01)
        {
            DS18B20_DQ_OUT(0);  /*  Write 1 */
            udelay(2);
            DS18B20_DQ_OUT(1);
            udelay(60);
        }
        else
        {
            DS18B20_DQ_OUT(0);  /*  Write 0 */
            udelay(60);
            DS18B20_DQ_OUT(1);
            udelay(2);
        }

        data >>= 1;             /* 右移,获取高一位数据 */
    }
}

static void ds18b20_start(void)
{
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0x44);   /*  convert */
}

static int ds18b20_init(void)
{
    gpio_direction_output(ds18b20.gpio, 0);
    ds18b20_reset();
    return ds18b20_check();	
}

注册字符设备,绑定相关回调函数

static int ds18b20_open(struct inode *inode, struct file *filp)
{
	return 0;
}

static ssize_t ds18b20_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) 
{
    int ret;
    ret = copy_to_user(buf, &ds18b20.data[0], 2);
	if(ret)
        return -ENOMEM;
	return ret;
}

static struct file_operations ds18b20_fops = {
	.owner	= THIS_MODULE,
	.open = ds18b20_open,
	.read	= ds18b20_read,
};

static void ds18b20_work_callback(struct work_struct *work)
{
    ds18b20_start();                            /*  ds1820 start convert */
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);                   /*  skip rom */
    ds18b20_write_byte(0xbe);                   /*  convert */
    ds18b20.data[0] = ds18b20_read_byte();      /*  LSB */
    ds18b20.data[1] = ds18b20_read_byte();      /*  MSB */
}

static void ds18b20_timer_callback(struct timer_list *arg)
{
    schedule_work(&ds18b20.work);	
    mod_timer(&ds18b20.timer, jiffies + (1000 * HZ/1000));	
}

static int ds18b20_module_init(void)
{
    int ret = 0;
    ds18b20.gpio = DS18B20_GPIO;
    if (!gpio_is_valid(ds18b20.gpio)) {
        return -EINVAL;
    }

    ret = gpio_request(ds18b20.gpio, "DS18B20-GPIO");
    if (ret) {
        printk(KERN_ERR "ds18b20 : Failed to request gpio\n");
        return ret;
	}

    ds18b20_init();

    if (ds18b20.major) {		
		ds18b20.dev_id = MKDEV(ds18b20.major, 0);
		ret = register_chrdev_region(ds18b20.dev_id, DS18B20_DEV_NUM, DS18B20_DEV);
		if(ret < 0) {
			pr_err("cannot register %s char driver [ret=%d]\n", DS18B20_DEV, DS18B20_DEV_NUM);
			goto free_gpio;
		}
	} 
    else {					
		ret = alloc_chrdev_region(&ds18b20.dev_id, 0, DS18B20_DEV_NUM, DS18B20_DEV);
		if(ret < 0) {
			pr_err("%s Couldn't alloc_chrdev_region, ret=%d\r\n", DS18B20_DEV, ret);
			goto free_gpio;
		}
		ds18b20.major = MAJOR(ds18b20.dev_id);	
		ds18b20.minor = MINOR(ds18b20.dev_id);	
	}
	
	ds18b20.cdev.owner = THIS_MODULE;
	cdev_init(&ds18b20.cdev, &ds18b20_fops);
	cdev_add(&ds18b20.cdev, ds18b20.dev_id, DS18B20_DEV_NUM);
	if(ret < 0)
		goto del_unregister;
		
	ds18b20.class = class_create(THIS_MODULE, DS18B20_DEV);
	if (IS_ERR(ds18b20.class)) {
		goto del_cdev;
	}

	ds18b20.device = device_create(ds18b20.class, NULL, ds18b20.dev_id, NULL, DS18B20_DEV);
	if (IS_ERR(ds18b20.device)) {
		goto destroy_class;
	}

	timer_setup(&ds18b20.timer, ds18b20_timer_callback, 0);
    ds18b20.timer.expires=jiffies + msecs_to_jiffies(1000);
    add_timer(&ds18b20.timer);
	INIT_WORK(&ds18b20.work, ds18b20_work_callback);

    return 0;

destroy_class:
	class_destroy(ds18b20.class);
del_cdev:
	cdev_del(&ds18b20.cdev);
del_unregister:
	unregister_chrdev_region(ds18b20.dev_id, DS18B20_DEV_NUM);
free_gpio:
	gpio_free(ds18b20.gpio);
	return -EIO;
}

整合代码

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/errno.h>

#define DS18B20_DEV_NUM			1		  
#define DS18B20_DEV		        "ds18b20"	
#define DS18B20_GPIO            48	
#define DS18B20_DQ_OUT(x)       gpio_direction_output(ds18b20.gpio, x)
#define DS18B20_DQ_IN           ds18b20_get_io()

struct ds18b20_dev {
    dev_t dev_id;		
	struct cdev cdev;	
	struct class *class;	
	struct device *device;	
	int major;			
	int minor;	
    int gpio;				
    unsigned char data[2]; 
	struct timer_list timer;	
    struct work_struct work;
};

struct ds18b20_dev ds18b20;

static int ds18b20_get_io(void)
{
    gpio_direction_input(ds18b20.gpio);
    return gpio_get_value(ds18b20.gpio); 
}

static void ds18b20_reset(void)
{
    DS18B20_DQ_OUT(0);  /* 拉低DQ,复位 */
    udelay(750);      /* 拉低750us */
    DS18B20_DQ_OUT(1);  /* DQ=1, 释放复位 */
    udelay(15);       /* 延迟15US */
}

uint8_t ds18b20_check(void)
{
    uint8_t retry = 0;
    uint8_t rval = 0;

    while (DS18B20_DQ_IN && retry < 200)    /* 等待DQ变低, 等待200us */
    {
        retry++;
        udelay(1);
    }

    if (retry >= 200)
    {
        rval = 1;
    }
    else
    {
        retry = 0;

        while (!DS18B20_DQ_IN && retry < 240)   /* 等待DQ变高, 等待240us */
        {
            retry++;
            udelay(1);
        }

        if (retry >= 240) rval = 1;
    }

    return rval;
}

static uint8_t ds18b20_read_bit(void)
{
    uint8_t data = 0;
    DS18B20_DQ_OUT(0);
    udelay(2);
    DS18B20_DQ_OUT(1);
    udelay(12);

    if (DS18B20_DQ_IN)
    {
        data = 1;
    }

    udelay(50);
    return data;
}

static uint8_t ds18b20_read_byte(void)
{
    uint8_t i, b, data = 0;

    for (i = 0; i < 8; i++)
    {
        b = ds18b20_read_bit(); /* DS18B20先输出低位数据 ,高位数据后输出 */

        data |= b << i;         /* 填充data的每一位 */
    }

    return data;
}

static void ds18b20_write_byte(uint8_t data)
{
    uint8_t j;
    for (j = 1; j <= 8; j++)
    {
        if (data & 0x01)
        {
            DS18B20_DQ_OUT(0);  /*  Write 1 */
            udelay(2);
            DS18B20_DQ_OUT(1);
            udelay(60);
        }
        else
        {
            DS18B20_DQ_OUT(0);  /*  Write 0 */
            udelay(60);
            DS18B20_DQ_OUT(1);
            udelay(2);
        }

        data >>= 1;             /* 右移,获取高一位数据 */
    }
}

static void ds18b20_start(void)
{
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0x44);   /*  convert */
}

static int ds18b20_init(void)
{
    gpio_direction_output(ds18b20.gpio, 0);
    ds18b20_reset();
    return ds18b20_check();	
}
 
static int ds18b20_open(struct inode *inode, struct file *filp)
{
	return 0;
}

static ssize_t ds18b20_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) 
{
    int ret;
    ret = copy_to_user(buf, &ds18b20.data[0], 2);
	if(ret)
        return -ENOMEM;
	return ret;
}

static struct file_operations ds18b20_fops = {
	.owner	= THIS_MODULE,
	.open = ds18b20_open,
	.read	= ds18b20_read,
};

static void ds18b20_work_callback(struct work_struct *work)
{
    ds18b20_start();                            /*  ds1820 start convert */
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);                   /*  skip rom */
    ds18b20_write_byte(0xbe);                   /*  convert */
    ds18b20.data[0] = ds18b20_read_byte();      /*  LSB */
    ds18b20.data[1] = ds18b20_read_byte();      /*  MSB */
}

static void ds18b20_timer_callback(struct timer_list *arg)
{
    schedule_work(&ds18b20.work);	
    mod_timer(&ds18b20.timer, jiffies + (1000 * HZ/1000));	
}

static int ds18b20_module_init(void)
{
    int ret = 0;
    ds18b20.gpio = DS18B20_GPIO;
    if (!gpio_is_valid(ds18b20.gpio)) {
        return -EINVAL;
    }

    ret = gpio_request(ds18b20.gpio, "DS18B20-GPIO");
    if (ret) {
        printk(KERN_ERR "ds18b20 : Failed to request gpio\n");
        return ret;
	}

    ds18b20_init();

    if (ds18b20.major) {		
		ds18b20.dev_id = MKDEV(ds18b20.major, 0);
		ret = register_chrdev_region(ds18b20.dev_id, DS18B20_DEV_NUM, DS18B20_DEV);
		if(ret < 0) {
			pr_err("cannot register %s char driver [ret=%d]\n", DS18B20_DEV, DS18B20_DEV_NUM);
			goto free_gpio;
		}
	} 
    else {					
		ret = alloc_chrdev_region(&ds18b20.dev_id, 0, DS18B20_DEV_NUM, DS18B20_DEV);
		if(ret < 0) {
			pr_err("%s Couldn't alloc_chrdev_region, ret=%d\r\n", DS18B20_DEV, ret);
			goto free_gpio;
		}
		ds18b20.major = MAJOR(ds18b20.dev_id);	
		ds18b20.minor = MINOR(ds18b20.dev_id);	
	}
	
	ds18b20.cdev.owner = THIS_MODULE;
	cdev_init(&ds18b20.cdev, &ds18b20_fops);
	cdev_add(&ds18b20.cdev, ds18b20.dev_id, DS18B20_DEV_NUM);
	if(ret < 0)
		goto del_unregister;
		
	ds18b20.class = class_create(THIS_MODULE, DS18B20_DEV);
	if (IS_ERR(ds18b20.class)) {
		goto del_cdev;
	}

	ds18b20.device = device_create(ds18b20.class, NULL, ds18b20.dev_id, NULL, DS18B20_DEV);
	if (IS_ERR(ds18b20.device)) {
		goto destroy_class;
	}

	timer_setup(&ds18b20.timer, ds18b20_timer_callback, 0);
    ds18b20.timer.expires=jiffies + msecs_to_jiffies(1000);
    add_timer(&ds18b20.timer);
	INIT_WORK(&ds18b20.work, ds18b20_work_callback);

    return 0;

destroy_class:
	class_destroy(ds18b20.class);
del_cdev:
	cdev_del(&ds18b20.cdev);
del_unregister:
	unregister_chrdev_region(ds18b20.dev_id, DS18B20_DEV_NUM);
free_gpio:
	gpio_free(ds18b20.gpio);
	return -EIO;
}


static void ds18b20_module_exit(void)
{
	cdev_del(&ds18b20.cdev);
	unregister_chrdev_region(ds18b20.dev_id, DS18B20_DEV_NUM); 
	device_destroy(ds18b20.class, ds18b20.dev_id);
	class_destroy(ds18b20.class);
	del_timer(&ds18b20.timer);
    cancel_work_sync(&ds18b20.work);
    gpio_free(ds18b20.gpio); 
}

module_init(ds18b20_module_init);
module_exit(ds18b20_module_exit);
MODULE_LICENSE("GPL");

Makefile文件

obj-m += ds18b20.o 
KDIR:=/home/asensing/loongson/linux-4.19
ARCH=loongarch 
CROSS_COMPILE=loongarch64-linux-gnu-
PWD?=$(shell pwd) 
all:
	make -C $(KDIR) M=$(PWD) modules 

构建脚本

export PATH=$PATH:/home/asensing/loongson/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.3-1/bin
make -j8
loongarch64-linux-gnu-gcc test.c -o test
FILE=$PWD/$(basename $PWD).ko
scp $FILE test root@192.168.137.216:/home/root

测试用例

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"

#define DEV_NAME "/dev/ds18b20"

int main()
{
    int fd, ret;
    unsigned char result[2];
    unsigned char TH, TL;
    short tmp = 0;
    float temperature;
    int flag = 0;

    fd = open(DEV_NAME, 0);

    if(fd < 0)
    {
        printf("open %s device failed\n", DEV_NAME);
        exit(1);
    }
    else
        printf("Open %s success!\n", DEV_NAME);

    while(1)
    {
        ret = read(fd, &result, sizeof(result)); 
		if(ret == 0) {	/* 读取到数据 */
			TL = result[0];
			TH = result[1];
    
			if(TH > 7) {	/* 负数处理 */
				TH = ~TH;
				TL = ~TL;
				flag = 1;	/* 标记为负数 */
			}
			tmp = TH;
			tmp <<= 8;
			tmp += TL;

			if(flag == 1) {
				temperature = (float)(tmp+1) * 0.0625; /* 计算负数的温度 */
				temperature = -temperature;
			}else {
				temperature = (float)tmp *0.0625;	/* 计算正数的温度 */
			}            

			if(temperature < 125 && temperature > -55) {	/* 温度范围 */
				printf("Environment Temperature Now : %0.2f℃\n", temperature);
			}
		}
		flag = 0;
		sleep(1);
    }
	close(fd);	/* 关闭文件 */
}

实验效果

插入驱动后,使用测试用例实时读取环境温度值

在这里插入图片描述

广东太热,我要回非洲!

在这里插入图片描述

参考

以上驱动参考自RT-Thread的工程:rtt-psoc62/one-wire/ds18b20.c at main · hywing/rtt-psoc62 (github.com)

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

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

相关文章

细粒度图像分类论文阅读笔记

细粒度图像分类论文阅读笔记 摘要Abstract1. 用于细粒度图像分类的聚合注意力模块1.1 文献摘要1.2 研究背景1.3 本文创新点1.4 计算机视觉中的注意力机制1.5 模型方法1.5.1 聚合注意力模块1.5.2 通道注意力模块通道注意力代码实现 1.5.3 空间注意力模块空间注意力代码实现 1.5.…

[MQTT]Mosquitto的權限管理_使用者/密碼(pwfile)和訪問控制清單(aclfile)

延續Mosquitto的內網連接(intranet)和使用者/密碼權限設置文章&#xff0c;經解讀mosquitto官網文檔&#xff0c;在權限管理部分&#xff0c;除了設置使用者/密碼(pwfile)之外&#xff0c;還有訪問控制清單(Access Control List, aclfile)可以設置。經過測試&#xff0c;同時設…

Python中使用PyQT5库时报错:没有Qt平台插件可以初始化

一、发现问题&#xff1a;无限易pythonGo打开执行的时候报&#xff1a;“没有Qt平台插件可以初始化&#xff0c;请重新安装应用程序。”的错误&#xff0c;点击确定后无限易崩溃闪退。 二、解决问题&#xff1a; 1、重新安装依赖&#xff0c;打开CMD输入pip list&#xff0c;查…

开发uniapp插件包aar文件,使uniapp可以调用jar包

背景 使用 uniapp 开发应用时&#xff0c;很多时候都需要调用第三方的sdk&#xff0c;一般以 jar 为主。为了应对这个问题&#xff0c;官方提供了插件方案&#xff0c;可以将第三方 jar 包进行封装为 aar 包后&#xff0c;再集成到 uniapp 中使用。 一、环境安装工具 1、jdk…

拓扑排序——C语言

拓扑排序&#xff08;Topological Sorting&#xff09;是一种用于有向无环图&#xff08;DAG&#xff09;的排序算法&#xff0c;其输出是图中所有顶点的线性排序&#xff0c;使得对于每条有向边 (u, v)&#xff0c;顶点 u 在 v 之前出现。拓扑排序确定了项目网络图中的起始事件…

嵌入式中逻辑分析仪与示波器的基本原理

大家好,今天主要给大家分享一下,嵌入式中如何使用逻辑分析仪和示波器的方法,希望对大家有所帮助。 https://dreamsourcelab.cn/ 第一:什么是逻辑分析仪 是否遇到使用示波器分析数字电路的冏境:深度不够,时间太短,无法抓到想要的波形,没有协议内容解析? 逻辑分析仪…

深度学习11-13

1.神经元的个数对结果的影响&#xff1a; &#xff08;http://cs.stanford.edu/people/karpathy/convnetjs/demo/classify2d.html&#xff09; &#xff08;1&#xff09;神经元3个的时候 &#xff08;2&#xff09;神经元是10个的时候 神经元个数越多&#xff0c;可能会产生…

注意 llamaIndex 中 Chroma 的坑!

llamaIndex 做索引是默认存在内存中&#xff0c;由于索引需要通过网络调用 API&#xff0c;而且索引是比较耗时的操作&#xff0c;为了避免每次都进行索引&#xff0c;使用向量数据库进行 Embedding 存储以提高效率。首先将 Document 解析成 Node&#xff0c;索引时调用 Embedd…

解析PDF文件中的图片为文本

解析PDF文件中的图片为文本 1 介绍 解析PDF文件中的图片&#xff0c;由两种思路&#xff0c;一种是自己读取PDF文件中的图片&#xff0c;然后用OCR解析&#xff0c;例如&#xff1a;使用PyMuPDF读取pdf文件&#xff0c;再用PaddleOCR或者Tesseract-OCR识别文字。另一种使用第…

小鹏汽车2025冲刺类L4智驾,挑战与机遇并存

随着科技的飞速发展&#xff0c;智能驾驶已成为汽车行业的前沿领域。近日&#xff0c;小鹏汽车在AI DAY上宣布国内首个量产上车的端到端大模型&#xff0c;这一创新举措无疑为智能驾驶的发展注入了新的活力。然而&#xff0c;在迈向2025年实现类L4级智能驾驶的道路上&#xff0…

DHCP原理1-单个局域网出现多个DHCP服务器会发生什么

1. 背景 DHCP全称是Dynamic Host Configuration Protocol。其协议标准是RFC1541&#xff08;已被RFC2131取代&#xff09;&#xff0c;主要实现服务器向客户端动态分配IP地址&#xff08;如IP地址、子网掩码、网关、DNS&#xff09;和配置信息。其系统架构是标准的C/S架构。RFC…

运算放大器(运放)低通滤波反相放大器电路和积分器电路

低通滤波反相放大器电路 运放积分器电路请访问下行链接 运算放大器(运放)积分器电路 设计目标 输入ViMin输入ViMax输出VoMin输出VoMaxBW&#xff1a;fp电源Vee电源Vcc–0.1V0.1V–2V2V2kHz–2.5V2.5V 设计说明 这款可调式低通反相放大器电路可将信号电平放大 26dB 或 20V/…

算是一些Transformer学习当中的重点内容

一、基础概念 Transformer是一种神经网络结构&#xff0c;由Vaswani等人在2017年的论文Attentions All YouNeed”中提出&#xff0c;用于处理机器翻译、语言建模和文本生成等自然语言处理任务。Transformer同样是encoder-decoder的结构&#xff0c;只不过这里的“encoder”和“…

OpenCV机器学习-人脸识别

一 基本概念 1 计算机视觉与机器学习的关系 计算机视觉是机器学习的一种应用&#xff0c;而且是最有价的应用。 2 人脸识别 哈尔(haar)级联方法 Harr是专门为解决人脸识别而推出的&#xff1b; 在深度学习还不流行时&#xff0c;Harr已可以商用&#xff1b; 深度学习方法&am…

thrift接口调用工具

写了一个thrift接口调用工具 导入thrift文件就可以直接调用相应接口 工具会根据thrift文件中接口的参数名&#xff0c;参数类型&#xff0c;返回值等等&#xff0c;自动生成接口参数&#xff0c;和结果json化显示。 https://github.com/HuaGouFdog/Fdog-Kit

C++初学者指南第一步---14.函数调用机制

C初学者指南第一步—14.函数调用机制 文章目录 C初学者指南第一步---14.函数调用机制1.记住&#xff1a;内存的结构2.函数调用是如何工作的3. 不要引用局部变量4. 常见编译器优化5. Inlining内联 1.记住&#xff1a;内存的结构 堆&#xff08;自由存储&#xff09; 用于动态存…

鸿蒙开发系统基础能力:【@ohos.hiAppEvent (应用打点)】

应用打点 本模块提供了应用事件打点能力&#xff0c;包括对打点数据的落盘&#xff0c;以及对打点功能的管理配置。 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import hiAppEve…

英伟达下一代DLSS或利用人工智能

英伟达的黄仁勋在2024年Computex展会上的问答环节中&#xff0c;提前透露了公司未来几代深度学习超采样&#xff08;DLSS&#xff09;技术的发展方向。在回答有关DLSS的问题时&#xff0c;黄仁勋表示&#xff0c;未来我们将看到通过纯粹的人工智能生成的纹理和对象。他还提到&a…

通过ESP32读取I2C温湿度传感器项目:协议与代码实例

简介 在本项目中&#xff0c;我们将使用ESP32开发板读取I2C温湿度传感器的数据。我们将详细介绍I2C协议&#xff0c;并提供图文并茂的代码实例&#xff0c;帮助你快速上手。 项目流程 选择硬件&#xff1a;ESP32开发板、I2C温湿度传感器&#xff08;如DHT12、HTU21D、SHT30等&a…

yii2 ActiveForm使用技巧

持续更新&#xff1a; 1、搜索输入框&#xff1a;form-inline <?php $form ActiveForm::begin([action > [index],method > get,options > [class > form-inline] &#xff08;增加此行代码&#xff09; ]); ?>