(51單片機)LCD顯示數據存儲(DS1302時鐘模塊教學)(LCD1602教程)(獨立按鍵教程)(延時函數教程)(I2C總線認識)(AT24C02認識)

目錄

?演示視頻:

?源代碼

?main.c

LCD1602.c

LCD1602.h

AT24C02.c

AT24C02.h

Key.c

?Key.h

I2C.c

I2C.h

Delay.c?

?Delay.h

?代碼解析與教程:

?Dealy模塊

?LCD1602模塊

?Key模塊

I2C總線模塊

AT24C02模塊?/E2PROM模塊

?main模塊


?演示視頻:

E2PROM數據存儲

?源代碼

如上圖將11個文放在Keli5 中即可,然后燒錄在單片機中就行了

燒錄軟件用的是STC-ISP,不知道怎么安裝的可以去看江科大的視頻:

【51單片機入門教程-2020版 程序全程純手打 從零開始入門】https://www.bilibili.com/video/BV1Mb411e7re?p=2&vd_source=ada7b122ae16cc583b4add52ad89fd5e

源代碼:

頭文件要記得宏定義和重定義,避免重復調用:

#ifndef _Timer0_h_//名字根據文件名定義即可
#define _Timer0_h_//聲明函數……#endif

?main.c

#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "Key.h"
#include "Delay.h"
#include "AT24C02.h"//獲取按鍵值
unsigned char KeyNum;
//16位的int類型的數
unsigned int Num;//主函數
void main()
{LCD_Init();//初始化LCDLCD_ShowNum(1,1,Num,5);//初始化顯示while(1){KeyNum=Key();//獲取按鍵值if(KeyNum==1)	//K1按鍵,Num自增{Num++;LCD_ShowNum(1,1,Num,5);//LCD顯示當前Num}if(KeyNum==2)	//K2按鍵,Num自減{Num--;LCD_ShowNum(1,1,Num,5);//LCD顯示當前Num}if(KeyNum==3)	//K3按鍵,向AT24C02寫入數據{AT24C02_WriteByte(0,Num%256);//獲取高8位,存到0字節地址Delay(5);//注意寫周期5msAT24C02_WriteByte(1,Num/256);//獲取低8位,存到1字節地址Delay(5);LCD_ShowString(2,1,"Write OK");//LCD顯示Delay(1000);//顯示1秒后消失LCD_ShowString(2,1,"        ");//顯示1秒后消失}if(KeyNum==4)	//K4按鍵,從AT24C02讀取數據{Num=AT24C02_ReadByte(0);//返回值Data賦值給Num,獲取0字節地址的高8位Num|=AT24C02_ReadByte(1)<<8;//返回值Data賦值給Num,獲取1字節地址的低8位,因為Num是16字節,先左移8將前8位變成0,再|(有1即1)將低8位獲取出來LCD_ShowNum(1,1,Num,5);//LCD顯示當前Num(Data)LCD_ShowString(2,1,"Read OK ");//LCD顯示Delay(1000);//顯示1秒后消失LCD_ShowString(2,1,"        ");//顯示1秒后消失}}
}

LCD1602.c

#include <STC89C5xRC.H>//引腳配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//函數定義:
/*** @brief  LCD1602延時函數,12MHz調用可延時1ms* @param  無* @retval 無*/
void LCD_Delay()		//@11.0592MHz
{unsigned char i, j;i = 11;j = 190;do{while (--j);} while (--i);
}/*** @brief  LCD1602寫命令* @param  Command 要寫入的命令* @retval 無*/
void LCD_WriteCommand(unsigned char Command)
{LCD_RS=0;LCD_RW=0;LCD_DataPort=Command;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602寫數據* @param  Data 要寫入的數據* @retval 無*/
void LCD_WriteData(unsigned char Data)
{LCD_RS=1;LCD_RW=0;LCD_DataPort=Data;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602設置光標位置* @param  Line 行位置,范圍:1~2* @param  Column 列位置,范圍:1~16* @retval 無*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{if(Line==1){LCD_WriteCommand(0x80|(Column-1));}else if(Line==2){LCD_WriteCommand(0x80|(Column-1+0x40));}
}/*** @brief  LCD1602初始化函數* @param  無* @retval 無*/
void LCD_Init()
{LCD_WriteCommand(0x38);//八位數據接口,兩行顯示,5*7點陣LCD_WriteCommand(0x0c);//顯示開,光標關,閃爍關LCD_WriteCommand(0x06);//數據讀寫操作后,光標自動加一,畫面不動LCD_WriteCommand(0x01);//光標復位,清屏
}/*** @brief  在LCD1602指定位置上顯示一個字符* @param  Line 行位置,范圍:1~2* @param  Column 列位置,范圍:1~16* @param  Char 要顯示的字符* @retval 無*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}/*** @brief  在LCD1602指定位置開始顯示所給字符串* @param  Line 起始行位置,范圍:1~2* @param  Column 起始列位置,范圍:1~16* @param  String 要顯示的字符串* @retval 無*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=0;String[i]!='\0';i++){LCD_WriteData(String[i]);}
}/*** @brief  返回值=X的Y次方*/
int LCD_Pow(int X,int Y)
{unsigned char i;int Result=1;for(i=0;i<Y;i++){Result*=X;}return Result;
}/*** @brief  在LCD1602指定位置開始顯示所給數字* @param  Line 起始行位置,范圍:1~2* @param  Column 起始列位置,范圍:1~16* @param  Number 要顯示的數字,范圍:0~65535* @param  Length 要顯示數字的長度,范圍:1~5* @retval 無*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief  在LCD1602指定位置開始以有符號十進制顯示所給數字* @param  Line 起始行位置,范圍:1~2* @param  Column 起始列位置,范圍:1~16* @param  Number 要顯示的數字,范圍:-32768~32767* @param  Length 要顯示數字的長度,范圍:1~5* @retval 無*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{unsigned char i;unsigned int Number1;LCD_SetCursor(Line,Column);if(Number>=0){LCD_WriteData('+');Number1=Number;}else{LCD_WriteData('-');Number1=-Number;}for(i=Length;i>0;i--){LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief  在LCD1602指定位置開始以十六進制顯示所給數字* @param  Line 起始行位置,范圍:1~2* @param  Column 起始列位置,范圍:1~16* @param  Number 要顯示的數字,范圍:0~0xFFFF* @param  Length 要顯示數字的長度,范圍:1~4* @retval 無*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i,SingleNumber;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){SingleNumber=Number/LCD_Pow(16,i-1)%16;if(SingleNumber<10){LCD_WriteData(SingleNumber+'0');}else{LCD_WriteData(SingleNumber-10+'A');}}
}/*** @brief  在LCD1602指定位置開始以二進制顯示所給數字* @param  Line 起始行位置,范圍:1~2* @param  Column 起始列位置,范圍:1~16* @param  Number 要顯示的數字,范圍:0~1111 1111 1111 1111* @param  Length 要顯示數字的長度,范圍:1~16* @retval 無*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');}
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__//用戶調用函數:
void LCD_Init();//初始化
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);//顯示單個字符
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);//顯示字符串
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//顯示數字
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);//顯示帶符號數字
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//顯示十進制數字
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//顯示二進制數字#endif

AT24C02.c

//AT24C02.c#include <STC89C5xRC.H>
#include "I2C.h"#define AT24C02_ADDRESS 0xA0/*** @brief  AT24C02寫入一個字節* @param  WordAddress 要寫入字節的地址* @param  Data 要寫入的數據* @retval 無*/void AT24C02_WriteByte(unsigned char WordAddress,Data){I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_SendByte(Data);I2C_ReceiveAck();I2C_Shop();
}/*** @brief  AT24C02讀取一個字節* @param  WordAddress 要讀出字節的地址* @retval 讀出的數據*/unsigned char AT24C02_ReadByte(unsigned char WordAddress){unsigned char Data;I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_Start();I2C_SendByte(AT24C02_ADDRESS|0x01);I2C_ReceiveAck();Data=I2C_ReceiveByte();I2C_SendAck(1);I2C_Shop();return Data;
}

AT24C02.h

//AT24C02.h#ifndef __AT24C02_H__
#define __AT24C02_H__void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);
#endif

Key.c

#include <STC89C5xRC.H>
#include "Delay.h"unsigned char Key()//獲取獨立按鍵
{unsigned char KeyNumber=0;//進行判斷是否摁下按鍵和防抖操作if(P31==0){Delay(20);while(P31==0);Delay(20);KeyNumber=1;}if(P30==0){Delay(20);while(P30==0);Delay(20);KeyNumber=2;}if(P32==0){Delay(20);while(P32==0);Delay(20);KeyNumber=3;}if(P33==0){Delay(20);while(P33==0);Delay(20);KeyNumber=4;}return KeyNumber;
}

?Key.h

#ifndef _Key_h_
#define _Key_h_unsigned char Key();#endif

I2C.c

//I2C.c#include <STC89C5xRC.H>sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;//I2C開始
void I2C_Start(){I2C_SDA=1;I2C_SCL=1;I2C_SDA=0;I2C_SCL=0;
}//I2C停止
void I2C_Shop(){I2C_SDA=0;I2C_SCL=1;I2C_SDA=1;
}//I2C發送一個字節
void I2C_SendByte(unsigned char Byte){unsigned char i;for(i=0;i<8;i++){I2C_SDA=Byte&(0x80>>i);I2C_SCL=1;I2C_SCL=0;}
}//I2C接收一個字節
unsigned char I2C_ReceiveByte(){unsigned char i,Byte=0x00;I2C_SDA=1;for(i=0;i<8;i++){I2C_SCL=1;if(I2C_SDA){Byte|=(0x80>>i);}I2C_SCL=0;}return Byte;
}//I2C發送應答
void I2C_SendAck(unsigned char AckBit){I2C_SDA=AckBit;I2C_SCL=1;I2C_SCL=0;
}//I2C接收應答
unsigned char I2C_ReceiveAck(){unsigned char AckBit;I2C_SDA=1;I2C_SCL=1;AckBit=I2C_SDA;I2C_SCL=0;return AckBit;
}

I2C.h

//I2C.h#ifndef __I2C_H__
#define __I2C_H__unsigned char I2C_ReceiveAck();
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveByte();
void I2C_SendByte(unsigned char Byte);
void I2C_Shop();
void I2C_Start();#endif

Delay.c?

//Delay.c#include <STC89C5xRC.H>
#include <INTRINS.H>//延時函數
void Delay(unsigned int xms)		//@11.0592MHz
{unsigned char i, j;while(xms){i = 2;j = 199;do{while (--j);} while (--i);xms--;}
}

?Delay.h

//Delay.h#ifndef __Delay_H__
#define __Delay_H__//延時函數頭文件
void Delay(unsigned int xms);
#endif

?代碼解析與教程:

?Dealy模塊
  • 包含源代碼與頭文件,不需要知道怎么實現的會用即可,后續使用,直接將頭文件和源代碼拿過來用即可;

xms是定義的毫秒,1000毫秒就是1秒;模版生成的是1毫秒的,因此xms等于1000

?LCD1602模塊
  • 包含源代碼與頭文件,不需要知道怎么實現的會用即可,后續使用,直接將頭文件和源代碼拿過來用即可;使用格式:(參考江科大的視頻素材)

?

  • LCD1602相關重要知識:
    • LCD1602有兩上下兩行顯示屏,每行各有16個小顯示屏,如上圖中的LCD_ShowString(1,3,"Hello"),第一個參數是第一行還是第二行,第2個參數是對應第幾行的第幾個小顯示屏,最后一個是輸出的東西,同理,到LCD_ShowNum(1,9,123,3)里,前三個和前面一樣,最后一個參數是顯示的位數,不夠就在前面補0,例如輸入1,參數為4,顯示就是0001,輸入23,參數為3,顯示就是023

?

  • 上圖是LCD1602的開發原理模塊圖,由圖可知,P10-P17是控制顯示屏的重點;像矩陣那樣,S1,由P17和P13控制,同理,其他按鍵一樣,由于開發板限制,我們一般使用列遍歷來控制按鍵,例如:S1,S5,S9,S13他們四個共用P13,所以將其為1列,將P13設定為1,P17設定為0,S1就會亮,其他按鍵同理。
?Key模塊
  • 包含源代碼與頭文件,不需要知道怎么實現的會用即可,后續使用,直接將頭文件和源代碼拿過來用即可;
    ?
    序號1是按鍵的防抖操作,不需要理解,有按鍵的地方直接用即可
    序號2是獨立按鍵控制變量。
    KeyNumber就是返回值,按鍵K1就返回1,其他同理
I2C總線模塊
  • 包含源代碼與頭文件,需要知道怎么實現的,會用,后續使用,直接將頭文件和源代碼拿過來用即可;因為這部分比較難,輕度認識理解就行,越深越難
  • 在此之前,我們要認識一下存儲器:

  • 本篇博客,以及博主的板子型號(STC89c52rc),用的儲存器就是E2PROM儲存器,簡單介紹一下,RAM就是可讀寫儲存器,SRAM是靜態的,容量較大,成本高,類似于我們手機內存,DRAM是動態的,容量較小,成本較低,類似于我們手機的運行內存;ROM按常理來說是不可寫的,只能讀,但是他比RAM不易丟失,有斷電保護,斷電后數據不易丟失,因此非常受大家的喜歡,所以在后續的更新中,好多ROM也可以讀寫了,例如E2PROM。
  • 了解上面之后,I2C總線可以理解成一個傳輸協議,或者傳輸方式,規則;作用是將一個機器(主機)的數據傳輸到另一個機器(從機);來看E2PROM原理圖

?

  • 可以看到SCL,SDA是I2C接口,A0,A1,A2是I2C地址,通過這些東西,將主機(單片機)數據傳遞到從機(E2PROM);下面來看傳輸是怎么實現的
  • I2C總線傳輸時有兩大部分,時序結構和數據幀,時序結構就是SCL,SDA這種東西的先后順序或者說他倆的一些重要關系
  • 時序結構有6個小模塊,看圖:

這是開始和結束兩部分中間框起來的部分是數據確認階段,高電平是1(高一點的部分),低電平是0(低一點的部分);圖中可以看到在數據確認階段SCL始終為1,SDA也會變化,因此有


//定義SCL,SDA的引腳
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;//I2C開始
void I2C_Start(){I2C_SDA=1;I2C_SCL=1;I2C_SDA=0;I2C_SCL=0;
}//I2C停止
void I2C_Shop(){
//因為開始后SCL=0了,所有這里不需要重復定義了I2C_SDA=0;I2C_SCL=1;I2C_SDA=1;
}

接下來是發送數據,發送一個字節(8個bit),在數據確認期間,SCL先0后1再0,SDA是數據,有可能是1,有可能是0,也會變化,即可發送一個bit,然后循環8次就是一個字節:

//I2C發送一個字節
void I2C_SendByte(unsigned char Byte){unsigned char i;for(i=0;i<8;i++){I2C_SDA=Byte&(0x80>>i);I2C_SCL=1;I2C_SCL=0;}
}

發送字節是參數Byte,i是循環次數,也是右移幾個單位,重點來了:注意看圖中的先后順序,SDA先變化,數據是高位在前,0x80是1000 0000,Byte&(有0即0)0x80就是保留Byte的第一位(最高位),其他全變0;然后變化SCL0,1,0;循環八次

?

接下來是接收數據,接收一個字節(8個bit),在數據確認期間,SCL先0后1再0,SDA是數據,有可能是1,有可能是0,也會變化,即可發送一個bit,然后循環8次就是一個字節:

//I2C接收一個字節
unsigned char I2C_ReceiveByte(){unsigned char i,Byte=0x00;I2C_SDA=1;for(i=0;i<8;i++){if(I2C_SDA){Byte|=(0x80>>i);}I2C_SCL=1;I2C_SCL=0;}return Byte;
}

接收字節是無參數,返回值是Data,i是循環次數,也是右移幾個單位,重點來了:注意,主機接收之前需要釋放SDA(使SDA=1);注意看圖中的先后順序,SDA先變化,數據是高位在前,0x80是1000 0000,Byte&(有0即0)0x80就是保留Byte的第一位(最高位),其他全變0;然后變化SCL0,1,0;循環八次

?
接下來是發送應答和就收應答,作用就是在發送和接收時進行一個反饋,告訴你發送或者接收成功。
?
//I2C發送應答
void I2C_SendAck(unsigned char AckBit){I2C_SDA=AckBit;I2C_SCL=1;I2C_SCL=0;
}//I2C接收應答
unsigned char I2C_ReceiveAck(){unsigned char AckBit;I2C_SDA=1;AckBit=I2C_SDA;I2C_SCL=1;I2C_SCL=0;return AckBit;
}
發送應答參數AckBit是應答數據,0就是表示應答,1是不應答; 注意看圖中的先后順序,SDA先變化,將應答數據賦值給SDA;然后變化SCL0,1,0;
接收應答無參數,返回值是AckBit是應答數據,0就是表示應答,1是不應答; 注意,主機接收之前需要釋放SDA(使SDA=1);注意看圖中的先后順序,SDA先變化將SDA賦值給AckBit;然后變化SCL0,1,0;
  • 了解時序結構之后,來看數據幀,也就是數據是怎么在I2C中傳輸的:

發送一幀數據是有I2C時序結構的6個小模塊組成的,圖中都標注了;需要注意的是要告訴I2C總線向誰發送,也就是要先發送從機地址,從機地址最后一個是告訴你是讀還是寫;

接收一幀數據是有I2C時序結構的6個小模塊組成的,圖中都標注了;需要注意的是要告訴I2C總線向誰接收,也就是要先發送從機地址,從機地址最后一個是告訴你是讀還是寫;注意最后一個發送應答是1,表示非應答

復合格式數據是有I2C時序結構的6個小模塊組成的,圖中都標注了;需要注意的是要告訴I2C總線向誰發送并接收,也就是要先發送從機地址,從機地址最后一個是告訴你是讀還是寫;注意最后一個發送應答是1,表示非應答

AT24C02模塊?/E2PROM模塊
  • 包含源代碼與頭文件,需要知道怎么實現的,會用,后續使用,直接將頭文件和源代碼拿過來用即可;因為這部分比較難,輕度認識理解就行,越深越難
  • AT24C02是E2PROM模塊中的一小塊,可以理解上述中所提到的從機主機就是單片機,因此從機地址就是AT24C02地址;

字節寫,隨機讀數據幀是有I2C時序結構的6個小模塊組成的,圖中不再標注了;需要注意的是要告訴I2C總線讀還是寫,也就是要發送從機地址SLAVE ADDRESS,從機地址最后一個是告訴你是讀還是寫;還有一個就是發送存儲字節地址WORD ADDRESS;注意最后一個發送應答是1,表示非應答

//AT24C02.c#include <STC89C5xRC.H>
#include "I2C.h"#define AT24C02_ADDRESS 0xA0/*** @brief  AT24C02寫入一個字節* @param  WordAddress 要寫入字節的地址* @param  Data 要寫入的數據* @retval 無*/void AT24C02_WriteByte(unsigned char WordAddress,Data){I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_SendByte(Data);I2C_ReceiveAck();I2C_Shop();
}/*** @brief  AT24C02讀取一個字節* @param  WordAddress 要讀出字節的地址* @retval 讀出的數據*/unsigned char AT24C02_ReadByte(unsigned char WordAddress){unsigned char Data;I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_Start();I2C_SendByte(AT24C02_ADDRESS|0x01);I2C_ReceiveAck();Data=I2C_ReceiveByte();I2C_SendAck(1);I2C_Shop();return Data;
}

按照圖中的I2C總線時序結構,依次調用函數,即可實現

注意寫周期是5ms,意味著每次寫完后要延時5ms;

?main模塊
  • 注釋寫的很清楚,這里不做解釋了
#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "Key.h"
#include "Delay.h"
#include "AT24C02.h"//獲取按鍵值
unsigned char KeyNum;
//16位的int類型的數
unsigned int Num;//主函數
void main()
{LCD_Init();//初始化LCDLCD_ShowNum(1,1,Num,5);//初始化顯示while(1){KeyNum=Key();//獲取按鍵值if(KeyNum==1)	//K1按鍵,Num自增{Num++;LCD_ShowNum(1,1,Num,5);//LCD顯示當前Num}if(KeyNum==2)	//K2按鍵,Num自減{Num--;LCD_ShowNum(1,1,Num,5);//LCD顯示當前Num}if(KeyNum==3)	//K3按鍵,向AT24C02寫入數據{AT24C02_WriteByte(0,Num%256);//獲取高8位,存到0字節地址Delay(5);//注意寫周期5msAT24C02_WriteByte(1,Num/256);//獲取低8位,存到1字節地址Delay(5);LCD_ShowString(2,1,"Write OK");//LCD顯示Delay(1000);//顯示1秒后消失LCD_ShowString(2,1,"        ");//顯示1秒后消失}if(KeyNum==4)	//K4按鍵,從AT24C02讀取數據{Num=AT24C02_ReadByte(0);//返回值Data賦值給Num,獲取0字節地址的高8位Num|=AT24C02_ReadByte(1)<<8;//返回值Data賦值給Num,獲取1字節地址的低8位,因為Num是16字節,先左移8將前8位變成0,再|(有1即1)將低8位獲取出來LCD_ShowNum(1,1,Num,5);//LCD顯示當前Num(Data)LCD_ShowString(2,1,"Read OK ");//LCD顯示Delay(1000);//顯示1秒后消失LCD_ShowString(2,1,"        ");//顯示1秒后消失}}
}

?注:該代碼是本人自己所寫,可能不夠好,不夠簡便,歡迎大家指出我的不足之處。如果遇見看不懂的地方,可以在評論區打出來,進行討論,或者聯系我。上述內容全是我自己理解的,如果你有別的想法,或者認為我的理解不對,歡迎指出!!!如果可以,可以點一個免費的贊支持一下嗎?謝謝各位彥祖亦菲!!!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/903093.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/903093.shtml
英文地址,請注明出處:http://en.pswp.cn/news/903093.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

電子病歷高質量語料庫構建方法與架構項目(數據遺忘篇)

引言 在人工智能與醫療健康的深度融合時代,醫療數據的價值與風險并存。跨機構和平臺的醫療數據共享對于推動醫學研究、提高診斷精度和實現個性化治療至關重要,但同時也帶來了前所未有的隱私挑戰。先進的AI技術可以從理論上去標識化的醫療掃描中重新識別個人身份,例如從MRI數…

CentOS創建swap內存

服務器版本為CentOS7 一、檢查現有 swap 空間 sudo swapon --show如果系統中沒有 swap 空間或者現有的 swap 空間不足&#xff0c;可以繼續后續步驟來創建 swap 空間。 二、創建 swap 文件&#xff08;推薦 2GB 作為示例&#xff09; sudo dd if/dev/zero of/swapfile bs1M …

在Android中如何使用Protobuf上傳協議

在 Android 中使用 Protobuf&#xff08;Protocol Buffers&#xff09;主要分為以下幾個步驟&#xff1a; ? 1. 添加 Protobuf 插件和依賴 在項目的 build.gradle&#xff08;Project 級&#xff09;文件中添加 Google 的 Maven 倉庫&#xff08;通常默認已有&#xff09;&am…

Android學習總結之ANR問題

一、ANR 基礎概念與核心原理&#xff08;必考題&#xff09; 1. 什么是 ANR&#xff1f;為什么會發生 ANR&#xff1f; 答案要點&#xff1a; 定義&#xff1a;ANR&#xff08;Application Not Responding&#xff09;即應用無響應&#xff0c;是 Android 系統檢測到主線程&…

視頻監控從安裝到優化的技術指南,視頻匯聚系統EasyCVR智能安防系統構建之道

在當今數字化安防時代&#xff0c;監控系統的安裝與配置對于保障各類場所的安全起著至關重要的作用。從前期規劃到實際安裝&#xff0c;再到后期的功能實現與維護&#xff0c;每一個環節都不容小覷。本文將詳細闡述監控安裝過程中的關鍵要點&#xff0c;并結合EasyCVR平臺功能&…

如何避免IDEA每次打開新項目都重復配置Maven?

每次打開新項目都要重新設置Maven路徑&#xff1f;每次導入工程都要手動調整settings.xml&#xff1f;如果你也受夠了IDEA這種“健忘”行為&#xff0c;那么這篇文章就是為你準備的&#xff01;今天我們就來徹底解決這個問題&#xff0c;讓IDEA記住你的Maven配置&#xff0c;一…

PostgesSQL外部數據封裝FDW

PostgesSQL外部數據封裝FDW 1. FDW外部數據配置&#xff08;單表&#xff09;1.1 遠端數據庫創建測試表1.2 安裝擴展postges\_fdw1.3 創建外部服務SERVER1.4 創建用戶映射USER MAPPING1.5 創建遠程表FOREIGN TABLE1.6 數據庫更新測試 2. FDW外部數據配置&#xff08;用戶&#…

策略模式(Strategy Pattern)詳解

文章目錄 1. 什么是策略模式&#xff1f;2. 為什么需要策略模式&#xff1f;3. 策略模式的核心概念3.1 策略&#xff08;Strategy&#xff09;3.2 具體策略&#xff08;Concrete Strategy&#xff09;3.3 上下文&#xff08;Context&#xff09; 4. 策略模式的結構5. 策略模式的…

在 Vue3 中封裝的 Axios 實例中,若需要為部分接口提供手動取消請求的功能

核心思路 封裝接口時返回 Promise 和 abort 方法&#xff1a; 為需要支持取消的接口返回一個對象&#xff0c;包含 promise 和 abort 方法&#xff0c;用戶可通過 abort 主動中斷請求。使用 AbortController 或 CancelToken&#xff1a; 推薦 AbortController&#xff08;瀏覽…

Flink介紹——實時計算核心論文之Dataflow論文詳解

引入 在過去的幾篇文章里&#xff0c;我們看到了大數據的流式處理系統是如何一步一步進化的。從最早出現的S4&#xff0c;到能夠做到“至少一次”處理的Storm&#xff0c;最后是能夠做到“正好一次”數據處理的MillWheel。我們會發現&#xff0c;這些流式處理框架&#xff0c;…

Python自動化解決滑塊驗證碼的最佳實踐

1. 引言&#xff1a;滑塊驗證碼的挑戰與自動化需求 滑塊驗證碼&#xff08;Slider CAPTCHA&#xff09;是當前互聯網廣泛使用的反爬機制之一&#xff0c;它要求用戶手動拖動滑塊到指定位置以完成驗證。這種驗證方式可以有效阻止簡單的自動化腳本&#xff0c;但對爬蟲開發者來說…

路由與OSPF學習

【路由是跨網段通訊的必要條件】 路由指的是在網絡中&#xff0c;數據包從源主機傳輸到目的主機的路徑選擇過程。 路由通常涉及以下幾個關鍵元素&#xff1a; 1.路由器&#xff1a;是一種網絡設備&#xff0c;負責將數據包從一個網絡傳輸到另一個網絡。路由器根據路由表來決定…

(done) 吳恩達版提示詞工程 5. 推理 (情緒分類,控制輸出格式,輸出 JSON,集成多個任務,文本主題推斷和索引,主題內容提醒)

url: https://www.bilibili.com/video/BV1Z14y1Z7LJ?spm_id_from333.788.videopod.episodes&vd_source7a1a0bc74158c6993c7355c5490fc600&p2 別人的筆記 url: https://zhuanlan.zhihu.com/p/626966526 5. 推理任務&#xff08;Inferring&#xff09; 這個視頻是關于…

MySQL VS SQL Server:優缺點全解析

數據庫選型、企業協作、技術生態、云數據庫 1.1 MySQL優缺點分析 優點 開源免費 社區版完全免費&#xff0c;適合預算有限的企業 允許修改源碼定制功能&#xff08;需遵守GPL協議&#xff09; 跨平臺兼容性 支持Windows/Linux/macOS&#xff0c;適配混合環境部署 云服務商…

Pycharm 代理配置

Pycharm 代理配置 文章目錄 Pycharm 代理配置1. 設置系統代理1.1 作用范圍1.2 使用場景1.3 設置步驟 2. 設置 python 運行/調試代理2.1 作用范圍2.2 使用場景2.3 設置步驟 Pycharm 工具作為一款強大的 IDE&#xff0c;其代理配置在實際開發中也是必不可少的&#xff0c;下面介紹…

maven打包時配置多環境參數

1. pom配置 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.…

國產三維CAD皇冠CAD在機械及汽車零部件設計建模教程:斜滑動軸承

在線解讀『斜滑動軸承』的三維建模流程&#xff0c;講解布爾運算、旋轉凸臺/基體、異型導向孔、裝飾螺紋線等操作技巧&#xff0c;一起來皇冠CAD&#xff08;CrownCAD&#xff09;直播間學習制作步驟吧&#xff01; 斜滑動軸承憑借其獨特的工作原理和廣泛的應用領域&#xff0c…

linux(操作系統概述和虛擬機的安裝)

1.操作系統 一、主流服務器操作系統 Windows server 市場地位&#xff1a;適合傳統企業&#xff08;主要以中小型企業、金融機構和教育機構為主&#xff09; 核心特點&#xff1a; 企業級功能&#xff1a;活動目錄、組策略、IIS/Web服務器、Exchange郵件服務 易用性&#xff1a…

鴻蒙生態新利器:華為ArkUI-X混合開發框架深度解析

鴻蒙生態新利器&#xff1a;華為ArkUI-X混合開發框架深度解析 作者&#xff1a;王老漢 | 鴻蒙生態開發者 | 2025年4月 &#x1f4e2; 前言&#xff1a;開發者們的新機遇 各位鴻蒙開發者朋友們&#xff0c;是否還在為多平臺開發重復造輪子而苦惱&#xff1f;今天給大家介紹一位…

數據結構初階:二叉樹(四)

概述&#xff1a;本篇博客主要介紹鏈式結構二叉樹的實現。 目錄 1.實現鏈式結構二叉樹 1.1 二叉樹的頭文件&#xff08;tree.h&#xff09; 1.2 創建二叉樹 1.3 前中后序遍歷 1.3.1 遍歷規則 1.3.1.1 前序遍歷代碼實現 1.3.1.2 中序遍歷代碼實現 1.3.1.3 后序遍歷代…