<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:wfw="http://wellformedweb.org/CommentAPI/">
<channel>
<title>小夏的猪窝 - 笔记</title>
<link>https://blog.x-tools.top/category/MarkDown/</link>
<atom:link href="https://blog.x-tools.top/feed/category/MarkDown/" rel="self" type="application/rss+xml" />
<language>zh-CN</language>
<description>这里是笔记存放的地方！</description>
<lastBuildDate>Sun, 12 Jan 2025 09:27:00 +0000</lastBuildDate>
<pubDate>Sun, 12 Jan 2025 09:27:00 +0000</pubDate>
<item>
<title>Auto_Si9000 阻抗计算神器，让 PCB 设计效率飙升！</title>
<link>https://blog.x-tools.top/archives/103/</link>
<guid>https://blog.x-tools.top/archives/103/</guid>
<pubDate>Sun, 12 Jan 2025 09:27:00 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[前言该项目的上篇文章是：关于SI9000计算阻抗接口的研究；上篇讲解了Si9000的接口调用，可以被任何高级编程语言使用，如上篇文章中的Python；本篇发布前，本人也使用Python写了6个常...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h2>前言</h2><p>该项目的上篇文章是：<a href="https://blog.x-tools.top/archives/98/">关于SI9000计算阻抗接口的研究</a>；<br>上篇讲解了Si9000的接口调用，可以被任何高级编程语言使用，如上篇文章中的Python；<br>本篇发布前，本人也使用Python写了6个常见的模型，包括正算、反算，但由于Python的UI方面没有过多的知识储备，<br>导致Python始终是使用命令行终端来呈现的... 总之难用就对了，而且终端的话无法做到批量的数据正算、反算；<br>这里也放出Python的GitHub项目地址：<a href="https://github.com/XiaM-Admin/Auto_Si9000_Py">Auto_Si9000_Py</a>，仅供学习参考；<br>以上这就是我转换到.NET C# WPF编写的原因；</p><h2>Auto_Si9000 功能</h2><p>1、支持常见的8个阻抗模型：<br>外层单线不对地,外层单线对地,<br>内层单线不对地,内层单线对地,<br>外层双线不对地,外层双线对地,<br>内层双线不对地,内层双线对地；</p><p>2、支持批量阻抗的正算、反算；</p><p>3、支持生成原生的Si9000软件界面的预览图，并支持复制到剪贴板；<br>预览图中还圈出了重要的数据，如线宽、线距、对地数据，用于EQ的建议；</p><h2>软件截图</h2><p>程序主界面：<br><img src="https://image.180402.xyz/2025/01/12/678389db06bbd.png" alt="1736673754308.png" title="1736673754308.png"></p><p>预览界面：<br><img src="https://image.180402.xyz/2025/01/12/678389f5d6580.png" alt="1736673781214.png" title="1736673781214.png"></p><p>支持复制到剪贴板：<br><img src="https://image.180402.xyz/2025/01/12/67838a24dc27b.png" alt="1736673828246.png" title="1736673828246.png"></p><h2>项目地址</h2><p><a href="https://github.com/XiaM-Admin/Auto_Si9000_WPF"><a href="https://github.com/XiaM-Admin/Auto_Si9000_WPF">https://github.com/XiaM-Admin/Auto_Si9000_WPF</a></a><br>如果帮助到你，可以点一个小小的Star哦~</p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/103/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>关于SI9000计算阻抗接口的研究</title>
<link>https://blog.x-tools.top/archives/98/</link>
<guid>https://blog.x-tools.top/archives/98/</guid>
<pubDate>Tue, 26 Nov 2024 01:50:24 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[开篇在PCB设计中，阻抗控制主要是指控制信号线的特性阻抗，使其与传输线或连接设备的阻抗匹配，以确保信号在传输过程中不产生过多的反射和损耗，常用于传输线的设计中。上述的重点就是阻抗匹配，客户端若在...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h2>开篇</h2><p><font style="color:rgb(36, 41, 47);">在PCB设计中，阻抗控制主要是指控制信号线的特性阻抗，使其与传输线或连接设备的阻抗匹配，以确保信号在传输过程中不产生过多的反射和损耗，常用于传输线的设计中。上述的重点就是</font><strong><font style="color:rgb(36, 41, 47);">阻抗匹配</font></strong><font style="color:rgb(36, 41, 47);">，客户端若在PCB中存在阻抗管控的要求，需要某一段线路的阻抗在XΩ±Y%（例：50Ω±10%）的范围内，PCB厂商在生产的过程中需要尽量保证阻抗线完整、平滑。</font></p><p><font style="color:rgb(36, 41, 47);">除了在生产过程中保证应该有的质量保证，还需要在工程设计阶段对资料中阻抗线的理论阻抗值进行模拟，如果模拟的阻抗值超出客户要求的阻抗管控范围，或偏差较大时，PCB厂商通常会对阻抗线进行建议调整，以确保阻抗值在客户要求的范围内。此外PCB生产完毕后，还需要指定的阻抗条测试模块，对PCB的阻抗进行测试，此时测量出来的就是板内实际的阻抗值了。</font></p><p><font style="color:rgb(36, 41, 47);">那么，如何对阻抗进行模拟计算呢？</font></p><h2><font style="color:rgb(36, 41, 47);">Polar SI9000</font></h2><p>我们需要使用到各种阻抗模拟的软件，本文使用的软件为：<strong>Polar SI9000</strong>，SI9000是Polar公司开发的<font style="color:rgb(36, 41, 47);">一款用于PCB设计的阻抗模拟软件，可以帮助设计师精确计算和优化传输线的特性阻抗。该软件中有各种阻抗线的模拟层叠结构，常用的有单线、单线共面、双线、双线共面，以及提供了内层、外层、盖油、不盖油的几类模拟阻抗模拟计算结构；</font></p><p><font style="color:rgb(36, 41, 47);">若需要模拟阻抗，只需要选择一个符合客户资料设计的阻抗线模型，填入需要的参数后，点击Calculate(计算)即可实现对理论阻抗的模拟。接下来我们使用Coated Microstrip1B(外层单线盖油)模型来实现对阻抗的模拟计算：</font></p><p>首先，填入软件需要的参数：介质层厚度(H1)、介质层介电常数(Er1)、线路下线宽(W1)、线路上线宽(W2)、线路厚度(T1)、基材上油墨厚度(C1)、线路上基材厚度(C2)、油墨介电常数(CEr)；</p><p>这些参数根据PCB厂商总结的常规参数填入即可，其中W1与W2，阻抗线的上下线宽通常是相差1Mil（受蚀刻药水的影响），1Mil是PCB厂商的常规蚀刻要求侵蚀的量，W1-W2=1Mil；关于板材以及油墨的介电常数需要让板材、油墨供应商来提供；填完参数点计算即可出现相应的阻抗Zo值了。</p><p>以上是一个阻抗仿真的步骤，实际上操作会比文本描述更加繁琐，更何况一个PCB中常规情况下不仅仅只有1个阻抗需要管控。并且SI9000的保存做的不是很好，如果PCB的层压叠构改变，所有阻抗都需要重新计算！非常难受... 这就让我产生了对SI9000阻抗程序的研究，找到软件的接口，制作一个基于SI9000计算接口的阻抗计算项目；</p><p><img src="https://image.180402.xyz/S3/1732583638018.png" alt="" title=""></p><h2>CalcEngineBEMDll.dll</h2><p>旧版本的SI9000安装目录中，没有<strong>CalcEngineBEMDll.dll</strong>，应该是集成在软件中了，本文使用的SI9000版本是V7.1.0，其中CalcEngineBEMDll.dll版本为V3.30，PolarGraphDll.dll的版本为V1.30。</p><p>该阻抗计算软件的接口均在<strong>CalcEngineBEMDll.dll</strong>中，SI9000.exe本体就是调用dll中的开放的接口来实现阻抗值的计算。为什么？因为SI8000是SI9000的老版本，8000的安装目录中提供了两个Excel文件，分别为Si8000.xls、Si8000Expert.xls，这些Excel中的VBA代码均被加密，使用网上的破解方法进入查看工程代码后，发现表中实现阻抗值计算的方法均是来自CalcEngineBEMDll.dll，该dll使用depends.exe加载后显示存在139个方法，其中阻抗计算的方法就有95个，在depends.exe加载的dll并不能展示方法所需的参数个数、参数类型等信息，但是在SI8000的Excel中VBA工程中所有方法的参数、参数类型都在其中！</p><p>以上，我们可以知道，阻抗计算方法在DLL中，方法可以被调用，方法的传参可以参考VBA工程；但前提是，用户电脑上必须安装好SI9000软件才可以；</p><p>接下来，本文中我将使用Python对DLL中计算方法进行调用，其它的语言请读者自行尝试。</p><p><img src="https://image.180402.xyz/S3/1732583638076.png" alt="" title=""></p><h2>Python调用</h2><p>Python是一个强大的高级编程语言，简单易用，各种领域都会有它的身影，无论是大小项目，都可以使用现有的pip包轻松实现。</p><p>示例项目使用的包为Python自带的<strong>ctypes</strong>，这个项目结构如下：</p><p>|--Auto_SI9000</p><p>|----main.py &gt; 调用calcFun中的类实现阻抗值计算</p><p>|----models.py &gt; 定义一些需要使用的结构体</p><p>|----si9000.py &gt; 加载DLL，定义DLL中方法的传参及返回值</p><p>|----calcFun.py &gt; Calc类(单计算)，Calc_Plus类(多计算，继承Calc)</p><p>|---lib文件夹 &gt; 存放需加载的DLL相关文件</p><p>接下来展示一下调用DLL的简单代码流程：</p><p>1、首先调用DLL中的ClaimFlexLicence方法，认证一下产品Key（仅需要认证一次）；</p><p>2、使用IsCalculationModelAllowed方法，指定需要使用的模型并允许DLL可以准备开始计算；</p><p>3、调用计算方法CoatedMicrostrip1B方法，并传入需要前面讲到的单线模型需要的一些参数（H1、Er1等），调用完成后会立刻返回，它的返回值是int(long)类型，1或0；该方法会将传入的参数进行检查，检查后会立刻返回检查的结果，返回1，则代表计算已经开始，返回0，代表计算参数存在错误，需要重新检查参数正确性！</p><p>4、调用QueryCalculationFinished等待方法，等待计算结束；</p><p>5、使用QueryCalculationResult方法获取阻抗计算结果，该方法如果直接传入结构体，会出现写入权限限制的问题，需要将变量的地址作为参数解决该问题；</p><p>最后，结构体中的<strong>dImpedance</strong>就是结果阻抗值了！</p><p>以上的调用流程均是来自VBA工程中的，其中部分方法可以跳过，或更改流程，读者可自行尝试。</p><p><img src="https://image.180402.xyz/S3/1732583638156.png" alt="" title=""></p><h2>最后</h2><p>本文到此为止就结束了，更多的DLL方法请自行在VBA工程中解读；</p><p>该项目目前还未完成，现只提供了一个单线模型的计算方法示例；</p><p>我会在文本末尾添加上本次示例项目的下载链接（Python代码，SI9000安装包），请自行下载，感谢各位！</p><p>项目下载链接：<a href="https://image.180402.xyz/S3/Auto_SI9000%20V2.exe">https://image.180402.xyz/S3/Auto_SI9000%20V2.exe</a></p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/98/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>关于Yolo在脚本中的应用及介绍</title>
<link>https://blog.x-tools.top/archives/96/</link>
<guid>https://blog.x-tools.top/archives/96/</guid>
<pubDate>Wed, 11 Sep 2024 06:26:51 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[YOLO，全称为"You Only Look Once"，是一种实时目标检测算法。它由Joseph Redmon、Santosh Divvala、Ross Girshick和Ali Farhad...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<p>YOLO，全称为"You Only Look Once"，是一种实时目标检测算法。它由Joseph Redmon、Santosh Divvala、Ross Girshick和Ali Farhadi在2016年提出，核心在于将目标检测任务视为一个回归问题，直接从完整的输入图像中预测出边界框（bbox）和类别的概率。</p><h2>YOLO的基本原理：</h2><ol><li><strong>统一检测</strong>：YOLO摒弃了传统两阶段检测法的复杂流程，采用单阶段策略，无需生成候选区域，直接在整张图像的SxS网格上执行检测。每个网格旨在判断是否有物体存在及其中心位置是否落于该网格。</li><li><strong>边界框预测</strong>：每个网格预测B个边界框，包含物体的位置信息（x, y, width, height）及置信度分数，该分数反映框内有物体的概率及框的准确度。同时，预测C个类别概率，指明框内物体可能所属的类别。</li><li><strong>损失函数</strong>：通过一个多任务损失函数整合分类、定位及置信度的误差，以此来训练网络，优化检测性能。  <br>YOLO因其实时性和高效性，在诸如视频监控、自动驾驶、无人机等领域得到广泛应用，成为目标检测技术中的一个重要里程碑。</li></ol><h3>YOLOv8版本介绍:</h3><p>YOLOv8是YOLO（You Only Look Once）系列目标检测模型的最新版本，由 Ultralytics 团队开发。YOLO 系列因其速度与准确性平衡而广受欢迎，尤其适合实时对象检测任务。YOLOv8 在继承了前代版本优势的基础上，引入了多项改进和新特性，主要亮点包括：</p><ol><li><strong>基于PyTorch的模型架构</strong>：YOLOv8完全使用PyTorch构建，这使得模型更易于定制、调试和部署。</li><li><strong>无代码训练与推理</strong>：Ultralytics为YOLOv8提供了一个强大的命令行界面(CLI)工具，允许用户无需编写代码即可进行模型训练、微调、推理等操作，极大地降低了使用的门槛。</li><li><strong>模型优化</strong>：YOLOv8对模型架构进行了优化，引入了EfficientNet等高效网络结构作为骨干网络，提升了模型在不同尺寸目标上的检测性能，同时保持了高效的推理速度。</li><li><strong>自动注释与数据增强</strong>：集成了自动标注工具和先进的数据增强技术，帮助用户更高效地准备训练数据。</li><li><strong>多任务学习</strong>：除了基本的目标检测外，YOLOv8还支持实例分割、关键点检测等多种任务，实现了统一的模型框架处理多种计算机视觉任务。</li><li><strong>模型大小可选</strong>：YOLOv8提供了从Nano到X的大规模模型变体，用户可以根据具体需求选择合适的模型大小，平衡精度与速度。</li><li><strong>推理优化</strong>：针对推理速度进行了特别优化，支持ONNX、TensorRT、OpenVINO等多种推理加速方式，确保在各种硬件平台上都能实现快速推理。</li><li><strong>更新的损失函数与训练策略</strong>：采用更先进的损失函数和训练策略，如自适应anchors生成、更精细的梯度优化方法等，进一步提升训练效率和检测精度。  <br>总的来说，YOLOv8是一个高度优化且用户友好的目标检测框架，不仅在性能上有所提升，而且在易用性和灵活性方面也做了大量改进，非常适合研究人员和开发者用于各种计算机视觉项目。</li></ol><h2>阴阳师游戏中的实际应用场景:</h2><ol><li><p>探索任务的优化：</p><ol><li>在Buff可以实现快速检测出：经验、金币、达摩（Buff）；</li><li>同时检测出战斗标志，通过勾股定理找到Buff距离最近的战斗标志；</li><li><strong>2步骤</strong>的优化：可以检索出所有斜边的值，若在范围内，则点击战斗标志；</li><li><strong>3步骤</strong>的优化可以避免：场景内有一只需战斗的Buff怪，但没有这只怪的战斗图标时，此根据b的逻辑就会打其它不想打的Buff怪；</li></ol></li><li><p>场景识别的优化：</p><ol><li>YOLOv8有分类的功能，可以将游戏中所有场景进行归类，跑一个场景识别模型；</li><li>目前根据猜想可以训练的场景分类有：庭院、式神录、战斗场景、斗技、逢魔之时等各种场景；（本人尚未有时间实现）</li></ol></li></ol><h2>CSharp中的YOLOv8:</h2><p>YOLOv8的实现是使用YOLOv8.NET（Nuget包）来实现的；</p><p>经本人电脑测试，该包的GPU版本一致是报错（dll找不到、dll载入失败等），在CPU环境下使用YOLO会导致处理器占用急剧上升，但也还好，占用利用率差不多处于50%-70%之间（仅单线程测试）；</p><p>YOLO在脚本软件中，如果是CPU支持，还是尽量少使用模型检测；后续还是会继续研究尝试，开启GPU使用...</p><h3>关于少用YOLO模型检查，可以做到的：</h3><ul><li>在探索任务检测目标时的YOLO扫描频次减少、周期间隔增加；</li><li>在场景判断时，优先使用大漠插件判断，若没有结果则启用模型检测；</li></ul><h3>关于CSharp中多线程使用YOLO：</h3><ul><li><p>作为静态辅助类（未测试多线程占用表现）：</p><ul><li>需加锁lock使用；</li><li>多个模型切换时，可以缓存对象到本地，再次切换时直接调用缓存对象；</li></ul></li><li><p>动态实例类（未实现）：</p><ul><li>我的猜测时无需做加锁处理，因为每个实例对象均互不影响，后期做验证；</li></ul></li></ul>
]]></content:encoded>
<slash:comments>2</slash:comments>
<comments>https://blog.x-tools.top/archives/96/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>STM32 - DS18B20驱动</title>
<link>https://blog.x-tools.top/archives/77/</link>
<guid>https://blog.x-tools.top/archives/77/</guid>
<pubDate>Wed, 16 Nov 2022 10:05:00 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[&lt;!--[toc]--&gt;DS18B20简单介绍一下，查询数据手册可以知道：一个温度传感器，测量范围在-55°C ~ +125°C，仅需要单片机一个IO接口，寄生电源模式（没玩过），宽...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<p>&lt;!--[toc]--&gt;</p><h1>DS18B20</h1><p>简单介绍一下，查询数据手册可以知道：<br>一个温度传感器，<br>测量范围在<code>-55°C ~ +125°C</code>，<br>仅需要单片机一个IO接口，<br>寄生电源模式（没玩过），<br>宽电压范围 <code>+3.0V ~ +5.5V</code>。</p><h2>通信时序图</h2><p><strong>时序图</strong>：<br><img src="http://cdn.x-tools.top/MarkDownImg/2022111663695527.png" alt="" title=""><br><strong>参数表</strong>：<br><img src="http://cdn.x-tools.top/MarkDownImg/2022111663808258.png" alt="" title=""></p><p>如图有：</p><ul><li>写指令时序</li><li>读数据时序</li><li>重置重置时序</li><li>检测时序</li></ul><h3>写指令函数</h3><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111663874886.png" alt="" title=""><br>观察写指令时序图，<br>首先将电平从低拉高后等待<code>tREC</code>的时间，时间查看参数表中最小为1us，<br>最小延迟1us是为了使电平稳定。<br>延迟1-2us后，<br>将电平改变成有效数据位的高低电平后，观察时序图<code>tSLOT</code>一个周期时间在60-120us之间，所以我们延迟60us即可。<br>如部分代码(其中使用了部分宏定义，若需要更全的文件，请跳至最后下载附件即可)：</p><pre><code class="lang-C">/*******************************************************************************
  * 函数名：DS18B20_WriteByte
  * 功  能：向DS18B20写入一个字节
  * 参  数：u8Data:要写入的数据
  * 返回值：无
  * 说  明：
*******************************************************************************/
void DS18B20_WriteByte(uint8_t u8Data)
{
    uint8_t tempIndex,tempData;
    DS18B20_DQModeOutput();//设置为输出
    for (tempIndex = 1; tempIndex &lt;= 8; tempIndex++)
    {
        tempData = (u8Data &amp; 0x01);
        u8Data &gt;&gt;= 1;
        if (tempData == 1)
        {
            DS18B20_DQReset();//低电平
            delay_us(2);
            DS18B20_DQSet();//高电平
            delay_us(60);//延时60us
        }else
        {
            DS18B20_DQReset();//低电平
            delay_us(60);//延时60us
            DS18B20_DQSet();//高电平
            delay_us(2);
        }        
    }
}</code></pre><h3>读数据函数</h3><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111664447699.png" alt="" title=""><br>同样和写指令时序一样，一个周期为60us到120us内，读取电平的有效数据时间在15us内都是有效的，<br>所以选择在12us后读取数据的电平，因为一个周期还没结束，所以多等待50us结束读取。<br><strong>拉低电平 -&gt; 等待2us -&gt; 拉高电平 -&gt; 等待12us -&gt; 读取电平 -&gt; 等待50us</strong><br>部分代码(其中使用了部分宏定义，若需要更全的文件，请跳至最后下载附件即可)：</p><pre><code class="lang-C">/*******************************************************************************
  * 函数名：DS18B20_ReadByte
  * 功  能：从DS18B20读取一个字节
  * 参  数：无
  * 返回值：u8Data读出的数据
  * 说  明：无
*******************************************************************************/
uint8_t DS18B20_ReadByte(void)
{
    uint8_t i,j, u8Ddata = 0;
    
    for (i = 1; i &lt;= 8; i++)
    {        
        j = DS18B20_ReadBit();
        u8Ddata = (j &lt;&lt; 7) | (u8Ddata &gt;&gt; 1);
    }    
    return u8Ddata;
}</code></pre><h2>附件</h2><p>该附件包含：</p><ul><li>DS18B20.c 驱动文件</li><li>DS18B20.h 驱动头文件</li><li>maxim-ds18b20.pdf 传感器文档</li></ul><p>注意：此驱动使用的延迟方法利用定时器作为延迟，可自行更改。</p><p>附件：<a href="https://b.x-tools.top/typecho/uploads/2022/11/3611929055.zip">DS18B20 STM32驱动.zip</a></p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/77/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>嵌入式 - 时序图写代码</title>
<link>https://blog.x-tools.top/archives/75/</link>
<guid>https://blog.x-tools.top/archives/75/</guid>
<pubDate>Wed, 16 Nov 2022 06:27:00 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[&lt;!--[toc]--&gt;IIC，I2（方）C ，利用总线SCL、SDA，写时序读取数据时序图：datasheet总线的概念总线占两线：SCL、SDA为什么是总线：可以在总线上连接很多...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<p>&lt;!--[toc]--&gt;</p><blockquote>IIC，I2（方）C ，利用总线SCL、SDA，写时序读取数据</blockquote><p>时序图：datasheet</p><h1>总线的概念</h1><p>总线占两线：SCL、SDA</p><p>为什么是总线：可以在总线上连接很多IIC设备，这样可以节省2个io口</p><h1>从机地址</h1><p>从机地址：身份证、与生俱来，生产厂家规定</p><p>当总线发送IIC的从机地址后，此IIC设备将返回一个应答信号</p><p>从机地址是IIC设备独有的，可以可能被自己定义。</p><p>从机地址一般为7位，通常情况下（24C02举例）：</p><ul><li>前四位固定</li><li>后三位自定义</li><li><p>最后一位：方向位 控制读写</p><ul><li>为0：主机写设备操作</li><li>为1：主机读设备操作</li></ul></li></ul><p>以上8位构成了寻址字节</p><h1>寻址字节</h1><blockquote>单片机是怎么发送寻址字节</blockquote><p>IIC只有一位的数据接口，他只能一位一位的发送，所以IIC是<strong>串行发送</strong></p><ol><li>首先建立通信需要向总线发送一个从机地址，并且最后一位方向位为0</li><li>等待设备的应答信号，就能继续发送代码</li></ol><h1>观察时序 写代码 24C02</h1><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111547162589.png" style="height:130px;" /><br>上图红框中为寻址字节。</p><ul><li>中间的存储单元地址为存储器存放数据的地址</li><li>后方的数据为设备向单片机发送的数据</li></ul><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111547536418.png" style="height:330px;" /><br>上图红框部分与下图绿框部分一致。</p><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111547581705.png" alt="" title=""></p><ul><li><strong>MSB</strong>意为数据 字节最高位</li><li><strong>ACK</strong>意为应答信号</li></ul><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111547707103.png" alt="" title=""></p><h2>启动START函数</h2><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111547786735.png" alt="" title=""></p><p>带有参数的时序图</p><p><strong>首先分析启动部分（START CONDITION）：</strong></p><p><strong>SCL</strong>：保持一段时间的高电平</p><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111547862105.png" alt="" title=""></p><p><strong>SDA</strong>：</p><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111547908780.png" alt="" title=""></p><p>如图意思为，使SDA保持高电平一段时间（tCHDX）</p><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111550230692.png" alt="" title=""></p><p>这样写代码即可。</p><p>接下来继续分析SDA：</p><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111550314721.png" alt="" title=""></p><p>以上一个START启动阶段就写完了。</p><p><strong>tCHCL：高时钟脉冲宽度</strong></p><h2>寻址字节发送</h2><p>每经过一个SCL的方波周期，SDA就要发送一个数据</p><p>其SCL经过一个高脉冲信号（由低电平转为高电平），IIC设备都会检测SDA信号</p><p>那么就要先将SCL从高变为低，这样才会向设备发送一个高脉冲信号</p><ul><li>发送时，需要在SCL发送高脉冲信号前改变SDA的值后，才能有效的正确的发送读取。</li><li>也就是当SCL处于低电平时改变SDA信号直至信号改变成功后，再将SCL调整到高电平。</li></ul><p>SCL从低电平转换为高电平结束的时间成为<code>时钟周期</code></p><hr><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111553054275.png" alt="" title=""></p><p>上图中<strong>tCLDX</strong>表明：当SCL变为0后，SDA电平转换的时间</p><p>上图中<strong>tDXCX</strong>为：输入转换到时钟转换 意思为：<code>SDA电平转换后需要经过一段时间才能让SCL电平置为高电平</code></p><p>因为<strong>tCHCL：低时钟脉冲宽度</strong> 中的时间包含 <strong>tDXCX</strong>，所以我们只需要考虑前者的时间间隔即可。</p><h2>应答信号</h2><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111552349032.png" alt="" title=""></p><p>当到达第九个时钟周期时，需要将SDA置为高电平，用于准备接受应答信号。</p><ul><li>当设备发送了应答信号后，就将SDA引脚的电平拉低，置为低电平。</li><li>那么当SDA为0时，设备就回应了单片机的寻址地址指令，如图循环判断即可做到等待。</li></ul><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111552493824.png" alt="" title=""></p><hr><p><strong>等待应答，不是应该先把SCL拉低，然后SDA拉高，然后再拉高SCL读取SDA信号是否被拉低，因为在SCL为高电平的时候SDA电平不能变化</strong></p><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111554004982.png" alt="" title=""></p><h2>STOP停止函数</h2><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111554301630.png" alt="" title=""></p><p>观察时序图，初始都为0，SCL为1 SDA需要在一段时间后调整至高电平即可。</p><p><img src="http://cdn.x-tools.top/MarkDownImg/2022111554286033.png" alt="" title=""></p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/75/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>ESP32开发版 SPI接口查询记录</title>
<link>https://blog.x-tools.top/archives/72/</link>
<guid>https://blog.x-tools.top/archives/72/</guid>
<pubDate>Fri, 04 Nov 2022 09:38:00 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[&lt;!--[toc]--&gt;ESP32 SPI通信研究笔记使用ESP32加SPI通信连接TFT2.4寸屏幕 实现屏幕最基本的输出材料准备GOOUUU-ESP32开发版，某宝购入。2.4寸...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<p>&lt;!--[toc]--&gt;</p><h1>ESP32 SPI通信研究笔记</h1><p>使用ESP32加SPI通信连接TFT2.4寸屏幕 实现屏幕最基本的输出</p><h2>材料准备</h2><ul><li>GOOUUU-ESP32开发版，某宝购入。</li><li>2.4寸TFT液晶显示屏裸屏 驱动：ST7789V，某宝购入。</li><li>[可选] 立创EDA自己画的装裸屏用的PCB板<img src="http://cdn.x-tools.top/MarkDownImg/202211461011338.png" alt="" title=""><br>如果你买的是裸屏，就需要按照引脚、原理图自己画个底板。</li></ul><h2>资料准备</h2><p>这里资料都是网上找的。</p><ul><li><a href="https://file.x-tools.top/d/%E5%85%B1%E4%BA%AB%E8%B5%84%E6%BA%90/%E5%B5%8C%E5%85%A5%E5%BC%8F/ESP32/2.4TFT7PIspi-GMT024-01.rar">2.4TFT7PIspi-GMT024-01.rar</a><br>购入TFT屏幕时附赠的案例，已修改ESP32对应功能引脚。</li><li>ESP32功能引脚图、以及IDE中数字引脚与功能的对应图。<a href="https://file.x-tools.top/%E5%85%B1%E4%BA%AB%E8%B5%84%E6%BA%90/%E5%B5%8C%E5%85%A5%E5%BC%8F/ESP32">链接</a><br><img src="http://cdn.x-tools.top/MarkDownImg/202211461813381.png" alt="" title=""><br><img src="http://cdn.x-tools.top/MarkDownImg/202211461828351.png" alt="" title=""></li></ul><h2>SPI通信</h2><p><code>SPI</code>通信是一种全双工、高速的通信方式，其通信速度和<code>IIC</code>相比是遥遥领先...<br>成功建立SPI通信至少需要4个引脚：MISO、MOSI、SCLK、CS，引脚作用分别是：主设备数据输入，从设备数据输出、主设备数据输出，从设备数据输入、时钟信号，由主设备产生、从设备片选信号，由主设备控制。</p><pre><code class="lang-c">MISO：主设备数据输入，从设备数据输出;
MOSI：主设备数据输出，从设备数据输入;
SCLK：时钟信号，由主设备产生;
CS：从设备片选信号，由主设备控制;</code></pre><h2>操作</h2><p>本次TFT屏幕裸屏引出的引脚分别是：CS、DC、RST、SDA、SCL以及供电、供地。</p><ol><li><p>依次连接相关引脚：</p><pre><code class="lang-c">SCK - 22 - G22
SDA - 21 - G21
RST - 15 - G15
DC  - 32 - G32
CS  - 14 - G14</code></pre></li><li>连接后，验证上传程序，就可以看见效果...如图：<br><img src="http://cdn.x-tools.top/MarkDownImg/202211463389721.png" alt="" title=""></li></ol><h2>完结</h2><p>本文只是测试TFT引脚连接对应ESP32功能引脚，并不是一个符合规范的程序示例。<br>连接成功后，可以尝试使用更多外置的库文件，来使用此TFT屏幕。<br>另外，嘉立创免费打板，6。</p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/72/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>CSharp - 判断当前环境是Debug还是Release</title>
<link>https://blog.x-tools.top/archives/67/</link>
<guid>https://blog.x-tools.top/archives/67/</guid>
<pubDate>Wed, 28 Sep 2022 02:26:36 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[最近在软件开发和发布过程中遇到了这样的烦恼：开发过程是在Debug模式下写的，需要与服务器对接一个指定的调试指令，才能正常调试。但是在发布时，需要手动将指令接口换成用户使用环境,切换至Relea...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<p><strong>最近在软件开发和发布过程中遇到了这样的烦恼：</strong></p><ol><li>开发过程是在Debug模式下写的，需要与服务器对接一个指定的调试指令，才能正常调试。</li><li>但是在发布时，需要手动将指令接口换成用户使用环境,切换至Release环境编译生产软件才可。</li><li>这就导致，如果说，忘记了自己切换，这就影响了用户体验。</li></ol><p><strong>那么怎么改成自动？</strong><br>我需要使用编译预处理指令<code>#if</code>等操作，<br>如下：</p><pre><code class="lang-csharp">#if DEBUG
    Console.WriteLine(&quot;Debug模式&quot;);//调试环境
#else
    Console.WriteLine(&quot;Release模式&quot;);//生产发布环境
#endif</code></pre><p>这就能做到在切换发布环境时，编译器自动编译相应的代码了。</p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/67/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>JavaScript - 轮播图</title>
<link>https://blog.x-tools.top/archives/66/</link>
<guid>https://blog.x-tools.top/archives/66/</guid>
<pubDate>Tue, 27 Sep 2022 08:00:00 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[轮播图的几点功能：鼠标移入 显示上一张、下一张，移出 则隐藏。点击上下一张，自动切换显示图片，做到有动画效果、无缝切换。鼠标移出时自动每3秒切换图片，鼠标移入时则不自动切换。移动图片时下方小圆点...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<p>轮播图的几点功能：</p><ol><li>鼠标移入 显示上一张、下一张，移出 则隐藏。</li><li>点击上下一张，自动切换显示图片，做到有动画效果、无缝切换。</li><li>鼠标移出时自动每3秒切换图片，鼠标移入时则不自动切换。</li><li>移动图片时下方小圆点也跟随改变选中的图片位置。</li><li>可以点击下方小圆点，切换图片。</li></ol><p>直接放自己写的例子：</p><ol><li><p>首先网页部分及css，自己画的有点潦草...<br><strong>css部分</strong></p><pre><code class="lang-css">&lt;style&gt;
     * {
         margin: 0;
         padding: 0;
     }

     ol {
         list-style: none;
         position: absolute;
         left: 50%;
         bottom: 0;
         transform: translate(-55%, 0);
     }

     ol li {
         display: inline-block;
         width: 10px;
         height: 10px;
         background: rgba(91, 66, 66, 0.3);
         border-radius: 50%;
         border: solid 1px black;
         cursor: pointer;
     }

     .current {
         display: inline-block;
         width: 10px;
         height: 10px;
         background-color: white;
         border-radius: 50%;
         border: solid 1px black;
     }

     .banner {
         position: relative;
         margin: 50px auto 0 auto;
         width: 520px;
         height: 326px;
         overflow: hidden;
     }

     .banner ul {
         position: absolute;
         left: 0;
         top: 0;
         list-style: none;
         width: 550%;
         height: 100%;
         z-index: -1;
     }

     .banner #banner_pic li {
         float: left;

     }

     .banner a {
         display: inline-block;
         cursor: default;
     }

     .banner span {
         display: inline-block;
         width: 25px;
         height: 25px;
         text-align: center;
         font-size: 20px;
         line-height: 25px;
         cursor: pointer;
         color: white;
         background: rgba(0, 0, 0, .3);
     }

     .banner #next {
         display: none;
         position: absolute;
         left: 0;
         top: 150px;
         border-radius: 25%;
     }

     .banner #forward {
         display: none;
         position: absolute;
         right: 0;
         top: 150px;
         border-radius: 25%;
     }

     img {
         display: inline-block;
         width: 520px;
         height: 326px;
     }

     .circle li {
         margin: 0 2px 0 2px;
     }
 &lt;/style&gt;</code></pre><p><strong>html部分</strong></p><pre><code class="lang-html">&lt;body&gt;
&lt;div class=&quot;banner&quot;&gt;
 &lt;span id=&quot;next&quot;&gt;&lt;&lt;/span&gt;
 &lt;span id=&quot;forward&quot;&gt;&gt;&lt;/span&gt;

 &lt;ul id=&quot;banner_pic&quot;&gt;
     &lt;li&gt;
         &lt;a href=&quot;JavaScript:&quot;&gt;
             &lt;img src=&quot;./updatas/1.png&quot; alt=&quot;图&quot;&gt;
         &lt;/a&gt;
     &lt;/li&gt;
     &lt;li&gt;
         &lt;a href=&quot;JavaScript:&quot;&gt;
             &lt;img src=&quot;./updatas/2.png&quot; alt=&quot;图&quot;&gt;
         &lt;/a&gt;
     &lt;/li&gt;
     &lt;li&gt;
         &lt;a href=&quot;JavaScript:&quot;&gt;
             &lt;img src=&quot;./updatas/3.png&quot; alt=&quot;图&quot;&gt;
         &lt;/a&gt;
     &lt;/li&gt;
     &lt;li&gt;
         &lt;a href=&quot;JavaScript:&quot;&gt;
             &lt;img src=&quot;./updatas/4.png&quot; alt=&quot;图&quot;&gt;
         &lt;/a&gt;
     &lt;/li&gt;
 &lt;/ul&gt;
 &lt;ol class=&quot;circle&quot;&gt;

 &lt;/ol&gt;
&lt;/div&gt;
&lt;/body&gt;</code></pre></li><li><p>JavaScript部分</p><pre><code class="lang-javascript"> let main_box = document.querySelector(&quot;.banner&quot;);
 let to_left = main_box.children[0];
 let to_right = main_box.children[1];
 let now_pic = 0;
 let pic_count = 0;
 let pic_ul = document.querySelector(&quot;#banner_pic&quot;);
 let ol = document.querySelector(&quot;.circle&quot;);

 let ThrottleValve = false;
 /**
  * 自动下一章操作
  */
 const auto_fun = function () {
     if (ThrottleValve) return;
     else ThrottleValve = true;

     if (now_pic &gt; pic_count - 1)
         now_pic = 0;
     else if (now_pic === pic_count - 1) {//无缝处理
         new EaseAnimation(pic_ul, (now_pic + 1) * -520, function () {
             pic_ul.style.left = 0 + &quot;px&quot;;
             ThrottleValve = false;//节流阀
         });
         now_pic = 0;
         for (let i = 0; i &lt; ol.children.length; i++) {
             ol.children[i].className = &quot;&quot;;
         }
         ol.children[now_pic].className = &quot;current&quot;;
         return;
     } else
         now_pic++;

     new EaseAnimation(pic_ul, now_pic * -520, function () {
         ThrottleValve = false;//节流阀
     });
     for (let i = 0; i &lt; ol.children.length; i++) {
         ol.children[i].className = &quot;&quot;;
     }
     ol.children[now_pic].className = &quot;current&quot;;
 }
 /**
  * 选中一张操作
  */
 const TogglePicture = function (i) {
     now_pic = i;
     new EaseAnimation(pic_ul, now_pic * -520);
     for (let i = 0; i &lt; ol.children.length; i++) {
         ol.children[i].className = &quot;&quot;;
     }
     ol.children[now_pic].className = &quot;current&quot;;
 }

 //对齐小圆点
 for (let i = 0; i &lt; pic_ul.children.length; i++) {
     let li = document.createElement(&quot;li&quot;);
     if (i === now_pic) {
         li.className = &quot;current&quot;;
     }
     li.addEventListener(&quot;click&quot;, function () {
         TogglePicture(i);
     });
     ol.appendChild(li)
     pic_count++;
 }

 //实现无缝切换
 //1. 拷贝第一张复制到最后
 let pic_start = pic_ul.children[0].cloneNode(true);
 pic_ul.appendChild(pic_start)


 let auto_timer = setInterval(auto_fun, 3000);
 TogglePicture(now_pic);
 main_box.addEventListener(&quot;mouseenter&quot;, function () {
     to_left.style.display = &quot;block&quot;;
     to_right.style.display = &quot;block&quot;;
     clearInterval(auto_timer);
 })

 main_box.addEventListener(&quot;mouseleave&quot;, function () {
     main_box.children[0].style.display = &quot;none&quot;;
     main_box.children[1].style.display = &quot;none&quot;;
     auto_timer = setInterval(auto_fun, 3000);
 })

 to_left.addEventListener(&quot;click&quot;, function () {
     if (ThrottleValve) return;
     else ThrottleValve = true;

     if (now_pic &lt; 0)
         now_pic = pic_count - 1;
     if (now_pic === 0) {//无缝处理
         pic_ul.style.left = pic_count * -520 + &quot;px&quot;;
         now_pic = pic_count - 1;
     } else
         now_pic--;
     console.log(now_pic)
     new EaseAnimation(pic_ul, now_pic * -520, function () {
         ThrottleValve = false;
     });
     for (let i = 0; i &lt; ol.children.length; i++) {
         ol.children[i].className = &quot;&quot;;
     }
     ol.children[now_pic].className = &quot;current&quot;;
 })

 to_right.addEventListener(&quot;click&quot;, function () {
     auto_fun();
 })
</code></pre></li><li><p>还需要js外部文件的一个函数：</p><pre><code class="lang-JavaScript">/**
 * 缓动动画
 * @param obj 目标对象
 * @param target 目标位置
 * @param callback 回调函数
 * @constructor
 */
function EaseAnimation(obj, target, callback) {
 clearInterval(obj.timer);
 obj.timer = setInterval(function () {
     if (obj.offsetLeft === target) {
         clearInterval(obj.timer);
         callback &amp;&amp; callback();
     } else {
         let step = (target - obj.offsetLeft) / 10;
         step = step &gt; 0 ? Math.ceil(step) : Math.floor(step);
         obj.style.left = obj.offsetLeft + step + &quot;px&quot;;
     }
 }, 20)
}</code></pre></li></ol><p>B站课程中将下面的圆点索引和第几张图分开了，我不是按照课程上的写的。<br>我把图片和圆点使用同一个索引，将两者联系在一起。<br>轮播图前面还是挺简单的，但是无缝切换的要求给我绕半天....<br>注意：<br>当我们过快的点击切换图片时，动画效果会不好，所以我们需要<strong>节流阀</strong><br>利用一个flag标志，来控制用户过快的行为，当用户切换图片时关闭阀门，不允许用户再进行操作，我们开始执行动画效果展示，当动画完成时再将阀门打开。<br>这就是原生的JavaScript轮播图。</p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/66/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>CSharp - 硬件信息查询监控</title>
<link>https://blog.x-tools.top/archives/55/</link>
<guid>https://blog.x-tools.top/archives/55/</guid>
<pubDate>Thu, 04 Aug 2022 15:45:47 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[说明本篇文章采用第三方开源库openhardwaremonitor来辅助编写查询信息，并且网上大多都是采用这种方式监控硬件信息。常用的硬件信息有：温度、时钟频率、电压、内存占用、存储空间占用、网...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h1>说明</h1><p>本篇文章采用第三方开源库<code>openhardwaremonitor</code>来辅助编写查询信息，并且网上大多都是采用这种方式监控硬件信息。<br>常用的硬件信息有：温度、时钟频率、电压、内存占用、存储空间占用、网络传输状态···<br>这里仅获取到CPU温度以及GPU温度，其他查询方式类似，自己琢磨...</p><h1>一.下载第三方库</h1><p><strong>下载方式：</strong></p><ol><li>项目开源地址：<a href="https://github.com/hexagon-oss/openhardwaremonitor">https://github.com/hexagon-oss/openhardwaremonitor</a>，自己去releases中下载最新版本<br>并且自己编译好后，找到生成文件夹中的<code>OpenHardwareMonitorLib.dll</code>，我们就使用它！</li><li>这里提供文章的第三方dll文件<a href="https://b.x-tools.top/typecho/uploads/2022/08/787440883.rar">OpenHardwareMonitorLib.rar</a>，解压打开即可(Ver：0.9.7.11)</li></ol><h1>二.引用dll文件</h1><ol><li>如图打开项目 - 右键引用 - 添加引用<br> <img src="http://cdn.x-tools.top/MarkDownImg/20228484955154.png" alt="" title=""></li><li>点击"浏览" - 选中下载解压好的dll文件即可。</li></ol><h1>三.使用</h1><ol><li><p>这里首先引用命名空间</p><pre><code class="lang-csharp">using OpenHardwareMonitor.Hardware;
using System;</code></pre></li><li><p>然后复制粘贴下面的类</p><pre><code class="lang-csharp"> public class UpdateVisitor : IVisitor
 {
     public void VisitComputer(IComputer computer)
     {
         computer.Traverse(this);
     }

     public void VisitHardware(IHardware hardware)
     {
         hardware.Update();
         foreach (IHardware subHardware in hardware.SubHardware)
             subHardware.Accept(this);
     }

     public void VisitSensor(ISensor sensor) { }

     public void VisitParameter(IParameter parameter) { }
 }

 public class ComputerCore
 {
     private UpdateVisitor updateVisitor = new UpdateVisitor();
     private Computer computer = new Computer();

     public ComputerCore()
     {
         computer.Open();
         computer.CPUEnabled = true;//开启CPU信息监控
         computer.GPUEnabled = true;//开启GPU信息监控
         computer.Accept(updateVisitor);
     }

     /// &lt;summary&gt;
     /// 获取CPU温度
     /// &lt;/summary&gt;
     /// &lt;returns&gt;&lt;/returns&gt;
     public float GetCpuTemp()
     {
         computer.Accept(updateVisitor);
         float num = 0;
         float cc = 0;
         float avg = 0;
         for (int i = 0; i &lt; computer.Hardware.Length; i++)
         {
             //查找硬件类型为CPU
             if (computer.Hardware[i].HardwareType == HardwareType.CPU)
             {
                 for (int j = 0; j &lt; computer.Hardware[i].Sensors.Length; j++)
                 {
                     //找到温度传感器
                     if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature)
                     {
                         if (computer.Hardware[i].Sensors[j].Value is null)
                             continue;

                         num += (float)computer.Hardware[i].Sensors[j].Value;
                         if((float)computer.Hardware[i].Sensors[j].Value!=0)
                             cc++;
                         avg = num / cc;
                     }
                 }
             }
         }
         return avg;
     }

     /// &lt;summary&gt;
     /// 获取GPU温度
     /// &lt;/summary&gt;
     /// &lt;param name=&quot;isNva&quot;&gt;是不是英伟达GPU&lt;/param&gt;
     /// &lt;returns&gt;&lt;/returns&gt;
     public float GetGpuTemp(bool isNva = true)
     {
         computer.Accept(updateVisitor);
         HardwareType type = isNva ? HardwareType.GpuNvidia : HardwareType.GpuAti;

         for (int i = 0; i &lt; computer.Hardware.Length; i++)
         {
             //查找硬件类型为CPU
             if (computer.Hardware[i].HardwareType == type)
             {
                 for (int j = 0; j &lt; computer.Hardware[i].Sensors.Length; j++)
                 {
                     //找到温度传感器
                     if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature)
                     {
                         if (computer.Hardware[i].Sensors[j].Value is null)
                             continue;

                         return (float)computer.Hardware[i].Sensors[j].Value;
                     }
                 }
             }
         }
         return 0;
     }

 }
</code></pre></li><li>调用即可<br>实例化：<code>public ComputerCore CCore= new ComputerCore();</code><br>CPU温度：<code>CCore.GetCpuTemp()</code><br>GPU温度：<code>CCore.GetGpuTemp()</code>(英伟达显卡) - <code>CCore.GetGpuTemp(false)</code>(非英伟达显卡)</li></ol><h1>注意</h1><ul><li>项目框架的Framework 版本要求 4.8</li><li>引用后直接使用会出错，这里需要下载一个NuGet包<br><img src="http://cdn.x-tools.top/MarkDownImg/20228485425449.png" alt="" title=""><br>作者使用的就是5.0.0版本，我也就没找事，用最新版。可自行测试。</li><li>CPU温度因为有很多内核 每个内核温度不一样，所以我取了平均值。</li></ul>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/55/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
<item>
<title>记录一次服务器配置测试过程</title>
<link>https://blog.x-tools.top/archives/53/</link>
<guid>https://blog.x-tools.top/archives/53/</guid>
<pubDate>Wed, 20 Jul 2022 16:42:00 +0000</pubDate>
<dc:creator>小夏</dc:creator>
<description><![CDATA[服务器自启动我希望服务器在开机自启动某些python文件，可以使用shell命令操作。使用chkconfig服务配置shell文件存放目录：/etc/rc.d/init.d只要将自己的sh脚本文...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h1>服务器自启动</h1><p>我希望服务器在开机自启动某些python文件，可以使用shell命令操作。</p><ol><li>使用chkconfig服务配置</li><li>shell文件存放目录：<code>/etc/rc.d/init.d</code><br>只要将自己的sh脚本文件放入目录中即可，这里使用的是<code>start.sh</code>文件名。</li><li>增加脚本可执行权限<br><code>chmod +x  /etc/rc.d/init.d/start.sh</code></li><li><p>添加脚本到开机自动启动项目中</p><pre><code class="lang-shell">cd /etc/rc.d/init.d
chkconfig --add start.sh
chkconfig start.sh on</code></pre></li></ol><p>注意：自己的自启动脚本文件中开始的3行必须按照如下格式：</p><pre><code class="lang-shell">#!/bin/sh
#chkconfig:2345 80 90
#decription:autostart</code></pre><p>具体解释参照<a href="https://blog.csdn.net/qq_34185638/article/details/123745102">这个博客链接</a>即可</p><h1>修改linux的DNS解析</h1><p>本人使用的腾讯云服务器，在挂机器人启动GOCQ时，会出现如图的问题：<br><img src="http://cdn.x-tools.top/MarkDownImg/2022819564178.png" alt="" title=""><br>(上面一条红色信息请无视~)<br>我们只需要：</p><ol><li>修改resolv.conf即可，目录为<code>/etc/resolv.conf</code><br>vi /etc/resolv.conf</li><li><p>添加 或修改文件中的dns，无须重启服务器，保存立即生效</p><pre><code class="lang-c">; generated by /usr/sbin/dhclient-script
nameserver 114.114.114.114
nameserver 183.60.83.19
nameserver 183.60.82.98</code></pre></li><li>效果展示：<br><img src="http://cdn.x-tools.top/MarkDownImg/2022819784659.png" alt="" title=""></li></ol><h1>自启动Python的FastApi</h1><ol><li>需上面的步骤</li><li><p>只需要在自己的脚本中加入</p><pre><code class="lang-shell"># 自己python文件的位置
cd /PY/myapi
# 后台启用即可
nohup uvicorn main:app --port 3520 --reload  &gt; log.txt 2&gt;&amp;1 &amp;</code></pre></li></ol>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.x-tools.top/archives/53/#comments</comments>
<wfw:commentRss>https://blog.x-tools.top/feed/category/MarkDown/</wfw:commentRss>
</item>
</channel>
</rss>