当前位置: 首页 > news >正文

019——IIC模块驱动开发(基于EEPROM【AT24C02】和I.MX6uLL)

目录

一、 IIC基础知识

二、Linux中的IIC(韦东山老师的学习笔记)

1. I2C驱动程序的层次

2. I2C总线-设备-驱动模型

2.1 i2c_driver

2.2 i2c_client

三、 AT24C02 介绍

四、 AT24C02驱动开发

实验 

驱动程序

应用程序


一、 IIC基础知识

总线类设备驱动——IIC_iic设备驱动-CSDN博客

Exynos_4412——IIC总线概述_.若使用iic总线让从机给主机发送一个字节的数据0xa2,画出scl和sda上的时序图-CSDN博客

STM32——IIC总线(MPU6050应用)_mpu6050例程-CSDN博客

写过好多次啦不打算重复写了。

二、Linux中的IIC(韦东山老师的学习笔记)

参考资料:

  • Linux内核文档:

    • Documentation\i2c\instantiating-devices.rst

    • Documentation\i2c\writing-clients.rst

  • Linux内核驱动程序示例:

    • drivers/eeprom/at24.c

1. I2C驱动程序的层次

I2C Core就是I2C核心层,它的作用:

  • 提供统一的访问函数,比如i2c_transfer、i2c_smbus_xfer等

  • 实现I2C总线-设备-驱动模型,管理:I2C设备(i2c_client)、I2C设备驱动(i2c_driver)、I2C控制器(i2c_adapter)

2. I2C总线-设备-驱动模型

2.1 i2c_driver

i2c_driver表明能支持哪些设备:

  • 使用of_match_table来判断

    • 设备树中,某个I2C控制器节点下可以创建I2C设备的节点

      • 如果I2C设备节点的compatible属性跟of_match_table的某项兼容,则匹配成功

    • i2c_client.name跟某个of_match_table[i].compatible值相同,则匹配成功

  • 使用id_table来判断

    • i2c_client.name跟某个id_table[i].name值相同,则匹配成功

i2c_driver跟i2c_client匹配成功后,就调用i2c_driver.probe函数。

2.2 i2c_client

i2c_client表示一个I2C设备,创建i2c_client的方法有4种:

方法1

  • 通过I2C bus number来创建

    int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len);
  • 通过设备树来创建

	i2c1: i2c@400a0000 {/* ... master properties skipped ... */clock-frequency = <100000>;flash@50 {compatible = "atmel,24c256";reg = <0x50>;};pca9532: gpio@60 {compatible = "nxp,pca9532";gpio-controller;#gpio-cells = <2>;reg = <0x60>;};};

方法2

        有时候无法知道该设备挂载哪个I2C bus下,无法知道它对应的I2C bus number。 但是可以通过其他方法知道对应的i2c_adapter结构体。 可以使用下面两个函数来创建i2c_client:

  • i2c_new_device

  static struct i2c_board_info sfe4001_hwmon_info = {I2C_BOARD_INFO("max6647", 0x4e),};int sfe4001_init(struct efx_nic *efx){(...)efx->board_info.hwmon_client =i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);(...)}

i2c_new_probed_device

  static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };static int usb_hcd_nxp_probe(struct platform_device *pdev){(...)struct i2c_adapter *i2c_adap;struct i2c_board_info i2c_info;(...)i2c_adap = i2c_get_adapter(2);memset(&i2c_info, 0, sizeof(struct i2c_board_info));strscpy(i2c_info.type, "isp1301_nxp", sizeof(i2c_info.type));isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,normal_i2c, NULL);i2c_put_adapter(i2c_adap);(...)}

差别:

  • i2c_new_device:会创建i2c_client,即使该设备并不存在

  • i2c_new_probed_device:

    • 它成功的话,会创建i2c_client,并且表示这个设备肯定存在

    • I2C设备的地址可能发生变化,比如AT24C02的引脚A2A1A0电平不一样时,设备地址就不一样

    • 可以罗列出可能的地址

    • i2c_new_probed_device使用这些地址判断设备是否存在

  • 方法3(不推荐):由i2c_driver.detect函数来判断是否有对应的I2C设备并生成i2c_client

  • 方法4:通过用户空间(user-space)生成 调试时、或者不方便通过代码明确地生成i2c_client时,可以通过用户空间来生成。

  // 创建一个i2c_client, .name = "eeprom", .addr=0x50, .adapter是i2c-3# echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device// 删除一个i2c_client# echo 0x50 > /sys/bus/i2c/devices/i2c-3/delete_device

三、 AT24C02 介绍

        AT24C02 是基于 I2C 总线的存储器件,由于接口方便,体积小,数据掉电不丢失等特点,在仪器仪表及工业自动化控制中得到大量的应用。百问网提供的 EEPROM 模块使用的就是 AT24C02,使用 8 位地址,存储容量为 2K bit,即 2048bit = 256*8bit = 256 Byte, 其中它被分为 32 页,每页 8Byte。

        基于 I2C 接口的设备操作,我们主要关心的是 I2C 数据格式。 AT24C02 作为 EEPROM 存储设备,显然我们关心的是:怎么读写某个地址,即怎么发地址、怎么读写数据。 查阅《AT24CXX.pdf》手册,要写入一个字节,可如下操作:先发出设备地址, 再发出 WORD 地址(即存储地址),再发出数据。

        反之,要读 AT24C02,如下图:涉及 2 次 I2C 传输。 先发出设备地址, WORD地址;再次发出设备地址,读到数据。

四、 AT24C02驱动开发

实验 

 先添加设备树

这是我们的设备树目录

可以用find找到我们刚添加的设备目录 

咱们用的这个小工具有个配置项可以设置一下很方便

reg这个可能是特殊的加密文件需要用hexdump去看

虽然我们是iic-1但是内核是从0开始的所以这个就是我们的设备目录

插入模块后我们的驱动就出来了,没写的时候读出来是一堆乱码

验证一下它的非易失性

没毛病

驱动程序

#include "asm/uaccess.h"
#include "linux/delay.h"
#include "linux/i2c.h"
#include <linux/module.h>
#include <linux/poll.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>/* 主设备号                                                                 */
static int major = 0;
static struct class *my_i2c_class;static struct i2c_client *g_client;static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);
struct fasync_struct *i2c_fasync;/* 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t i2c_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{int err;unsigned char *kern_buf;struct i2c_msg msgs[2];/* 从0读取size字节 */kern_buf = kmalloc(size, GFP_KERNEL);/* 初始化i2c_msg * 1. 发起一次写操作: 把0发给AT24C02, 表示要从0地址读数据* 2. 发起一次读操作: 得到数据*/msgs[0].addr  = g_client->addr;msgs[0].flags = 0;  /* 写操作 */msgs[0].buf   = kern_buf;kern_buf[0]   = 0; /* 把数据0发给设备 */msgs[0].len   = 1;msgs[1].addr  = g_client->addr;msgs[1].flags = I2C_M_RD;  /* 写操作 */msgs[1].buf   = kern_buf;msgs[1].len   = size;err = i2c_transfer(g_client->adapter, msgs, 2);/* copy_to_user  */err = copy_to_user(buf, kern_buf, size);kfree(kern_buf);return size;
}static ssize_t i2c_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{int err;unsigned char kern_buf[9];struct i2c_msg msgs[1];int len;unsigned char addr = 0;/* 把size字节的数据写入地址0 *///kern_buf = kmalloc(size+1, GFP_KERNEL);while (size > 0){if (size > 8)len = 8;elselen = size;size -= len;/* copy_from_user  */err = copy_from_user(kern_buf+1, buf, len);buf += len;/* 初始化i2c_msg * 1. 发起一次写操作: 把0发给AT24C02, 表示要从0地址读数据* 2. 发起一次读操作: 得到数据*/msgs[0].addr  = g_client->addr;msgs[0].flags = 0;  /* 写操作 */msgs[0].buf   = kern_buf;kern_buf[0]   = addr;  /* 写AT24C02的地址 */msgs[0].len   = len+1;addr += len;err = i2c_transfer(g_client->adapter, msgs, 1);mdelay(20);}//kfree(kern_buf);return size;    
}static unsigned int i2c_drv_poll(struct file *fp, poll_table * wait)
{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);poll_wait(fp, &gpio_wait, wait);//return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;return 0;
}static int i2c_drv_fasync(int fd, struct file *file, int on)
{if (fasync_helper(fd, file, on, &i2c_fasync) >= 0)return 0;elsereturn -EIO;
}/* 定义自己的file_operations结构体                                              */
static struct file_operations i2c_drv_fops = {.owner	 = THIS_MODULE,.read    = i2c_drv_read,.write   = i2c_drv_write,.poll    = i2c_drv_poll,.fasync  = i2c_drv_fasync,
};static int i2c_drv_probe(struct i2c_client *client,const struct i2c_device_id *id)
{// struct device_node *np = client->dev.of_node;// struct i2c_adapter *adapter = client->adapter;/* 记录client */g_client = client;/* 注册字符设备 *//* 注册file_operations 	*/major = register_chrdev(0, "100ask_i2c", &i2c_drv_fops);  /* /dev/gpio_desc */my_i2c_class = class_create(THIS_MODULE, "100ask_i2c_class");if (IS_ERR(my_i2c_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "100ask_i2c");return PTR_ERR(my_i2c_class);}device_create(my_i2c_class, NULL, MKDEV(major, 0), NULL, "myi2c"); /* /dev/myi2c */return 0;
}static int i2c_drv_remove(struct i2c_client *client)
{/* 反注册字符设备 */device_destroy(my_i2c_class, MKDEV(major, 0));class_destroy(my_i2c_class);unregister_chrdev(major, "100ask_i2c");return 0;
}static const struct of_device_id myi2c_dt_match[] = {{ .compatible = "100ask,i2cdev" },{},
};static const struct i2c_device_id at24c02_ids[] = {{ "xxxxyyy",	(kernel_ulong_t)NULL },{ /* END OF LIST */ }
};
static struct i2c_driver my_i2c_driver = {.driver = {.name = "100ask_i2c_drv",.owner = THIS_MODULE,.of_match_table = myi2c_dt_match,},.probe = i2c_drv_probe,.remove = i2c_drv_remove,.id_table = at24c02_ids,
};static int __init i2c_drv_init(void)
{/* 注册i2c_driver */return i2c_add_driver(&my_i2c_driver);
}static void __exit i2c_drv_exit(void)
{/* 反注册i2c_driver */i2c_del_driver(&my_i2c_driver);
}/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */module_init(i2c_drv_init);
module_exit(i2c_drv_exit);MODULE_LICENSE("GPL");

应用程序


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>static int fd;/** ./i2c_test /dev/myi2c string * ./i2c_test /dev/myi2c**/
int main(int argc, char **argv)
{int ret;char buf[100];/* 1. 判断参数 */if (argc < 2) {printf("Usage:\n", argv[0]);printf("      %s <dev>, read at24c02\n", argv[0]);printf("      %s <dev> <string>, write at24c02\n", argv[0]);return -1;}/* 2. 打开文件 */fd = open(argv[1], O_RDWR | O_NONBLOCK);if (fd == -1){printf("can not open file %s\n", argv[1]);return -1;}if (argc == 3){ret = write(fd, argv[2], strlen(argv[2]) + 1);}else{ret = read(fd, buf, 100);printf("read: %s\n", buf);}close(fd);return 0;
}

相关文章:

019——IIC模块驱动开发(基于EEPROM【AT24C02】和I.MX6uLL)

目录 一、 IIC基础知识 二、Linux中的IIC&#xff08;韦东山老师的学习笔记&#xff09; 1. I2C驱动程序的层次 2. I2C总线-设备-驱动模型 2.1 i2c_driver 2.2 i2c_client 三、 AT24C02 介绍 四、 AT24C02驱动开发 实验 驱动程序 应用程序 一、 IIC基础知识 总线类…...

【开发篇】十三、JVM基础参数设置与垃圾回收器的选择

文章目录 1、-Xmx 和 –Xms2、-XX:MaxMetaspaceSize 和 –XX:MetaspaceSize3、-Xss4、不建议改的参数5、其他参数6、选择GC回收器的调试思路7、CMS的并发模式失败现象的解决8、调优案例 GC问题解决方式&#xff1a; 优化JVM基础参数&#xff0c;避免频繁Full GC减少对象的产生…...

多维 HighCharts

1&#xff1a;showHighChart.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><!-- js脚本都是官方的,后两个是highchart脚本 --><script type"text/javascript" src"jquery1.7.1.mi…...

单细胞RNA测序(scRNA-seq)cellranger count的细胞定量和aggr整合

单细胞RNA测序(scRNA-seq)基础知识可查看以下文章: 单细胞RNA测序(scRNA-seq)工作流程入门 单细胞RNA测序(scRNA-seq)细胞分离与扩增 单细胞RNA测序(scRNA-seq)SRA数据下载及fastq-dumq数据拆分 单细胞RNA测序(scRNA-seq)Cellranger流程入门和数据质控 细胞定量…...

Unity URP 2021 Release-Notes

&#x1f308;Unity URP 2021 Release-Notes 本文信息收集来自自动搜集工具&#x1f448; 版本更新内容2021.3.32URP: Vulkan URP will use MSAA samples count fallback from player settings. Prior to this x2 fallback would have been to upgrade to x4.(UUM-741)2021.3.…...

最新IntelliJ IDEA 2024.1 安装和快速配置教程

IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版 文章目录 IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版前言 第一步&#xff1a; IntelliJ IDEA 2024.1安装教程第 0 步&…...

24应届生求职中QAQ

有没有大佬给个机会帮忙内推一下啊&#xff0c;找工作太难了QAQ。 最近一直在BOOS上找工作&#xff0c;但是结果不太理想&#xff0c;一直没有找到满意的工作&#xff0c;有没有大佬帮忙内推一下&#xff0c;有的话请私信我QAQ。...

centos7离线安装postgresql13

**一.**安装存储库RPM yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm二.使用yumdownloader下载安装包 mkdir pg_yum cd pg_yum yumdownloader --resolve postgresql13-server**三.**上传rpm包到安…...

【JavaSE】搞定String类

前言 本篇会细致讲解String类的常见用法&#xff0c;让小伙伴们搞定String类~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 常用的三种字符串构造 字符串长度length 字符串比较 比较 比较字符串的内容equals…...

数字乡村创新实践探索农业现代化与农村治理现代化新路径:科技赋能农村全面振兴与农民幸福生活

目录 引言 一、数字乡村与农业现代化 1、智慧农业技术的应用 2、农业产业链的数字化转型 二、数字乡村与农村治理现代化 1、农村信息化水平的提升 2、农村治理模式的创新 三、科技赋能农村全面振兴与农民幸福生活 1、提升农业生产效益与农民收入 2、促进农村产业结构…...

【从零开始手搓12306项目】四、12306是如何成为全球最忙碌的网站之一?

4.1 12306有多忙碌 一天的请求量大概1600亿&#xff0c;平均180万/秒&#xff08;二八理论&#xff1a;20%的事件产生80%的请求&#xff09;&#xff0c;不适合二八理论&#xff0c;因为12306分时间放票 平均一年售出30亿张&#xff0c;高峰期日售票能力达到了2000万张 高峰期…...

WebKit简介及工作流程

文章目录 一、WebKit简介二、WebKit结构三、Webkit工作流程四、WebKit常见问题五、WebKit优点六、相关链接 一、WebKit简介 WebKit是一个开源的浏览器引擎&#xff0c;它的起源可以追溯到2001年&#xff0c;当时苹果公司推出了其首款基于Unix的操作系统Mac OS X。在2002年&…...

软考-系统集成项目管理中级--进度管理(输入输出很重要!!!本章占分较高,着重复习)

本章历年考题分值统计(16年11月及以后按新教材考的&#xff09; 本章重点常考知识点汇总清单(学握部分可直接理解记忆) 12、参数估算:参数估算是一种基于历史数据和项目参数&#xff0c;使用某种算法来计算成本或持续时间的估算技术。参数估算是指利用历史数据之间的统计关系和…...

AndroidAutomotive模块介绍(一)整体介绍

前言 Android Automotive 是一个基本 Android 平台&#xff0c;可运行 IVI 系统中预安装的 Android 应用以及可选的第二方和第三方 Android 应用。 本系列文档将会系统的介绍 Android Automotive 的功能、架构、逻辑等。模块逻辑将从 应用api接口、系统服务、底层服务&#x…...

【开发问题记录】Nacos修改服务实例权重时报错

问题记录 一、问题描述1.1 产生原因1.2 产生问题 二、问题解决2.1 docker部署的nacos解决方案2.1.1 进入nacos容器2.1.2 查看当前目录2.1.3 进入data文件夹2.1.4 删除protocol文件2.2 本地部署的nacos 一、问题描述 1.1 产生原因 在运行项目时&#xff0c;在本地启动了一个服务…...

高级IO和5种IO模型

目录 1. 高级IO1.1 IO的基本概念1.2 OS如何得知外设当中有数据可读取1.3 OS如何处理从网卡中读取到的数据包1.4 IO的步骤 2. 五种IO模型2.1 利用钓鱼来理解2.2 阻塞IO2.3 非阻塞IO2.4 信号驱动IO2.5 IO多路转接2.6 异步IO 3. 高级IO的概念3.1 同步通信 VS 异步通信3.2 阻塞 VS …...

OpenHarmony轻量系统开发【7】驱动之I2C显示OLED屏幕

7.1实验效果 Hispark WiFi开发套件又提供一个oled屏幕&#xff0c;但是鸿蒙源码中没有这个屏幕的驱动&#xff0c;我们需要自己去移植。 以下是移植效果&#xff1a; 接口&#xff1a;I2C 使用引脚&#xff1a;HI_IO_NAME_GPIO_13 、 HI_IO_NAME_GPIO_14 7.2代码 这里我直…...

C#:循环中断

任务描述 实现九九乘法表&#xff0c;按照编程要求&#xff0c;使用break跳出循环 测试说明 测试过程&#xff1a; 平台将编译用户补全代码&#xff0c;并根据程序的输出判断程序是否正确。 以下是测试样例&#xff1a; 测试输入&#xff1a; 预期输出&#xff1a; we found…...

34. UE5 RPG实现鼠标点击移动

在前面&#xff0c;我们实现过使用键盘按键wasd去实现控制角色的移动&#xff0c;现在&#xff0c;我们实现了InputAction按键触发&#xff0c;后面&#xff0c;实现一下通过鼠标点击地面实现角色移动。 我们将实现两种效果的切换&#xff0c;如果你点击地面快速松开&#xff0…...

《二》Qt Creator工具介绍与使用

一、关于界面 点击文件--->新建文件或项目会出现如下图&#xff1a; 我们选择第一个 点击下一步下一步&#xff1a; 继续下一步直到结束&#xff1a; 二&#xff0c;具体文件介绍 我们点击pro查看以下 QT core gui第1行 表示使用qt的core和gui库&#xff0c;如果以后…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...