JZ2440 裸機驅動 第10章 系統時鐘和定時器

来源:http://www.cnblogs.com/sz189981/archive/2017/10/22/7712295.html
-Advertisement-
Play Games

瞭解S3C2410/S3C2440的時鐘體繫結構 掌握通過設置MPLL改變系統時鐘的方法 掌握在不同的頻率下設置存儲控制器的方法 掌握PWM定時器的用法 瞭解WATCHDOG定時器的用法 ...


本章目標      瞭解S3C2410/S3C2440的時鐘體繫結構     掌握通過設置MPLL改變系統時鐘的方法     掌握在不同的頻率下設置存儲控制器的方法     掌握PWM定時器的用法     瞭解WATCHDOG定時器的用法 10.1 時鐘體系及各類時鐘部件 10.1.1 S3C2410/S3C2440時鐘系統     S3C2410/S3C2440的時鐘控制邏輯既可以外接晶振,然後通過內部電路產生時鐘源;也 可以直接使用外部提供的時鐘源,它們通過引腳的設置來選擇。時鐘控制邏輯給整個晶元提 供3種時鐘:FCLK用於CPU核;HCLK用於AHB匯流排上的設備,比如CPU核、存儲控制器、 中斷控制器、LCD控制器、DMA和USB主機模塊等;PCLK用於APB匯流排上的設備,比如 WATCHDOG、IIS、I2C、PWM定時器、MMC介面、ADC、UART、GPIO、RTC和SPI。     為了降低電磁干擾、降低板間佈線的要求,S3C2410/S3C2440外接的晶振頻率通常很低, 本開發板上為12MHz,需要通過時鐘控制邏輯的PLL提高系統時鐘。     S3C2410/S3C2440有兩個PLL:MPLL和UPLL。UPLL專用於USB設備,MPLL用於設置 FCLK、HCLK、PCLK。它們的設置相似,本書以MPLL為例。     上電時,PLL沒被啟動,FCLK即等於外部輸入時鐘,稱為Fin。     若要提高系統時鐘,需要開啟PLL。     PLL設置過程如下所示,請參考圖10.1,跟隨FCLK的圖像瞭解啟動過程。     (1)上電幾毫秒後,晶振輸出穩定,FCLK = Fin(晶振頻率),nRESET信號恢復高電平後, CPU開始執行命令。     (2)可以在程式開頭啟動MPLL,設置MPLL的幾個寄存器後,需要等待一段時間(Lock Time), MPLL輸出才穩定。在這段時間(Lock Time)內,FCLK停振,CPU停止工作。Lock Time的長短由 寄存器LOCKTIME設定。     (3)Lock Time之後,MPLL輸出正常,CPU工作在新的FCLK之下。     FCLK、HCLK和PCLK的比例是可以改變的,設置它們三者的比例,啟動MPLL只需要設置3個 寄存器(對於S3C2440的一些時鐘比例,還需要額外設置一個寄存器)。     【1】LOCKTIME寄存器(LOCK TIME COUNT):用於設置“Lock Time”的長度。
    前面說過,MPLL啟動後需要等待一段時間,使得其輸出穩定。S3C2410中,位[23:12]用於UPLL, 位[11:0]用於MPLL。S3C2440中,位[31:16]用於UPLL,位[15:0]用於MPLL。一般而言,使用它的 預設值即可,S3C2410中預設值為0x00FF FFFF,S3C2440中預設值為0xFFFF FFFF。     【2】MPLLCON寄存器(Main PLL Control):用於設置FCLK與Fin的倍數。     位[19:12]的值稱為MDIV,位[9:4]的值稱為PDIV,位[1:0]的值稱為SDIV。FCLK與Fin的關係 有如下計算公式:     ① 對於S3C2410: MPLL(FCLK) = (     m * Fin) / (p * 2^s)     ② 對於S3C2440: MPLL(FCLK) = (2 * m * Fin) / (p * 2^s)     其中:m = MDIV + 8,p = PDIV + 2,s = SDIV。     當設置MPLLCON之後——相當於圖10.1中的“首先使用軟體設置PLL”,Lock Time就被自動插入。 Lock Time之後,MPLL輸出穩定,CPU工作在新的FCLK下。     【3】CLKDIVN寄存器(CLOCK DIVIDER CONTROL):用於設置FCLK、HCLK、PCLK三者的比例。     對於S3C2410、S3C2440,這個寄存器表現稍有不同,請參考表10.1和圖10.2.      對於S3C2440的一些時鐘比例,還需要額外的設置一個寄存器CAMDIVN。圖10.2中, HDIVN為CLKDIVN寄存器為位[2:1],PDIVN為位[0];HCLK4_HALF、HCLK3_HALF分 別為CAMDIVN寄存器的位[9]、[8]。各種時鐘對比對應的寄存器設置如圖10.2所示。      對於S3C2410,HDIVN是CLKDIVN寄存器的位[1];      對於S3C2440,HDIVN是CLKDIVN寄存器的位[2:1],如果HDIVN非0,CPU的匯流排模式 應該從“fast bus mode”變為“asynchronous bus mode”,這可以通過如下指令來完成:
# MMU_SetAsyncBusMode
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #R1_nF:OR:RL_iA
mcr p15, 0, r0, c1, c0, 0
    其中的“R1_nF:OR:R1_iA”等於0xC000 0000。如果HDIVN非0時,而CPU的匯流排模式仍是 “fast bus mode”,則CPU的工作頻率將自動變為HCLK,而不再是FCLK。 10.1.2 PWM定時器     S3C2410/S3C2440的定時器部件完全一樣,共有5個16位定時器。其中定時器0、1、2、3 有PWM功能;定時器4沒有輸出引腳。     定時器部件的時鐘源為PCLK,首先通過兩個8位的預分頻器降低頻率:定時器0、1共用第 一個預分頻器,定時器2、3、4共用第二個預分頻器。預分頻器的輸出將進入第二部分分頻器, 它們輸出5種頻率的時鐘:2分頻、4分頻、8分頻、16分頻或者外部時鐘TCLK0/TCLK1。每個 定時器的工作時鐘可以從這5種頻率中選擇。     這兩個預分頻都可以通過TCFG0寄存器來設置,每個定時器工作在哪種頻率下也可以通過 TCFG1寄存器來選擇。如圖10.3所示,形象地說明定時器的結構。                                               圖10.3 定時器結構圖      上面只是確定了定時器的工作頻率,至於定時器如何工作還得瞭解其內部結構,如圖 10.4所示。           定時器內部控制邏輯的工作流程如下:     (1)程式初始,設定TCMPBn、TCNTBn這兩個寄存器,它們表示定時器n的比較值、 初始計數值。
    (2)隨之設置TCON寄存器啟動定時器n,這時,TCMPBn、TCNTBn的值將被裝入其 內部寄存器TCMPn、TCNTn中。在定時器n的工作頻率下,TCNTn開始減1計數,其值可 以通過讀取TCNTOn寄存器得知。      (3)當TCNTn的值等於TCMPn的值時,定時器n的輸出管腳TOUTn反轉;TCNTn繼續 減1計數。     (4)當TCNTn的值達到0時,其輸出管腳TOUTn再次反轉,並觸發定時器n的中斷(如果   中斷使能了的話)。     (5)當TCNTn的值達到0時,如果TCON寄存器中將定時器n設為“自動載入”,則TCMPB0 和TCNTB0寄存器的值將被自動裝入TCMP0和TCNT0寄存器中,下一個計數流程開始。     定時器n的輸出管腳TOUTn初始狀態為高電平,以後在TCNTn的值等於TCMPn的值、 TCNTn的值時反轉。也可以通過TCON寄存器設置其初始電平,這樣TOUTn的輸出就完全 反相了。通過設置TCMPBn、TCNTBn的值可以設置管腳TOUTn輸出信號的占空比,這就 是所謂的PWM,所以這些定時器又被稱為PWM定時器。     下麵講解定時器時寄存器的使用方法。     (1)TCFG0寄存器(TIMER CONFIGURATION)     位[7:0]、位[15:8]分別被用於控制預分頻器0、1,它們的值為0~255。經過預分頻器出來 的時鐘頻率為:PCLK/{prescaler value + 1}。     (2)TCFG1寄存器     經過預分頻器得到的時鐘將被2、4、8、16分頻,除了這4種頻率外,額外的,定時器0、1 還可以工作在外接的TCLK0時鐘下,定時器2、3、4還可以工作在外接的TCLK1時鐘下。     通過TCFG1寄存器來設置這5個定時器,分別工作於這5個頻率中哪一個下,如表10.2所示。          這樣,定時器n的工作頻率或者外接的TCLK0或TCLK1可以通過這個公式計算:         定時器工作頻率 = PCLK / {prescaler value +1} / {divider value}         {prescaler value} = 0~255         {divider value}    = 2、4、8、16     (3)TCNTBn/TCMPBn寄存器(COUNT BUFFER REGISTER & COMPARE BUFFER REGISTER)。
    n為0~4,這兩個寄存器都只用到位[15:0],TCNTBn中保存定時器的初始值,TCMPBn 中保存比較值。它們的值在啟動定時器時,被傳到定時器內部寄存器TCNTn、TCMPn中。     沒有TCMPB4,因為定時器4沒有輸出管腳。     (4)TCNTOn寄存器(COUNT OBSERVATION)     n為0~4,定時器n被啟動後,內部寄存器TCNTn在其工作時鐘下不斷減1計數,可以通過 讀取TCNTOn寄存器得知其值。     (5)TCON寄存器(TIMER CONTROL)     它有以下4個作用:     ① 第一次啟動定時器時,手動將TCNTBn/TCMPBn寄存器中的數據裝入內部寄存器 TCNTn、TCMPn中。     ② 啟動、停止定時器。     ③決定在定時器計數到達0時,是否自動將TCNTBn/TCMPBn寄存器的值裝入內部 寄存器TCNTn、TCMPn中。     ④ 決定定時器的管腳TOUTn的輸出電平是否反轉、     TCON寄存器位[3:0]、位[11:8]、位[15:12]、位[19:16]、位[22:20]分別用於定時器0~4。 除了定時器因為沒有輸出引腳在沒有“輸出反轉”位外,其他位的功能相似。表10.3以定時器 0為例說明這些位的作用。           在第一次使用定時器時,需要設置“手動更新”位為1,以使TCNTBn/TCMPBn寄存器的 值裝入內部寄存器TCNTn、TCMPn中。下一次如果還要設置這一位,需要先將它清0。     定時器還有其他功能,比如DMA、Dead zone等,需要瞭解的讀者清參考數據手冊。 寄存器中涉及它們的部分這裡就省略了。 10.1.3 WATCHDOG定時器     WATCHDOG定時器可以像一般16位定時器一樣用於產生周期性中斷,也可以用於發 出複位信號以重啟失常的系統。它與PWM定時器的結構類似,如圖10.5所示。      同樣,WATCHDOG定時器的8位分頻器將PCLK分頻後,被再次分頻得到4種頻率: 16、32、64、128分頻,WATCHDOG定時器可以選擇工作在哪種頻率之下。WTCNT 寄存器按照其工作頻率減1計數,當達到0時,可以產生中斷信號,可以輸出複位信號。 在第一次使用WATCHDOG定時器時,需要向WTCNT寄存器中寫入初始計數值,以後 在計數值達到0時,自動從WATDAT寄存器中寄存器中裝入,重新開始下一個計數周期。     使用WATCHDOG定時器的“WATCHDOG功能”時,在正常的程式中,必須不斷重新 設置WTCNT寄存器使得它不為0,這樣可以保證系統不被重啟,這稱為喂狗。     WATCHDOG定時器所涉及的寄存器如下:     (1)WTCON寄存器(WATCHDOG TIMER CONTROL)     用於設置預分頻繫數,選擇工作頻率,決定是否使用中斷、是否啟用WATDOG功能(即 是否輸出複位信號),各位的作用如表10.4所示。           與PWM定時器相似,WATDOG定時器的工作頻率通過這個公式計算:     WATDOG定時器工作頻率 = PCLK / {prescaler value + 1} / {divider value}     {prescaler value} = 0~255;{divider value} = 16、32、64、128     (2)WTDAT寄存器(WATCHDOG TIMER DATA)。     用於決定WATCHDOG定時器的超時周期,在定時器啟動後,當計數達到0時,WTDAT 寄存器的值會自動傳入WTCNT寄存器。不過,第一次啟動WATDOG定時器時,WTDAT 寄存器的值會自動傳入WTCNT寄存器。     (3)WTCNT寄存器(WATCHDOG TIMER COUNT)。     在啟動WATDOG定時器前,必須往這個寄存器寫入初始值。啟動定時器後,它減1計數, 當計數值到達0時:     如果中斷被使能的話發出中斷;     如果WATCHDOG功能被使能的話,發出複位信號,裝載WTDAT寄存器的值並重新計數。 10.2 MPLL和定時器操作實例 10.2.1 程式設計     本實例講解MPLL、定時器的使用。首先啟動MPLL提高系統時鐘,初始化存儲控制器使 SDRAM工作在新的HCLK下,然後將定時器0設為0.5s產生一次中斷,在中斷程式中改變 LED的狀態。 10.2.2 代碼詳解     源碼在/work/hardware/timer目錄下。     本實驗的重點在4點:     ① 設置/啟動 MPLL;     ② 根據HCLK設置存儲控制器;     ③ 初始化定時器0;     ④ 初始化定時器中斷。     相關函數在init.c中。 1.設置/啟動 MPLL     clock_init函數用於設置MPLL,本開發板的輸入時鐘頻率Fin為12MHz,將FCLK、HCLK、 PCLK分別設為200MHz、100MHz和50MHz,代碼如下:
 1 行號
 2 23行 #define s3c2410_MPLL_200MHz    ((0x5c << 12) | (0x04 << 4) | (0x00))    /*MDIV = 0x5c, PDIV = 0x04, SDIV = 0*/
 3 24行 #define s3c2440_MPLL_200MHz    ((0x5c << 12) | (0x01 << 4) | (0x02))
 4 25行 /*
 5 26行 *對於MPLLCON寄存器,[19:12]為MDIV、[1:0]為SDIV
 6 27行 *有如下公式:
 7 28行 *    s3c2410:MPLL(FCLK) = (m * Fin)/(p * 2^s)
 8 29行 *    s3c2440:MPLL(FCLK) = (2*m*Fin)/(p * 2^s)
 9 30行 *    其中:m = MDIV + 8,p = PDIV +2, s = SDIV
10 31行 *對於本開發板,Fin = 12MHz
11 32行 *設置CLKDIVN,令分頻比為:FCLK:HCLK:PCLK = 1:2:4
12 33行 *FCLK = 200MHz,HCLK = 100MHz,PCLK = 50MHz
13 34行 */
14 35行 void clock_init(void)
15 36行 {
16 37行     //LOCKTIME = 0x00ff ffff    //使用預設值即可
17 38行     CLKDIVN = 0x03;            //FCLK:HCLK:PCLK = 1:2:4,HDIVN = 1, PDIVN = 1
18 39行 
19 40行     /*如果HDIVN非0,CPU的匯流排模式應該從“fast bus mode”變為“asynchronous bus mode”*/
20 41行 __asm__(
21 42行     "mrc p15, 0, r1, c1, c0, 0\n"    //讀出控制寄存器
22 43行     "orr r1, r1, #0xc0000000\n"      //設置為“asynchronous bus mode”
23 44行     "mcr p15, 0, r1, c1, c0, 0\n"    //寫入控制寄存器
24 45行 )
25 46行 
26 47行     /*判斷是s3c2410還是s3c2440*/
27 48行     if((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
28 49行     {
29 50行         MPLLCON = S3C2410_MPLL_200MHz;    /*現在,FCLK = 200MHz,HCLK = 100MHz,PCLK = 50MHz*/
30 51行     }
31 52行     else
32 53行     {
33 54行         MPLLCON = S3C2440_MPLL_200MHz;
34 55行     }
35 56行 }
36 57行 
init.c->clock_init.c()     如果處理器是S3C2410,使用第50行設置MPLL寄存器,令MDIV = 0x5c,PDIV = 0x04,  SDIV = 0,所以:
    MPLL(FCLK) = (m * Fin)/(p * 2^s) = (0x5c + 8) * 12MHz/((0x04 + 2)*2^0) = 200MHz
    HCLK = FCLK/2 = 100MHz
    PCLK = FCLK/4 = 50MHz
    如果處理器是S3C2440,使用第54行設置MPLL寄存器,使用第29行的公式可以計算 出MPLL = 200MHz,所以FCLK、HCLK、PCLK分別為200MHz、100MHz和50MHz。  2.設置存儲控制器 memsetup函數被用來設置存儲控制器,代碼如下:
 1 行號
 2 58行/*
 3 59行*設置存儲控制器以使用SDRAM
 4 60行*/
 5 61行void memsetup(void) 
 6 62行{
 7 63行    volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
 8 64行    
 9 65行    /*這個函數之所以這樣賦值,而不是像前面的實驗(比如mmu實驗)那樣將配置值
10 66行    *寫在數組中,是因為要生成位置無關代碼,使得這個函數可以被覆制到
11 67行    *SDRAM之前就可以在Steppingstone中運行
12 68行    */    
13 69行    /*存儲控制器13個寄存器的值*/
14 70行    p[0] = 0x22011110;    //BWSCON
15 71行    P[1] = 0x00000700;    //BANKCON0
16 72行    p[2] = 0x00000700;    //BANKCON1
17 73行    p[3] = 0x00000700;    //BANKCON2
18 74行    p[4] = 0x00000700;    //BANKCON3
19 75行    p[5] = 0x00000700;    //BANKCON4
20 76行    p[6] = 0x00000700;    //BANKCON5
21 77行    p[7] = 0x00018005;    //BANKCON6
22 78行    p[8] = 0x00018005;    //BANKCON7
23 79行
24 80行    /*REFRESH,
25 81行    *HCLK = 12MHz :0x008c 07a3
26 82行    *HCLK = 100MHz:0x008c 04f4
27 83行    */
28 84行    p[9]  = 0x008c04f4;
29 85行    p[10] = 0x000000b1;    //BANKSIZE
30 86行    p[11] = 0x00000030;    //MRSRB6
31 87行    p[12] = 0x00000030;    //MRSRB7
32 88行}
33 89行
init.c->memsetup()     除REFRESH寄存器外,其他寄存器的值與第6章的實驗程式一樣。現在HCLK等於 100MHz,REFRESH寄存器的值需要重新計算。參考第6章的公式可以計算:     R_CNT = 2^11 + 1 - 100MHz * 7.8125uS = 0x04F4,     所以,REFRESH = 0x008c0000 + R_CNT = 0x008c04f4。     在連接腳本timer.lds中,全部代碼的起始運行地址都被設為0x3000 0000,但是在執行 memsetup函數時,代碼還在內部SRAM(steppingston)中,為了能在此處運行這個函數, 它應該是位置無關的。 3.初始化定時器0     timer0_init函數用於初始化定時器0,根據相關寄存器的格式並參考代碼中的註釋就可 以理解這個函數,代碼如下:
 1 行號
 2 124行/*
 3 125行*Timer input clock Frequency = PCLK / (prescaler value + 1) / (divider value)
 4 126行*(prescaler value) = 0~255
 5 127行*(divider value) = 2、4、8、16
 6 128行*本實驗的Timer0的時鐘頻率 = 100MHz/(99 + 1)/(16) = 62500Hz
 7 129行*設置Timer0 0.5s觸發一次中斷
 8 130行*/
 9 131行void timer0_init(void)
10 132行{
11 133行    TCFG0    = 99;        //預分頻器 0 = 99
12 134行    TCFG1    = 0x03;      //選擇16分頻
13 135行    TCNTB0   = 31250;     //0.5s觸發一次中斷
14 136行    TCON    |= (1 << 1);  //手動更新
15 137行    TCON     = 0x09;      //自動載入,清除“手動更新”位,啟動定時器0
16 138行}
17 139行
init.c->timer0_init() 4.定時器中斷     head.S中調用timer0_init函數之後,定時器開始工作;調用init_irq函數使能定時器0 中斷、設置CPSR寄存器開啟IRQ中斷後,每當定時器0計數達到0時,就會觸發中斷。 init_irq函數很簡單,在init.c中,代碼如下:
行號
140行/*
141行*定時器0中斷使能
142行*/
143行void init_irq(void)
144行{
145行    //定時器0中斷使能
146行    INTMSK &= (~(1 << 10));
147行}
init.c->init_irq()     發生定時器中斷時,CPU將調用其中斷服務程式Timer0_Handler,它在interrupt.c中:
 1 行號
 2 03行void Timer0_Handler(void)
 3 04行{
 4 05行    /*
 5 06行    *每次中斷令3個LED改變狀態
 6 07行    */
 7 08行    if(INTOFFSET == 10)
 8 09行    {
 9 10行        GPFDAT = ~(GPFDAT & (0x7 << 4));
10 11行    }
11 12行    //清除中斷
12 13行    SRCPND = 1 << INTOFFSET;
13 14行    INTPND = INTPND;
14 15行}
interrupt.c     定時器0的中斷使用SRCPND、INTPND寄存器中的位10來表示。中斷服務程式 Timer0_Handler先判斷是否定時器0的中斷,若是則反轉3個LED的狀態。 10.2.3 實例測試     在timer目錄下執行make命令生成timer.bin可執行程式,燒入NAND Flash中執行, 即可看到3個LED每1s閃爍一次。     將head.S中對clock_init函數的調用去掉,不啟動MPLL;並隨之將init.c中的 memsetup函數的REFRESH寄存器改為12MHz對應的0x008c 07a3.重新編譯、燒寫, 可以看到差不多8sLED閃爍一次。 附:代碼: 鏈接: https://pan.baidu.com/s/1kV24a9L 密碼: tfab
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Redis4.0 Cluster — Centos7, Ruby redis-trib.rb , gem redis ...
  • 一、安裝包 先從網路上,下載Mysql安裝包,複製到U盤 下載地址:https://dev.mysql.com/downloads/mysql/ 二、掛載U盤 2.1查看分區 先輸入命令 cat /proc/partitions 插入U盤,重新輸入命令 cat /proc/partitions 結果 ...
  • 熟悉Oracle上機環境及Oracle客戶端的配置;熟練掌握和使用DDL語言,建立、修改和刪除資料庫表、主鍵、外鍵約束關係和索引。 (修改資料庫表名) 將資料庫表S1改名為Student_Temp。 在定義外鍵約束條件時,不能把其他表中沒有的屬性定義在本表的外鍵中,否則會生辰一個錯誤; 在建表時,因 ...
  • 一、流程式控制制語句 1) 迴圈語句 == loop .. end loop 簡單的迴圈,至少被執行一次 == while ... loop end loop == for 2) 控制語句 == goto 用於跳轉到指定的標號去執行,不建議使用 語法: goto 標號名 == null 語句 null語 ...
  • 一、概述 pl/sql (procedural lanaguage/sql)是 oracle 在標準 sql 上的擴展 。不僅允許嵌入sql 語言,還可以定義變數和常量,允許使用條件語句和迴圈語句,允許使用例外處理錯誤。 -- 可以用來編寫過程,函數,和觸發器 -- 上述對象是放在資料庫中的 //數 ...
  • 工作中遇到的數據更新,學習記錄。 1、使用update進行數據更新 1)最簡單的更新 update tablea a set a.price=1.00 2)帶條件的數據更新 update tablea a set a.price = 2.00 where a.id='02' 3)兩張表關聯更新為固定 ...
  • 瞭解UART原理; 掌握S3C2410/S3C2440中UART的使用 ...
  • Centos 7 安裝與配置 1. 安裝VMware。 2. 安裝centos7 首先右鍵“新建虛擬機”,選擇 “典型”安裝,如下圖: 點擊下一步,選擇“稍後安裝操作系統”,如圖: 選擇好對應的操作系統, 然後,選擇centos的目錄路徑,如圖: 指定磁碟容量,預設20g,可以調整。空間逐漸增加,上 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...