前面视频中我们了解了 s k 九八二二灯带的驱动原理,接下来就通过程序代码来实现这一驱动的过程。 在写代码之前,先把灯带跟单片机连接好,这次使用的是 stc 八 g e k 零八 a 单片机, 灯带的数据线和时钟线分别接在单片机的 p 一 三和 p 一 五引脚上,灯带的电源负极线连接在单片机的 g、 n、 d 引脚上, 由于这种灯带对电流要求比较高,而单片机的输出电流有限,所以如果点亮的灯珠比较多,就需要在灯带的电源线上外接一个输出电流足够大的五伏电源,否则就可能导致灯珠乱闪或者不亮。 一切就绪,下面开始看程序代码。 这些是已经写好的驱动程序,我把这些函数按照功能分成了两类, 第一类是基础驱动,就是根据前面视频里的思路创建出的五个函数,包括出土化灯带的函数 s k 九八二二 init、 发送数据的函数 s k 九八二二三 byte 以及发送其实码颜色码、结束码的函数。先看出式化函数, 为了信号传输的稳定,这里将单片机上 p 一 的三和五两个端口都配置成推挽模式, 然后将数据线和时钟线都设置成空闲状态的低电瓶,并且稍微延时一下,让这两条线上的电瓶状态稳定。 这里事先创建了两个红定义,用 s k 九八二二 s d n 代替数据引脚的 p 一 三,用 s k 九八二二 s clock 代替时钟引脚的 p 一 五,以便于日后更换端口。 然后是发送一个字节数据的函数 s k 九八二二三 byte 参数, date 是 要发送的一个字节的数据,使用高位先发的顺序对数据进行发送, 所以先从数据的最高位开始读取,然后将读取到的这一位数值。至于数据线上,如果是一,就将数据线拉高,如果是零,就将数据线拉低, 然后稍微延时一下。因为数据线上的电瓶状态从改变到稳定需要一个过程, 根据 s k 九八二二的持续要求,这个过程需要大于十纳秒的时间,只要符合这个要求,在时钟信号的上升延之前,无论数据线上的电瓶如何波动,都会被灯珠无视掉。 然后是对时钟速度的要求,在一个时钟周期里,高电频和低电频的持续时间都要大于三十纳秒, 比如让单片机以主频三十兆赫兹的速度运行,那么一个时钟周期大概是三十三纳秒,是满足大于十纳秒和三十纳秒的要求的。 所以这里以红定义的方式,用 sk 九八二二低类函数名的形式来替代消耗一个时钟周期的函数。 回到函数中,设置完数据线的电瓶状态之后,接下来就是将时钟线拉高,读取数据线上的电瓶状态,然后同样等待一个低类的时间 之后再次将时钟线拉低,并且给一个 delay 的 时间,将这一位数据存进灯珠,然后将 date 的 值左移一位,让后一位变成最高位。 如此循环八次,一个字节的数据 date 就 发送完成了。这是最核心的一个函数,因为后面的奇石码、颜色码和结束码都要靠它来进行发送。 顺便再看一下红定义,出于好奇,又将 di 函数分别定义成了一微秒和五十毫秒,从而延迟时间是灯珠要求的三十多倍和一百六十多万倍。结果发现居然依旧可以让灯珠点亮, 有兴趣的小伙伴也可以尝试一下其他的速度。 接下来就是用来点亮灯珠的函数。首先是骑士码的函数 s k 九八二二 start code, 内容是连续发送四个字节的零 x 零零。然后是颜色码的函数 s k 九八二 color code。 按照平时的习惯,这里把四个参数的顺序排列成了亮度和红绿蓝的顺序。 在函数中先发送一个亮度值,数值范围是零到三十一,发送的数值是亮度值跟零 x 一 零相距,得到的就是以三个一开头加五位亮度值的格式。 随后是连续发送三个字节的颜色值。这里注意发送顺序一定要先发蓝色,再发绿色和红色。 最后就是结束码的函数 s k 九八二二 n code。 按照之前提到的公式,将数据零 x 零零连续发送一半灯珠数的次数。 这里的灯珠数量 led number 同样也是事先红定义好的数值,比如要点亮八颗灯珠, led number 就 代表八。 另外,如果打算用统一的亮度值,也可以再红定一个 led bright, 点亮多个灯珠的时候就不用逐一修改了。至此,最基本的驱动函数就完成了,总共只有五个函数, 接下来就实验一下这几个函数。在主程序中添加驱动程序的头文件 s k 九八二二点 h, 在 main 函数中添加灯带的出场函数。 然后发送一个奇石码。接下来连续发送八种颜色的颜色码,最后发送一个结束码, 这样看到的就是前面视频中的连续八颗被点亮不同颜色的灯珠了。 现在试一下,在每个颜色码后面都添加一个结束码和一个延时函数,再看一下,现在灯带上就变成了只有第一颗灯珠不断变换颜色了。函数运行成功, 利用这五个基础函数就可以创建出各种效果的显示函数了。
粉丝7851获赞6.7万

这是 rgbw 全彩灯带,点亮它能做点东西,比如全彩像素中 全彩补光灯。不过在开始之前先要学会驱动他。 灯带的灯珠有 rgbw 四个颜色, 相比 rgb 灯珠会更亮一点。灯珠的型号是 sk 六八幺二,工作电压五伏, 驱动这个灯带或者灯珠只需要电源正负极,还有数据输入三根线,灯珠的四个 银角是这样连接的,所以只要构造数据信号就能驱动他。那么用 stm 三二八二六六啊,对呢,或者五幺都是可以的。重点在于却搞明白怎么编程得到正确的数据信号。 八二六六跟耳朵运动都容易找到对应的驱动库,驱动库的用法往上一大把,就不去重复了。我们把重点放在编程的思路和方法上,因为无论用什么芯片和语言,只要方法对了,都能实现。 这是灯珠手册上的数据结构,以绿红蓝白的顺序发四个字节,这三十二比特的数据从低硬串行输入,想点亮几个灯就送几个三十二比特,最后再跟一个复位码就能点亮了。 我们很早就学过伊比特有零和一两个码源,根据手册,只要构造这三种脉冲就可以了。这个表是脉冲的时间要求。我们确定一个具体值, 马云周期设定在一点二六微秒,零马正迈宽零点三微秒,一马正迈宽零点七五微秒,复位码负迈宽二百零五微秒。 有了这些参数,那就很简单了,只要做两个子程序,一个发送复位信号,另一个串行发送八个比特。 这种硬件控制我用会编语言,如果你用 c 语言或者其他高级语言,要注意编译优化等级对指令长度的影响,这个影响我们可以在评论区去讨论。 试波器的黄色波形观察串形数据,蓝色 波形观察程序执行时间,先做发送复位码的指程序,用一个延迟程序就够了,先把数据引脚拉低,再延迟二百零五微秒就可以了。烧路运行 复位码,复麦宽是二百零四点五微秒,只要大于两百微秒就可以。 再做一个串琴发送巴克比特的子程序。这个程序的核心只有一个循环和一个判断循环八次,把一个字节从高位开始按位读出, 每次循环根据读书的位去设置零码或一码的脉冲宽度。这程序目前是有问题的,因为零码和一码的跳转直行长度不相等。运行来看看现在零码和一码脉冲等宽, 发送的数据每隔零点五秒从零到二百五十五递增。如果零码和一码判断执行时间相等,执行时间和数据位的间隔不会这样跳动。 跳动的原因是因为不同的处理器跳转指令执行的时间有差异,必须消除时间差才能得到满意的脉冲。针对我的处理器,我添加了一些控操作,让判断的分支指令走过相同的时间。 这是修正后的波形,最低位仍然递增,但判断分支执行时间相等了。程序执行时间不变了。 把程序改成全发零码,周期一点二六微秒,正迈宽零点三二微秒。再把程序改成全发一码,周期一点二六微秒,正迈 宽零点七七微秒。零码和一码的周期是稳定的,驱动程序就这么搞定了, 现在把阿基 b 做成交叉递增和递减,这个波形就是我们想要的结果。 感谢您的关注,我是机电匠,我们下期再见。

今天我们来看一个一体机的故障,就是开机之后呢,这个位置直接显示没网之前都是连好的无线网,然后打开之后呢没有 wifi 的 图标, 但是蓝牙的图标呢还是正常的蓝牙和 wifi 呢,在同一张网卡上面, 我们尝试更换了网卡,然后呢又重装了系统,现在隔了一段时间之后呢,这个故障现象呢又重新出现了,现在进设备管理器看看,我们直接先打开我的电脑,然后呢在这个此电脑上面右击点击管理, 然后进设备管理器。 好,我们可以看到这个网络设备器这一块啊,我们的无线网卡呢是 b 一 二零零,然后呢这个无线网卡上面显示一个感叹号啊,这是驱动出了问题,这种现象呢会时不时的发生, 就是频繁的掉驱动,那这是由于什么原因导致的呢?一般是两种原因, 第一个呢就是由于这个散热,就是有的网卡他离硬盘特别近,或者是离风扇特别近,然后这个热量呢致死,这个网卡工作异常 比较容易出问题的两个牌子,第一个就是联想,第二个就是华硕, 一般都是出现在一体机或者笔记本里面啊,有一些笔记本的这个硬盘呢啊,它是设计在网卡上面的,然后呢两个就是贴的距离特别近, 那这种情况呢就是容易导致网卡异常啊,那我们只需要把这个笔记本的硬盘换到另外一个槽里面去就 ok 了。 然后有的离风扇或者是电池这些散热比较厉害的这种部件呢,离得比较近,也会出现类似的现象。 还有一个原因呢,就是供电导致的,这个主板的供电呢,出现问题的时候,它就容易出现这种情况,比如说有一些旧的机型啊,它这个蓝桥的供电出现问题了, 一些新的笔记本呢,现在已经没有蓝桥了啊,那你们直接把这个蓝桥的功能集成在 cpu 或者是 pch 里面了, 重装驱动,重新插拔网卡,换网卡,重装系统,这些都是治标不治本, 这些方法针对这种故障,有的时候是完全没用的,有的时候只能管一阵子,起不到长久有效的解决。 那么我们应该怎么去解决这种问题呢?现在呢我们来展示一些错误的做法。首先呢就是重装驱动,重装驱动呢有两种方法,第一种呢就是把设备的驱动给它卸载掉,右键属性选择驱动程序标签, 选择最下面的卸载设备,然后勾选尝试删除此设备的驱动程序,点击卸载, 然后呢这个设备呢就被卸载掉了,卸载了之后呢再重新安装,这个地方依旧提示修复啊,我们再点修复点下一步, 好,现在就开始修复了,修复完成,我们来看一下右下角,好,现在变成可用的了, 然后重启完,我们发现又不行了啊,能够短暂的管一段时间,但是这个时间呢他就有不确定性。现在我们展示的呢是第二种错误做法, 在没有卸载原驱动的情况下,我们直接打开官方驱动,点击修复。之所以要展示错误的做法,就是希望大家能看到最后的结果,这样可以避免大家绕弯路, 它提示修复成功,我们点完成,然后我们看右下角,它依旧没有出现这个 wifi 的 图标。好,我们现在呢重启一下试试。 好,现在重启好了,然后我们发现呢,这个依旧没有解决啊,那我们尝试关机看看, 然后重新开机, 重新开机了之后呢,仍然没有出现啊。其实呢,这个在重启和关机开机的这个过程当中啊,有一定几率他是可能会被修复掉的啊,但是呢, 即使修复了,他也是治标不治本啊,所以这个方法呢,其实是没有用的啊。另外这个问题呢, 在我们重装系统之前就已经频繁出现过了,而现在的这个系统呢,其实是被重装过了啊,那其实问题并没有得到解决, 所以重装系统肯定也是没有用的。然后呢,更换网卡有没有用呢啊?这个其实也是没有用的, 这台机器已经更换过网卡了啊,我们用的是 wifi 七的 b e 二零零同款的机型呢,没有出问题的。这个主板呢,它其实是可以完美支持的啊,所以换网卡也是没有用的。 当然呢,如果是把内置网卡换成外置网卡,那肯定是可以的,因为 pci 或者 m 二接口的这个网卡的话呢,直接换成 usb 接口的网卡,散热问题就不存在了,供电呢也会发生变化。 不过这种方法虽然能解决问题,但是呢,插在 usb 口上面,第一个呢是不够美观和方便。第二个呢是在没有主板设计缺陷的情况下呢,内置网卡肯定要比外置网卡的稳定性和性能更好。 然后呢,这里我们点到设备管理器里面,点开这个带感叹号的驱动啊,我们可以看到这个上面显示是由于该设备有问题, windows 已将其停止,代码是四十三, 代码四十三呢是设备硬件故障,接触不良或供电不足,所以我们这里呢优先先从热量防护和供电这两个方向去解决。除了主板本身的供电问题以外, 我们也要排除一下有没有外接 usb 设备存在短路进水或导致 usb 口不识别的情况,比如一些外接的键盘、鼠标和 usb 设备,尤其是 u 盘或者是移动硬盘。 先排除外接设备导致的主板供电异常。然后呢我们再进行拆机检查流程,好,我们现在呢关机来拆机看一下。 拆开后呢,我们发现这个主板的保护盖呢,它是金属的啊,它会跟这些 usb 口还有电源接口啊,然后屏幕的这些接口网口相连啊,它这个有的时候是接触的比较近。 好,我们继续往后看啊,我们发现这个风扇呢,它是压着这个网卡的,所以呢我们先把转接板和网卡都拆下来, 把接口清洁一下,然后在风扇上做一些隔热处理,再重新把网卡上回去,然后供电呢,我们这个电源呢, 换一个联想的十九伏四点七四安的这个电源来试一下。 至于主板本身是否存在供电问题呢,我们先把其他流程走完,如果还存在问题,那我们再更换主板,先把风扇下口处这个地方贴一些铝箔胶带纸,给它隔绝热量, 确保跟网卡接触的部分啊不是那么烫。 然后我们再把这个促栓胶带给它贴回去,再隔绝一层。好,这就 ok 了,隔热呢就完成了。好,然后我们现在复原, 复原的时候呢,我们把这个外壳,这个离 usb 近的这几个卡扣给它弄远一点,包括这个电源的口这个地方也给它留一点间隙出来, 不要让它直接接触在上面,防止这个地方出现外壳导电之类的问题, 这里我们再加一个海绵垫。 好,这就复原了。好,通电试机。 好,进来系统了,我们来看一下右下角。好,现在已经显示 wifi 图标了啊,已经可以看得到 wifi 了, 好,这就没有问题了,如果这里 wifi 图标呢还是没有显现,我们可以再次进入设备管理器里面卸载驱动,重新再安装最后一遍。 然后呢为了万无一失,我们把芯片组驱动和 bios 驱动最新版本给它更新一下,首先我们把芯片组驱动给它更新一下, 完成重启的时候按 f 二进 bios, 进来了之后呢,我们直接找到最右侧的工具,这个工具呢就是用来升级 bios 的, 好,点击华硕升级 bios 应用程序二,然后我们找到对应的磁盘和 bios 文件,找到之后点击,然后它提示你是否要阅读此文件,点确定, 问你是否升级,点确定,然后升级就正在进行了。 好,升级好了之后呢,上面就提示升级成功,系统将重新启动,点击一下确定就 ok 了,这就升级好了。 好,现在呢就进系统了,这就全部搞定了。然后在视频发布前,我们测试了一整天,开关电脑了很多次, 下载播放影音文件,启动游戏都进行了测试,再也没有出现之前的故障了。

大家好,这里是爆改车间,今天主任呢把这块屏幕的驱动代码整理一下,分享给大家,这个代码呢,主人只测试了这个标签的 二点一三寸屏幕,然后背面是背面是这样子的,这款屏幕是测试成功的,其他的屏幕的主页手里也没有,然后也没有测试,不一定都能用,主要给大家提供一个思路,但他主要根据自己手里屏幕的 资料文档,参考这个驱动代码,然后修改控制命令和参数啊,就可以驱动起来各种各样的屏幕了,只要二十四 c 的墨水平,大部分驱动电路啊都是一样的,只是驱动命令 最轻的代码呢,很简单,我们用的是硬件 spi id 五和第七接口啊,就不需要在这里定义了,这几个根据呢我们电路里面的设置,然后定义一下接口,我们使用的 es b 二六六,然后开发发现 d m c u 就不可以使用这种低开头的接口。好记,有趣的时候把微型模式填充代码里面的的自控函数啊,可以整合进来,这样的话呢就有了这个英文字库,还有这个汇读函数,可以画方块,圆圈,三角形什么的 线,非常的方便。我这边我觉得大家可能更多使用的都是静态同样显示,所以我们直接给图片取模,然后决定显示就行了。这个方法呢非常简单,我给大家演示一下。首先呢我们要用 windows 画板创建一个像素为为二一二乘以一零四的画布,然后呢我们在这个画布上呢就可以随意的去 编辑图像,我们画一个人,画一些图像,可以往里输入一些文字,我们也可以直接打开一个图像,把它编辑成这个大小,我成为 bmp 图像 a, 然后呢我们要打开这个图像群模软件,这个图像群模软件,然后打开刚才我们 绘制的这个图像,这里选择垂直扫描,然后单色,然后最大的宽度和高度呢是二幺二乘一零四 点点头,然后点颜色反转,然后这样设置好以后呢点保存,然后保存成一个点 c 的文件,保存完以后这个文件就会自动被打开,这个速度呢就是我们的,然后呢我们把这个全选复制, 然后再来到我们的代码里,然后我们找一个地方,我们把它粘贴到这里的最后,然后我们这个速度的名字是这个,我们把它复制一下住函数这里,这个呢就是显示全屏图像,然后呢这个就是显示图像的这个速度的名字,然后我们把刚才生成的这个什么粘贴在这里,然后点上传。 嗯,好嘞,各位,现在程序已经上传上来了,这就是刚才我们绘制的图像,刚才这个数字 一到九啊,是局部刷新测试,我们可以控制这个字的局部刷新,这块字母呢就是我们用的那个微信的字库,我们直接使用的字库,然后生成的这个 图像,然后呢这个是,哎,这是一个计时,应该测试这个什么屏动态抓心的能力,但其实把它做成一个时钟啊,也是可以的,但是这样的话他屏幕会一直保持在通电状态,可能会比较消耗他的寿命。 嗯,这比如我们可以把它做成没有秒的,然后设置成分钟的,然后每一分钟啊给它更新一次,然后就进入休眠,这样的话呢这个屏幕的寿命就会变很长了。那马上呢,我都我做了几个测试,然后都加了这个中文的注释, 然后下面还有一些很重要的单子,比较明显,还有这个清空屏幕,然后全部显示白色清空屏幕调出来的黑色,然后这些 还说呢,大家可以直接调用测试一下就可以了。当然这个手摸屏呢,最有意思的就是我们设定好图像之后呢,哎,就可以把电拔掉了,然后他就可以永久显示,然后非常有趣。嗯,所以说呢,我们连驱动版都可以,不要直接 哎,这个屏幕他就会永永远显示这个图像,非常好玩。好,我们这就到这里,我们下期再见,大家一起想想能让他做些什么东西吧。

接下来咱们就实现 rtc 驱动的代码,放在驱动层,对应 rtc driver 点 c, 看一下它的结果函数对外暴露两个,一个是 set rtc time 设置时间,一个是获取时间。 get rtc time 参数,我们在这定义了一个结构体类型, rtc time 向下 t, 成员包括年月、日时、分秒。结果函数比较简单,咱们直接写一下代码。在 driver 目录我们新增一个点 c 文件, 叫做 rtc driver 点 c。 然后我们在 hellok 这里还要新增几个库文件,首先是 rtc 点 c, 然后还有 pmu 点 c 以及 bpk 点 c, 要涉及到这三个片上外设。在这首先我们来实现 rtc 抽象的结构函数。首先是使能 pmu 和 bpk 的 时钟,要用 rcu block enable r c u p m u 然后我们使能 b k p 的 时钟。不对, 我们来看一下是 b k p i 然后使能对后背寄存器和 r t c 的 血权限调用 p m u 我 们直接使用 back up right enable 就 可以了,它没有参数。接下来复位后背寄存器, 我们首次出水话可以将后备寄存器里面的数据全部清零复位 b k p d e i n i t 然后使能外部的低速时钟,并等待其稳定。调用 r c u o s c i on 这个函数传入的参数, r c u x l x t a l 接下来是等待它稳定。 r c u o s c i stab wait 接下来是设置 r t c 的 时钟输入源。 r c u r t c clock config 参数是 r c u r t c 选择 l x t a l 接下来是使能 r t c 时钟,我们选择好了时钟输入源, 那么就接下来把它使能了。 r c u r t c 接下来是等待 app 一 接口时钟和 r t c 时钟同步, 我们要调用一个接口函数 r t c register sync wait, 没有参数。 接下来是等待上次对 rtc 写寄存器完成调用 rtc 的 结果函数 rtc lw f f wait, 然后上一次写操作完成了,我们就可以设置 rtc 的 寄存器,设置分频为三二七六七, rtc pr e 这个结构函数,我们设置三二七六七。接下来我们再调用这个结构函数, 等待设置分频值完成。我们可以去设置一个初始的时间,比如说我们就将计数计算器里面的值设置为零,这样代表的时间就是一九七零年一月一号零点零分零秒, 这是一个零时区的日历时间,那么对应北京时间就是八点零分零秒。 rtc counter sight, 我 们就设置为零,这样就可以了。这个触指法啊,现在有个问题,系统每一次复位或者是重新上电 都会去调用 rtc driver, 也就会复位,后备计算器也会重新去设置时间,即使我们有 纽扣电池,也会每一次复位都会重新计时,这样就有问题,那怎么办?这个时候我们就可以去用后备寄存器里面,它不是有四十二个数据寄存器吗?大家回想一下是不是?那怎么用?我们在这使用 b k p write data, 我们往其中的一个数据寄存器也写入一个模码, b k p data 零,这个寄存器写入一个模码,比如说零 x 五 a 五 a, 咱们在这把它使用红来定义一下,我们叫做 magic code, 这个模码有什么用?我们在这写进去了, 我们在进入到这个函数的时候做一下判断。 if 我 们去读一下这个计算器的数据, b k p read data 读出来以后,我们判断一下,如果不等于 我们写入的这个模码,然后就去执行这些出式化。当设备第一次上电的时候,运行程序从这个计算器里面读取数据,那肯定不是这个模码,然后就执行这些出式化,然后写入模码数据,等到系统复位, 在执行这个结果函数的时候,因为有纽扣电池,那这个后备寄存器里面的数据肯定是不会丢失的,还保存下来了,读取出来发现是模板,那就不再执行这些抽象了。

每天推荐一款黑科技软件,今天推荐的软件是打印机工具箱,吾爱大佬推出的打印机驱动神器,软件完全免费,体积只有七百 kb 左右,无需复杂安装,双击就能运行。 启动快,不占内存,适配主流 windows 系统,内置惠普、佳能、爱普生、三星等主流品牌驱动库,不用记官网,不用查型号, 打印机连上电脑,一键自动扫描,一分钟智能匹配最优驱动,小众品牌还能手动搜索所有驱动,百分之一百免费下载, 无广告、无付费、无会员。还支持菜鸟、拼多多等电商打印组建,不管是家庭办公还是电商打单,驱动安装、故障排查、维护更新一站式搞定,电脑小白也能轻松用好打印机。

建筑开发中如何实现底层驱动与上层应用的结偶?分享一下我最近的学习。事情是这样的,我在开发一个底层驱动时,由于业务需要,直接调用了上层应用的接口,结果在代码屏损时,被领导一眼指出了问题。 他说,这样虽然功能实现了,却让底层驱动和上层代码紧密合在一起,一旦上层接口变动,底层驱动也得跟着改,维护成本高,附用性也很差,长期来看是加固上的隐患。 我当时还有点困惑,那该怎么在底层触发某些业务逻辑呢?领导接着给了我一个具体方案,用回调函数来封装这些调用。 具体来说就是把底层需要执行的操作抽上层。回调接口由上层应用在初步化时注册对应的实现函数,底层驱动在需要时直接调用注册进来的回调方法, 而完全不需要知道上层具体是谁、怎么实现的。这个思路一出来,我顿时茅塞顿开。没错,这样一来,底层驱动保持独立,不依赖于任何上层具体代码,上层业务可以,上层业务可以灵活实现回调,完成自己的逻辑。 两者通过抽象的接口,通信饱和性大大降低,也容易测试和扩展。这件事让我再次意识到,好的代码结构不仅仅是功能能跑,还要考虑层次清晰、职责分明。 尤其像驱动层、服务层、应用层之间,一定要通过约定的接口事件或回调的方式来通信,而不直接跨层调用。


数据说可能会就全部满哦,那应该不会这么倒霉,上期视频那个零零七 b 的 蓝屏错误,有很多朋友说修复引导或者是注入 r s t 驱动能解决,那么这两种办法究竟靠不靠谱呢?咱们试试看。 嗯,先进来吧。好嘞, 小姐姐反馈,他的笔记本电脑有很多重要资料,但是目前开机就蓝屏,进不去系统。 我那天大概录了一个视频啊,他现在还能开机吗?嗯,昨天就是这样子,就是先蓝屏啊,等一会就是这样,这样子啊,等一会还是他一直循环是吧?对,好嘞,我知道了, 目前的状态进不去系统,咱们先尝试一下安全模式是否正常, 可以看到安全模式下故障依旧。那接下来咱们先试试在 pe 下面修复引导能不能成功。这年头胆大的人还不少,又是一个硬盘锁,资料的话,目前看应该是保住了。 在工具里面找到 uefi 引导修复工具, esp 分 区选择计盘, windows 目录选择 c 盘, 提示,修复成功之后直接重启, 可以看到故障依旧,证明这个修复引导的办法是没有用的。那接下来咱们试一下网友的第二种办法,就是注入这个 i s t 驱动, 注入成功继续重启,你觉得这次能修复吗? 可以看到故障依旧还是零零七 b, 这个时候咱们就可以给他备份资料,安排大宝剑了。像这种零零七 b 的 错误真的是遇到了头疼,十个九个都修不好,除非是一些固动电脑,可以调硬盘模式的那种。 所以说兄弟们,下次再遇到这种新一点的电脑,零零七 b 的 就不要再浪费时间了,直接备份资料,重装系统。

好,看完规则之后,我们来看我们用来生成代码的那个做来做实验的那个类图。啊,我没有直接选择我们刚才的那个案例里面那个类图,因为那类图相对来说 比较简单,虽然说类比较多,但是呢它的结构比较简单,那我们这里面我们挑了一个复杂结构的一个类图, 那为了搞清楚是不是这样啊?我们先开一个 agent, 然后呢还是同样的提示词,同样的图,但是我们在大模型选这个 gpt 五点二,我们来看看是不是这个问题啊?我们提交。

在低代码、规则引擎这些领域,业务脚本往往扮演着最后一公里的角色。但问题就出在这,如果缺乏清晰的边界,这些脚本就像脱缰的野马,迅速演化成难以控制的混乱状态。 随意定义函数,随意导出结构、随意访问全局对象,还跟配置强藕合,却又没法较验,这不就是系统失控的前兆吗? 维护成本蹭蹭往上涨,想想都头疼。咱们先来剖析一下传统模式的痛点。你看,业务脚本自己说了算,想定义什么函数就定义什么,想导出什么就导出什么,直接依赖大局环境,这叫结构主权。 听起来挺自由,但对平台来说简直是灾难。平台根本没法知道他到底导出了哪些东西,有没有遗漏,有没有写了一堆没人用的函数,甚至有人故意破坏导出结构,平台也防不胜防。 这种失控感是低代码平台绝对不能容忍的,他会把整个系统的稳定性拖垮。那怎么办呢?总不能让脚本继续为所欲为吧? 必须得立规矩。我们的核心思路就是平台来定义一个统一的接口,也就是契约,让脚本在这个框架内活动。看这个 script handler 类型,定义一个函数,接受 event 和 rule 两个参数,返回 any 或者 promise。 这可不是给业务开发者随便发挥的自由空间,这是平台级的硬性规定,所有脚本都得遵守这个签名。这样做第一明确了平台的控制权, 第二统一了函数签名,方便后续做各种编印、校验和治理工作。 这是第一步,也是最关键的一步。刚才说了,传统模式下,脚本既声明自己能干啥,又决定怎么把能力暴露出去,这就给了平台失控的风险。 我们的解决方案是把权力收回来,谁来决定需要哪些能力。不是脚本,而是配置。通过 roon 这个配置项明确声明,当 change 的 函数, 当 delete 事件发生时,调用名为 on delete 的 函数。这个入 on 就是 我们所谓的唯一实施员, single source of truth s s o t。 平台只认这个配置,从中就知道系统里有哪些事件,以及对应的处理函数应该叫什么名字。 脚本不再拥有结构主权,它只需要按照这个约定去实现具体的逻辑就行了。光有配置还不够,我们还得在编一层面动刀子,彻底消灭所谓的自由函数。 什么意思呢?就是不让脚本开发者直接在顶层定义那些函数,比如 function, on, change, e。 我们要把它们都挂载到一个统一的宿主对象上,比如 exact。 这个过程发生在编辑期,平台会先扫描入答配置,拿到所有需要的函数名,集合 f s。 然后在编辑阶段就把脚本里定义的函数,比如原本的 on change, 重写成 exact, on change 等形式。 接着通过 b 包翻译生成一个 factory 函数,这个函数负责创建执行环境,并注入必要的依赖。最后平台根据入 on, 自动从 exact 对 象里提取函数并导出。 这样做的好处显而易见,所有函数都被统一托管了,不再污染 b 包的顶层,也方便我们对这些函数进行统一管理,比如加个日制,做个权限检查,或者做 aop 增强等等。为了进一步保障安全,我们引入了沙箱模型, 这个沙箱的最小实现单元核心原则就是禁止脚本直接访问 windows 或者 global 这些全局对象。 所有的能力,包括数据、服务、工具、函数等等,都必须显示地注入到脚本的执行环境中。 这就像给脚本提供了一个隔离的工作区,它只能使用被允许的工具,不能随便乱跑。这个 factory 函数就是沙乡的核心,它负责创建这个隔离环境,注入依赖,然后执行脚本代码,最终返回一个包含所有可用函数的 exact 对 象。 这个 xck 对 象本质上就是脚本的运行时实力。平台最终导出的结构就是从这个 xck 里按照 run 的 映涉关系把对应的函数取出来。这样一来,脚本就被牢牢地限制在沙箱里,无法越界。 有了这套机制,我们就能有效地控制各种风险。比如,开发者少导出了函数怎么办?没关系,平台可以自动补齐。 如果他多导出了或者写错了结构,平台也能忽略掉那些未声明的能力,或者直接按规则统一生成正确的结构。 记住,结构永远由平台掌控。而且我们还能在编一期做校验,如果入 他 on 里写了某个函数,但脚本里没实现,那就直接报错,编一失败。反过来,如果脚本里实现了个函数,但如果 on 里没引用,那就给个警告,提醒你可能有荣誉代码。 甚至可以在运行期用 rap 函数对每个导出的函数进行增强。比如加个 before 执行前, after 执行后 error 错误处理的钩子,实现更精细的监控和治理。 总结一下,我们提出的这套方案本质上是一个配置驱动的编一期受控的运行期隔离的脚本执行引擎。 他具备几个关键特性,首先,他把脚本 dsl 化,让业务逻辑更规范。其次,他借鉴了编纫器的思想,进行编纫器的重写和校研。在此,他采用了沙箱安全模型隔离脚本的执行环境。 最后,他提供了强大的平台级可治理能力,可以说,这已经触及了低代码规则引擎、表达式系统等领域的内核级设计。 如果你正在做表单规则引擎、 bpm、 动态脚本表达式加事件系统,或者更广泛的可配置业务逻辑平台,那么这套方案提供了一个非常坚实的基础, 它不仅解决了当前的问题,更重要的是它指明了一个可以长期演进,不会轻易推翻重来的正确方向。 未来,我们可以基于此扩展出更详细的规范和白皮书,比如脚本执行引擎安全白皮书、低代码脚本 dsl 设计规范等等。这套方案的价值就在于它的前瞻性和可持续性。

如果你是一位 windows 驱动开发者,那你肯定对一个问题特别头疼,对吧?就是每当代码里涉及到多线程或者中断处理的时候,眼前就会冒出一堆同步机制,让你选那个。纠结啊,真的是谁用谁知道? 没错,我说的就是他们自选锁,快速护智体,还有那个听起来很厉害的推锁。说真的,他们之间到底有啥区别?在我的这个场景下,哪一个才是最好的选择?是不是感觉每次都像在赌一把? 哎,别担心,今天呢,咱们的目标就是把这些让人头大的概念一个一个的掰开、揉碎了,讲的明明白白,我保证听完之后,你心里头就跟明镜儿似的,下次再碰到这种问题,绝对能一眼看穿,做出最正确的选择。 好,那在咱们开始之前呢,得先搞明白一个最基本的问题,我们到底为啥需要同步这么个东西? 其实很简单,你想想啊,在内核这个世界里,病发那简直是家常便饭。你的代码可能同时在好几个 cpu 上跑, 各种中断, a、 p、 c 随时都可能插进来执行,要是没有个东西护着,那些共享的数据可能一瞬间就面目全非了,然后砰,系统就蓝屏了。 行,那咱们就先从最简单最直接的那个开始说起。自选锁,我喜欢把它叫做一种暴力美学,为什么这么说呢?因为它简单粗暴,但在某些情况下效率高得惊人。所以,自选锁到底是个啥? 其实很简单,你想象一下这个场景,一个 cpu 想去拿一个锁,结果发现锁已经被别人占了, 这时候他怎么办?换做别的锁,可能就让县城去睡觉了,但自选锁不,他特别执着,他会让 cpu 就 在原地不停地空转,一遍又一遍地问,锁好了没?锁好了没?这个过程就叫自选 他的 api, 你 看,也是简单的不能再简单了。一个促使化,一个获取,一个释放。就这三板斧,非常直接,没什么花里胡哨的。 好。重点来了,用自选锁有几条铁律,你必须刻在脑子里。最关键的一点是,一旦你拿到了自选锁,当前 cpu 的 i r q l 就 会被立刻抬高到 dispatch level。 这意味着什么?意味着在这个 cpu 上,线层调度 停了,完全停了。所以啊,你看,他一边在疯狂烧 cpu, 一 边还给你设下了一个天大的陷阱, 锁定的代码里,你绝对绝对不能碰任何可能导致缺页中断的东西,不然,嘿,等着蓝屏吧。 所以杰诺就很清楚了,自选锁只能用来保护那种几条指令就能跑完的特别短的代码。 那问题就来了,如果我要保护的代码没那么短,要花点时间呢?总不能让 cpu 一 直在那傻转吧,这太浪费了。没错,所以我们需要一种更文明、更聪明的方式,来认识一下我们的下一个主角,护赤体。 在内核里呢,我们最常用的是两种,护赤体、快速护赤体和守护护赤体。它们俩最大的不同就在于怎么对待 apc, 也就是异步过程调用。 你看这个快速护持体,它工作在 passive level, 比较温和,就只禁用普通的 a p c。 但这个守护护持体呢,就严格多了,它可能会把 i r q l 抬高到 a p c level, 把所有的 a p c 都给禁掉,这个区别很重要。哦,对了,它们都支持的规就是说同一个县城可以重复获取同一个锁。 所以你看护智体的核心思路就跟自选锁完全反过来了。它的哲学是等待,而不是空转现成。拿不到锁怎么办?很简单,它会主动让出 cpu, 然后自己去排队睡觉,等锁空出来了再给唤醒。 这就意味着它非常适合用在那些持有锁时间比较长,或者需要在锁里访问分页内存的场景,安全又搞笑。 好了,说完了,老将,我们该请出今天的明星选手了。推锁,这可是现代 windows 核心理的一个大宝贝,他在性能和功能之间找到了一个堪称完美的平衡。 那推索到底牛在哪呢?他最大的一个亮点就是天生就支持毒血分离。这是什么意思呢?就是说,对于毒操作,他可以让一大堆县城同时进来,大家一起读,互不干扰。但只要有一个血操作要进来,他就避实清场,自己一个人独占。 你看它的 a p i r 设计的就特别直观,名字里带 exclusive 的 就是给学者用的独占模式,带 share 的 就是给读者用的共享模式。你想想,在那种读远大于写的场景里,这种设计能带来的性能提升,那简直是指数级的 好。到现在为止,三大主角,自选锁、互斥题、推锁我们都认识了,那最关键的问题来了,时机,写代码的时候,我到底该用哪个?别急,我给你准备了一个决策手册 来,跟着我走,就三步,保定你选不凑。第一步,先问自己,我的代码现在在每一个 i r k l 上跑,如果答案是 dispatch level 或者高,那想都别想,你唯一的选择就是次选锁。 第二步,如果是在 passive level, 再问自己,我拿锁的时间会不会很长?需不需要访问分页内存?只要有一个答案是是,那就用护尺体。第三步,如果前面两个都不满足,再看看你的场景是不是读多写少。如果是,那为了性能,果断上推锁。 你可能会好奇,为啥这个推锁能做到这么高小呢?咱们稍微往底层钻一钻,看看他背后藏着的秘密,然后我再给你念叨几句最后的安全紧箍咒, 噔噔噔,答案揭晓!推锁的全部秘密就在这么一个普普通通的纸张大小的变量里,是不是觉得有点不可思议?这么复杂的功能就靠这么点空间实现了,所以他的开销才能做到这么小。 这个小小的变量是怎么玩出这么多花样的呢?你看啊,当他的值是零,锁就是空闲的,谁都可以来拿。当他的某一个特定比特位被设为一,就代表被一个学者给霸占了。当他被当成一个数字,不停的加一,这个数字就代表着有多少个读者在里面。 最绝的是,一旦发生抢锁,这个变量马上摇身一变,变成一个真正的时针,指向一个排队等候的现成队列。不得不说,这个设计真的是太巧妙了,简直是天才。 当然了,工具再好,用错了也会出大事。所以请大家务必记住这句话,把它刻在心里,不管你用的是那种锁,死锁永远是那把悬在你头顶的利剑。 那么,为了不在病发的世界里翻车,这几条生存法则你必须遵守。第一,能不欠套锁就别欠套,实在没办法,那也必须保重,不管在代码的哪个角落,获取这几把锁的顺序必须是完全一样的。第二, i r q l i r q l 重要的事情说三遍,每种锁都有它的 i r q l 要求,搞错了就是蓝屏,没得商量。 最后,善用工具,微软给你准备了 s d v 和驱动程序验证器,这两个神器一定要打开,它们就像你的贴身保镖,能提前帮你揪出好多好多隐藏的 bug。 好 了,聊到这儿,从最暴力的自选锁,到最聪明的呼气体,再到最高效的推锁, windows 核心理,这几个看家的同步工具咱们就算是都过了一遍。 我希望今天聊的这些能帮你把脑子里那团乱麻给理顺了。最后,留个问题给大家吧,在你的实际开发工作里,有没有碰到过什么特别棘手的内核同步问题,或者有什么独门秘籍,欢迎在下面分享出来,咱们一块聊聊,共同进步。

老板娘波轮洗衣机常见的故障代码有哪些?一零一约开盖一一排水超时。一二开盖一闪一三,帐篷开关常开一场,一四进水超时。一六水位传感器报警。 一七驱动板与显示板通讯报警。一八电压过低报警。一九电压过高报警。