基于51单片机和WS2812B彩色灯带的流水灯
目录
- 系列文章目录
- 前言
- 一、效果展示
- 二、原理分析
- 三、各模块代码
- 四、主函数
- 总结
系列文章目录
前言
用彩色灯带按自己想法DIY一条流水灯,谁不喜欢呢?
所用单片机:STC15W204S
(也可以用其他1T单片机,例如,STC8G系列、STC32G系列)
用到的外设:WS2812B彩色灯带(60个灯珠)
效果查看/操作演示:B站搜索“甘腾胜”或“gantengsheng”查看。
源代码下载:B站对应视频的简介有工程文件下载链接。
一、效果展示
二、原理分析
1、用什么MCU
如果只是驱动一条灯带,并且灯珠的数量不多(少于或等于77个)的话,用STC15W204S是比较合适的。因为只需用到一个引脚,用引脚多的单片机会比较浪费,STC15W204S总共有8个引脚,除了供电的VCC和GND,就只有P30~P33和P54~P55共6个IO口引脚。并且STC15W204S是1T单片机,适合驱动灯带。
我买的板子PCB板上印错了,P54、P55印成了P34、P35。
2、显示缓存
每个灯珠需要写入24Bit(3个字节)控制显示的颜色,共有Quantity个灯珠的话,要用3*Quantity个字节作为WS2812B彩色灯带的显示缓存。
必须要用到显示缓存,不能只对其中一个灯珠的WS2812B芯片写入数据,因为灯珠内的WS2812B芯片接收的数据是靠上一个灯珠内的WS2812B芯片传递过来的。
更显灯带显示的时候要通过数据线写入3*Quantity个字节。
3、WS2812B芯片
WS2812B芯片要求我们要按G(绿)、R(红)、B(蓝)的顺序发送数据,并且每个字节要高位先发。具体的时序要求可以看一下其他博主的介绍。我们可以用空操作 nop(); 来延时,分频系数为1,频率为24.000MHz的话,一个 nop(); 执行的时长就是1/24us。
为了方便向灯珠中的WS2812B芯片写入数据,缓存数组中的数据每3个字节为一组,每组的3个字节按G、R、B的顺序存放,这样的话,需要更新显示时,就按照索引的顺序,将3*Quantity个字节发送给灯带即可。修改缓存的时候每一组也是需要按照G、R、B的顺序赋值。
第一个灯珠接收了3个字节的数据后,会将后面的数据直接传给第二个灯珠,以此类推。
4、不同灯珠数量的灯带
已经考虑到了这种情况,所以代码中作了相应的处理,修改宏定义中Quantity对应的数值即可,经过测试,如果用STC15W204S的话,1~77个灯都是可以驱动的。
5、亮度的调整
G、R、B的值越大,就表示该种颜色越亮,所以想要调整亮度的话,修改G、R、B的值就行了。
6、函数的设计
可以根据自己的需求设计对应的函数。我觉得以下函数是必须的,其他的可以自由发挥。
①写一个字节的函数
②显示缓存数据清零的函数
③更改一个灯珠对应的三个字节的缓存的函数
④更新显示的函数(将缓存数组的数据全部发送给灯带)
三、各模块代码
无
四、主函数
main.c
/*
by甘腾胜@20250131
效果查看/操作演示:可以在B站搜索“甘腾胜”或“gantengsheng”查看
开发环境:Keil C51
单片机:STC15W204S
分频系数及频率:1T@24.000MHz
外设:WS2812B彩色灯带(60个灯珠)
注意:
(1)驱动WS2812B彩色点阵屏最好用1T的单片机,想用传统的12T单片机,则需要用较高频率的晶振,并且要使能6T(双倍速)模式
(2)如果使用STC15W204S这款单片机,并且灯珠数量小于等于77的话,根据实际灯珠数量修改宏定义中Quantity对应的数值即可
*/#include <STC15F2K60S2.H> //包含寄存器定义的头文件
#include <INTRINS.H> //需要用空操作 _nop_(); 来延时//Quantity:灯珠的数量,如果用STC15W204S,则范围是:1~77(data不能超过256个字节,实测超过77就不能正常显示了)
//想控制更加多的灯珠,需要更换为有较多片外RAM的单片机,一个灯珠需要3个字节的RAM缓存
//并且把缓存数组的idata改成xdata
#define Quantity 60#define Duration1 15 //呼吸灯延时的时长,更改数值可以改变呼吸灯的快慢,数值越大,呼吸灯越慢
#define Duration2 25 //渐变灯延时的时长,更改数值可以改变渐变灯的快慢,数值越大,渐变灯越慢
#define Duration3 30 //流星流水灯延时的时长,更改数值可以改变移动的速度,数值越大,速度越慢//引脚定义
//有6个IO口,P30~P33和P54、P55
//我买的板子PCB板上印错了,P54、P55印成了P34、P35
sbit WS2812B_Din=P5^4;//用3*Quantity个字节作为WS2812B彩色灯带的显示缓存,共有Quantity个灯珠,每个灯珠需要写入24Bit(3个字节)控制显示的颜色
//WS2812B芯片要求按G、R、B的顺序发送数据,并且每个字节要高位先发
//缓存数组中每三个字节为一组,每一组分别对应一个灯珠的G(绿)、R(红)、B(蓝)三原色
//第一组对应数据传输方向的第一个灯珠,第二组对应第二个灯珠,以此类推
//STC15W204S只有256K的片内RAM空间,没有片外RAM空间,只能用idata修饰,不能用xdata修饰,否则灯带不能正常显示
//STC15W204S最多只能定义七十多个灯珠的缓存,想要控制更加多的灯,需要用有较多片外RAM空间的单片机,并且要把idata改成xdata
//想更改灯带的显示,先更改此显示缓存中的数据,再通过函数WS2812B_UpdateDisplay将显示缓存的数据写入每个灯珠的WS2812B芯片内
unsigned char idata WS2812B_Buffer[3*Quantity];//用来实现流水灯退出的效果
unsigned char code Table0[]={
0,0,0, //无显示
};//通过查表的方法显示流水灯,三个为一组,一组对应一个灯珠的R、G、B的值
unsigned char code Table1[]={ //流星流水灯
255,0,0,191,0,0,127,0,0,95,0,0,63,0,0,47,0,0,31,0,0,23,0,0, //红
15,0,0,11,0,0,7,0,0,5,0,0,3,0,0,2,0,0,1,0,0,0,0,0,0,255,0,0,191,0,0,127,0,0,95,0,0,63,0,0,47,0,0,31,0,0,23,0, //绿
0,15,0,0,11,0,0,7,0,0,5,0,0,3,0,0,2,0,0,1,0,0,0,0,0,0,255,0,0,191,0,0,127,0,0,95,0,0,63,0,0,47,0,0,31,0,0,23, //蓝
0,0,15,0,0,11,0,0,7,0,0,5,0,0,3,0,0,2,0,0,1,0,0,0,255,255,0,191,191,0,127,127,0,95,95,0,63,63,0,47,47,0,31,31,0,23,23,0, //黄
15,15,0,11,11,0,7,7,0,5,5,0,3,3,0,2,2,0,1,1,0,0,0,0,255,0,255,191,0,191,127,0,127,95,0,95,63,0,63,47,0,47,31,0,31,23,0,23, //紫
15,0,15,11,0,11,7,0,7,5,0,5,3,0,3,2,0,2,1,0,1,0,0,0,0,255,255,0,191,191,0,127,127,0,95,95,0,63,63,0,47,47,0,31,31,0,23,23, //青
0,15,15,0,11,11,0,7,7,0,5,5,0,3,3,0,2,2,0,1,1,0,0,0,255,255,255,191,191,191,127,127,127,95,95,95,63,63,63,47,47,47,31,31,31,23,23,23, //白
15,15,15,11,11,11,7,7,7,5,5,5,3,3,3,2,2,2,1,1,1,0,0,0,
};unsigned char code Table2[]={ //顺向逆向流星流水灯叠加
255,191,127,95,63,47,31,23,15,11,7,5,3,2,1,0,
};/*** @brief 延时函数,1T@24.000MHz调用可延时约xms毫秒* @param xms 要延时的时间,范围:0~65535* @retval 无*/
void Delay(unsigned int xms)
{unsigned char i,j;while(xms--){i=24;j=85;do{while(--j);}while(--i);}
}/*** @brief WS2812B彩带私有延时函数,1T@24.000MHz调用可延时约100us* @param 无* @retval 无*/
void WS2812B_Delay100us(void)
{unsigned char i,j;i=3;j=82;do{while(--j);}while(--i);
}/**
* @brief WS2812B彩色灯带清空显示缓存(需要调用函数WS2812B_UpdateDisplay才能更新灯带的显示)* @param 无* @retval 无*/
void WS2812B_Clear(void)
{unsigned int i; //如果用unsigned char而不用unsigned int的话,Quantity大于85之后,此函数就会陷入死循环//用unsigned int定义是为了方便拓展显示更多的灯珠for(i=0;i<3*Quantity;i++){WS2812B_Buffer[i]=0;}
}/*** @brief WS2812B彩色灯带按灯带数据传输方向移动显示数组Array中的数据(需要调用函数WS2812B_UpdateDisplay才能更新灯带的显示)* @param *Array Array为传递过来的指针(即内存地址),数组名就是数组的首地址* @param Offset 偏移量,范围:0~Array数组数据总数/3-1Array中的数据三个为一组,移动后第一个灯珠显示第Offset组的数据(第0组为数组Array中的前三个数据)* @retval 无*/
void WS2812B_MoveInOrder(unsigned char *Array,unsigned int Offset){ //Offset用unsigned int定义是为了方便拓展显示更长的流水灯unsigned int i;//缓存数组中的数据按数组索引增大的方向移动3个字节for(i=0;i<Quantity-1;i++){WS2812B_Buffer[3*(Quantity-i)-3]=WS2812B_Buffer[3*(Quantity-i)-6];WS2812B_Buffer[3*(Quantity-i)-2]=WS2812B_Buffer[3*(Quantity-i)-5];WS2812B_Buffer[3*(Quantity-i)-1]=WS2812B_Buffer[3*(Quantity-i)-4];}//移动后,对第一个灯珠对应的三个字节进行赋值,从而实现流水灯的效果Array+=Offset*3; //指针方面的知识不清楚的先去了解一下WS2812B_Buffer[1]=*Array; //WS2812B_Buffer中按G、R、B存放,WS2812B_Buffer[0]=*(Array+1); //Array数组中按R、G、B存放,WS2812B_Buffer[2]=*(Array+2); //赋值的时候需要调一下顺序
}/*** @brief WS2812B彩色灯带按灯带数据传输方向的反方向移动显示数组Array中的数据(需要调用函数WS2812B_UpdateDisplay才能更新灯带的显示)* @param *Array Array为传递过来的指针(即内存地址),数组名就是数组的首地址* @param Offset 偏移量,范围:0~Array数组数据总数/3-1Array中的数据三个为一组,移动后最后一个灯珠显示第Offset组的数据(第0组为数组Array中的前三个数据)* @retval 无*/
void WS2812B_MoveInReverseOrder(unsigned char *Array,unsigned int Offset)
{unsigned int i;//缓存数组中的数据按数组索引减小的方向移动3个字节for(i=0;i<Quantity-1;i++){WS2812B_Buffer[3*i ]=WS2812B_Buffer[3*i +3];WS2812B_Buffer[3*i+1]=WS2812B_Buffer[3*i+1+3];WS2812B_Buffer[3*i+2]=WS2812B_Buffer[3*i+2+3];}//移动后,对最后一个灯珠对应的三个字节进行赋值,从而实现流水灯的效果Array+=Offset*3;WS2812B_Buffer[3*Quantity-2]=*Array; //WS2812B_Buffer中按G、R、B存放,WS2812B_Buffer[3*Quantity-3]=*(Array+1); //Array数组中按R、G、B存放,WS2812B_Buffer[3*Quantity-1]=*(Array+2); //赋值的时候需要调一下顺序
}/*** @brief WS2812B彩色灯带设置一个灯珠的缓存(需要调用函数WS2812B_UpdateDisplay才能更新灯带的显示)* @param Position 要设置的位置,范围:0~Quantity-1,对应第1个到第Quantity个灯珠* @param R 红(Red),范围:0~255* @param G 绿(Green),范围:0~255* @param B 蓝(Blue),范围:0~255* @retval 无*/
void WS2812B_SetBuffer(unsigned int Position,unsigned char R,unsigned char G,unsigned char B)
{//缓存数组中,每三个为一组,每一组按G、R、B的顺序存放,//这样方便数据的写入,通过数据线按数组索引顺序直接写入缓存数组的3*Quantity个字节的数据就行了WS2812B_Buffer[3*Position ]=G;WS2812B_Buffer[3*Position+1]=R;WS2812B_Buffer[3*Position+2]=B;
}/*** @brief WS2812B彩色灯带写入一个字节* @brief 频率要求:1T@24.000MHz,如果要换其他频率,则需要调整“_nop_();”的数量* @param Byte 要写入的字节* @retval 无*/
void WS2812B_WriteByte(unsigned char Byte)
{unsigned char i;// EA=0; //关闭总中断(如果用到中断的话)(时序要求严格,不能被打断),并要求中断函数执行的时间不能太长//时间太长,相当于发送了重置信号for(i=0;i<8;i++){if(Byte&(0x80>>i)) //写1(高位先发){WS2812B_Din=1; //根据高电平的时长确定发送的是1还是0,跟DS18B20类似//用空操作进行延时,单片机使用不同的频率,就需要不一样“_nop_();”的数量_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();WS2812B_Din=0; //经测试,数据线拉低后不用加延时}else //写0{WS2812B_Din=1;_nop_();_nop_();_nop_();_nop_();_nop_();WS2812B_Din=0; //经测试,数据线拉低后不用加延时}}// EA=1; //开启总中断}/*** @brief WS2812B彩色灯带更新显示,将显示缓存数组WS2812B_Buffer的数据写入到灯珠的WS2812B芯片内* @param 无* @retval 无*/
void WS2812B_UpdateDisplay(void)
{unsigned int i;for(i=0;i<3*Quantity;i++){WS2812B_WriteByte(WS2812B_Buffer[i]);} //连续写入显示缓存的3*Quantity个字节WS2812B_Delay100us(); //Reset(重置)信号
}void main()
{unsigned int i,j,k;unsigned char Sum; //用来控制顺向和逆向流星流水灯的叠加显示//Sum表示顺向或逆向流星流水灯出现的个数总和-1P3M1=0;P3M0=0; //将P3口设置为上拉模式P5M1=0;P5M0=0; //将P5口设置为上拉模式while(1){//呼吸灯(红、绿、蓝、黄、紫、青、白)for(k=0;k<7;k++) //总共要显示七种颜色的呼吸灯{for(i=0;i<256;i=i+3) //变亮{for(j=0;j<Quantity;j++){switch(k){case 0:WS2812B_SetBuffer(j,i,0,0);break; //红case 1:WS2812B_SetBuffer(j,0,i,0);break; //绿case 2:WS2812B_SetBuffer(j,0,0,i);break; //蓝case 3:WS2812B_SetBuffer(j,i,i,0);break; //黄case 4:WS2812B_SetBuffer(j,i,0,i);break; //紫case 5:WS2812B_SetBuffer(j,0,i,i);break; //青case 6:WS2812B_SetBuffer(j,i,i,i);break; //白default:break;}}WS2812B_UpdateDisplay(); //更新显示Delay(Duration1); //延时“Duration1”ms}for(i=0;i<256;i=i+3) //变暗{for(j=0;j<Quantity;j++){switch(k){case 0:WS2812B_SetBuffer(j,255-i,0,0);break; //红case 1:WS2812B_SetBuffer(j,0,255-i,0);break; //绿case 2:WS2812B_SetBuffer(j,0,0,255-i);break; //蓝case 3:WS2812B_SetBuffer(j,255-i,255-i,0);break; //黄case 4:WS2812B_SetBuffer(j,255-i,0,255-i);break; //紫case 5:WS2812B_SetBuffer(j,0,255-i,255-i);break; //青case 6:WS2812B_SetBuffer(j,255-i,255-i,255-i);break; //白default:break;}}WS2812B_UpdateDisplay();Delay(Duration1); //更改延时时间可以改变呼吸灯的快慢}}//红绿蓝三原色渐变for(i=0;i<256;i=i+3) //红变亮,至全亮{for(j=0;j<Quantity;j++){WS2812B_SetBuffer(j,i,0,0);}WS2812B_UpdateDisplay(); //更新显示Delay(Duration1);}for(k=0;k<2;k++) //循环2次{for(i=0;i<256;i=i+3) //红->绿渐变{for(j=0;j<Quantity;j++){WS2812B_SetBuffer(j,255-i,i,0); //红变暗,至全灭,绿变亮,至全亮}WS2812B_UpdateDisplay(); //更新显示Delay(Duration2);}for(i=0;i<256;i=i+3) //绿->蓝渐变{for(j=0;j<Quantity;j++){WS2812B_SetBuffer(j,0,255-i,i); //绿变暗,至全灭,蓝变亮,至全亮}WS2812B_UpdateDisplay(); //更新显示Delay(Duration2);}for(i=0;i<256;i=i+3) //蓝->红渐变{for(j=0;j<Quantity;j++){WS2812B_SetBuffer(j,i,0,255-i); //蓝变暗,至全灭,红变亮,至全亮}WS2812B_UpdateDisplay(); //更新显示Delay(Duration2);}}for(i=0;i<256;i=i+3) //红变暗,至全灭{for(j=0;j<Quantity;j++){WS2812B_SetBuffer(j,255-i,0,0);}WS2812B_UpdateDisplay(); //更新显示Delay(Duration1);}//流星流水灯(红、绿、蓝、黄、紫、青、白)for(j=0;j<2;j++) //正向,循环2次{for(i=0;i<16*7;i++) //每种颜色流星灯的长度是16个灯珠,总共有7种颜色{WS2812B_MoveInOrder(Table1,i);WS2812B_UpdateDisplay();Delay(Duration3); //更改延时时间可以改变流星灯的速度}}for(i=0;i<Quantity;i++) //退出{WS2812B_MoveInOrder(Table0,0);WS2812B_UpdateDisplay();Delay(Duration3);}for(j=0;j<2;j++) //逆向,循环2次{for(i=0;i<16*7;i++){WS2812B_MoveInReverseOrder(Table1,i);WS2812B_UpdateDisplay();Delay(Duration3);}}for(i=0;i<Quantity;i++) //退出{WS2812B_MoveInReverseOrder(Table0,0);WS2812B_UpdateDisplay();Delay(Duration3);}//三原色流星流水灯顺向逆向叠加//相遇的时候会有颜色叠加,看不清楚可以增长延时观察for(k=0;k<2;k++) //循环2次{Sum=0;for(j=0;j<Quantity+16;j++) //顺红逆绿{WS2812B_Clear(); //清空缓存for(i=0;i<=Sum;i++){if(j<16) //流星灯进入过程{WS2812B_Buffer[3*(Sum-i)+1]=Table2[i]; //红WS2812B_Buffer[3*(Quantity-(Sum-i))-3]=Table2[i]; //绿}else if(j-i<Quantity) //完全进入及退出{WS2812B_Buffer[3*(j-i)+1]=Table2[i]; //红WS2812B_Buffer[3*(Quantity-(j-i))-3]=Table2[i]; //绿}}WS2812B_UpdateDisplay();Sum++; //每经过一个Delay延时,流星灯进入的数量+1if(Sum>15){Sum=15;} //流星灯长度为1~16,对应sum的0~15,完全进入后保持15不变//Table2数组中16个数据255,191,127,95,63,47,31,23,15,11,7,5,3,2,1,0,对应的灯珠的亮度Delay(Duration3);}Sum=0;for(j=0;j<Quantity+16;j++) //顺蓝逆红{WS2812B_Clear(); //清空缓存for(i=0;i<=Sum;i++){if(j<16) //流星灯进入过程{WS2812B_Buffer[3*(Sum-i)+2]=Table2[i]; //蓝WS2812B_Buffer[3*(Quantity-(Sum-i))-2]=Table2[i]; //红}else if(j-i<Quantity) //完全进入及退出{WS2812B_Buffer[3*(j-i)+2]=Table2[i]; //蓝WS2812B_Buffer[3*(Quantity-(j-i))-2]=Table2[i]; //红}}WS2812B_UpdateDisplay();Sum++;if(Sum>15){Sum=15;}Delay(Duration3);}Sum=0;for(j=0;j<Quantity+16;j++) //顺绿逆蓝{WS2812B_Clear();for(i=0;i<=Sum;i++){if(j<16){WS2812B_Buffer[3*(Sum-i)]=Table2[i]; //绿WS2812B_Buffer[3*(Quantity-(Sum-i))-1]=Table2[i]; //蓝}else if(j-i<Quantity){WS2812B_Buffer[3*(j-i)]=Table2[i]; //绿WS2812B_Buffer[3*(Quantity-(j-i))-1]=Table2[i]; //蓝}}WS2812B_UpdateDisplay();Sum++;if(Sum>15){Sum=15;}Delay(Duration3);}}}
}
总结
感觉WS2812B芯片对时序的要求并没有像手册说的那么严格。
相关文章:

基于51单片机和WS2812B彩色灯带的流水灯
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码四、主函数总结 系列文章目录 前言 用彩色灯带按自己想法DIY一条流水灯,谁不喜欢呢? 所用单片机:STC15W204S (也可以用其他1T单片机,例如,S…...

DFS(深度优先搜索)与回溯算法详解
DFS(深度优先搜索)与回溯算法详解 一、DFS 基础 1. 什么是DFS? 深度优先搜索(Depth-First Search,DFS)是一种用于遍历或搜索树或图的算法。其核心思想是: 一条路走到黑:从起点出发…...

服务器虚拟化技术详解与实战:架构、部署与优化
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 引言 在现代 IT 基础架构中,服务器虚拟化已成为提高资源利用率、降低运维成本、提升系统灵活性的重要手段。通过服务…...

数据分析系列--②RapidMiner导入数据和存储过程
一、下载数据 二、导入数据 1. 在本地计算机中创建3个文件夹 2. 从本地选择.csv或.xlsx 三、界面说明 四、存储过程 1.保存 Congratulations, you are done. 一、下载数据 点击下载AssociationAnalysisData.xlsx数据集 二、导入数据 1. 在本地计算机中创建3个文件夹 2. 从…...

CSS 背景与边框:从基础到高级应用
CSS 背景与边框:从基础到高级应用 1. CSS 背景样式1.1 背景颜色示例代码:设置背景颜色 1.2 背景图像示例代码:设置背景图像 1.3 控制背景平铺行为示例代码:控制背景平铺 1.4 调整背景图像大小示例代码:调整背景图像大小…...

国内外人工智能AI工具网站大全(一键收藏,应有尽有)
本文由 大侠(AhcaoZhu)原创,转载请声明。 链接: https://blog.csdn.net/Ahcao2008 国内外人工智能AI工具网站大全(一键收藏,应有尽有) 摘要一、AI写作工具二、AI图像工具2.1、常用AI图像工具2.2、AI图片插画生成2.3、AI图片背景移…...

Java中初步使用websocket(springBoot版本)
一、什么是websocket WebSocket是一种在Web应用程序中实现实时双向通信的协议。它为浏览器和服务器之间提供了一种持久连接,在一个连接上可以双向传输数据。相比传统的HTTP协议,WebSocket具有更低的延迟和更高的效率。 WebSocket使用了类似于握手的方式来…...

2025年大年初一篇,C#调用GPU并行计算推荐
C#调用GPU库的主要目的是利用GPU的并行计算能力,加速计算密集型任务,提高程序性能,支持大规模数据处理,优化资源利用,满足特定应用场景的需求,并提升用户体验。在需要处理大量并行数据或进行复杂计算的场景…...

K8S ReplicaSet 控制器
一、理论介绍 今天我们来实验 ReplicaSet 控制器(也叫工作负载)。官网描述如下: 1、是什么? ReplicaSet 副本集, 维护一组稳定的副本 Pod 集合。 2、为什么需要? 解决 pod 被删除了,不能自我恢…...

FreeRTOS学习 --- 任务调度
开启任务调度器 作用:用于启动任务调度器,任务调度器启动后, FreeRTOS 便会开始进行任务调度 该函数内部实现,如下: 1、创建空闲任务(优先级最低) 2、如果使能软件定时器,则创建定…...

【小鱼闪闪】单片机开发工具——米思齐软件下载安装(图文)
浏览器打开网址 mixly.org, 在软件平台选择mixly离线版。 最新版本为3.0,会支持audinio, ESP32、ESP8266 , 可以选择下载安装器或者完整版。 这里选择下载安装器,下载后运行“一键更新.bat”,即可自动下载最新版本的M…...

MFC开发,给对话框添加垂直滚动条并解决鼠标滚动响应的问题
无论在使用QT或者MFC进行界面开发时,都会出现在一个对话框里面存在好多的选项,导致对话框变得非常长或者非常大,就会显现的不美观,在这种情况下通常是添加一个页面的滚动条来解决这个问题,下面我们就来介绍给MFC的对话…...

动态规划DP 最长上升子序列模型 导弹防御模型(题目分析+C++完整代码实现)
概览检索 动态规划DP 最长上升子序列模型 导弹防御系统 原题链接 AcWiing 187. 导弹防御系统 题目描述 为了对抗附近恶意国家的威胁,R国更新了他们的导弹防御系统。 一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。 例如࿰…...

LevelDB 源码阅读:写入键值的工程实现和优化细节
读、写键值是 KV 数据库中最重要的两个操作,LevelDB 中提供了一个 Put 接口,用于写入键值对。使用方法很简单: leveldb::Status status leveldb::DB::Open(options, "./db", &db); status db->Put(leveldb::WriteOptions…...

药店药品销售管理系统的设计与实现
标题:药店药品销售管理系统的设计与实现 内容:1.摘要 摘要:本文介绍了药店药品销售管理系统的设计与实现。该系统旨在提高药店的运营效率和管理水平,通过信息化手段实现药品销售、库存管理、财务管理等功能。本文详细阐述了系统的需求分析、设计思路、技…...

人格分裂(交互问答)-小白想懂Elasticsearch
通过交互式追问了解一个中间件 ? 啥是Elasticsearch ! 分布式搜索和分析引擎 ? 为啥是分布式搜索,单体难道用不了吗 ? 实际上是说这个东西可以分布式部署 ! 单机可用但扩展性差,分布式通过分片、副本和负载均衡实现海量数据存储与高并发处理 ? 提…...

【论文投稿-第八届智能制造与自动化学术会议(IMA 2025)】HTML, CSS, JavaScript:三者的联系与区别
大会官网:www.icamima.org 目录 前言 一、HTML(超文本标记语言):网页的骨架 HTML 的作用: 例子: 总结: 二、CSS(层叠样式表):网页的外观设计 CSS 的…...

python | OpenCV小记(一):cv2.imread(f) 读取图像操作(待更新)
python | OpenCV小记(一):cv2.imread(f)读取图像操作 1. 为什么 [:, :, 0] 提取的是第一个通道(B 通道)?OpenCV 的通道存储格式索引操作 [:, :, 0] 的解释常见误解 1. 为什么 [:, :,…...

网络工程师 (9)文件管理
一、树形目录结构 (一)定义与构成 树形目录结构由一个根目录和若干层子文件夹(或称为子目录)组成,它像一棵倒置的树。这棵树的根称为根文件夹(也叫根目录),从根向下,每一…...

Java中的线程池参数(详解)
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {} 此构造方法的参数如下: int corePoolSize&…...

2 MapReduce
2 MapReduce 1. MapReduce 介绍1.1 MapReduce 设计构思 2. MapReduce 编程规范3. Mapper以及Reducer抽象类介绍1.Mapper抽象类的基本介绍2.Reducer抽象类基本介绍 4. WordCount示例编写5. MapReduce程序运行模式6. MapReduce的运行机制详解6.1 MapTask 工作机制6.2 ReduceTask …...

如何用函数去计算x年x月x日是(C#)
如何用函数去计算x年x月x日是? 由于现在人工智能的普及,我们往往会用计算机去算,或者去记录事情 1.计算某一年某一个月有多少天 2.计算某年某月某日是周几 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threadin…...

开发过程中如何减少属性注释?
一、注释冗余 举个例子,我们在开发项目中肯定会有状态字段,现在有个工单状态枚举 StatusEnum.java package cn.zxj.note;/*** author: Administrator* since: 2025/1/30 14:40* description:*/ public enum StatusEnum {TO_BE_SUBMITTED(1,"待提交…...

NX/UG二次开发—CAM—快速查找程序参数名称
使用UF_PARAM_XXX读取或设置参数时,会发现程序中有一个INT类型参数param_index,这个就是对应程序中的参数,比如读取程序余量,则param_index = UF_PARAM_STOCK_PART,读取程序的加工坐标系则param_index = UF_PARAM_MCS等等。 你需要读取什么参数,只要只能在uf_param_indic…...

socket实现HTTP请求,参考HttpURLConnection源码解析
背景 有台服务器,网卡绑定有2个ip地址,分别为: A:192.168.111.201 B:192.168.111.202 在这台服务器请求目标地址 C:192.168.111.203 时必须使用B作为源地址才能访问目标地址C,在这台服务器默认…...

访问CMOS RAM
实验内容、程序清单及运行结果 访问CMOS RAM(课本实验14) 代码如下: assume cs:code data segment time db yy/mm/dd hh:mm:ss$ ;int 21h 显示字符串,要求以$结尾 table db 9,8,7,4,2,0 ;各时间量的存放单元 data ends cod…...

解决AnyConnect开机自启动问题
文章目录 一、问题描述二、解决方案 (Windows)1.开启-设置2.点击“应用”3.点击“启动”,选择“关” 三、参考文章 一、问题描述 学校指定的VPN总是开机自启动,然而 设置-Preferences 中却没有取消开机自启的选项。 似乎开机自启是必然的,我…...

芯片AI深度实战:进阶篇之vim内verilog实时自定义检视
【痛点】 传统Verilog开发中,工程师不断"编码→仿真→查错"的循环。本文整合AST解析与Vim编辑器,在编码阶段即实现: ✔️ 自动标记逻辑问题 ✔️ AI+ 发现涉及多模块逻辑错误 ✔️ 强制代码风格 【解决方案】 1️⃣ 基于AST的精准模式匹配 - 深度集成…...

数据结构实战之线性表(一)
一.线性表的定义和特点 线性表的定义 线性表是一种数据结构,它包含了一系列具有相同特性的数据元素,数据元素之间存在着顺序关系。例如,26个英文字母的字符表 ( (A, B, C, ....., Z) ) 就是一个线性表,其中每个字母就是一个数据…...

jdk8项目升级到jdk17——岁月云实战
由于很早之前就升级springboot版本到2.7.9,以前做好了铺垫,相对升级要容易一些。 1 项目打包成exe 1.1 jpackage打包jar C:\Users\39305\Desktop\数量核对>jpackage ^ More? --type exe ^ More? --name zp-server ^ More? --input C:\Use…...