Mkdm的51单片机学习日记:实时时钟DS1302

15.2 SPI时序初步认识

单片机常用的通信协议有三种:SPI,UART,I2C

SPI:Serial Peripheral Interface 串行外围设备接口,是一种全双工,同步的通信总线

常用于单片机与EEPROM,FLASH,实时时钟,数字信号处理器等器件的通信

通信原理:主从方式,标准SPI一共有四条线:

SSEL:从设备片选使能信号,如果从设备是低电平使能,当拉低这个引脚时,从设备就会被选中

SCLK:时钟信号,主机产生,类似于I2C的SCL

MOSI:主机给从机发送指令或者数据的通道

MISO:主机读取从机的状态或者数据的通道

补充:CPOL:Clock Polarity 时钟极性,如果SCLK在空闲时刻的空闲状态是高电平,那么CPOL=1,如果SCLK空闲状态是低电平,那么CPOL = 0

CPHA: Clock Phase 时钟相位

如果主机在上升沿输出数据,从机就只能在下降沿采样这个数据

CPHA = 1:就表示数据的输出是在一个时钟周期的第一个沿上,至于这个沿是上升沿还是下降沿,这要视 CPOL 的值而定, CPOL=1 那就是下降沿,反之就是上升沿。那么数据的采样自然就是在第二个沿上了

CPHA=0,就表示数据的采样是在一个时钟周期的第一个沿上,同样它是什么沿由 CPOL决定。那么数据的输出自然就在第二个沿上了。
以CPOL=1 CPHA =1为例:(SCLK空闲时是高电平,在下降沿时数据输出,在上升沿时数据采样)

SCK第一个沿到来时MOSI和MISO都发生变化

SCK第二个沿到来时MOSI和MISO都不变,采样数据很稳定

注意:数据采样时MOSI和MISO一定是稳定的,发送数据时一定是不稳定的

15.3 实时时钟芯片DS1302

1、 DS1302 是一个实时时钟芯片,可以提供秒、分、小时、日期、月、年等信息,并且还有软件自动调整的能力,可以通过配置 AM/PM 来决定采用 24 小时格式还是 12 小时格式。

2、拥有 31 字节数据存储 RAM。

3、串行 I/O 通信方式,相对并行来说比较节省 IO 口的使用。

4、 DS1302 的工作电压比较宽,在 2.0~5.5V 的范围内都可以正常工作。

5、 DS1302 这种时钟芯片功耗一般都很低,它在工作电压 2.0V 的时候,工作电流小于300nA。

6、 DS1302 共有 8 个引脚,有两种封装形式,一种是 DIP-8 封装,芯片宽度(不含引脚)是 300mil,一种是 SOP-8 封装,有两种宽度,一种是 150mil,一种是 208mil。

1:VCC2 主电源正极引脚

2,3:晶振输入与输出引脚

4:GND

5:CE 使能引脚,接单片机IO口

6:数据传输引脚,接单片机IO口

7:SCLK通信时钟引脚

8:VCC1 备用时钟引脚(可以选择,如果选择就要加一个备用电源,在掉电时还是可以正常工作)

DS1302寄存器介绍:

先来说一下DS1302的一条指令,一共8位(1个字节)

7:固定为1

6:选择RAM功能还是时钟功能(DS1302可以当作RAM使用)

1到5:决定了寄存器的五位地址

0:读写位,如果是1就是一条要求读的指令,如果是0那就是一条要求写的指令

接下来再说寄存器:

一共有8个与时钟有关的寄存器,

寄存器0:最高位用来判断时钟在掉电以后是否正常运行,剩下的7位中,高三位是秒的10位(最大是5,也就是101,所以三位足够了),低四位是秒的个位(最大是9,1001)

注意:这些数字全部是BCD码

寄存器1:低七位中高三位是分的10位,低四位是分的个位

寄存器2:bit7是1代表12小时制,0代表24小时制

bit6固定为0,bit5在12小时制下0代表上午,1代表下午   24 小时制下和 bit4 一起代表了小时的十位(12小时制下小时的十位只有0或1,24小时制下是0,1,2)

低四位表示秒

寄存器3:高2位固定为0,bit5 和 bit4 是日期的十位,低 4 位是日期的个位。

寄存器 4:高 3 位固定是 0, bit4 是月的十位,低 4 位是月的个位。

寄存器 5:高 5 位固定是 0,低 3 位代表了星期。

寄存器 6:高 4 位代表了年的十位,低 4 位代表了年的个位。请特别注意,这里的 00~ 99 指的是 2000 年~2099 年。

寄存器 7:最高位一个写保护位,如果这一位是 1,那么是禁止给任何其它寄存器或者那 31 个字节的 RAM 写数据的。因此在写数据之前,这一位必须先写成 0。

DS1302通信时序介绍:

三根线,分别是 CE、 I/O 和 SCLK,DS1302的通信是SPI的变异种类
对比一下SPI通信 和DS1302与单片机之间的数据传输:

对于SPI通信,在CPOL = 0 且CPHA = 0的时候,上升沿从机进行数据采样,下降沿主机输出数据

(或者上升沿主机进行数据采样,下降沿从机输出数据)

对于DS1302,先发送一个指令,这个指令就已经告知选择RAM功能还是时钟功能,以及要操作的寄存器的五位地址,以及对这个进行读操作或是写操作,进行写操作时,就将8个位的数据写入      注意同样是在上升沿时DS1302作为从机进行数据采样

同理,再读数据时,在上升沿时DS1302作为从机先读取指令,在下降沿时输出数据

注意:SPI通信协议与DS1302的通信协议还是不完全相同的,单片机没有标准的SPI接口,只能用IO口模拟通信过程(所以数据读取和时钟沿变化不可能同时),必须要先读取IO口上的数据,再拉高SCLK产生上升沿(主机在接收数据时一定是上升沿)

先来一个简单的Lcd时钟,可以显示现在的年月日星期,以及时分秒

只写出main.c文件的代码,Lcd1602.c的代码请翻阅以前的博客:

#include <reg52.h>sbit DS1302_CE = P1^7;
sbit DS1302_CK = P3^5;
sbit DS1302_IO = P3^4;bit flag200ms = 0;       //200ms定时标志
unsigned char T0RH = 0;  //T0重载值的高字节
unsigned char T0RL = 0;  //T0重载值的低字节void ConfigTimer0(unsigned int ms);
void InitDS1302();
unsigned char DS1302SingleRead(unsigned char reg);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);void main()
{unsigned char i;unsigned char psec = 0xAA;//秒数的上一个状态unsigned char time[8];//读取DS1302时间的数据存储区unsigned char str[12];//要显示的字符串EA=1;//开启总中断ConfigTimer0(1);//定时器0的溢出时间是1msInitDS1302();InitLcd1602();//初始化函数while(1){if(flag200ms)//每过200ms就刷新一次time数组{flag200ms = 0;for(i=0;i<7;i++){time[i] = DS1302SingleRead(i);}if(time[0]!= psec){str[0]='2';str[1]='0';str[2] = (time[6]>>4) + '0'; str[3] = (time[6] & 0x0F) + '0';str[4] = '-';str[5] = (time[4]>>4) + '0'; str[6] = (time[4] & 0x0F) + '0'; str[7] = '-';str[8] = (time[3]>>4) + '0'; str[9] = (time[3] & 0x0F) + '0'; str[10] = '\0';LcdShowStr(0,0,str);str[0] = (time[5]&0x0F) + '0';str[1] = '\0';LcdShowStr(11,0,"week");LcdShowStr(15,0,str);str[0] = (time[2]>>4) + '0'; str[1] = (time[2] & 0x0F) + '0';str[2] = ':';str[3] = (time[1]>>4) + '0'; str[4] = (time[1] & 0x0F) + '0';str[5] = ':';str[6] = (time[0]>>4) + '0'; str[7] = (time[0] & 0x0F) + '0';str[8] = '\0';LcdShowStr(4,1,str);psec = time[0];}}}
}/* 发送一个字节到DS1302通信总线上 */
void DS1302ByteWrite(unsigned char dat)
{unsigned char mask;for(mask=0x01;mask!=0;mask<<=1){if((dat&mask) != 0){DS1302_IO = 1;}else{DS1302_IO = 0;}DS1302_CK=1;DS1302_CK=0;}DS1302_IO = 1;}/* 由DS1302通信总线上读取一个字节 */
unsigned char DS1302ByteRead()
{unsigned char mask;unsigned char dat = 0;for(mask=0x01;mask!=0;mask<<=1){if(DS1302_IO!=0)//必须先读取引脚状态,然后才能改变时钟,改变时钟以后这一位数据就处理完毕,进入下一个数据位(IO的数据就会变){dat|=mask;}DS1302_CK=1;DS1302_CK=0;}return dat;
}/* 用单次写操作向某一寄存器写入一个字节,reg-寄存器地址,dat-待写入字节 */
void DS1302SingleWrite(unsigned char reg, unsigned char dat)
{DS1302_CE = 1;DS1302ByteWrite((reg<<1)|0x80);//先给这个寄存器一个要写的命令DS1302ByteWrite(dat);//然后才能将数据写入DS1302_CE = 0;
}/* 用单次读操作从某一寄存器读取一个字节,reg-寄存器地址,返回值-读到的字节 */
unsigned char DS1302SingleRead(unsigned char reg)
{unsigned char dat;DS1302_CE = 1;DS1302ByteWrite((reg<<1)|0x81);//先给这个寄存器的地址处写一条指令,通知要读数据dat = DS1302ByteRead();DS1302_CE = 0;return dat;
}/* DS1302初始化,如发生掉电则重新设置初始时间 */
void InitDS1302()
{unsigned char i;unsigned char code InitTime[] = {  //2013年10月8日 星期二 12:30:00  是一个初始时间,掉电时进行初始化要给一个初始时间0x00,0x30,0x12, 0x08, 0x10, 0x02, 0x13};DS1302_CE = 0;DS1302_CK = 0;//完成初始化if((DS1302SingleRead(0)&0x80 )!= 0)//如果寄存器0的最高位CH不为0,那么说明正常运行{DS1302SingleWrite(7,0x00);//取消写保护for(i=0;i<7;i++){DS1302SingleWrite(i,InitTime[i]);}}}/* 配置并启动T0,ms-T0定时时间 */
void ConfigTimer0(unsigned int ms)
{unsigned long tmp;  //临时变量tmp = 11059200 / 12;      //定时器计数频率tmp = (tmp * ms) / 1000;  //计算所需的计数值tmp = 65536 - tmp;        //计算定时器重载值tmp = tmp + 12;           //补偿中断响应延时造成的误差T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节T0RL = (unsigned char)tmp;TMOD &= 0xF0;   //清零T0的控制位TMOD |= 0x01;   //配置T0为模式1TH0 = T0RH;     //加载T0重载值TL0 = T0RL;ET0 = 1;        //使能T0中断TR0 = 1;        //启动T0
}/* T0中断服务函数,执行200ms定时 */
void InterruptTimer0() interrupt 1
{static unsigned char tmr200ms = 0;TH0 = T0RH;  //重新加载重载值TL0 = T0RL;tmr200ms++;if (tmr200ms >= 200)  //定时200ms{tmr200ms = 0;flag200ms = 1;}
}

15.3.5 DS1302的BURST模式

上面的程序存在一个问题,比如当从00:00:59变到00:01:00的过程中,先读秒读到了59,然后下一个瞬间读分读到了1,就会显示00:01:59,一个时间很短的bug

为解决这个问题,要用到DS1302的突发模式,我们只将时钟的突发模式 clock Burst mode

如何触发BURST模式:

在给DS1302写指令时将5位地址全部都写成1即可

写数据时:10111110,即0xBE

读数据时:10111111,即0xBF

这样的指令会被DS1302自动识别为BURST模式

如果现在是在读操作,时钟现在的8个寄存器这8个字节会被锁存到另外一个缓冲区内,我们再从这个缓冲区中一次读取8个字节的数据

如果现在是写操作,就会将8个字节的数据全部写到缓冲区内,然后一次输入到8个寄存器中

注意:不管是读还是写,只要使用时钟的 burst 模式,则必须一次性读写 8 个寄存器,要把时钟的寄存器完全读出来或者完全写进去

下面展示一下BURST模式的时钟:

#include <reg52.h>sbit DS1302_CE = P1^7;
sbit DS1302_CK = P3^5;
sbit DS1302_IO = P3^4;bit flag200ms = 0;       //200ms定时标志
unsigned char T0RH = 0;  //T0重载值的高字节
unsigned char T0RL = 0;  //T0重载值的低字节void ConfigTimer0(unsigned int ms);
void InitDS1302();
unsigned char DS1302SingleRead(unsigned char reg);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
void DS1302BurstRead(unsigned char * dat);
void DS1302BurstWrite(unsigned char * dat);void main()
{unsigned char psec = 0xAA;//秒数的上一个状态unsigned char time[8];//读取DS1302时间的数据存储区unsigned char str[12];//要显示的字符串EA=1;//开启总中断ConfigTimer0(1);//定时器0的溢出时间是1msInitDS1302();InitLcd1602();//初始化函数while(1){if(flag200ms)//每过200ms就刷新一次time数组{flag200ms = 0;DS1302BurstRead(time);if(time[0]!= psec){str[0]='2';str[1]='0';str[2] = (time[6]>>4) + '0'; str[3] = (time[6] & 0x0F) + '0';str[4] = '-';str[5] = (time[4]>>4) + '0'; str[6] = (time[4] & 0x0F) + '0'; str[7] = '-';str[8] = (time[3]>>4) + '0'; str[9] = (time[3] & 0x0F) + '0'; str[10] = '\0';LcdShowStr(0,0,str);str[0] = (time[5]&0x0F) + '0';str[1] = '\0';LcdShowStr(11,0,"week");LcdShowStr(15,0,str);str[0] = (time[2]>>4) + '0'; str[1] = (time[2] & 0x0F) + '0';str[2] = ':';str[3] = (time[1]>>4) + '0'; str[4] = (time[1] & 0x0F) + '0';str[5] = ':';str[6] = (time[0]>>4) + '0'; str[7] = (time[0] & 0x0F) + '0';str[8] = '\0';LcdShowStr(4,1,str);psec = time[0];}}}
}/* 发送一个字节到DS1302通信总线上 */
void DS1302ByteWrite(unsigned char dat)
{unsigned char mask;for(mask=0x01;mask!=0;mask<<=1){if((dat&mask) != 0){DS1302_IO = 1;}else{DS1302_IO = 0;}DS1302_CK=1;DS1302_CK=0;}DS1302_IO = 1;}/* 由DS1302通信总线上读取一个字节 */
unsigned char DS1302ByteRead()
{unsigned char mask;unsigned char dat = 0;for(mask=0x01;mask!=0;mask<<=1){if(DS1302_IO!=0)//必须先读取引脚状态,然后才能改变时钟,改变时钟以后这一位数据就处理完毕,进入下一个数据位(IO的数据就会变){dat|=mask;}DS1302_CK=1;DS1302_CK=0;}return dat;
}/* 用单次写操作向某一寄存器写入一个字节,reg-寄存器地址,dat-待写入字节 */
void DS1302SingleWrite(unsigned char reg, unsigned char dat)
{DS1302_CE = 1;DS1302ByteWrite((reg<<1)|0x80);//先给这个寄存器一个要写的命令DS1302ByteWrite(dat);//然后才能将数据写入DS1302_CE = 0;
}/* 用单次读操作从某一寄存器读取一个字节,reg-寄存器地址,返回值-读到的字节 */
unsigned char DS1302SingleRead(unsigned char reg)
{unsigned char dat;DS1302_CE = 1;DS1302ByteWrite((reg<<1)|0x81);//先给这个寄存器的地址处写一条指令,通知要读数据dat = DS1302ByteRead();DS1302_CE = 0;return dat;
}/* 突发模式读取数据 */
void DS1302BurstRead(unsigned char * dat)
{unsigned char i=0;DS1302_CE = 1;DS1302ByteWrite(0xBF);for(i=0;i<8;i++){dat[i] = DS1302ByteRead();}DS1302_CE = 0;
}/* 突发模式写入数据 */
void DS1302BurstWrite(unsigned char * dat)
{unsigned char i=0;DS1302_CE = 1;DS1302ByteWrite(0xBE);for(i=0;i<8;i++){DS1302ByteWrite(dat[i]);}DS1302_CE = 0;
}/* DS1302初始化,如发生掉电则重新设置初始时间 */
void InitDS1302()
{//unsigned char i;unsigned char code InitTime[] = {  //2013年10月8日 星期二 12:30:00  是一个初始时间,掉电时进行初始化要给一个初始时间0x00,0x30,0x12, 0x08, 0x10, 0x02, 0x13};DS1302_CE = 0;DS1302_CK = 0;//完成初始化if((DS1302SingleRead(0)&0x80 )!= 0)//如果寄存器0的最高位CH不为0,那么说明正常运行{DS1302SingleWrite(7,0x00);//取消写保护DS1302BurstWrite(InitTime);}}/* 配置并启动T0,ms-T0定时时间 */
void ConfigTimer0(unsigned int ms)
{unsigned long tmp;  //临时变量tmp = 11059200 / 12;      //定时器计数频率tmp = (tmp * ms) / 1000;  //计算所需的计数值tmp = 65536 - tmp;        //计算定时器重载值tmp = tmp + 12;           //补偿中断响应延时造成的误差T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节T0RL = (unsigned char)tmp;TMOD &= 0xF0;   //清零T0的控制位TMOD |= 0x01;   //配置T0为模式1TH0 = T0RH;     //加载T0重载值TL0 = T0RL;ET0 = 1;        //使能T0中断TR0 = 1;        //启动T0
}/* T0中断服务函数,执行200ms定时 */
void InterruptTimer0() interrupt 1
{static unsigned char tmr200ms = 0;TH0 = T0RH;  //重新加载重载值TL0 = T0RL;tmr200ms++;if (tmr200ms >= 200)  //定时200ms{tmr200ms = 0;flag200ms = 1;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/57902.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用JMeter进行性能测试的保姆级教程

性能测试是确保网站在用户访问高峰时保持稳定和快速响应的关键环节。作为初学者&#xff0c;选择合适的工具尤为重要。JMeter 是一个强大的开源性能测试工具&#xff0c;可以帮助我们轻松模拟多用户场景&#xff0c;测试网站的稳定性与性能。本教程将引导你通过一个简单的登录场…

w~自动驾驶合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/12286744 #自动驾驶的技术发展路线 端到端自动驾驶 Recent Advancements in End-to-End Autonomous Driving using Deep Learning: A SurveyEnd-to-end Autonomous Driving: Challenges and Frontiers 在线高精地图 HDMa…

数据结构 - 散列表,初探

今天我们继续学习新的数据结构-散列表。 01定义 我们先来了解一些常见概念名词解释。 散列&#xff1a;散列表的实现叫做散列&#xff0c;是一种实现以常数级时间复杂度执行查找、插入和删除的技术&#xff1b; 散列值&#xff1a;通过散列函数对输入值&#xff08;key&…

前端零基础入门到上班:【Day2】开发环境VSCode安装

VSCode 安装教程&#xff1a;图文保姆教程 引言 在前端开发中&#xff0c;选择合适的代码编辑器是提高工作效率的重要一步。Visual Studio Code&#xff08;简称 VSCode&#xff09;作为一款强大的开源编辑器&#xff0c;因其简洁易用、功能强大、扩展性好而广受开发者喜爱。…

Python 协程详解----高性能爬虫

目录 1.基本概念 asyncio和async的关系 asyncio async & await关键字 协程基本语法 多任务协程返回值 案例1 协程在爬虫中的使用 aiohttp模块基本使用 协程案例-扒光一部小说需要多久? 操作数据库 异步redis 异步MySQL 案例2&#xff1a; 知识星球 | 深度连接…

Java篇图书管理系统

目录 前言 一. 图书管理系统的核心 二. 图书管理系统基本框架 2.1 book包 2.1.1 Book&#xff08;书籍类&#xff09; 2.1.2 Booklist (书架类&#xff09; 2.2 user包 2.2.1 User类 2.2.2 Administrator(管理员类) 2.2.3 Visitor&#xff08;用户类&#xff09; 2.…

基于Python大数据的王者荣耀战队数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Mybatis-03.入门-配置SQL提示

一.配置SQL提示 目前的Springboot框架在mybatis程序中编写sql语句并没有给到任何的提示信息&#xff0c;这对于开发者而言是很不友好的。因此我们需要配置SQL提示。 配置SQL提示 这样再去写SQL语句就会有提示了。 但是会发现指定表名时并没有给出提示。这是因为&#xff1a…

【综述整理】2015年至2022年图像美学质量评估数据集【附下载链接】

文章目录 2012年-美学数据集AVA-25万-MOS1~10数据集介绍 2015年-移动设备拍摄CLIVE-1K-MOS1~5数据集介绍 2016年-美学数据集AADB-10K-MOS1~10综述摘要 2017年-美学数据集FLICKR-AES-MOS1~5数据集介绍 2018年-户外自然场景KonIQ-10K-MOS1~5数据集介绍标签MOS&#xff0c;1-5分 2…

信息安全工程师(72)网络安全风险评估概述

前言 网络安全风险评估是一项重要的技术任务&#xff0c;它涉及对网络系统、信息系统和网络基础设施的全面评估&#xff0c;以确定存在的安全风险和威胁&#xff0c;并量化其潜在影响以及可能的发生频率。 一、定义与目的 网络安全风险评估是指对网络系统中存在的潜在威胁和风险…

记一次:使用使用Dbeaver连接Clickhouse

前言&#xff1a;使用了navicat连接了clickhouse我感觉不太好用&#xff0c;就整理了一下dbeaver连接 0、使用Navicat连接clickhouse 测试连接 但是不能双击打开&#xff0c;可是使用命令页界面&#xff0c;右键命令页界面&#xff0c;然后可以用sql去测试 但是不太好用&#…

LeetCode_231. 2 的幂_java

1、题目 231. 2 的幂https://leetcode.cn/problems/power-of-two/ 给你一个整数 n&#xff0c;请你判断该整数是否是 2 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果存在一个整数 x 使得 n &#xff0c;则认为 n 是 2 的幂次方…

6.1 特征值介绍

一、特征值和特征向量介绍 本章会开启线性代数的新内容。前面的第一部分是关于 A x b A\boldsymbol x\boldsymbol b Axb&#xff1a;平衡、均衡和稳定状态&#xff1b;现在的第二部分是关于变化的。时间会加入进来 —— 连续时间的微分方程 d u / d t A u \pmb{\textrm{d}…

CTF--Misc题型小结

&#xff08;萌新笔记&#xff0c;多多关照&#xff0c;不足之处请及时提出。&#xff09; 不定时更新~ 目录 密码学相关 文件类型判断 file命令 文件头类型 strings读取 隐写术 尺寸修改 文件头等缺失 EXIF隐写 thumbnail 隐写 文件分离&提取 binwalk foremo…

索引的使用和优化

索引就是一种快速查询和检索数据的数据结构&#xff0c;mysql中的索引结构有&#xff1a;B树和Hash。 索引的作用就相当于目录的作用&#xff0c;我么只需先去目录里面查找字的位置&#xff0c;然后回家诶翻到那一页就行了&#xff0c;这样查找非常快&#xff0c; 创建一个表结…

短视频矩阵系统源码开发优势,短视频矩阵系统oem部署

短视频矩阵系统就是在多个短视频平台上构建自己的内容生态&#xff0c;通过多平台、多账号、多内容的运营策略&#xff0c;实现品牌曝光、用户引流、产品销售等目的。短视频矩阵的核心在于通过矩阵式的布局&#xff0c;实现资源优化配置和利用&#xff0c;提升企业市场竞争力。…

.Net 8 Web API CRUD 操作

本次介绍分为3篇文章&#xff1a; 1&#xff1a;.Net 8 Web API CRUD 操作https://blog.csdn.net/hefeng_aspnet/article/details/143228383 2&#xff1a;在 .Net 8 API 中实现 Entity Framework 的 Code First 方法https://blog.csdn.net/hefeng_aspnet/article/details/1…

【C++干货篇】——类和对象的魅力(四)

【C干货篇】——类和对象的魅力&#xff08;四&#xff09; 1.取地址运算符的重载 1.1const 成员函数 将const修饰的成员函数称之为const成员函数&#xff0c;const修饰成员函数放到成员函数参数列表的后面。const实际修饰该成员函数隐含的this指针&#xff08;this指向的对…

nuxt3项目创建

安装 npx nuxilatest init <project-name> 此时会出现报错&#xff0c;需要在host文件中加入 185.199.108.133 raw.githubusercontent.com 再次执行命令&#xff0c;进入安装 此处选择npm&#xff0c;出现下图表示安装成功 启动项目 执行npm run dev&#xff0c;访…

【力扣 + 牛客 | SQL题 | 每日4题】牛客大厂笔试真题SQLW6, W7, W8

1. 牛客大厂笔试真题SQLW6&#xff1a;统计所有课程参加培训人次 1.1 题目&#xff1a; 描述 某公司员工培训信息数据如下&#xff1a; 员工培训信息表cultivate_tb(info_id-信息id,staff_id-员工id,course-培训课程)&#xff0c;如下所示&#xff1a; 注&#xff1a;该公…