活动介绍

public FileSaver(byte[] data, String dir, String fileName) { File file = new File(OisCameraPreview.SDCARD_DIRECTORY_PATH + "/Camera" + OisCameraPreview.this.mCameraId); this.dirFile = file; this.start = 0L; this.end = 0L; this.mData = data; String ldir = dir == null ? file.getPath() : this.dirFile.getPath() + File.separator + dir; mkdir(ldir); File file2 = new File(ldir, fileName); this.mFile = file2; try { file2.createNewFile(); } catch (IOException e) { e.printStackTrace(); } Log.d("kjx", this.mFile.getAbsolutePath()); }请解释代码

时间: 2025-04-05 20:12:24 浏览: 38
<think>好的,我现在需要帮助用户解释一段Java代码。首先,我要仔细阅读这段代码,理解它的结构和功能。这段代码看起来像是一个构造函数,用于保存文件。用户可能想知道这个构造函数的作用、各个参数的意义,以及代码的具体执行步骤。 首先,我会看构造函数的参数:byte数组data,字符串dir和fileName。这应该用于保存数据到指定目录的文件中。接下来,代码里创建了一个File对象,路径是OisCameraPreview.SDCARD_DIRECTORY_PATH加上"/Camera"和mCameraId。这可能是在SD卡上创建一个相机相关的目录。 然后,dirFile被赋值为这个File对象。接着初始化start和end为0L,可能是记录时间戳或其他用途。之后,将传入的data赋值给mData。接下来处理目录路径,如果dir为null,就使用file.getPath(),否则拼接dirFile的路径和dir。这里可能需要检查目录是否存在,所以调用了mkdir方法。 然后创建目标文件file2,路径是ldir和fileName。尝试创建新文件,如果失败则捕获异常并打印堆栈跟踪。最后记录文件的绝对路径到日志。 我需要逐步解释这些步骤,确保用户理解每个部分的作用。比如,File的创建、路径拼接、目录创建、文件生成以及异常处理。同时,注意代码中可能的错误点,比如IO异常的处理方式,以及目录是否存在时的处理逻辑。另外,要指出Log.d用于调试,输出文件路径是否正确。 可能用户想知道这段代码是否可靠,或者有没有潜在的问题。例如,mkdir函数是否确保目录创建成功?createNewFile()在文件已存在时的行为是什么?还有,是否应该检查SD卡是否可用?这些可能是用户没有直接问但需要注意的地方。 最后,总结整个构造函数的功能:根据参数确定目录和文件名,创建必要的目录结构,生成目标文件,并准备写入数据。可能需要提醒用户注意异常处理部分,因为这里只是打印了错误,没有进一步处理,可能导致文件未正确创建时的问题。</think>以下是对代码的逐步解释: 1. **构造函数定义** ```java public FileSaver(byte[] data, String dir, String fileName) ``` 这是一个用于保存文件的构造函数,接收三个参数: - `data`:要保存的二进制数据 - `dir`:目标子目录(可为空) - `fileName`:要保存的文件名 2. **基础路径构建** ```java File file = new File(OisCameraPreview.SDCARD_DIRECTORY_PATH + "/Camera" + OisCameraPreview.this.mCameraId); ``` - 拼接SD卡根目录路径(`OisCameraPreview.SDCARD_DIRECTORY_PATH`) - 添加固定子目录`/Camera` - 附加当前相机ID(`mCameraId`)区分不同相机设备 3. **成员变量初始化** ```java this.dirFile = file; // 存储基础目录对象 this.start = 0L; // 可能用于记录操作时间戳(开始) this.end = 0L; // 可能用于记录操作时间戳(结束) this.mData = data; // 存储待保存的数据 ``` 4. **目标路径处理** ```java String ldir = dir == null ? file.getPath() : this.dirFile.getPath() + File.separator + dir; ``` - 如果`dir`参数为空:直接使用基础目录路径 - 如果`dir`参数存在:在基础目录下创建子目录路径 5. **目录创建** ```java mkdir(ldir); // 应包含递归创建目录的逻辑(代码未展示) ``` 6. **目标文件创建** ```java File file2 = new File(ldir, fileName); this.mFile = file2; try { file2.createNewFile(); // 创建空文件 } catch (IOException e) { e.printStackTrace(); // 建议改为更健壮的异常处理 } ``` 7. **调试日志** ```java Log.d("kjx", this.mFile.getAbsolutePath()); // 输出最终文件路径 ``` **潜在改进建议**: 1. 应添加对SD卡可写状态的检查(`Environment.getExternalStorageState()`) 2. `mkdir`方法需实现递归目录创建(建议使用`file.mkdirs()`) 3. 文件创建失败时应抛出异常或返回错误状态 4. 建议添加文件存在性检查(`file.exists()`) 5. 时间戳字段(start/end)未在本段代码中使用,可能需要后续补充 **核心功能**:该构造函数根据传入参数,在设备存储的指定位置创建文件,为后续写入`mData`数据做准备。
阅读全文

相关推荐

private static void appendWithMediaStore(Context context, String fileName, String content) throws IOException { ContentResolver resolver = context.getContentResolver(); // 先查询是否已存在该文件 Uri queryUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI; String selection = MediaStore.Downloads.DISPLAY_NAME + "=? AND " + MediaStore.Downloads.RELATIVE_PATH + "=?"; String[] selectionArgs = new String[] { fileName, Environment.DIRECTORY_DOWNLOADS + "/" + LOG_DIR + "/" }; try (Cursor cursor = resolver.query(queryUri, new String[]{MediaStore.Downloads._ID}, selection, selectionArgs, null)) { Uri uri; if (cursor != null && cursor.moveToFirst()) { // 文件已存在,获取其Uri long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID)); uri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, id); } else { // 文件不存在,创建新文件 ContentValues values = new ContentValues(); values.put(MediaStore.Downloads.DISPLAY_NAME, fileName); values.put(MediaStore.Downloads.MIME_TYPE, "text/plain"); values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/" + LOG_DIR); uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values); } if (uri != null) { try (OutputStream out = resolver.openOutputStream(uri, "wa")) { out.write((content + "\n").getBytes()); } } } } 适配了android分区存储,这个方法记录log本身没什么问题。但是一旦卸载后重写安装,实际之前文件的权限就会丢失了,出现同名文件存在,但是写失败,导致直接崩溃。这个如何解决

<template> <view class="content"> <button @click="selectFile()">打开安卓文件管理器</button> <view> <text>单选URL</text> {{ filePath }} </view> <view><text>多选</text></view> <view v-for="(item, index) in fileList">{{ item }}</view> </view> </template> <script> export default { data() { return { filePath: '', fileList: [] }; }, onLoad() {}, methods: { selectFile() { let that = this; let main = plus.android.runtimeMainActivity(); let Intent = plus.android.importClass('android.content.Intent'); let intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType('*/*'); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); //关键!多选参数 intent.addCategory(Intent.CATEGORY_OPENABLE); main.startActivityForResult(intent, 200); // 获取回调 main.onActivityResult = function(requestCode, resultCode, data) { let Activity = plus.android.importClass('android.app.Activity'); let ContentUris = plus.android.importClass('android.content.ContentUris'); let Cursor = plus.android.importClass('android.database.Cursor'); let Uri = plus.android.importClass('android.net.Uri'); let Build = plus.android.importClass('android.os.Build'); let Environment = plus.android.importClass('android.os.Environment'); let DocumentsContract = plus.android.importClass('android.provider.DocumentsContract'); // 给系统导入 contentResolver let contentResolver = main.getContentResolver(); plus.android.importClass(contentResolver); // 返回路径 let path = ''; if (resultCode == Activity.RESULT_OK) { if (data.getData() != null) { let uri = data.getData(); //this 当前mainClass实例 path = getPath(this, uri); that.filePath = path; } else { try { let ClipData = plus.android.importClass('android.content.ClipData'); let clipData = new ClipData(); clipData = data.getClipData(); if (clipData != null) { for (let i = 0; i < clipData.getItemCount(); i++) { let item = clipData.getItemAt(i); let uri = item.getUri(); let url = getPath(this, uri); that.fileList.push(url); } } } catch (e) { console.log(e); } } console.log(path); } else { console.log(path); } function getPath(context, uri) { try { let isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider //一些三方的文件浏览器会进入到这个方法中,例如ES //QQ文件管理器不在此列 if (isExternalStorageDocument(uri)) { let docId = DocumentsContract.getDocumentId(uri); let split = docId.split(':'); let type = split[0]; // 如果是手机内部存储 if ('primary' == type.toLowerCase()) { return Environment.getExternalStorageDirectory() + '/' + split[1]; } else { return '/storage/' + type + '/' + split[1]; } } // DownloadsProvider else if (isDownloadsDocument(uri)) { let id = DocumentsContract.getDocumentId(uri); if (id.indexOf('raw:') > -1) { id = id.replace('raw:', ''); } // 不同系统获取的id开头可能不一样,在这后面便是真实的地址 if (id.substring(0, 5) == 'msf:') { return id.substring(5, id.length); } let contentUri = ContentUris.withAppendedId(Uri.parse('content://downloads/public_downloads'), ContentUris.parseId(uri)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { let MediaStore = plus.android.importClass('android.provider.MediaStore'); let docId = DocumentsContract.getDocumentId(uri); let split = docId.split(':'); let type = split[0]; let contentUri = null; if ('image' == type.toLowerCase()) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ('video' == type.toLowerCase()) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ('audio' == type.toLowerCase()) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } let selection = '_id=?'; let selectionArgs = [split[1]]; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ('content' == uri.getScheme().toLowerCase()) { if (isGooglePhotosUri(uri)) { return uri.getLastPathSegment(); } else if (isQQMediaDocument(uri)) { let paths = uri.getPath(); let Environment = plus.android.importClass('android.os.Environment'); let fileDir = Environment.getExternalStorageDirectory(); let files = plus.android.importClass('java.io.File'); let file = new files(fileDir, paths.substring('/QQBrowser'.length, paths.length)); return file.getPath(); } return getDataColumn(context, uri, null, null); } // File else if ('file' == uri.getScheme().toLowerCase()) { return uri.getPath(); } return null; } catch (e) { console.log(e); return null; } } // 通过uri 查找出绝对路径 function getDataColumn(context, uri, selection, selectionArgs) { try { let MediaStore = plus.android.importClass('android.provider.MediaStore'); let cursor = null; let column = MediaStore.MediaColumns.DATA; let projection = [column]; cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { let column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } catch (e) { console.log(e); return null; } } function isExternalStorageDocument(uri) { return 'com.android.externalstorage.documents' == uri.getAuthority() ? true : false; } function isDownloadsDocument(uri) { return 'com.android.providers.downloads.documents' == uri.getAuthority() ? true : false; } function isMediaDocument(uri) { return 'com.android.providers.media.documents' == uri.getAuthority() ? true : false; } /** * 使用第三方qq文件管理器打开 * * @param uri * @return */ function isQQMediaDocument(uri) { return 'com.tencent.mtt.fileprovider' == uri.getAuthority() ? true : false; } /** * @param uri The Uri to check. * @return Whether the Uri authority is Google Photos. */ function isGooglePhotosUri(uri) { return 'com.google.android.apps.photos.content' == uri.getAuthority() ? true : false; } }; } } }; </script> <style></style> 我现在需要读取选择的.bin文件,并且读到里边的内容和文件的大小,并可以将文件里边的二进制文件打印出来,手机app实现,请参考以下两个路径下中的方法进行更改https://www.html5plus.org/doc/zh_cn/io.html文件和https://www.html5plus.org/doc/zh_cn/android.html文件

/*This file has been modified by Unisoc (Shanghai) Technologies Co., Ltd in 2024. * * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "recovery_utils/roots.h" #include <fcntl.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <iostream> #include <string> #include <vector> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> #include <ext4_utils/ext4_utils.h> #include <ext4_utils/wipe.h> #include <fs_mgr.h> #include <fs_mgr/roots.h> #include "otautil/sysutil.h" //hook #include <include/hook/librecovery_utils_stubs.h> using android::fs_mgr::Fstab; using android::fs_mgr::FstabEntry; using android::fs_mgr::ReadDefaultFstab; using android::base::ReadFileToString; static Fstab fstab; constexpr const char* CACHE_ROOT = "/cache"; void load_volume_table() { if (!ReadDefaultFstab(&fstab)) { LOG(ERROR) << "Failed to read default fstab"; return; } fstab.emplace_back(FstabEntry{ .blk_device = "ramdisk", .mount_point = "/tmp", .fs_type = "ramdisk", .length = 0, }); std::cout << "recovery filesystem table" << std::endl << "=========================" << std::endl; for (size_t i = 0; i < fstab.size(); ++i) { auto& entry = fstab[i]; if (strcmp(entry.mount_point.c_str(), "/storage/sdcard0") == 0) load_volume_table_impl(entry); std::cout << " " << i << " " << entry.mount_point << " " << " " << entry.fs_type << " " << entry.blk_device << " " << entry.length << std::endl; } std::cout << std::endl; } Volume* volume_for_mount_point(const std::string& mount_point) { return android::fs_mgr::GetEntryForMountPoint(&fstab, mount_point); } // Mount the volume specified by path at the given mount_point. int ensure_path_mounted_at(const std::string& path, const std::string& mount_point) { return android::fs_mgr::EnsurePathMounted(&fstab, path, mount_point) ? 0 : -1; } int ensure_path_mounted(const std::string& path) { // Mount at the default mount point. return android::fs_mgr::EnsurePathMounted(&fstab, path) ? 0 : -1; } int ensure_path_unmounted(const std::string& path) { return android::fs_mgr::EnsurePathUnmounted(&fstab, path) ? 0 : -1; } static int exec_cmd(const std::vector<std::string>& args) { CHECK(!args.empty()); auto argv = StringVectorToNullTerminatedArray(args); pid_t child; if ((child = fork()) == 0) { execv(argv[0], argv.data()); _exit(EXIT_FAILURE); } int status; waitpid(child, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOG(ERROR) << args[0] << " failed with status " << WEXITSTATUS(status); } return WEXITSTATUS(status); } static int64_t get_file_size(int fd, uint64_t reserve_len) { struct stat buf; int ret = fstat(fd, &buf); if (ret) return 0; int64_t computed_size; if (S_ISREG(buf.st_mode)) { computed_size = buf.st_size - reserve_len; } else if (S_ISBLK(buf.st_mode)) { uint64_t block_device_size = get_block_device_size(fd); if (block_device_size < reserve_len || block_device_size > std::numeric_limits<int64_t>::max()) { computed_size = 0; } else { computed_size = block_device_size - reserve_len; } } else { computed_size = 0; } return computed_size; } //#wangfengqiu@HQ, 2024/03/28, Add for: nuovo shield recovery clear data plan start bool forbiddenRecoveryByReserveProperty() { std::string content; std::vector<std::string> reserve2_property_path = { "/nuovo/productinfo/nuovo_forbidden_recovery.prop", // 原Nuovo路径 "/nuovo/productinfo/MACROPAY_forbidden_recovery.prop", // 新增MACROPAY路径 }; //Fstab defFstab; /*if (!ReadDefaultFstab(&defFstab)) { printf("Failed to read default fstab productinfo\n"); return false; }*/ //for (size_t i = 0; i < defFstab.size(); ++i) { //const auto& entry = defFstab[i]; //std::string::size_type pos = entry.blk_device.find("productinfo"); //if ((pos != std::string::npos) && (ensure_path_mounted(entry.mount_point.c_str()) == 0)) { //printf("mount productinfo success,mount point is %s \n", entry.mount_point.c_str()); for (const auto& path : reserve2_property_path) { if (android::base::ReadFileToString(path, &content) && (content.find("opporeserve.sys.custom.recovery.forbidden=1") != std::string::npos)) { printf("found forbidden recovery prop in %s! \n", path.c_str()); return true; } /* if (android::base::ReadFileToString(reserve2_property_path, &content) && (content.find("opporeserve.sys.custom.recovery.forbidden=1") != std::string::npos)) { printf("reserve found forbidden recovery prop! \n"); return true; }*/ //break; //} //} } printf("no forbidden prop found in reserve!\n"); return false; } //end of Start specific code //#endif /* VENDOR_EDIT */ int format_volume(const std::string& volume, const std::string& directory, std::string_view new_fstype) { const FstabEntry* v = android::fs_mgr::GetEntryForPath(&fstab, volume); if (v == nullptr) { LOG(ERROR) << "unknown volume \"" << volume << "\""; return -1; } if (v->fs_type == "ramdisk") { LOG(ERROR) << "can't format_volume \"" << volume << "\""; return -1; } if (v->mount_point != volume) { LOG(ERROR) << "can't give path \"" << volume << "\" to format_volume"; return -1; } if (ensure_path_unmounted(volume) != 0) { LOG(ERROR) << "format_volume: Failed to unmount \"" << v->mount_point << "\""; return -1; } if (v->fs_type != "ext4" && v->fs_type != "f2fs") { LOG(ERROR) << "format_volume: fs_type \"" << v->fs_type << "\" unsupported"; return -1; } bool needs_casefold = false; if (volume == "/data") { needs_casefold = android::base::GetBoolProperty("external_storage.casefold.enabled", false); } int64_t length = 0; if (v->length > 0) { length = v->length; } else if (v->length < 0) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDONLY)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; return -1; } length = get_file_size(fd.get(), -v->length); if (length <= 0) { LOG(ERROR) << "get_file_size: invalid size " << length << " for " << v->blk_device; return -1; } } // If the raw disk will be used as a metadata encrypted device mapper target, // next boot will do encrypt_in_place the raw disk. While fs_mgr mounts /data // as RO to avoid write file operations before encrypt_inplace, this code path // is not well tested so we would like to avoid it if possible. For safety, // let vold do the formatting on boot for metadata encrypted devices, except // when user specified a new fstype. Because init formats /data according // to fstab, it's difficult to override the fstab in init. if (!v->metadata_key_dir.empty() && length == 0 && new_fstype.empty()) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDWR)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; return -1; } int64_t device_size = get_file_size(fd.get(), 0); if (device_size > 0 && !wipe_block_device(fd.get(), device_size)) { LOG(INFO) << "format_volume: wipe metadata encrypted " << v->blk_device << " with size " << device_size; return 0; } } if ((v->fs_type == "ext4" && new_fstype.empty()) || new_fstype == "ext4") { LOG(INFO) << "Formatting " << v->blk_device << " as ext4"; static constexpr int kBlockSize = 4096; std::vector<std::string> mke2fs_args = { "/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize), }; // Following is added for Project ID's quota as they require wider inodes. // The Quotas themselves are enabled by tune2fs on boot. mke2fs_args.push_back("-I"); mke2fs_args.push_back("512"); if (v->fs_mgr_flags.ext_meta_csum) { mke2fs_args.push_back("-O"); mke2fs_args.push_back("metadata_csum"); mke2fs_args.push_back("-O"); mke2fs_args.push_back("64bit"); mke2fs_args.push_back("-O"); mke2fs_args.push_back("extent"); } int raid_stride = v->logical_blk_size / kBlockSize; int raid_stripe_width = v->erase_blk_size / kBlockSize; // stride should be the max of 8KB and logical block size if (v->logical_blk_size != 0 && v->logical_blk_size < 8192) { raid_stride = 8192 / kBlockSize; } if (v->erase_blk_size != 0 && v->logical_blk_size != 0) { mke2fs_args.push_back("-E"); mke2fs_args.push_back( android::base::StringPrintf("stride=%d,stripe-width=%d", raid_stride, raid_stripe_width)); } mke2fs_args.push_back(v->blk_device); if (length != 0) { mke2fs_args.push_back(std::to_string(length / kBlockSize)); } int result = exec_cmd(mke2fs_args); if (result == 0 && !directory.empty()) { std::vector<std::string> e2fsdroid_args = { "/system/bin/e2fsdroid", "-e", "-f", directory, "-a", volume, v->blk_device, }; result = exec_cmd(e2fsdroid_args); } if (result != 0) { PLOG(ERROR) << "format_volume: Failed to make ext4 on " << v->blk_device; return -1; } return 0; } // Has to be f2fs because we checked earlier. LOG(INFO) << "Formatting " << v->blk_device << " as f2fs"; static constexpr int kSectorSize = 4096; std::vector<std::string> make_f2fs_cmd = { "/system/bin/make_f2fs", "-g", "android", }; make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("project_quota,extra_attr"); if (needs_casefold) { make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("casefold"); make_f2fs_cmd.push_back("-C"); make_f2fs_cmd.push_back("utf8"); } if (v->fs_mgr_flags.fs_compress) { make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("compression"); make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("extra_attr"); } make_f2fs_cmd.push_back(v->blk_device); if (length >= kSectorSize) { make_f2fs_cmd.push_back(std::to_string(length / kSectorSize)); } if (exec_cmd(make_f2fs_cmd) != 0) { PLOG(ERROR) << "format_volume: Failed to make_f2fs on " << v->blk_device; return -1; } if (!directory.empty()) { std::vector<std::string> sload_f2fs_cmd = { "/system/bin/sload_f2fs", "-f", directory, "-t", volume, v->blk_device, }; if (exec_cmd(sload_f2fs_cmd) != 0) { PLOG(ERROR) << "format_volume: Failed to sload_f2fs on " << v->blk_device; return -1; } } return 0; } int format_volume(const std::string& volume) { return format_volume(volume, "", ""); } int setup_install_mounts() { if (fstab.empty()) { LOG(ERROR) << "can't set up install mounts: no fstab loaded"; return -1; } for (const FstabEntry& entry : fstab) { // We don't want to do anything with "/". if (entry.mount_point == "/") { continue; } if (entry.mount_point == "/tmp" || entry.mount_point == "/cache") { if (ensure_path_mounted(entry.mount_point) != 0) { LOG(ERROR) << "Failed to mount " << entry.mount_point; return -1; } } else { if (ensure_path_unmounted(entry.mount_point) != 0) { LOG(ERROR) << "Failed to unmount " << entry.mount_point; return -1; } } } return 0; } bool HasCache() { CHECK(!fstab.empty()); static bool has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; return has_cache; } 总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件,例如 修改前: "1. my_product: +730.66MB 2. my_product/app: +322.14MB 3. my_product/priv-app: +277.58MB 4. my_product/del-app-pre: +193.83MB 5. my_product/priv-app/GoogleVelvet_CTS: +187.39MB" 修改后: 1. my_product/priv-app/GoogleVelvet_CTS: +187.39MB"

etc/init.rc: mkdir nuovo 0770 system system mount ext4 /dev/block/mmcblk0p1 /nuovo recovery_main.cpp: if (forbiddenRecoveryByReserveProperty()){ device->RemoveMenuItemForAction(Device::REBOOT_BOOTLOADER); device->RemoveMenuItemForAction(Device::ENTER_FASTBOOT); device->RemoveMenuItemForAction(Device::APPLY_ADB_SIDELOAD); device->RemoveMenuItemForAction(Device::APPLY_SDCARD); device->RemoveMenuItemForAction(Device::WIPE_DATA); device->RemoveMenuItemForAction(Device::WIPE_CACHE); device->RemoveMenuItemForAction(Device::MOUNT_SYSTEM); device->RemoveMenuItemForAction(Device::VIEW_RECOVERY_LOGS); device->RemoveMenuItemForAction(Device::RUN_GRAPHICS_TEST); device->RemoveMenuItemForAction(Device::RUN_LOCALE_TEST); } recovery_utils/include/recovery_utils/roots.h: bool forbiddenRecoveryByReserveProperty(); recovery_utils/roots.cpp: bool forbiddenRecoveryByReserveProperty() { std::string content; std::string reserve2_property_path; //Fstab defFstab; /*if (!ReadDefaultFstab(&defFstab)) { printf("Failed to read default fstab productinfo\n"); return false; }*/ //for (size_t i = 0; i < defFstab.size(); ++i) { //const auto& entry = defFstab[i]; //std::string::size_type pos = entry.blk_device.find("productinfo"); //if ((pos != std::string::npos) && (ensure_path_mounted(entry.mount_point.c_str()) == 0)) { //printf("mount productinfo success,mount point is %s \n", entry.mount_point.c_str()); reserve2_property_path = "/nuovo/productinfo/nuovo_forbidden_recovery.prop"; if (android::base::ReadFileToString(reserve2_property_path, &content) && (content.find("opporeserve.sys.custom.recovery.forbidden=1") != std::string::npos)) { printf("reserve found forbidden recovery prop! \n"); return true; } //break; //} //} printf("no forbidden prop found in reserve!\n"); return false; } services/core/java/com/android/server/am/OomAdjuster.java: if(app.processName!=null && (app.processName.contains("com.oplus.autotest") || app.processName.contains("com.oppo.autotest") || app.processName.contains("com.promobitech.nuovo"))){ app.mState.setCurAdj(ProcessList.FOREGROUND_APP_ADJ); } / services/java/com/android/server/SystemServer.java: t.traceBegin("MakeOplusCustomizeService Ready"); try{ Slog.i(TAG, "OplusCustomizeService Service"); OplusCustomizeService.getInstance().systemReady(); }catch (Throwable e){ reportWtf("starting OplusCustomizeService ready", e); } t.traceEnd();这是Nuovo禁止recovery需求的修改代码,解析一下,如果下载乃dlc需要同样需求怎么实现 frameworks/base/services/core/java/com/android/server/OplusCustomizeService.java: private static final String TAG = "OplusCustomizeService"; private static OplusCustomizeService sInstance = null; private static boolean DEBUG = false; private Context mContext; private static final String PKGNAME_LOCKASSISTANT = "com.coloros.lockassistant"; private static final String PKGNAME_PAYJOY = "com.payjoy.status"; private static final String PKGNAME_NUOVO = "com.promobitech.nuovo"; private static final String SIM_UNLOCK_TIME_FLAG_FILE = "/mnt/vendor/productinfo/" + "unlock_time.cfg"; private static final String DISABLE_LOCKASSISTANT_FLAG_FILE = "/mnt/vendor/productinfo/" + "disable_lockassistant.cfg"; private static final String INTENT_ACTION_SIM_UNLOCK_DISABLE_TIMER = "oplus.action.sim.unlock.disable.timer"; private static final String DISABLE_LOCKASSISTANT = "disable"; private static final String CUSTOM_FORBIDDEN_RECOVERY_FLAG_FILE = "/mnt/vendor/productinfo/custom_forbidden_recovery.prop"; private static final String NUOVO_FORBIDDEN_RECOVERY_FLAG_FILE = "/mnt/vendor/productinfo/nuovo_forbidden_recovery.prop"; private static final String DISALLOW_RECOVERY_CONFIG = "opporeserve.sys.custom.recovery.forbidden=1"; private static final String ALLOW_RECOVERY_CONFIG = "opporeserve.sys.custom.recovery.forbidden=0"; private static final String APP_FEATURE_DISALLOW_RECOVERY_PACKAGES = "oplus_device_owner_disallow_recovery_packages"; private static final long ONE_DAY_MILLIS_SECONDS = 24 * 60 * 60 * 1000; private static final int LIMIT_DAYS = 7; private static final int FEESTATE_UNLOCKED = 5; private static final int SIM_UNLOCKED = 6; private IntentFilter mIntentSimUnlockFilter; private SimUnlockReceiver mSimUnlockReceiver; private IntentFilter mIntentBootFilter; private BootCompleteBroadcastReceiver mBootCompleteReceiver; private PackageManager mPm; private PendingIntent mPendingIntent; private Object mObj = null; // #ifdef [email protected], added for India DLC private AirtelBroadcastReceiver airtelBroadcastReceiver; private IntentFilter mIntentairtelFilter; public static final String AIRTEL_ISLOCK_STATE = "persist.sys.airtelstate"; private static final String REVOKE_ROLE_MANAGER_ACCESS = "revoke_role_manager_access"; private RoleManager roleManager; private final String roleNames[] = {RoleManager.ROLE_ASSISTANT,RoleManager.ROLE_BROWSER,RoleManager.ROLE_DIALER,RoleManager.ROLE_SMS, RoleManager.ROLE_EMERGENCY,RoleManager.ROLE_HOME,RoleManager.ROLE_CALL_REDIRECTION,RoleManager.ROLE_CALL_SCREENING}; // endif public OplusCustomizeService() { } public void systemReady(){ try { initRecoveryConfig(); LocalServices.getService(UserManagerInternal.class) .addUserRestrictionsListener(mUserRestrictionsListener); }catch (Exception e) { Slog.e(TAG, "systemReady error:" + e.toString()); } } private final UserRestrictionsListener mUserRestrictionsListener = new UserRestrictionsListener() { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { DevicePolicyManager devicePolicyManager = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); boolean isNuovo = SystemProperties.getBoolean("persist.sys.oppo.nuovo", false); Slog.d(TAG," gaojie DISALLOW_FACTORY_RESET result" +isNuovo); if (isNuovo) { //合约到期 nuovo不是device owner 不启用禁止recovery功能 if (((devicePolicyManager != null) && !devicePolicyManager.isDeviceManaged()) || !hasNuovo()) { saveOplusFile(ALLOW_RECOVERY_CONFIG.getBytes(),NUOVO_FORBIDDEN_RECOVERY_FLAG_FILE); Slog.d(TAG," Nuovo ALLOW_RECOVERY_CONFIG " ); SystemProperties.set("persist.sys.oppo.nuovo",Boolean.toString(false)); } } else { //激活nuovo后启用禁止recovery功能 if ((devicePolicyManager != null) && (devicePolicyManager.isDeviceManaged()) && hasNuovo() && PKGNAME_NUOVO.equals(devicePolicyManager.getDeviceOwner())) { saveOplusFile(DISALLOW_RECOVERY_CONFIG.getBytes(),NUOVO_FORBIDDEN_RECOVERY_FLAG_FILE); SystemProperties.set("persist.sys.oppo.nuovo", Boolean.toString(true)); Slog.d(TAG," Nuovo DISALLOW_FACTORY_RESET " ); } } } }; private void initRecoveryConfig() { DevicePolicyManager devicePolicyManager = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); Slog.d(TAG, "initRecoveryConfig"); if (((devicePolicyManager != null) && !devicePolicyManager.isDeviceManaged()) || !hasNuovo()) { Slog.d(TAG, "initRecoveryConfig del"); deleteOplusFile(NUOVO_FORBIDDEN_RECOVERY_FLAG_FILE); SystemProperties.set("persist.sys.oppo.nuovo", Boolean.toString(false)); } } private final UserRestrictionsListener mUserRestrictionsListener = new UserRestrictionsListener() { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, UserManager.DISALLOW_FACTORY_RESET)) { DevicePolicyManager devicePolicyManager = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); boolean result = newRestrictions.getBoolean(UserManager.DISALLOW_FACTORY_RESET); Slog.d(TAG," gaojie DISALLOW_FACTORY_RESET result" +result); if ((devicePolicyManager != null) && (devicePolicyManager.isDeviceManaged()) && hasPayjoy() && (PKGNAME_PAYJOY.equals(devicePolicyManager.getDeviceOwner()))) { if (result) { saveOplusFile(DISALLOW_RECOVERY_CONFIG.getBytes(),CUSTOM_FORBIDDEN_RECOVERY_FLAG_FILE); Slog.d(TAG," gaojie DISALLOW_FACTORY_RESET " ); } else { saveOplusFile(ALLOW_RECOVERY_CONFIG.getBytes(),CUSTOM_FORBIDDEN_RECOVERY_FLAG_FILE); Slog.d(TAG," gaojie ALLOW_RECOVERY_CONFIG " ); } } } } };将这段改成如果存在包禁用recobery功能

使用了代码在Device Exploere 看不了data.txt .package com.example.myapplication; import android.content.Context; import android.os.Build; import android.os.Environment; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Objects; public class FileSaveQQ { public static boolean saveUserInfo(Context context, String account, String password) { FileOutputStream fos = null; String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { String SDPath ; if (Build.VERSION.SDK_INT > 29) { SDPath = context.getExternalFilesDir(null).getAbsolutePath(); } else { SDPath = Environment.getExternalStorageDirectory().getPath(); } File file = new File(SDPath, "data.txt"); try { fos = new FileOutputStream(file); fos.write((account + ":" + password).getBytes()); //将数据转换为字节码的形式写入data.txt文件中 fos.close(); } catch (Exception e) { e.printStackTrace(); } } return true; } //从data.txt文件中获取存储的QQ账号和密码 public static Map<String, String> getUserInfo(Context context) { String content = ""; FileInputStream fis = null; String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { String SDPath ; if (Build.VERSION.SDK_INT > 29) { SDPath = Objects.requireNonNull(context.getExternalFilesDir(null)).getAbsolutePath(); } else { SDPath = Environment.getExternalStorageDirectory().getPath(); } File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "data.txt"); try { fis = new FileInputStream(file); //获取文件的输入流对象fis byte[] buffer = new byte[fis.available()]; fis.read(buffer);//通过read()方法读取字节码中的数据 content = new String(buffer); //将获取的字节码转换为字符串 Map<String, String> userMap = new HashMap<String, String>(); String[] infos = content.split(":");//将字符串以“:”分隔后形成一个数组的形式 userMap.put("account", infos[0]); //将数组中的第一个数据放入userMap集合中 userMap.put("password", infos[1]); //将数组中的第二个数据放入userMap集合中 return userMap; } catch (Exception e) { e.printStackTrace(); return null; } finally { try { if (fis != null) { fis.close(); } } catch (IOException e) { e.printStackTrace(); } } } return null; } }

<activity android:name=".opp.BluetoothOppLauncherActivity" android:process="@string/process" android:theme="@android:style/Theme.Material.Light.Dialog" android:label="@string/bt_share_picker_label" android:excludeFromRecents="true" android:configChanges="orientation|keyboardHidden|screenSize" android:enabled="@bool/profile_supported_opp"> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> <data android:mimeType="video/*" /> <data android:mimeType="audio/*" /> <data android:mimeType="text/x-vcard" /> <data android:mimeType="text/x-vcalendar" /> <data android:mimeType="text/calendar" /> <data android:mimeType="text/plain" /> <data android:mimeType="text/html" /> <data android:mimeType="text/xml" /> <data android:mimeType="application/zip" /> <data android:mimeType="application/vnd.ms-excel" /> <data android:mimeType="application/msword" /> <data android:mimeType="application/vnd.ms-powerpoint" /> <data android:mimeType="application/pdf" /> <data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" /> <data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" /> <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" /> <data android:mimeType="application/x-hwp" /> <data android:mimeType="application/ogg" /> <data android:mimeType="application/mspowerpoint" /> <data android:mimeType="application/vnd.android.package-archive" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SEND_MULTIPLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> <data android:mimeType="video/*" /> <data android:mimeType="audio/*" /> <data android:mimeType="x-mixmedia/*" /> <data android:mimeType="text/x-vcard" /> <data android:mimeType="text/x-vcalendar" /> <data android:mimeType="text/plain" /> <data android:mimeType="application/zip" /> <data android:mimeType="application/msword" /> <data android:mimeType="application/vnd.ms-excel" /> <data android:mimeType="application/vnd.ms-powerpoint" /> <data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" /> <data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" /> <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" /> <data android:mimeType="application/pdf" /> <data android:mimeType="application/ogg" /> <data android:mimeType="application/mspowerpoint" /> </intent-filter> <intent-filter> <action android:name="android.btopp.intent.action.OPEN" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.item/vnd.android.btopp" /> </intent-filter> </activity>

private static List<ImportViewModel> readExcelFile() { List<ImportViewModel> datas = new ArrayList<>(); FileInputStream inputStream = null; Workbook workbook = null; try { inputStream = new FileInputStream("/sdcard/Template/IC1001.xlsx"); workbook = WorkbookFactory.create(inputStream); Sheet sheet = workbook.getSheetAt(4); Iterator<Row> rowIterator = sheet.rowIterator(); while (rowIterator.hasNext()) { Row row = rowIterator.next(); ImportViewModel importViewModel = new ImportViewModel(); Iterator<Cell> columnIterator = row.cellIterator(); while (columnIterator.hasNext()) { importViewModel.setName("商品名称:" + columnIterator.next().getStringCellValue()); importViewModel.setType("商品类型:" + columnIterator.next().getStringCellValue()); importViewModel.setStyle("商品款式:" + columnIterator.next().getStringCellValue()); importViewModel.setInventoryNum("预期应有库存:" + columnIterator.next().getStringCellValue()); datas.add(importViewModel); } } } catch (IOException | InvalidFormatException e) { e.printStackTrace(); } finally { try { if (workbook != null) { workbook.close(); } if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } return datas; }@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = findViewById(R.id.list_view); List<ImportViewModel> data = readExcelFile(); // 调用您的 readExcelFile() 方法获取数据 // ImportViewModelAdapter adapter = new ImportViewModelAdapter(data); // listView.setAdapter(adapter); RfApplication.toneGenerator = new ToneGenerator(streamType, percantageVolume);Unable to start activity ComponentInfo{com.ives.upcrfid_zebra/com.ives.upcrfid_zebra.MainActivity}: java.lang.IllegalArgumentException: Sheet index (4) is out of range (0..0)

inventoryButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (isFastClick()) { showLoadToast(); goToMainActivity(); loadExcelFile(); } } private boolean isFastClick() { return ButtonOnCilk.isFastViewClick(inventoryButton, getBaseContext()); } private void showLoadToast() { CustomToast.showLoad(HomeActivity.this, getString(R.string.load)); } private void goToMainActivity() { Intent intent = new Intent(getApplicationContext(), MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); } private void loadExcelFile() { new AsyncTask<Void, Void, List<String>>() { @Override protected List<String> doInBackground(Void... voids) { return readExcelFile(); } @Override protected void onPostExecute(List<String> data) { showDataInListView(data); } }.execute(); } private void showDataInListView(List<String> data) { listView = findViewById(R.id.rv_list); if (listView != null) { ArrayAdapter<String> adapter = new ArrayAdapter<>(HomeActivity.this, android.R.layout.simple_list_item_1, data); listView.setAdapter(adapter); } } });private List<String> readExcelFile() { List<String> datas = new ArrayList<>(); try { FileInputStream inputStream = new FileInputStream("/sdcard/Template/IC1001.xlsx"); Workbook workbook = WorkbookFactory.create(inputStream); Sheet sheet = workbook.getSheetAt(0); for (Row row : sheet) { for (Cell cell : row) { datas.add(cell.toString()); } } workbook.close(); } catch (IOException | InvalidFormatException e) { e.printStackTrace(); } return datas; }报错

#include "gd32f4xx_gpio.h" #include "gd32f4xx_rcu.h" #include "gd32f4xx_sdio.h" #include "gd32f4xx_misc.h" #include "Serial.h" #include "sdcard.h" #include "Delay.h" #include "ff.h" #include <string.h> #include <stdio.h> uint32_t SD_Get_RCA(void) { //发送 CMD3(请求分配 RCA) sdio_command_response_config(3, 0, SDIO_RESPONSETYPE_SHORT); // uint32_t timeout = 1000; // while (!sdio_flag_get(SDIO_FLAG_CMDRECV)) { // if (timeout-- == 0) { // return 0; // } // } sdio_flag_clear(SDIO_FLAG_CMDRECV); //从 RESP1 寄存器提取 RCA(高16位) uint32_t RCA = (sdio_response_get(SDIO_RESPONSE0) >> 16); return RCA; } void TF_Init() { uint32_t RCA=SD_Get_RCA(); rcu_periph_clock_enable(RCU_SDIO); rcu_periph_clock_enable(RCU_GPIOC); gpio_mode_set(GPIOC,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_9); gpio_output_options_set(GPIOC,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9); sdio_clock_config(SDIO_SDIOCLKEDGE_RISING,SDIO_CLOCKBYPASS_DISABLE,SDIO_CLOCKPWRSAVE_DISABLE,256); sdio_bus_mode_set(SDIO_BUSMODE_4BIT); sdio_clock_enable(); sdio_power_state_set(SDIO_POWER_ON); Delay_ms(2); // sdio_wait_type_set(); sdio_command_response_config(0,0,SDIO_RESPONSETYPE_NO); //发送CMD0,复位卡 while(sdio_flag_get(SDIO_FLAG_CMDSEND)==SET); sdio_command_response_config(8,0x1AA,SDIO_RESPONSETYPE_SHORT); //发送CMD8,检查电压支持 uint32_t response = sdio_response_get(SDIO_RESP0); sdio_command_response_config(55,RCA<<16,SDIO_RESPONSETYPE_SHORT); //发送CMD55,下次命令时特定应用命令 sdio_command_response_config(41,(1UL << 30) | 0x00FF8000,SDIO_RESPONSETYPE_LONG); while((response&0x80000000)==0); sdio_csm_enable(); sdio_dsm_enable(); sdio_command_response_config(2,0,SDIO_RESPONSETYPE_LONG); sdio_command_response_config(7,RCA,SDIO_RESPONSETYPE_SHORT); //发送CMD7,选择卡 sdio_command_response_config(16,512,SDIO_RESPONSETYPE_SHORT); } void TF_WriteData(uint8_t *data,uint32_t Len,uint32_t timeout,uint32_t WritAddr) { uint32_t RCA=SD_Get_RCA(); sdio_command_response_config(24,WritAddr,SDIO_RESPONSETYPE_SHORT); //CMD24单块写,CMD25多块写 sdio_wait_type_set(SDIO_WAITTYPE_NO); while(sdio_flag_get(SDIO_FLAG_CMDRECV)); sdio_flag_clear(SDIO_FLAG_CMDRECV); sdio_data_config(timeout,Len,SDIO_DATABLOCKSIZE_512BYTES); sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK,SDIO_TRANSDIRECTION_TOCARD); sdio_dma_disable(); sdio_command_response_config(13,RCA<<16,SDIO_RESPONSETYPE_SHORT); for(uint16_t i=0;i<128;i++) { sdio_data_write(*(uint32_t*)data); data+=4; } while(sdio_flag_get(SDIO_FLAG_DTEND)); sdio_flag_clear(SDIO_FLAG_DTEND); nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); nvic_irq_enable(SDIO_IRQn,2,2); sdio_interrupt_enable(SDIO_INT_DTCRCERR); sdio_interrupt_enable(SDIO_INT_FLAG_DTEND); } uint32_t TF_ReadData(uint8_t *buffer,uint32_t timeout) { uint32_t RCA=SD_Get_RCA(); sdio_command_response_config(17,RCA,SDIO_RESPONSETYPE_SHORT); //发送CMD17,读取单个块 sdio_data_config(timeout,512,SDIO_DATABLOCKSIZE_512BYTES); sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK,SDIO_TRANSDIRECTION_TOSDIO); sdio_dma_disable(); //禁用DMA,使用轮询 while (sdio_flag_get(SDIO_FLAG_RXDTVAL)==SET) //等待数据可用 for(uint16_t i=0;i<128;i++) { buffer[i]=sdio_data_read(); } while (sdio_flag_get(SDIO_FLAG_DTEND)==SET) //等待数据可用 sdio_flag_clear(SDIO_FLAG_DTEND); return *buffer; } void SDIO_IRQHandler() { if(sdio_interrupt_flag_get(SDIO_INT_FLAG_DTCRCERR)==SET) { sdio_command_response_config(12,0,SDIO_RESPONSETYPE_SHORT); } sdio_interrupt_flag_clear(SDIO_INT_FLAG_DTCRCERR); if(sdio_interrupt_flag_get(SDIO_INT_FLAG_DTEND)==SET) { TF_Init(); } sdio_interrupt_flag_clear(SDIO_INT_FLAG_DTEND); } #define CONFIG_FILE "config.ini" #define FLASH_RATIO_ADDR 0x0000 // 变比存储地址 #define FLASH_LIMIT_ADDR 0x0004 // 阈值存储地址 FATFS fs; // FatFs文件系统对象 FIL fil; // 文件对象 FRESULT fr; // 文件操作结果 // 解析配置文件 int parse_config(const char* buffer, float* ratio, float* limit) { if (buffer == NULL || ratio == NULL || limit == NULL) return 0; char *p = (char*)buffer; *ratio = 0.0f; *limit = 0.0f; int found = 0; // 查找Ratio部分 while ((p = strstr(p, "[Ratio]")) != NULL) { p += strlen("[Ratio]"); char *ch0 = strstr(p, "Ch0"); if (ch0 && sscanf(ch0, "Ch0 = %f", ratio) == 1) { found++; break; } } p = (char*)buffer; // 查找Limit部分 while ((p = strstr(p, "[Limit]")) != NULL) { p += strlen("[Limit]"); char *ch0 = strstr(p, "Ch0"); if (ch0 && sscanf(ch0, "Ch0 = %f", limit) == 1) { found++; break; } } return (found == 2); } sd_error_enum sd_init_status = SD_ERROR; // SD卡初始化状态 void update_config_from_sd(void) { FIL config_file; UINT bytes_read; char buffer[256]; float ratio = 0.0f, limit = 0.0f; // SD卡重新初始化 if(sd_init_status != SD_OK) { printf("Reinitializing SD card...\r\n"); sd_init_status = sd_init(); if(sd_init_status != SD_OK) { printf("SD init failed: %d\r\n", sd_init_status); return; } } // 挂载文件系统(带超时) FRESULT fr; uint32_t mount_timeout = 5000; do { fr = f_mount(0,&fs); // 挂载到根目录 if(fr == FR_OK) break; delay_1ms(1); } while(mount_timeout-- > 0); if(fr != FR_OK) { printf("Mount error: %d\r\n", fr); return; } printf("Filesystem mounted\r\n"); // 检查文件是否存在 - 使用绝对路径 FILINFO fno; fr = f_stat("config.ini", &fno); // 关键修复:添加根目录前缀 if(fr != FR_OK) { printf("config.ini not found! Error: %d\r\n", fr); f_mount(0, NULL); return; } // 打开文件 f_mkdir("/"); // 确保根目录存在 fr = f_open(&config_file, "config.ini", FA_READ); // 使用绝对路径 if(fr != FR_OK) { printf("File open error: %d\r\n", fr); f_mount(0, NULL); return; } // 读取文件内容 fr = f_read(&config_file, buffer, sizeof(buffer)-1, &bytes_read); if(fr != FR_OK || bytes_read == 0) { printf("Read error: %d, Bytes: %d\r\n", fr, bytes_read); f_close(&config_file); f_mount(0, NULL); return; } buffer[bytes_read] = '\0'; f_close(&config_file); printf("File content:\r\n%s\r\n", buffer); // 打印文件内容 // 解析配置 if(parse_config(buffer, &ratio, &limit)) { printf("Parsed: Ratio=%.2f, Limit=%.2f\r\n", ratio, limit); // 保存到FLASH spi_flash_sector_erase(FLASH_RATIO_ADDR); spi_flash_buffer_write((uint8_t*)&ratio, FLASH_RATIO_ADDR, sizeof(ratio)); spi_flash_sector_erase(FLASH_LIMIT_ADDR); spi_flash_buffer_write((uint8_t*)&limit, FLASH_LIMIT_ADDR, sizeof(limit)); } else { printf("Config parse failed\r\n"); } // 卸载文件系统 f_mount(0, NULL); printf("Config update complete\r\n"); } // 命令处理函数 void process_command(const char* cmd) { if (strcmp(cmd, "conf") == 0) { USART0_SendData((uint16_t*)"Updating config...\r\n", 20); update_config_from_sd(); } else if (strcmp(cmd, "help") == 0) { USART0_SendData((uint16_t*)"Available commands:\r\n", 21); USART0_SendData((uint16_t*)" conf - Update config from SD card\r\n", 36); USART0_SendData((uint16_t*)" help - Show this help\r\n", 25); } else { char unknown_msg[64]; sprintf(unknown_msg, "Unknown command: %s\r\n", cmd); USART0_SendData((uint16_t*)unknown_msg, strlen(unknown_msg)); USART0_SendData((uint16_t*)"Type 'help' for available commands\r\n", 36); } } FATFS fs; FIL current_log_file, current_sample_file, current_overlimit_file, current_hidedata_file; uint8_t log_file_open = 0, sample_file_open = 0, overlimit_file_open = 0, hidedata_file_open = 0; uint32_t log_id = 0; // 辅助函数:获取日期时间字符串 void get_datetime_string(char* datetime_str) { // 需要实现RTC获取时间功能 // 格式: YYYYMMDDHHMMSS sprintf(datetime_str, "20250101120000"); // 示例 } // 辅助函数:从Flash获取下一个日志ID uint32_t get_next_log_id(void) { uint32_t id = 0; // 从Flash读取ID (地址0x2000) // spi_flash_buffer_read((uint8_t*)&id, 0x2000, 4); return id; } // 辅助函数:保存日志ID到Flash void save_log_id_to_flash(uint32_t id) { // spi_flash_sector_erase(0x2000); // spi_flash_buffer_write((uint8_t*)&id, 0x2000, 4); } // 1. 存储系统初始化 void storage_init(void) { FRESULT res; // 挂载文件系统 res = f_mount(1,&fs); if (res != FR_OK) { USART0_SendData((uint16_t*)"SD mount failed\r\n", 16); return; } // 创建存储目录 f_mkdir("sample"); f_mkdir("overLimit"); f_mkdir("log"); f_mkdir("hideData"); // 初始化日志ID log_id = get_next_log_id(); // 创建日志文件 char log_filename[32]; sprintf(log_filename, "log/log%u.txt", log_id); res = f_open(¤t_log_file, log_filename, FA_CREATE_ALWAYS | FA_WRITE); if (res == FR_OK) { log_file_open = 1; // 更新日志ID并保存 save_log_id_to_flash(log_id + 1); } } void log_operation(const char* operation) { if (!log_file_open) return; char datetime_str[16]; get_datetime_string(datetime_str); char log_entry[128]; sprintf(log_entry, "[%s] %s\r\n", datetime_str, operation); UINT bytes_written; f_write(¤t_log_file, log_entry, strlen(log_entry), &bytes_written); f_sync(¤t_log_file); } void store_sample_data(float voltage) { if (!sample_file_open) { char datetime_str[16]; get_datetime_string(datetime_str); char filename[32]; sprintf(filename, "sample/sampleData%s.txt", datetime_str); if (f_open(¤t_sample_file, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) { sample_file_open = 1; } } if (sample_file_open) { char data_line[64]; sprintf(data_line, "%.1fV\r\n", voltage); UINT bytes_written; f_write(¤t_sample_file, data_line, strlen(data_line), &bytes_written); f_sync(¤t_sample_file); } } void store_overlimit_data(float voltage, float limit) { if (!overlimit_file_open) { char datetime_str[16]; get_datetime_string(datetime_str); char filename[32]; sprintf(filename, "overLimit/overLimit%s.txt", datetime_str); if (f_open(¤t_overlimit_file, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) { overlimit_file_open = 1; } } if (overlimit_file_open) { char data_line[64]; sprintf(data_line, "%.1fV > %.1fV\r\n", voltage, limit); UINT bytes_written; f_write(¤t_overlimit_file, data_line, strlen(data_line), &bytes_written); f_sync(¤t_overlimit_file); } } void store_hidedata(float voltage) { if (!hidedata_file_open) { char datetime_str[16]; get_datetime_string(datetime_str); char filename[32]; sprintf(filename, "hideData/hideData%s.txt", datetime_str); if (f_open(¤t_hidedata_file, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) { hidedata_file_open = 1; } } if (hidedata_file_open) { char data_line[64]; sprintf(data_line, "HIDE: %.1fV\r\n", voltage); UINT bytes_written; f_write(¤t_hidedata_file, data_line, strlen(data_line), &bytes_written); f_sync(¤t_hidedata_file); } } void save_config_to_file(float ratio, float limit) { FIL config_file; if (f_open(&config_file, "config.ini", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) { return; } char config_data[128]; sprintf(config_data, "[Ratio]\r\n" "Ch0 = %.1f\r\n" "\r\n" "[Limit]\r\n" "Ch0 = %.1f\r\n", ratio, limit); UINT bytes_written; f_write(&config_file, config_data, strlen(config_data), &bytes_written); f_close(&config_file); } // 写入Flash的辅助函数 void write_config_to_flash(float ratio, float limit) { spi_flash_sector_erase(FLASH_RATIO_ADDR); spi_flash_buffer_write((uint8_t*)&ratio, FLASH_RATIO_ADDR, sizeof(ratio)); spi_flash_sector_erase(FLASH_LIMIT_ADDR); spi_flash_buffer_write((uint8_t*)&limit, FLASH_LIMIT_ADDR, sizeof(limit)); } // 读取配置文件 void read_config_file(void) { UINT bytes_read; char buffer[256]; // 读取缓冲区 float ratio = 0.0f, limit = 0.0f; // 挂载文件系统 fr = f_mount(1,&fs); if (fr != FR_OK) { // 错误处理 return; } // 打开配置文件 fr = f_open(&fil, CONFIG_FILE, FA_READ); if (fr == FR_OK) { // 读取文件内容 fr = f_read(&fil, buffer, sizeof(buffer) - 1, &bytes_read); if (fr == FR_OK) { buffer[bytes_read] = '\0'; // 确保字符串结束 // 解析配置 if (parse_config(buffer, &ratio, &limit)) { // 写入Flash write_config_to_flash(ratio, limit); } } f_close(&fil); // 关闭文件 } } typedef enum { FR_OK = 0, /* (0) Succeeded */ FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ FR_INT_ERR, /* (2) Assertion failed */ FR_NOT_READY, /* (3) The physical drive cannot work */ FR_NO_FILE, /* (4) Could not find the file */ FR_NO_PATH, /* (5) Could not find the path */ FR_INVALID_NAME, /* (6) The path name format is invalid */ FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ FR_EXIST, /* (8) Acces denied due to prohibited access */ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ FR_NOT_ENABLED, /* (12) The volume has no work area */ FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ } FRESULT; ====system init==== conf Command received: conf Updating config from SD card... Filesystem mounted SD init success config.ini not found! Error: 3 > test Command received: test ====System selftest===== flash.......ok flash ID:0xC84013 TF card...........ok TF card memory: 30721024 KB RTC: Current time: 2025-05-01 : 08:32:47 ====system selftest==== TF卡在读卡器中识别到了相应的配置文件,优化代码,解决问题

--函数名称:my_getedataLen_Type --功能说明:获取对应数据的类型和长度 --形 参:data:待传入的数据 --返 回 值:datalen:数据的长度 data_type:数据的类型 function my_getdataLen_Type(data) local datalen = -1 local data_type = type(data) if data_type == 'number' then -- 将数字转换为字符串后再计算长度 datalen = string.len(tostring(data)) elseif data_type == 'string' then datalen = string.len(data) elseif data_type == 'table' then datalen = #data end return datalen, data_type end --函数名称:my_split --功能说明:将一个字符串按照指定的分隔符分割成多个子字符串,并将这些子字符串存储在一个表(数组)中返回。 --形 参:str:字符串 pat:分隔符 --返 回 值:返回存储所有子字符串的表 t function my_split(str, pat) local i = 1 -- 初始化计数器 i,用于记录分割后的子字符串数量 local t = {} -- 创建一个空表 t,用于存储分割后的子字符串 local last_end = 0 -- 初始化变量 last_end,记录上一个分隔符结束的位置 local s, e = string.find(str, pat, 1) -- 在字符串 str 中从位置 1 开始查找分隔符 pat,返回分隔符的起始位置 s 和结束位置 e while s -- 如果找到了分隔符(s 不为 nil) do table.insert(t, string.sub(str, last_end + 1, last_end + s - last_end - 1)) -- 截取从 last_end + 1 到分隔符起始位置 s - 1 ?淖幼址⒔洳迦氲奖?t 中 last_end = e -- 更新 last_end 为当前分隔符结束的位置 e s, e = string.find(str, pat, last_end + 1) -- 在字符串 str 中从 last_end + 1 的位置开始继续查找分隔符 pat i = i + 1 -- 增加计数器 i end if last_end <= #str --如果 last_end 小于等于字符串 str 的长度(即还有未处理的剩余部分) then cap = string.sub(str, last_end + 1) -- 截取从 last_end + 1 到字符串结尾的子字符串 table.insert(t, cap) -- 将该子字符串插入到表 t 中 end return t -- 返回存储所有子字符串的表 t end --函数名称:my_ShowRecord_FromFile --功能说明:用于处理从文件中读取的字符串数据,按行分割后,去除每行中的回车符和换行符,并在每行末尾添加分号,最后将处理后的数据添加到记录显示区域。 --形 参:mystr:读取的字符串 --返 回 值:无 function my_ShowRecord_FromFile(mystr) local line_data = my_split(mystr, '% ') -- -- 调用 my_split 函数,将 mystr 字符串按照换行符 '\n' 分割成多个子字符串,存储在 line_data 表中 for i = 1, #(line_data) -- 遍历 line_data 表中的每个元素 do if line_data[i] ~= nil -- 如果当前元素不为空 then feed_dog() -- 调用 feed_dog 函数(可能是用于防止系统“看门狗”超时等操作) -- 去除当前行数据中的回车符 ' ' 和换行符 '\n' line_data[i] = string.gsub(line_data[i], "% ", '') line_data[i] = string.gsub(line_data[i], "%\n", '') --line_data[i] = line_data[i]..';' -- 在当前行数据末尾添加分号 ';' -- 将处理后的行数据添加到记录显示区域 sc_ShowRecord 中,格式为 '$NUM;' 加上处理后的行数据 set_history_graph_value(26,6,line_data[i]) set_value(26,9,line_data[i]) end end end function my_read_filedata(file) local count = 0 --每次要读取到的字节数 local read_cnt = 0 --要读取多少次 多少块 local offset = 0 --读取偏移地址 local all_byte = 0 --要读取的所有的字节数 local read_byte_Tb = {} --用于存储从文件中读取的原始字节数据 local read_char_Tb = {} --用于将字节数据转换为字符数据 local read_str = '' --用于存储最终拼接成的字符串形式的文件内容。 local open_state = file_open(file, FA_READ) --以只读的方式进行打开 if open_state == true then set_text(26, 5, 'open on') --获取当前文件大小 all_byte = file_size() if all_byte > 0 then read_cnt = math.modf(all_byte/WriteOnceSize) --计算出完整的有多少块 if all_byte % WriteOnceSize > 0 then read_cnt = read_cnt + 1 --最后一块未满的一块 end for i = 1, read_cnt do --复位读字节数组 read_byte_Tb = {} --用于存储从文件中读取的原始字节数据 read_char_Tb = {} --用于将字节数据转换为字符数据 --计算读取的偏移位置 offset = (i - 1) * WriteOnceSize local offst_result = file_seek(offset) --文件偏移失败 if offst_result == false then set_text(26, 5, 'offest fail') break else set_text(26, 5, 'offest on') end --计算本次读的个数 count = WriteOnceSize if i == read_cnt --最后一块 then if all_byte % WriteOnceSize > 0 then count = all_byte % WriteOnceSize end end --读取字节转换为字符并拼接成字符串 read_byte_Tb = file_read(count) if #(read_byte_Tb) > 0 then set_text(26, 5, 'read ok') for j = 0, #(read_byte_Tb) do read_char_Tb[j + 1] = string.char(read_byte_Tb[j]) --将当前字节的数据转换为字符 从下标1开始 Lua 中数组索引通常从 1 开始 end read_str = read_str..table.concat(read_char_Tb) --将read_char_Tb数组中的每一个数据拼接到一个字符串中 追加到 read_str 字符串变量中,从而逐步构建完整的文件内容字符串 elseif read_byte_Tb ==nil --显示文件读取错误的提示信息,提醒用户重新尝试 then set_text(26, 5, 'read fail') break; end end my_ShowRecord_FromFile(read_str) else --区域显示文件不存在或无内容的提示信息,提醒用户检查 SD 卡中的文件 set_text(26, 5, 'dont exist') end else set_text(26, 5, 'open fail') end --关闭文件 file_close() end --函数名称:my_write_filedata --功能说明:使对应的要写入的数据的类型值 转成数值类型存到发送函数中 利用file_write() :函数进行发送 --形 参:file:文件的绝对路径 data:要写入SD卡的数据 open_mode:打开的模式 --返 回 值:无 function my_write_filedata(file, data, open_mode) local count = 0 -- 当前写入块大小(每次) local write_cnt = 0 -- 总写入次数 要写入几次才能写完 local seek_ops = 0 -- 写入偏移量 local all_byte = 0 -- 原文件大小(追加模式用) 在原有文件大小的后面进行添加 --获取待写入数据的数据类型和长度 local wrire_len, data_type = my_getdataLen_Type(data) local write_byte_Tb = {} -- 写入缓存 --打开文件 local open_state = file_open(file, open_mode) if open_state == true then set_text(28, 6, 'open on') --获取当前文件大小,仅在追加文件末尾写入执行 追加模式获取原文件大小 if open_mode == add_write then all_byte = file_size() end --若有数据要写入 if wrire_len > 0 then --计算data要写多少次 计算写入次数 也就是有多少块数据 write_cnt = math.modf(wrire_len / WriteOnceSize) if wrire_len % WriteOnceSize > 0 then write_cnt = write_cnt + 1 end --循环分块写入 for i = 1, write_cnt do --复位写字节数组 清空临时表 write_byte_Tb = {} --计算写的位置 seek_ops = (i - 1) * WriteOnceSize +all_byte local offst_result = file_seek(seek_ops) --若文件偏移失败 if offst_result == false then --提示信息 set_text(28, 6, 'offst off') break else set_text(28, 6, 'offst ok') end --计算本次写的个数(字节数) count = WriteOnceSize --当前写入块的大小 if i == write_cnt --最后一块 then if wrire_len % WriteOnceSize > 0 then count = wrire_len % WriteOnceSize --当前写入块的大小 end end --填充写入字节数组 准备写入数据 for j = 1, count do --if data_type == 'string' or data_type == 'number' if data_type == 'string' then --字符串类型,将每个字符转换为字节数组 -- 字符串转字节 --local str = (data_type == 'string') and data or tostring(data) --write_byte_Tb[j - 1] = string.byte(str, ((i - 1) * WriteOnceSize + j), ((i - 1) * WriteOnceSize + j)) --tonumber():将结果显式转换为数值类型 --字符串类型,将每个字符转换为字节数组 填写到发送函数中 write_byte_Tb[j - 1] = tonumber(string.byte(data, ((i - 1) * WriteOnceSize + j), ((i - 1) * WriteOnceSize + j))) elseif data_type == 'table' then --数组类型,字节赋值 -- 直接使用字节数组 write_byte_Tb[j - 1] = data[((i - 1) * WriteOnceSize + j)] end end -- 执行写入 local IswriteOK = file_write(write_byte_Tb) if IswriteOK == false then set_text(28, 6, 'write off') else set_text(28, 6, 'write ok') end end end else set_text(28, 6, 'open fail') end --关闭文件 file_close() end local gas =0 --保存采集到气体的浓度值 --定时回调函数,系统每隔1秒钟自动调用 function on_systick() gas= get_value(0,14) --local tabl ={} --tabl[1]=a --local str = " ".. tostring(gas) local str = tostring(gas).." " my_write_filedata(sd_dir..'/'..'1.txt', str, add_write) --读取 my_read_filedata(sd_dir..'/'..'1.txt') end 现在读写都能够正常运行 但发现了一个bug 现在sd已经有下入的浮点数数据 我想要利用函数my_read_filedata进行只读 结果是卡在一个数进行不动了 这是什么原因

/************************************************************ °æÈ¨£º2025CIMC Copyright¡£ Îļþ£ºFunction.c ×÷Õß: Lingyu Meng ƽ̨: 2025CIMC IHD-V04 °æ±¾: Lingyu Meng 2025/2/16 V0.01 original ************************************************************/ /************************* Í·Îļþ *************************/ #include “Function.h” #include “LED.h” #include “RTC.h” #include “USART0.h” #include “SPI_FLASH.h” #include “ff.h” #include “diskio.h” #include “sdcard.h” #include “sys_check.h” #include “oled.h” #include “conf_read.h” #include “ratio_set.h” #include “limit_set.h” #include “key.h” #include “adc.h” #include “RTC.h” /************************* ºê¶¨Òå *************************/ #define BUFFER_SIZE 256 #define TX_BUFFER_SIZE BUFFER_SIZE #define RX_BUFFER_SIZE BUFFER_SIZE #define FLASH_WRITE_ADDRESS 0x000000 #define FLASH_READ_ADDRESS FLASH_WRITE_ADDRESS // ²ÉÑùÖÜÆÚ³£Á¿¶¨Òå #define CYCLE_5S 1 #define CYCLE_10S 10 #define CYCLE_15S 15 // Flash´æ´¢µØÖ·¶¨Òå #define SAMPLE_CYCLE_ADDR 0x000100 /************************ ±äÁ¿¶¨Òå ************************/ uint8_t tx_buffer[TX_BUFFER_SIZE]; uint8_t rx_buffer[TX_BUFFER_SIZE]; uint16_t i = 0, count, result = 0; uint8_t is_successful = 0; //FIL fdst; UINT br, bw; BYTE buffer[128]; BYTE filebuffer[128]; typedef struct { int count; // µ±Ç°ÎļþÊý¾Ý¼ÆÊý // unsigned long datetime; // µ±Ç°ÎļþµÄʱ¼ä´Á FIL file; // µ±Ç°Îļþ¶ÔÏó } DataFileInfo; static DataFileInfo data_file_info = {0, {0}}; // È«¾Ö±äÁ¿ uint32_t sample_cycle = CYCLE_5S; // µ±Ç°²ÉÑùÖÜÆÚ£¬µ¥Î»Ãë /************************ º¯Êý¶¨Òå **********************/ ErrStatus memory_compare(uint8_t src,uint8_t dst,uint16_t length); void nvic_config(void); void write_file(void); /************************************************************ Function : System_Init Comment : ÓÃÓÚ³õʼ»¯MCU Parameter: null Return : null Author : Lingyu Meng Date : 2025-02-30 V0.1 original ************************************************************/ void System_Init(void) { systick_config(); // ʱÖÓÅäÖà nvic_config(); // ÅäÖÃÖжϿØÖÆÆ÷ KEY_Init(); // KEY³õʼ»¯ LED_Init(); USART0_Config(); // ´®¿Ú³õʼ»¯ nvic_irq_enable(USART0_IRQn, 0, 0); // ʹÄÜUSART0ÖÐ¶Ï usart_interrupt_enable(USART0, USART_INT_RBNE); // ½ÓÊÕÖжϴò¿ª ADC_port_init(); // ADC³õʼ»¯ OLED_Init(); TF_Init(); spi_flash_init(); // ³õʼ»¯SPI Flash RTC_Init(); // ´ÓFlash¶ÁÈ¡±£´æµÄ²ÉÑùÖÜÆÚ uint32_t saved_cycle; spi_flash_buffer_read((uint8_t*)&saved_cycle, SAMPLE_CYCLE_ADDR, sizeof(uint32_t)); // ÑéÖ¤¶ÁÈ¡µÄÖµÊÇ·ñÓÐЧ if (saved_cycle == CYCLE_5S || saved_cycle == CYCLE_10S || saved_cycle == CYCLE_15S) { sample_cycle = saved_cycle; printf("Loaded saved sample cycle: %d s\r\n", sample_cycle); } else { // ÎÞЧֵ£¬Ê¹ÓÃĬÈÏ5Ãë sample_cycle = CYCLE_5S; printf("Using default sample cycle: %d s\r\n", sample_cycle); // ±£´æÄ¬ÈÏÖµµ½Flash spi_flash_sector_erase(SAMPLE_CYCLE_ADDR); spi_flash_buffer_write((uint8_t*)&sample_cycle, SAMPLE_CYCLE_ADDR, sizeof(uint32_t)); } // ¶ÁÈ¡¶ÓÎé±àºÅ Team_num(); delay_1ms(10); } /************************************************************ Function : UsrFunction Comment : Óû§³ÌÐò¹¦ÄÜ Parameter: null Return : null Author : Liu Tao @ GigaDevice Date : 2025-05-10 V0.1 original ************************************************************/ void UsrFunction(void) { uint8_t sampling_enabled = 0; // ²ÉÑùʹÄܱêÖ¾ uint32_t last_sample_time = 0; // ÉϴβÉÑùʱ¼ä uint32_t last_led_toggle_time = 0; // LEDÇл»Ê±¼ä uint8_t led_state = 0; // LEDµ±Ç°×´Ì¬ // ¾²Ì¬±äÁ¿¼Ç¼°´¼üÉÏ´Î״̬£¨ÓÃÓÚ±ßÔµ¼ì²â£© static uint8_t last_key2 = 1, last_key3 = 1, last_key4 = 1; printf("====system init====\r\n"); Read_Team_num(); // ¶ÁÈ¡¶ÓÎé±àºÅ printf("\n\r====system ready====\r\n"); OLED_ShowString(0, 0, "system idle", 16); OLED_Refresh(); while (1) { uint32_t current_tick = systick_get_tick(); // ================ °´¼ü´¦Àí ================ // ¼ì²âKEY1°´ÏÂʼþ if (KEY_Stat(KEY_PORT, KEY1_PIN)) { // °´¼ü״̬·­×ª sampling_enabled = !sampling_enabled; if (sampling_enabled) { // Æô¶¯²ÉÑù printf("Output==> Periodic Sampling (Key Start)\r\n"); printf("Output==> sample cycle: %ds\r\n", sample_cycle); last_sample_time = current_tick; last_led_toggle_time = current_tick; led_state = 0; OLED_Clear(); OLED_ShowString(0, 0, "Sampling...", 16); OLED_Refresh(); } else { // Í£Ö¹²ÉÑù printf("Output==> Periodic Sampling STOP (Key Stop)\r\n"); gpio_bit_reset(GPIOA, GPIO_PIN_5); // ¹Ø±ÕLED1 OLED_Clear(); OLED_ShowString(0, 0, "system idle", 16); OLED_Refresh(); } // Ìí¼ÓÈ¥¶¶ÑÓʱ delay_1ms(50); } // ¼ì²âKEY2°´ÏÂʼþ£¨ÖÜÆÚÉèΪ5s£© uint8_t current_key2 = KEY_Stat(KEY_PORT, KEY2_PIN); if (current_key2 && !last_key2) { sample_cycle = CYCLE_5S; printf("Output==> sample cycle adjust: %ds\r\n", sample_cycle); // ±£´æµ½Flash spi_flash_sector_erase(SAMPLE_CYCLE_ADDR); spi_flash_buffer_write((uint8_t*)&sample_cycle, SAMPLE_CYCLE_ADDR, sizeof(uint32_t)); // Èç¹ûÕýÔÚ²ÉÑù£¬¸üвÉÑùʱ¼ä if (sampling_enabled) { last_sample_time = current_tick; } } last_key2 = current_key2; // ¼ì²âKEY3°´ÏÂʼþ£¨ÖÜÆÚÉèΪ10s£© uint8_t current_key3 = KEY_Stat(KEY_PORT, KEY3_PIN); if (current_key3 && !last_key3) { sample_cycle = CYCLE_10S; printf("Output==> sample cycle adjust: %ds\r\n", sample_cycle); // ±£´æµ½Flash spi_flash_sector_erase(SAMPLE_CYCLE_ADDR); spi_flash_buffer_write((uint8_t*)&sample_cycle, SAMPLE_CYCLE_ADDR, sizeof(uint32_t)); // Èç¹ûÕýÔÚ²ÉÑù£¬¸üвÉÑùʱ¼ä if (sampling_enabled) { last_sample_time = current_tick; } } last_key3 = current_key3; // ¼ì²âKEY4°´ÏÂʼþ£¨ÖÜÆÚÉèΪ15s£© uint8_t current_key4 = KEY_Stat(KEY_PORT, KEY4_PIN); if (current_key4 && !last_key4) { sample_cycle = CYCLE_15S; printf("Output==> sample cycle adjust: %ds\r\n", sample_cycle); // ±£´æµ½Flash spi_flash_sector_erase(SAMPLE_CYCLE_ADDR); spi_flash_buffer_write((uint8_t*)&sample_cycle, SAMPLE_CYCLE_ADDR, sizeof(uint32_t)); // Èç¹ûÕýÔÚ²ÉÑù£¬¸üвÉÑùʱ¼ä if (sampling_enabled) { last_sample_time = current_tick; } } last_key4 = current_key4; // ================ ´®¿ÚÃüÁî´¦Àí ================ if (cmd_ready) { cmd_ready = 0; int len = cmd_index; // ÇåÀíÃüÁîĩβµÄ¿Õ°××Ö·û while (len > 0 && (cmd_buffer[len - 1] == '\r' || cmd_buffer[len - 1] == '\n' || cmd_buffer[len - 1] == ' ')) { cmd_buffer[len - 1] = '\0'; len--; } // ²âÊÔÃüÁî if (strcmp((const char*)cmd_buffer, "test") == 0) { sys_check(); // ϵͳ×Ô¼ì } // RTCÅäÖÃÃüÁî else if (strcmp((const char*)cmd_buffer, "RTC Config") == 0) { printf("\r\nInput Datetime\r\n"); while (cmd_ready == 0) delay_1ms(10); char datetime_str[64]; strcpy(datetime_str, (const char*)cmd_buffer); cmd_ready = 0; rtc_settime(datetime_str); } // ÏÔʾµ±Ç°Ê±¼ä else if (strcmp((const char*)cmd_buffer, "RTC now") == 0) { rtc_show_time(); } // conf¼ì²â else if (strcmp((const char*)cmd_buffer, "conf") == 0) { conf(); } // ratio¼ì²â else if (strcmp((const char*)cmd_buffer, "ratio") == 0) { ratio_set(); } // limit¼ì²â else if (strcmp((const char*)cmd_buffer, "limit") == 0) { limit_set(); } // conf_read¼ì²â else if (strcmp((const char*)cmd_buffer, "conf_read") == 0) { printf("\r\nread parameters from flash\r\n"); conf_read(); } // conf_save¼ì²â else if (strcmp((const char*)cmd_buffer, "conf_save") == 0) { conf_save(); } // Æô¶¯²ÉÑùÃüÁî else if (strcmp((const char*)cmd_buffer, "start") == 0) { sampling_enabled = 1; printf("Output==> Periodic Sampling\r\n"); printf("Output==> sample cycle: %ds\r\n", sample_cycle); last_sample_time = current_tick; last_led_toggle_time = current_tick; led_state = 0; OLED_Clear(); OLED_ShowString(0, 0, "Sampling...", 16); OLED_Refresh(); } // Í£Ö¹²ÉÑùÃüÁî else if (strcmp((const char*)cmd_buffer, "stop") == 0) { if (sampling_enabled) { sampling_enabled = 0; printf("Output==> Periodic Sampling STOP\r\n"); gpio_bit_reset(GPIOA, GPIO_PIN_5); // ¹Ø±ÕLED1 OLED_Clear(); OLED_ShowString(0, 0, "system idle", 16); OLED_Refresh(); } } } // ================ ²ÉÑùÈÎÎñ ) ================ if (sampling_enabled) { // LEDÉÁ˸¿ØÖÆ£¨·Ç×èÈû·½Ê½£© if (current_tick - last_led_toggle_time >= 500) { last_led_toggle_time = current_tick; led_state = !led_state; if (led_state) { gpio_bit_set(GPIOA, GPIO_PIN_5); // LEDÁÁ } else { gpio_bit_reset(GPIOA, GPIO_PIN_5); // LEDÃð } } // ²ÉÑù¶¨Ê±£¨Ê¹Óõ±Ç°ÖÜÆÚ£© if (current_tick - last_sample_time >= sample_cycle * 1000) { // ¶ÁÈ¡RTCʱ¼ä // ¶ÁÈ¡ADCÖµ adc_flag_clear(ADC0, ADC_FLAG_EOC); while (SET != adc_flag_get(ADC0, ADC_FLAG_EOC)) {} // µÈ´ýת»»Íê³É uint16_t adc_value = ADC_RDATA(ADC0); float vol_value = adc_value * 3.3f / 4095.0f; rtc_current_time_get(&rtc_initpara); // ת»»Îª10½øÖÆ uint8_t hour = bcd_to_dec(rtc_initpara.hour); uint8_t minute = bcd_to_dec(rtc_initpara.minute); uint8_t second = bcd_to_dec(rtc_initpara.second); uint8_t year = bcd_to_dec(rtc_initpara.year); uint8_t month = bcd_to_dec(rtc_initpara.month); uint8_t day = bcd_to_dec(rtc_initpara.date); /**************** OLED?? ****************/ char time_str[16]; char volt_str[16]; sprintf(time_str, "%02u:%02u:%02u", hour, minute, second); sprintf(volt_str, "%.2f V", vol_value); OLED_Clear(); OLED_ShowString(0, 0, time_str, 16); OLED_ShowString(0, 16, volt_str, 16); OLED_Refresh(); /***************´®¿ÚÊä³ö****************/ printf("20%02u-%02u-%02u %02u:%02u:%02u %.2fV\r\n", year, month, day, hour, minute, second, vol_value); /*************** ´æ´¢Êý¾Ý *************** int count; // µ±Ç°ÎļþÊý¾Ý¼ÆÊý unsigned long datetime; // µ±Ç°ÎļþµÄʱ¼ä´Á FIL file; // µ±Ç°Îļþ¶ÔÏóDataFileInfo data_file_info = {0, 0, {0}};*/ FRESULT res; FATFS fs; char dir_path[] = "0:/sample"; // Ä¿±êĿ¼ char filename[64]; if (data_file_info.count == 0) { //³õʼ»¯´æ´¢É豸 DSTATUS status = disk_initialize(0); if (status != 0) { printf("Disk initialize failed. Status: 0x%02X\n", status); return; } //¹ÒÔØÎļþϵͳ res = f_mount(0, &fs); if (res != FR_OK) { printf("Mount failed=%d\n", res); return; } // ¹Ø±Õ֮ǰ´ò¿ªµÄÎļþ if (data_file_info.file.fs) { f_close(&data_file_info.file); } //È·±£Ä¿±êĿ¼´æÔÚ FILINFO fno; res = f_stat(dir_path, &fno); if (res == FR_NO_FILE) { // Ŀ¼²»´æÔÚ res = f_mkdir(dir_path); // ´´½¨Ä¿Â¼ if (res != FR_OK) { printf("Ŀ¼´´½¨Ê§°Ü %s: %d\n", dir_path, res); return; } } else if (res != FR_OK) { printf("Ŀ¼·ÃÎÊ´íÎó: %d\n", res); return; } // Éú³É´øÂ·¾¶µÄÎļþÃû snprintf(filename, sizeof(filename), "%s/sampleDeta20%02d%02d%02d%02d%02d%02d.txt", dir_path, year, month, day, hour, minute, second); // ´´½¨ÐÂÎļþ res = f_open(&data_file_info.file, filename, FA_CREATE_ALWAYS | FA_WRITE); if (res != FR_OK) { printf("Îļþ´´½¨Ê§°Ü %s: %d\n", filename, res); // return; }else{ printf(“Îļþ´´½¨³É¹¦”); f_open(&data_file_info.file, filename, FA_CREATE_ALWAYS | FA_WRITE); } } // дÈëÊý¾Ý char data_line[50]; snprintf(data_line, sizeof(data_line), "20%02d-%02d-%02d %02d:%02d:%02d %.2f V\r\n", year, month, day, hour, minute, second, vol_value); UINT bw; // f_open(&data_file_info.file, filename, FA_CREATE_ALWAYS | FA_WRITE); res = f_write(&data_file_info.file, data_line, strlen(data_line), &bw); // f_close(&data_file_info.file); // f_mount(0, NULL);//Ð¶ÔØÎļþϵͳ if (res != FR_OK || bw != strlen(data_line)) { printf(“Êý¾ÝдÈëʧ°Ü: %d\n”, res); } else { f_sync(&data_file_info.file); data_file_info.count++; // ´ïµ½10ÌõÊý¾ÝºóÖØÖà if (data_file_info.count >= 10) { data_file_info.count = 0; f_mount(0, NULL);//Ð¶ÔØÎļþϵͳ } } last_sample_time = current_tick; } } else { // ¿ÕÏÐ״̬ÏÂÌí¼ÓСÑÓʱ delay_1ms(10); } } } void nvic_config(void) { nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3); // ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é nvic_irq_enable(SDIO_IRQn, 0, 0); // ʹÄÜSDIOÖжϣ¬ÓÅÏȼ¶Îª0 } /* ͨ¹ý´®¿ÚÊäÈëдÈëÎļþ */ void write_file(void) { printf(“Input data (press Enter to save):\r\n”); uint16_t index = 0; while(1){ if(usart_flag_get(USART0, USART_FLAG_RBNE) != RESET){ char ch = usart_data_receive(USART0); // Èç¹û½ÓÊÕ»º³åÇø·Ç¿Õ£¬´ÓUSART0½ÓÊÕÒ»¸ö×Ö·û if(ch == '\r'){ // ¼ì²é½ÓÊÕµ½µÄ×Ö·ûÊÇ·ñΪ»Ø³µ¼ü£¨'\r'£© filebuffer[index] = '\0'; // Èç¹ûÊǻسµ¼ü£¬ÔÚµ±Ç°Î»ÖÃÌí¼Ó×Ö·û´®½áÊø·û '\0' break; // Ìø³öÑ­»·£¬½áÊøÊý¾Ý½ÓÊÕ } filebuffer[index++] = ch; // ´æ´¢½ÓÊÕµ½µÄ×Ö·û if(index >= sizeof(filebuffer)-1) break; // Èç¹û»º³åÇøÂúÔò½áÊø½ÓÊÕ } } } /! \brief memory compare function \param[in] src: source data pointer \param[in] dst: destination data pointer \param[in] length: the compare data length \param[out] none \retval ErrStatus: ERROR or SUCCESS / ErrStatus memory_compare(uint8_t src, uint8_t dst, uint16_t length) { while(length --){ if(*src++ != *dst++) return ERROR; } return SUCCESS; } 把 int count; // µ±Ç°ÎļþÊý¾Ý¼ÆÊý unsigned long datetime; // µ±Ç°ÎļþµÄʱ¼ä´Á FIL file; // µ±Ç°Îļþ¶ÔÏóDataFileInfo data_file_info = {0, 0, {0}};*/ FRESULT res; FATFS fs; char dir_path[] = "0:/sample"; // Ä¿±êĿ¼ char filename[64]; if (data_file_info.count == 0) { //³õʼ»¯´æ´¢É豸 DSTATUS status = disk_initialize(0); if (status != 0) { printf("Disk initialize failed. Status: 0x%02X\n", status); return; } //¹ÒÔØÎļþϵͳ res = f_mount(0, &fs); if (res != FR_OK) { printf("Mount failed=%d\n", res); return; } // ¹Ø±Õ֮ǰ´ò¿ªµÄÎļþ if (data_file_info.file.fs) { f_close(&data_file_info.file); } //È·±£Ä¿±êĿ¼´æÔÚ FILINFO fno; res = f_stat(dir_path, &fno); if (res == FR_NO_FILE) { // Ŀ¼²»´æÔÚ res = f_mkdir(dir_path); // ´´½¨Ä¿Â¼ if (res != FR_OK) { printf("Ŀ¼´´½¨Ê§°Ü %s: %d\n", dir_path, res); return; } } else if (res != FR_OK) { printf("Ŀ¼·ÃÎÊ´íÎó: %d\n", res); return; } // Éú³É´øÂ·¾¶µÄÎļþÃû snprintf(filename, sizeof(filename), "%s/sampleDeta20%02d%02d%02d%02d%02d%02d.txt", dir_path, year, month, day, hour, minute, second); // ´´½¨ÐÂÎļþ res = f_open(&data_file_info.file, filename, FA_CREATE_ALWAYS | FA_WRITE); if (res != FR_OK) { printf("Îļþ´´½¨Ê§°Ü %s: %d\n", filename, res); // return; }else{ printf(“Îļþ´´½¨³É¹¦”); f_open(&data_file_info.file, filename, FA_CREATE_ALWAYS | FA_WRITE); } } // дÈëÊý¾Ý char data_line[50]; snprintf(data_line, sizeof(data_line), "20%02d-%02d-%02d %02d:%02d:%02d %.2f V\r\n", year, month, day, hour, minute, second, vol_value); UINT bw; // f_open(&data_file_info.file, filename, FA_CREATE_ALWAYS | FA_WRITE); res = f_write(&data_file_info.file, data_line, strlen(data_line), &bw); // f_close(&data_file_info.file); // f_mount(0, NULL);//Ð¶ÔØÎļþϵͳ if (res != FR_OK || bw != strlen(data_line)) { printf(“Êý¾ÝдÈëʧ°Ü: %d\n”, res); } else { f_sync(&data_file_info.file); data_file_info.count++; // ´ïµ½10ÌõÊý¾ÝºóÖØÖà if (data_file_info.count >= 10) { data_file_info.count = 0; f_mount(0, NULL);//Ð¶ÔØÎļþϵͳ } }封装起来,void write_data_to_file(const char* dir_path, int year, int month, int day, int hour, int minute, int second, float vol_value),只需要封装起来,不要改这里面的程序,一点也不要改,因为测试他没有错

大家在看

recommend-type

polkit-0.96-11.el6_10.2.x86_64.rpm离线升级包下载(Polkit漏洞CentOS6修复升级包)

CentOS 6.X版本专用 升级命令: rpm -Uvh polkit-0.96-11.el6_10.2.x86_64.rpm 或yum localinstall -y polkit-0.96-11.el6_10.2.x86_64.rpm 参考链接: https://ubuntu.com/security/CVE-2021-4034 https://access.redhat.com/security/cve/CVE-2021-4034 https://security-tracker.debian.org/tracker/CVE-2021-4034 https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt
recommend-type

ray-optics:光学系统的几何光线追踪

射线光学 安装 要使用pip安装rayoptics ,请使用 > pip install rayoptics 或者,可以使用conda从conda - forge渠道安装rayoptics > conda install rayoptics --channel conda-forge 文献资料 射线光学位于“ 成像光学设计和分析工具 RayOptics是一个Python几何光学和成像光学库。 它为分析成像和相干光学系统提供了几何射线追踪基础。 在此基础上提供了许多标准的几何分析选项,例如横向射线和波前像差分析。 y-ybar图和镜头布局视图中近轴光线的图形编辑也支持光学系统的近轴布局。 支持导入Zemax .zmx和CODEV .seq文件。 RayOptics可用于Python脚本,Python和IPython外壳,Jupyter笔记本以及基于Qt的图形用户界面应用程序中。 笔记 该项
recommend-type

微信qq浏览器打开提示

自己的域名总是被举报,变红?搞一个遮罩呗! 跳转浏览器提示就OK了,亲测在PHP网站完美使用。 1.上传插件整个文件夹到/public目录。得到:/public/WxqqJump 2.修改/public/index.php文件。在第一行&lt;?php下新增代码 当不再使用或者需要临时关闭跳转时,只需//注销该行代码即可。
recommend-type

扑翼无人机准定常空气动力学及控制Matlab代码.rar

1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 5.作者介绍:某大厂资深算法工程师,从事Matlab算法仿真工作10年;擅长智能优化算法、神经网络预测、信号处理、元胞自动机等多种领域的算法仿真实验,更多仿真源码、数据集定制私信+。
recommend-type

Pixhawk4飞控驱动.zip

已安装成功

最新推荐

recommend-type

spring-webflux-5.0.0.M5.jar中文文档.zip

1、压缩文件中包含: 中文文档、jar包下载地址、Maven依赖、Gradle依赖、源代码下载地址。 2、使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 3、特殊说明: (1)本文档为人性化翻译,精心制作,请放心使用; (2)只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; (3)不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 4、温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件。 5、本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册。
recommend-type

美国国际航空交通数据分析报告(1990-2020)

根据给定的信息,我们可以从中提取和分析以下知识点: 1. 数据集概述: 该数据集名为“U.S. International Air Traffic data(1990-2020)”,记录了美国与国际间航空客运和货运的详细统计信息。数据集涵盖的时间范围从1990年至2020年,这说明它包含了长达30年的时间序列数据,对于进行长期趋势分析非常有价值。 2. 数据来源及意义: 此数据来源于《美国国际航空客运和货运统计报告》,该报告是美国运输部(USDOT)所管理的T-100计划的一部分。T-100计划旨在收集和发布美国和国际航空公司在美国机场的出入境交通报告,这表明数据的权威性和可靠性较高,适用于政府、企业和学术研究等领域。 3. 数据内容及应用: 数据集包含两个主要的CSV文件,分别是“International_Report_Departures.csv”和“International_Report_Passengers.csv”。 a. International_Report_Departures.csv文件可能包含了以下内容: - 离港航班信息:记录了各航空公司的航班号、起飞和到达时间、起飞和到达机场的代码以及国际地区等信息。 - 航空公司信息:可能包括航空公司代码、名称以及所属国家等。 - 飞机机型信息:如飞机类型、座位容量等,这有助于分析不同机型的使用频率和趋势。 - 航线信息:包括航线的起始和目的国家及城市,对于研究航线网络和优化航班计划具有参考价值。 这些数据可以用于航空交通流量分析、机场运营效率评估、航空市场分析等。 b. International_Report_Passengers.csv文件可能包含了以下内容: - 航班乘客信息:可能包括乘客的国籍、年龄、性别等信息。 - 航班类型:如全客机、全货机或混合型航班,可以分析乘客运输和货物运输的比例。 - 乘客数量:记录了各航班或航线的乘客数量,对于分析航空市场容量和增长趋势很有帮助。 - 飞行里程信息:有助于了解国际间不同航线的长度和飞行距离,为票价设置和燃油成本分析提供数据支持。 这些数据可以用于航空客运市场分析、需求预测、收益管理等方面。 4. 数据分析和应用实例: - 航空流量分析:通过分析离港航班数据,可以观察到哪些航线最为繁忙,哪些机场的国际航空流量最大,这有助于航空公司调整航班时刻表和运力分配。 - 市场研究:乘客数据可以揭示不同国家和地区之间的人口流动趋势,帮助航空公司和政府机构了解国际旅行市场的需求变化。 - 飞机利用率:结合飞机机型和飞行频率信息,可以对特定机型的使用率进行分析,评估飞机维护需求和燃油效率。 - 安全监管:通过对比不同航空公司和航班的安全记录,监管机构可以更有效地评估航空公司的安全性能,并采取必要的监管措施。 5. 技术和方法论: 分析此类数据通常涉及数据清洗、数据整合、统计分析、时间序列分析、预测建模等数据科学方法。使用Excel、SQL、R、Python等工具进行数据处理和分析是常见的做法。例如,可以使用Python的Pandas库来清洗和准备数据,使用Matplotlib和Seaborn库来可视化数据,然后利用Scikit-learn或Statsmodels库来构建预测模型。 通过以上知识点的提取和分析,我们可以理解到“U.S. International Air Traffic data(1990-2020)-数据集”的重要性,它不仅记录了跨越30年的航空交通数据,还为各种分析和应用提供了详实的基础信息。对于航空业从业者、政策制定者、研究人员以及数据分析师来说,这是一个极具价值的数据资源。
recommend-type

统计学视角:深入理解最小二乘法的概率论基础

# 1. 最小二乘法的基本概念 最小二乘法(Least Squares Method, LSM)是统计学和数据分析中广泛使用的一种数学优化技术。其主要目的是通过最小化误差的平方和来寻找数据的最佳函数匹配。这种方法最早由高斯提出,但在工程、物理、经济和其他领域中有着广泛的应用。 在本章中,我们将首先了
recommend-type

vscode中使用Codeium

<think>好的,我需要回答用户如何在VSCode中使用Codeium插件的问题。首先,我需要回顾用户提供的引用内容,看看是否有相关信息。用户提供的引用[1]提到了Codeium Chat可以解释代码中的问题,引用[2]提到了在IDEA中的一些问题,可能对VSCode的安装有帮助。用户还提到了安装步骤、基本功能、常见问题等。 首先,我应该分步骤说明安装过程,包括在VSCode扩展商店搜索Codeium并安装。然后,登录部分可能需要用户访问仪表板获取API密钥,引用[2]中提到登录问题,可能需要提醒用户注意网络或权限设置。 接下来是基本功能,比如代码自动补全和Chat功能。引用[1]提到C
recommend-type

UniMoCo:统一框架下的多监督视觉学习方法

在详细解析“unimoco”这个概念之前,我们需要明确几个关键点。首先,“unimoco”代表的是一种视觉表示学习方法,它在机器学习尤其是深度学习领域中扮演着重要角色。其次,文章作者通过这篇论文介绍了UniMoCo的全称,即“Unsupervised, Semi-Supervised and Full-Supervised Visual Representation Learning”,其背后的含义是在于UniMoCo框架整合了无监督学习、半监督学习和全监督学习三种不同的学习策略。最后,该框架被官方用PyTorch库实现,并被提供给了研究者和开发者社区。 ### 1. 对比学习(Contrastive Learning) UniMoCo的概念根植于对比学习的思想,这是一种无监督学习的范式。对比学习的核心在于让模型学会区分不同的样本,通过将相似的样本拉近,将不相似的样本推远,从而学习到有效的数据表示。对比学习与传统的分类任务最大的不同在于不需要手动标注的标签来指导学习过程,取而代之的是从数据自身结构中挖掘信息。 ### 2. MoCo(Momentum Contrast) UniMoCo的实现基于MoCo框架,MoCo是一种基于队列(queue)的对比学习方法,它在训练过程中维持一个动态的队列,其中包含了成对的负样本。MoCo通过 Momentum Encoder(动量编码器)和一个队列来保持稳定和历史性的负样本信息,使得模型能够持续地进行对比学习,即使是在没有足够负样本的情况下。 ### 3. 无监督学习(Unsupervised Learning) 在无监督学习场景中,数据样本没有被标记任何类别或标签,算法需自行发现数据中的模式和结构。UniMoCo框架中,无监督学习的关键在于使用没有标签的数据进行训练,其目的是让模型学习到数据的基础特征表示,这对于那些标注资源稀缺的领域具有重要意义。 ### 4. 半监督学习(Semi-Supervised Learning) 半监督学习结合了无监督和有监督学习的优势,它使用少量的标注数据与大量的未标注数据进行训练。UniMoCo中实现半监督学习的方式,可能是通过将已标注的数据作为对比学习的一部分,以此来指导模型学习到更精准的特征表示。这对于那些拥有少量标注数据的场景尤为有用。 ### 5. 全监督学习(Full-Supervised Learning) 在全监督学习中,所有的训练样本都有相应的标签,这种学习方式的目的是让模型学习到映射关系,从输入到输出。在UniMoCo中,全监督学习用于训练阶段,让模型在有明确指示的学习目标下进行优化,学习到的任务相关的特征表示。这通常用于有充足标注数据的场景,比如图像分类任务。 ### 6. PyTorch PyTorch是一个开源机器学习库,由Facebook的人工智能研究团队开发,主要用于计算机视觉和自然语言处理等任务。它被广泛用于研究和生产环境,并且因其易用性、灵活性和动态计算图等特性受到研究人员的青睐。UniMoCo官方实现选择PyTorch作为开发平台,说明了其对科研社区的支持和对易于实现的重视。 ### 7. 可视化表示学习(Visual Representation Learning) 可视化表示学习的目的是从原始视觉数据中提取特征,并将它们转换为能够反映重要信息且更易于处理的形式。在UniMoCo中,无论是无监督、半监督还是全监督学习,最终的目标都是让模型学习到有效的视觉表示,这些表示可以用于下游任务,如图像分类、目标检测、图像分割等。 ### 8. 标签队列(Label Queue) UniMoCo通过标签队列维护受监管的标签,这可能意味着对于那些半监督或全监督学习的任务,模型在进行对比学习时,会参考这些来自标签队列的数据。标签队列机制能帮助模型更好地利用有限的标注数据,增强模型的泛化能力。 ### 结论 UniMoCo的提出,以及其官方PyTorch实现的发布,将对计算机视觉领域产生深远影响。它不仅提供了一个统一的对比学习框架,使得从无监督到全监督的学习过程更加灵活和高效,而且为研究者们提供了一个强力的工具,以便更好地探索和实现各种视觉任务。UniMoCo的研究和应用前景,为机器学习尤其是深度学习在视觉领域的研究和实践提供了新的视角和可能。
recommend-type

【MATLAB算法精讲】:最小二乘法的实现与案例深度分析

# 1. 最小二乘法的基本原理 最小二乘法是一种数学优化技术,它通过最小化误差的平方和来寻找数据的最佳函数匹配。其核心思想是选择一条曲线,使得所有观察点到这条曲线的距离之和最小。这种方法广泛应用于统计学、信号处理、工程学和经济学等领域,尤其适用于需要通过一组数据点来确定函数参数的情况。 ## 1.1 统计学视角下的最小二乘法 在统计学中,最小二乘法经常用于
recommend-type

Idea使用教程+jdk配置

<think>好的,我现在需要回答用户关于IntelliJ IDEA使用教程和JDK配置方法的问题。首先,用户明确提到了参考站内引用中的内容,引用[1]和引用[2]都涉及JDK的配置步骤,但看起来这些引用内容可能来自其他问题或文档,可能与当前问题不完全相关,但用户希望我利用这些信息来组织回答。 首先,我需要确认IntelliJ IDEA配置JDK的基本步骤,并整合用户提供的引用内容。引用[1]提到选择JDK安装根目录,例如D:\develop\Java\jdk-17,这说明配置时需要定位到JDK的主目录。引用[2]则提到了通过New按钮选择JDK版本,并完成项目创建,这部分可能涉及到项目设置
recommend-type

GitHub入门实践:审查拉取请求指南

从提供的文件信息中,我们可以抽取以下知识点: **GitHub入门与Pull Request(PR)的审查** **知识点1:GitHub简介** GitHub是一个基于Git的在线代码托管和版本控制平台,它允许开发者在互联网上进行代码的托管和协作。通过GitHub,用户可以跟踪和管理代码变更,参与开源项目,或者创建自己的私有仓库进行项目协作。GitHub为每个项目提供了问题跟踪和任务管理功能,支持Pull Request机制,以便用户之间可以进行代码的审查和讨论。 **知识点2:Pull Request的作用与审查** Pull Request(PR)是协作开发中的一个重要机制,它允许开发者向代码库贡献代码。当开发者在自己的分支上完成开发后,他们可以向主分支(或其他分支)提交一个PR,请求合入他们的更改。此时,其他开发者,包括项目的维护者,可以审查PR中的代码变更,进行讨论,并最终决定是否合并这些变更到目标分支。 **知识点3:审查Pull Request的步骤** 1. 访问GitHub仓库,并查看“Pull requests”标签下的PR列表。 2. 选择一个PR进行审查,点击进入查看详细内容。 3. 查看PR的标题、描述以及涉及的文件变更。 4. 浏览代码的具体差异,可以逐行审查,也可以查看代码变更的概览。 5. 在PR页面添加评论,可以针对整个PR,也可以针对特定的代码行或文件。 6. 当审查完成后,可以提交评论,或者批准、请求修改或关闭PR。 **知识点4:代码审查的最佳实践** 1. 确保PR的目标清晰且具有针对性,避免过于宽泛。 2. 在审查代码时,注意代码的质量、结构以及是否符合项目的编码规范。 3. 提供建设性的反馈,指出代码的优点和需要改进的地方。 4. 使用清晰、具体的语言,避免模糊和主观的评论。 5. 鼓励开发者间的协作,而不是单向的批评。 6. 经常审查PR,以避免延迟和工作积压。 **知识点5:HTML基础** HTML(HyperText Markup Language)是用于创建网页的标准标记语言。它通过各种标签(如`<p>`用于段落,`<img>`用于图片,`<a>`用于链接等)来定义网页的结构和内容。HTML文档由元素组成,这些元素通过开始标签和结束标签来标识。例如,`<p>This is a paragraph.</p>`。HTML的最新版本是HTML5,它引入了许多新的元素和API,增强了对多媒体、图形和本地存储的支持。 **知识点6:GitHub Pages功能介绍** GitHub Pages是一个静态站点托管服务,允许用户直接从GitHub仓库中发布个人、组织或项目的网站。你可以通过设置一个专门的分支来存放你的网站源代码,然后利用GitHub Pages的设置选项,选择分支并发布你的网站。发布的网站将可以通过一个自定义的URL访问,这个URL通常是`username.github.io/repo-name`的格式。这为开发者提供了一个简单而快速的方法来搭建个人或项目的展示页面。 **知识点7:简单的游戏开发实践** 文件描述中提到了一个基于项目的学习活动,通过游戏的形式,让入门人员体验操作和理解基本的游戏开发概念。在这个活动中,参与者通过键盘操作控制形状的旋转和移动,目标是创建无空隙的完整行,这涉及到游戏逻辑、用户输入处理和图形界面显示等基础知识。该活动可能使用了HTML、JavaScript和CSS等前端技术实现,参与者通过实践操作来学习如何编程,并理解基本的游戏设计原理。
recommend-type

【R语言高级教程】:最小二乘法从入门到精通

# 1. 最小二乘法的理论基础 最小二乘法是数学优化技术之一,广泛应用于统计学、数据分析和工程学等领域。其核心思想在于找到一条直线(或曲线),使得所有观测点到该直线的垂直距离之和最小,即误差平方和最小。这一方法不仅简单易行,而且可以有效减少异常值对模型的影响,使得参数估计更加稳定。 ## 1.1 最小二乘法的数学表述 在最基本的线性回归模型中,最小二乘法通过最小化误差的平方和来寻找最
recommend-type

cadence画PCB时改变线长

<think>好的,我现在需要帮助用户解决在Cadence PCB设计中调整走线长度的问题。首先,我得回想一下用户提到的引用内容,尤其是引用1、2和3,里面提到了实时显示走线长度、约束导向设计以及过孔对长度的影响。用户可能已经知道如何显示长度,现在想知道如何调整它们。 用户的问题是如何调整走线长度以满足特定需求,比如等长布线或时序要求。我应该先分步骤说明不同的调整方法,比如手动调整、使用自动优化工具、蛇形走线,以及设置约束管理器中的规则。 记得引用中的信息,比如引用2提到的约束导向环境和实时长度显示,所以需要提到约束管理器的使用。引用3讨论了过孔对长度的影响,调整过孔数量可能也是一种方法。