FPGA学习—通过数码管实现电子秒表模拟
文章目录
- 一、数码管简介
- 二、项目分析
- 三、项目源码及分析
- 四、实现效果
- 五、总结
一、数码管简介
请参阅博主以前写过的一篇电子时钟模拟,在此不再赘述。
https://blog.csdn.net/qq_54347584/article/details/130402287
二、项目分析
- 项目说明:本次项目是为了通过数码管实现秒表模拟。其中,六位数码管分别显示秒表的分位,秒位,毫秒位(由于毫秒有三位,在此只取百位和十位),其中分位和秒位,秒位和毫秒位之间用小数点隔开
- 本次项目拟设置四个模块,分别为:按键消抖模块,计数模块,数码管驱动模块,以及顶层模块
- 按键消抖模块要求:传出两个按键的脉冲信号,一个用来暂停/开始秒表的计数,一个用来清空秒表的计数
- 计数模块要求:能传出秒表的各位值以及小数点位置
- 数码管驱动模块要求:能正常显示秒表各位值
三、项目源码及分析
数码管驱动模块:
代码分析:
- 由于本开发板有六位数码管,每位数码管设置显示0-F,因此在此模块中,博主定义了一个24位的din信号(六位每位能显示十六个字符(因此每位需要四位位宽))以此来给每位数码管赋值
- 同时博主将八段式数码管拆分为七段加一段小数点,因此设计了一个六位的point_n以此来控制小数点的显示
- 其余代码与博主以前写的数码管动态显示0-F类似,在此不再赘述(如果是FPGA初学者,没有数码管开发经验,请仔细阅读博主动态显示及电子时钟两篇博客!!)
/**************************************功能介绍***********************************
Date : 2023-08-01 11:08:11
Author : majiko
Version : 1.0
Description: 动态数码管模块(动态扫描)
*********************************************************************************///---------<模块及端口声名>------------------------------------------------------
module seg_driver( input clk ,input rst_n ,input [23:0] din ,//输入6位数码管显示数据,每位数码管占4位input [5:0] point_n ,//输入小数点控制位output reg [5:0] seg_sel ,//输出位选output reg [7:0] seg_dig //输出段选
);
//---------<参数定义>--------------------------------------------------------- parameter TIME_1MS = 50_000;//1ms//数码管显示字符编码localparam NUM_0 = 7'b100_0000,//0NUM_1 = 7'b111_1001,//1NUM_2 = 7'b010_0100,//NUM_3 = 7'b011_0000,//NUM_4 = 7'b001_1001,//NUM_5 = 7'b001_0010,//NUM_6 = 7'b000_0010,//NUM_7 = 7'b111_1000,//NUM_8 = 7'b000_0000,//NUM_9 = 7'b001_1000,//A = 7'b000_1000,//B = 7'b000_0011,//bC = 7'b100_0110,//D = 7'b010_0001,//dE = 7'b000_1110,//E替换为FF = 7'b011_1111,//F替换为--DIV = 7'b011_1111;//---------<内部信号定义>-----------------------------------------------------reg [15:0] cnt_1ms ;//1ms计数器(扫描间隔计数器)wire add_cnt_1ms ;wire end_cnt_1ms ;reg [3:0] disp_data ;//每一位数码管显示的数值reg point_n_r ;//每一位数码管显示的小数点//****************************************************************
//--cnt_1ms
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_1ms <= 'd0;end else if(add_cnt_1ms)begin if(end_cnt_1ms)begin cnt_1ms <= 'd0;endelse begin cnt_1ms <= cnt_1ms + 1'b1;end endend assign add_cnt_1ms = 1'b1;//数码管一直亮assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == TIME_1MS - 1;//****************************************************************
//--seg_sel
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginseg_sel <= 6'b111_110;//循环移位实现时,需要给位选赋初值end else if(end_cnt_1ms)begin seg_sel <= {seg_sel[4:0],seg_sel[5]};//循环左移end end//****************************************************************
//--disp_data
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begindisp_data <= 'd0;point_n_r <= 1'b1;end else begin case (seg_sel)6'b111_110 : begin disp_data <= din[3:0] ; point_n_r <= point_n[0]; end//第一位数码管显示的数值6'b111_101 : begin disp_data <= din[7:4] ; point_n_r <= point_n[1]; end6'b111_011 : begin disp_data <= din[11:8] ; point_n_r <= point_n[2]; end6'b110_111 : begin disp_data <= din[15:12]; point_n_r <= point_n[3]; end6'b101_111 : begin disp_data <= din[19:16]; point_n_r <= point_n[4]; end6'b011_111 : begin disp_data <= din[23:20]; point_n_r <= point_n[5]; enddefault: disp_data <= 'd0;endcaseend end//****************************************************************
//--seg_dig
//****************************************************************// always @(posedge clk or negedge rst_n)begin // if(!rst_n)begin// seg_dig <= 8'hff;//数码管的段选如何赋值好?// end // else begin // case (disp_data)// 0 : seg_dig <= {point_n_r,NUM_0};// 1 : seg_dig <= {point_n_r,NUM_1};// 2 : seg_dig <= {point_n_r,NUM_2};// 3 : seg_dig <= {point_n_r,NUM_3};// 4 : seg_dig <= {point_n_r,NUM_4};// 5 : seg_dig <= {point_n_r,NUM_5};// 6 : seg_dig <= {point_n_r,NUM_6};// 7 : seg_dig <= {point_n_r,NUM_7};// 8 : seg_dig <= {point_n_r,NUM_8};// 9 : seg_dig <= {point_n_r,NUM_9};// 10 : seg_dig <= {point_n_r,A };// 11 : seg_dig <= {point_n_r,B };// 12 : seg_dig <= {point_n_r,C };// 13 : seg_dig <= {point_n_r,D };// 14 : seg_dig <= {point_n_r,E };// 15 : seg_dig <= {point_n_r,F };// default: seg_dig <= 8'hff;// endcase// end // endalways @(*)begin case (disp_data)0 : seg_dig <= {point_n_r,NUM_0};1 : seg_dig <= {point_n_r,NUM_1};2 : seg_dig <= {point_n_r,NUM_2};3 : seg_dig <= {point_n_r,NUM_3};4 : seg_dig <= {point_n_r,NUM_4};5 : seg_dig <= {point_n_r,NUM_5};6 : seg_dig <= {point_n_r,NUM_6};7 : seg_dig <= {point_n_r,NUM_7};8 : seg_dig <= {point_n_r,NUM_8};9 : seg_dig <= {point_n_r,NUM_9};10 : seg_dig <= {point_n_r,A };11 : seg_dig <= {point_n_r,B };12 : seg_dig <= {point_n_r,C };13 : seg_dig <= {point_n_r,D };14 : seg_dig <= {point_n_r,E };15 : seg_dig <= {point_n_r,F };16 : seg_dig <= {point_n_r,DIV };default: seg_dig <= 8'b1101_1111;endcaseendendmodule
计数器模块:
代码分析:
- 由项目分析可以得出,由于数码管资源有限,毫秒位只能实现百位和十位的显示,因此我们不妨设置一个基准单位为10ms,每当计数到10ms时,毫秒计数器才进行加一(这样毫秒计数器只需加到100次即可)
- 除此之外,秒位计数器和分位计数器的技术条件分别为毫秒计数器计满和秒位计数器计满
- 由于本次项目需要引入按键信号进行秒表的暂停、继续以及清空,因此博主引入了两位按键信号。
- 一位按键控制秒表的暂停与继续。由上述分析可知,如果想要暂停秒表的计数,我们只需暂停基准单位10ms的计数即可(其余三个计数器,均要在10ms计数器工作的前提下才能逐级工作),因此我们只需要引入一个中间信号flag,用flag作为其计数的条件即可(博主将flag初值设为0不计数,按键按下后flag反转为1开始计数,再次按下再次反转,停止计数)
- 剩余一位按键用于四个计数器的清零,一旦四个计数器全部清零,传出的数码管数据自然为0
- 在代码的最后博主将毫秒,秒,分计数器的值赋给dout,再将其传入数码管驱动模块即可(之所以是这个顺序是因为博主前面数码管驱动模块对位选信号赋值好像写反了,不过影响不大)
module counter (input wire clk ,input wire rst_n ,input wire [1:0] key_in ,//按键信号输入output wire [23:0] dout ,//数码管各位值输出output wire [5:0] point_out //小数点输出
);//内部参数定义
parameter TIME_10ms = 19'd500_000;//10ms计数器,计满秒表毫秒位加1
parameter TIME_990ms = 7'd100 ;//计数器毫秒位,以10ms为单位
parameter TIME_1s = 6'd60 ;//计数器秒位,计满清零
parameter TIME_1min = 6'd60 ;//计数器分位,计满清零//内部信号定义
reg [18:0] cnt_10ms ;//10毫秒计数器寄存器
reg [6:0] cnt_99ms ;//毫秒位计数寄存器
reg [5:0] cnt_1s ;//秒位计数器寄存器
reg [5:0] cnt_1min ;//分位计数器寄存器wire add_cnt_10ms ;
wire end_cnt_10ms ;wire add_cnt_990ms ;
wire end_cnt_990ms ;wire add_cnt_1s ;
wire end_cnt_1s ;wire add_cnt_1min ;
wire end_cnt_1min ;reg flag ;//运行/暂停标志信号寄存器
reg flag_0 ;//清零信号标志寄存器//10毫秒计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_10ms <= 1'b0;endelse if(add_cnt_10ms)beginif(end_cnt_10ms)begincnt_10ms <= 1'b0;endelse begincnt_10ms <= cnt_10ms + 1'b1;endendelse begincnt_10ms <= cnt_10ms;end
endassign add_cnt_10ms = 1'b1 && flag;//运行标志位有效
assign end_cnt_10ms = (add_cnt_10ms && cnt_10ms == TIME_10ms - 1'b1) || key_in[1];//按下清零按键也会清零//毫秒位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_99ms <= 1'b0;endelse if(add_cnt_990ms)beginif(end_cnt_990ms)begincnt_99ms <= 1'b0;endelse begincnt_99ms <= cnt_99ms + 1'b1;endendelse begincnt_99ms <= cnt_99ms;end
endassign add_cnt_990ms = end_cnt_10ms;
assign end_cnt_990ms = (add_cnt_990ms && cnt_99ms == TIME_990ms - 1'b1) || key_in[1];//秒位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_1s <= 1'b0;endelse if(add_cnt_1s)beginif(end_cnt_1s)begincnt_1s <= 1'b0;endelse begincnt_1s <= cnt_1s + 1'b1;endendelse begincnt_1s <= cnt_1s;end
endassign add_cnt_1s = end_cnt_990ms;
assign end_cnt_1s = (add_cnt_1s && cnt_1s == TIME_1s - 1'b1) || key_in[1];//分位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_1min <= 1'b0;endelse if(add_cnt_1min)beginif(end_cnt_1min)begincnt_1min <= 1'b0;endelse begincnt_1min <= cnt_1min + 1'b1;endendelse begincnt_1min <= cnt_1min;end
endassign add_cnt_1min = end_cnt_1s;
assign end_cnt_1min = (add_cnt_1min && cnt_1min == TIME_1min - 1'b1) || key_in[1];//flag信号控制秒表运行/暂停
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginflag <= 1'b0;endelse if(key_in[0])beginflag <= ~flag;endelse beginflag <= flag;end
end//输出值赋值
assign dout[23:20] = cnt_99ms % 10;
assign dout[19:16] = cnt_99ms / 10;
assign dout[15:12] = cnt_1s % 10;
assign dout[11:8] = cnt_1s / 10;
assign dout[7:4] = cnt_1min % 10;
assign dout[3:0] = cnt_1min / 10;
assign point_out = 6'b110_101 ;endmodule
按键消抖模块:
代码分析:请详细参阅博主所写的按键消抖模块博文,在此不再赘述
module key_filter#(parameter WIDTH = 2)//参数化按键位宽
(input wire clk ,input wire rst_n ,input wire [WIDTH - 1:0] key_in ,//按键输入信号output reg [WIDTH - 1:0] key_out //输出稳定的脉冲信号
);parameter MAX = 20'd1_000_000;reg [19:0] cnt_delay ; //20ms延时计数寄存器
wire add_cnt_delay ; //开始计数的标志
wire end_cnt_delay ; //结束计数的标志reg [WIDTH - 1:0] key_r0 ; //同步
reg [WIDTH - 1:0] key_r1 ; //打一拍
reg [WIDTH - 1:0] key_r2 ; //打两拍wire [WIDTH - 1:0] nedge ; //下降沿寄存器//同步打拍
always @(posedge clk or negedge rst_n) beginif(!rst_n)beginkey_r0 <= {WIDTH{1'b1}};key_r1 <= {WIDTH{1'b1}};key_r2 <= {WIDTH{1'b1}};endelse beginkey_r0 <= key_in; //同步key_r1 <= key_r0; //寄存一拍key_r2 <= key_r1; //寄存两拍end
end//20ms计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_delay <= 1'b0;endelse if(add_cnt_delay )beginif(nedge)begin //检测到下降沿从0开始计数cnt_delay <= 1'b0;endelse if(cnt_delay == MAX - 1'b1)begincnt_delay <= cnt_delay; //计数计满结束后保持,避免产生多个输出脉冲endelse begincnt_delay <= cnt_delay + 1'b1;endendelse begincnt_delay <= 1'b0;end
endassign nedge = ~key_r1 & key_r2; //下降沿检测
assign add_cnt_delay = 1'b1;
assign end_cnt_delay = add_cnt_delay && cnt_delay == MAX - 1'b1;//key_out脉冲信号赋值
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey_out <= 'd0;endelse if(cnt_delay == MAX - 2'd2)begin //计数计满前一个脉冲时产生按键脉冲key_out <= ~key_in;endelse beginkey_out <= 'd0;end
endendmodule
顶层模块:
/****
项目说明:本次项目是为了通过数码管实现秒表模拟。其中,六位数码管分别显示秒表的分位,秒位,毫秒位(百位和十位)。本次项目拟设置四个模块,分别为:按键消抖模块,计数模块,数码管驱动模块,以及顶层模块。本项目按键消抖模块要求传出两个按键的脉冲信号,一个用来暂停/开始秒表的计数,一个用来清空秒表的计数。本项目计数模块要求能传出秒表的各位值以及小数点位置本项目数码管驱动模块要求能正常显示秒表各位值
****/
module top(input wire clk ,input wire rst_n ,input wire [1:0] key_in ,output wire [5:0] sel ,output wire [7:0] seg
);wire [1:0] key_out ;
wire [23:0] din ;
wire [5:0] point_n ;seg_driver u_seg_driver( .clk (clk ),.rst_n (rst_n ),.din (din ),.point_n (point_n),.seg_sel (sel ),.seg_dig (seg )
);key_filter u_key_filter(.clk (clk ),.rst_n (rst_n ),.key_in (key_in ),.key_out (key_out)
);counter u_counter(.clk (clk ),.rst_n (rst_n ),.key_in (key_out ),.dout (din ),.point_out (point_n )
);endmodule
四、实现效果

五、总结
本项目主要锻炼了FPGA的数码管开发和计数器编写,实际仍未FPGA学习基础,博主学习时常常被数码管位选信号的段选信号的赋值绕晕,解决方法也只有自己亲自编写几遍,否则仍然无法理解余晖效应和动态扫面是如何让数码管同时显示不同字符的。后续对于基础部分的学习博主应该还会写几篇关于蜂鸣器的博文,至此算是基础语法学习结束。
再往后博主学习到IP核HLS,通讯协议时,也许会继续编写博客,但也要看博主是否有足够的精力,以及能否自己理解并讲解清楚,否则话的还是请各位自行上网寻找视频教学资料,不管是野火还是正点原子,都有针对的FPGA学习视频。
学海无涯,大家有缘再见。
相关文章:
FPGA学习—通过数码管实现电子秒表模拟
文章目录 一、数码管简介二、项目分析三、项目源码及分析四、实现效果五、总结 一、数码管简介 请参阅博主以前写过的一篇电子时钟模拟,在此不再赘述。 https://blog.csdn.net/qq_54347584/article/details/130402287 二、项目分析 项目说明:本次项目…...
区块链媒体发稿:区块链媒体宣发常见问题解析
据统计,由于区块链应用和虚拟货币的兴起,越来越多媒体对区块链领域开展报导,特别是世界各国媒体宣发全是热火朝天。但是,随着推卸责任媒体宣发的五花八门,让很多人因而上当受骗,乃至伤害一大笔资产。身为投…...
openGauss学习笔记-28 openGauss 高级数据管理-NULL值
文章目录 openGauss学习笔记-28 openGauss 高级数据管理-NULL值28.1 IS NOT NULL28.2 IS NULL openGauss学习笔记-28 openGauss 高级数据管理-NULL值 NULL值代表未知数据。无法比较NULL和0,因为它们是不等价的。 创建表时,可以指定列可以存放或者不能存…...
DAO和XML文件参数和返回值
①MyBatis中resultType和resultMap的区别 1.使用MyBatis查询数据库记录时,返回类型常用的有两种:resultType和resultMap。那么两者之间有什么区别呢? 如果只是返回一个值,简单类型,比如说String或者int,那…...
vue 浏览器右侧可拖拽小组件
目录 0. 使用场景 1. 动图示例 2. 实现方式 2.1 创建drag.js 2.2 使用v-drag 3. 结尾 0. 使用场景 很多网页在浏览器右侧有"导航"或者“智能助手”的悬浮小气泡框,比如我们的csdn☞ 作为页面友好型的引导标注,某些场景下这些小气泡可以…...
SpringMvc学习笔记五
Restful 风格路由 1. 配置类 1.1、SpringMvcConfig配置类 Configuration ComponentScan({"com.itheima.controller", "com.itheima.config"}) 方式1.2 添加com.itheima.config 扫描目录 EnableWebMvc public class SpringMvcConfig { } 1.2、ServletCo…...
ORACLE-DG总结
述 当主库的某些日志没有成功传送到备库,那么这时候就发生了归档裂缝(Archive Gap)。目前Oracle提供了两种日志GAP的检测和处理机制,分别是自动GAP处理(Automatic Gap Resolution)和FAL进程GAP处理(FAL Gap Resolution)。自动GAP处理即主库上的ARCn进程会每分钟检查备库…...
机器学习中的 K-均值聚类算法及其优缺点
K-均值聚类算法是一种常用的无监督学习算法,用于将相似的数据点分组为聚类。 其步骤如下: 1. 初始化:选择聚类数K,随机选取K个聚类中心。 2. 计算距离:计算每个数据点与K个聚类中心的距离,将其分配到距离最…...
【数据化分析和建模】一般步骤(个人工作经验总结)
近期关于【数据化分析和建模】一般步骤的思考如下。 以终为始,要解决什么问题,实现什么效果? 数据可视化分析的首要目标是通过将数据以可视化图表的形式真实、完整地呈现业务现状,为发现业务问题打好基础,包括实时的…...
视频安防监控EasyCVR平台海康大华设备国标GB28181告警布防的报文说明
TSINGSEE青犀视频监控综合管理平台EasyCVR基于云边端协同,可支持海量视频的轻量化接入与汇聚管理。平台既具备传统安防视频监控的能力,比如:视频监控直播、云端录像、云存储、录像检索与回看、告警上报、平台级联、云台控制、语音对讲等&…...
T31开发笔记:librtmp拉流测试
若该文为原创文章,转载请注明原文出处。 T31使用librtmp拉流并保存成FLV文件或H264和AAC文件。 librtmp编译在前面有教程,自行编译。 实现的目的是想要获取获取rtmp的AAC流并播放,实时双向对讲功能。 一、硬件和开发环境 1、硬件࿱…...
2308C++概念化
原文 库 //概念化(需要C20) struct 可画 {void 画(小出流 &out) const {te::call([](auto const &s, auto &out)-> decltype(s.画(out)) { s.画(out); }, *this, out);} }; struct 方形 {void 画(小出流 &out) const { out << "方形"; } }…...
flutter开发实战-实现自定义按钮类似UIButton效果
flutter开发实战-实现自定义按钮类似UIButton效果 最近开发过程中需要实现一下UIButton效果的flutter按钮,这里使用的是监听手势点击事件。 一、GestureDetector GestureDetector属性定义 GestureDetector({super.key,this.child,this.onTapDown,this.onTapUp,t…...
深度优先搜索|1034, 1020, 1254
深度优先搜索|1034. 边界着色, 机器人的运动范围,529. 扫雷游戏 边界着色机器人的运动范围扫雷问题 边界着色 把这个题分段了,先找到包括 (row, col) 的连通分量,然后再去找符合条件的边界,找到以后涂上颜色就行。 c…...
都市信息供求网servlet+jsp新闻广告出售java源代码mysql
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 都市信息供求网servletjsp 系统1权限:管理…...
kubeadm init:failed to pull image registry.k8s.io/pause:3.6
错误信息: Unfortunately, an error has occurred: timed out waiting for the condition This error is likely caused by: - The kubelet is not running - The kubelet is unhealthy due to a misconfiguration of the node in some way…...
设计模式之简单工厂模式、工厂模式、抽象工厂模式
参考: 设计模式笔记 简单工厂模式 ● 将类的创建过程交给工厂类实现,如果需要一个类对象,则直接通过工厂创建一个类。 ● 简单工厂模式不符合开闭原则 ● 适用场景:工厂类负责创建的对象比较少;客户端只知道传入工厂…...
C# 控制台彩色深度打印 工具类
文章目录 前言Nuget 环境安装代码使用打印结果 总结 前言 有时候我们想要靠打印获得程序信息,因为Dubeg模式需要一点一点断点进入进出,但是我们觉得断点运行实在是太慢了,还是直接打印后找结果会好一点。 Nuget 环境安装 想自己写的话可以看…...
Pytorch Tensor维度变换方法
1.torch.reshape()、torch.view()可以调整Tensor的shape 2.torch.unsqueeze(index)可以为Tensor增加一个维度 3.squeeze()可以删减维度 4.expand()扩展维度 5.repeat()维度重复,不常用 6.transpose(dim1, dim2)交换dim1与dim2࿰…...
微信小程序之点击文字文字自动转语音进行播放,微信小程序文字识别转语音播放
需求 一堆题目,题干需要在点击的时候进行语音朗读,不做音频上传,不然不便于维护 解决方案 点击查看微信官方文档:微信同声传译 使用流程 后台配置 mp.weixin.qq.com 设置 > 第三方设置 > 插件管理 小程序插件使用流…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
命令行关闭Windows防火墙
命令行关闭Windows防火墙 引言一、防火墙:被低估的"智能安检员"二、优先尝试!90%问题无需关闭防火墙方案1:程序白名单(解决软件误拦截)方案2:开放特定端口(解决网游/开发端口不通)三、命令行极速关闭方案方法一:PowerShell(推荐Win10/11)方法二:CMD命令…...
GeoServer发布PostgreSQL图层后WFS查询无主键字段
在使用 GeoServer(版本 2.22.2) 发布 PostgreSQL(PostGIS)中的表为地图服务时,常常会遇到一个小问题: WFS 查询中,主键字段(如 id)莫名其妙地消失了! 即使你在…...
