主頁 > 軟體設計 > LPC2124單片機的基礎操作——GPIO、外部中斷、定時器和串口

LPC2124單片機的基礎操作——GPIO、外部中斷、定時器和串口

2021-04-08 11:59:46 軟體設計

LPC2124單片機的基礎操作——GPIO、外部中斷、定時器和串口

  • LPC2124的簡介
  • LPC2124之GPIO
    • GPIO簡介
    • 編程習慣
    • 代碼撰寫
  • LPC2124之EINT(外部中斷)
    • EINT簡介
    • 代碼撰寫
    • 電路仿真
  • LPC2124之TIMER(定時器)
    • TIMER簡介
    • 代碼撰寫
    • 電路仿真
  • LPC2124之UART(串口)
    • UART簡介
    • 代碼撰寫
    • 電路仿真

LPC2124的簡介

這是我第一次在CSDN發博客,正好學校里面開了嵌入式實驗課,根據自己的經驗和理解就想著總結一下,廢話就不多說了,LPC2124是恩智浦公司(就是那個給全國大學生智能車比賽贊助的公司)推出的一款ARM7架構的單片機,下圖給出其特性介紹,

在這里插入圖片描述
其實不難看出其各項引數算是比較落后的,零幾年的時候可能大家學習單片機的思路就是先學個51單片機、AVR單片機打個基礎再去學ARM7、ARM9架構按照這個順序的單片機,后來ARM公司推出了Cortex系列的架構,完全改變了處理器市場和我們學習的思路,比如我當時本科學單片機的時候先學個51單片機,之后就是STM32系列全家桶,這也得益于cortex架構的優秀性能以及更低的價格,那既然課程安排使用的是LPC2124,正好網上資料不多的情況(對比之下,stm32的資料是真的多,可以說是單片機中的頂流了),博主就從一款單片機最基礎的GPIO、外部中斷、定時器以及uart串口來講起,

LPC2124之GPIO

GPIO簡介

GPIO(General-purpose input/output)就是通用輸入輸出的意思,任何一款單片機最最最最基本的功能,我們平時習慣上稱之為IO口,可以輸出高電平、低電平或者模擬量,再者檢測IO口的電平等等,在使用LPC2124的IO口時,我們是通過操作暫存器的方式進行的,如果不太懂暫存器的話,簡單的理解就是每個暫存器對應一種特有的功能,我們需要給暫存器賦值以實作其功能,下圖給出GPIO相關的暫存器,

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
上圖我們只需要關注port0和port1的暫存器,port2和port3是針對lpc22系列的單片機的,不用考慮,為了方便理解下圖給出LPC2124的電路結構圖,
在這里插入圖片描述
不難看出LPC2124有P0和P1兩類埠,其中P0有31個引腳,P1有16個引腳,再來看GPIO的暫存器,
IOPIN(實際操作,P0口對應IO0PIN,P1口對應IO1PIN)是用來讀取引腳電平值,1為高電平,0為低電平,是只讀型別,無法寫入,復位值是0x00000000,32位,假設IO0PIN的值是0x00008000,也就是P0.15是高電平,其余都是低電平,因為32暫存器用16進制(0x)來表示就是八位,0x00008000用二進制表示就是00000000000000001000000000000000,
IODIR(實際操作,P0口對應IO0DIR,P1口對應IO1DIR)是設定引腳是輸出(1)還是輸入(0)的,讀寫型別,復位值0x00000000,32位,假設IO1DIR=0x00000002,就是將P1.1設定為輸出,
IOSET(實際操作,P0口對應IO0SET,P1口對應IO1SET)是設定引腳輸出高電平(1),0無意義,32位,假設IO0SET=0x00000002,就是將P0.1設定為輸出高電平,
IOCLR(實際操作,P0口對應IO0CLR,P1口對應IO1CLR)是設定引腳輸出低電平(1),0無意義,32位,假設IO0CLR=0x00000002,就是將P0.1設定為輸出低電平,

編程習慣

在實際撰寫代碼之前,先說明一下博主本次單片機的編程習慣,

  1. 新建一個檔案夾LPC2124_CODE,包含RESOURSE、SYSTEM、USER這三個子檔案,
    在這里插入圖片描述
  2. 打開keil4,新建工程,選擇LPC2124,并將startup.s添加到工程中,
    在這里插入圖片描述
    在這里插入圖片描述
    在這里插入圖片描述
  3. 進入工程,右鍵進入manage components,添加三個分組RESOURSE、SYSTEM、USER,
    在這里插入圖片描述
    在這里插入圖片描述
  4. 在USER檔案夾中新建main.c,在SYSTEM檔案夾中新建sys.c和sys.h,在RESOURSE檔案夾中新建gpio.c和gpio.h
    在這里插入圖片描述
    在這里插入圖片描述
    在這里插入圖片描述
    在這里插入圖片描述
    在這里插入圖片描述
  5. 將main.c添加到之前創建的USER分組下,將sys.c添加到之前創建的SYSTEM分組下,將gpio.c添加到之前創建的RESOURSE分組下,
    在這里插入圖片描述
    在這里插入圖片描述
    在這里插入圖片描述
  6. 打開魔術棒,選擇C/C++的include paths,添加頭檔案的路徑(SYSTEM檔案夾以及RESOURSE檔案夾)包含進來,
    在這里插入圖片描述
    在這里插入圖片描述

代碼撰寫

  1. 在sys.h中添加下面的代碼,其中#ifndef#define#endif結構主要是為了防止重復定義的錯誤,其余的主要是進行一些型別定義以及sys.c的函式的申明,
#ifndef __SYS_H
#define __SYS_H	 
#include "LPC21xx.H"
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
void delay_ms(u32 num); //ms級粗延遲,最小單位為1ms,無法小數延遲
void delay_s(u32 num); //s級粗延遲,建議最小單位為s,可以小數延遲,最小小數點后三位
#endif
  1. 在sys.c中添加下面的代碼,主要是進行了ms級以及s級的粗略延時函式的撰寫,
#include "sys.h"
u32 times = 100;//回圈次數默認為100
void delay_ms(u32 num){                         
  u32 i,j;
  for(i=0;i<(num * 22);i++)
  for(j=0;j<times;j++);
}
void delay_s(u32 num){                         
  u32 i,j;
  for(i=0;i<(num * 22000);i++)
  for(j=0;j<times;j++);
}
  1. 在gpio.h中添加下面的代碼,主要是對gpio.c的函式進行申明,包含了P0/P1口引腳電平設定為高電平(gpio0_seH、gpio1_seH),P0/P1口引腳電平設定為低電平(gpio0_seL、gpio1_seL),判斷P0/P1口引腳電平(gpio0_geN、gpio1_geN),
#ifndef __GPIO_H
#define __GPIO_H
#include "sys.h"

void gpio0_seH(u16 pin_num); //設定GPIO0引腳為高電平
void gpio0_seL(u16 pin_num); //設定GPIO0引腳為低電平
u32 gpio0_geN(u16 pin_num); //讀取GPIO0引腳電平
void gpio1_seH(u16 pin_num); //設定GPIO1引腳為高電平
void gpio1_seL(u16 pin_num); //設定GPIO1引腳為低電平
u32 gpio1_geN(u16 pin_num); //讀取GPIO1引腳電平

#endif
  1. 在gpio.c中添加下面的代碼,主要是對gpio的暫存器操作封裝為函式操作,讀者完全可以通過函式呼叫的方式進行管腳的操作,讀者如果對位操作不太清楚的話,可以簡單的理解為左移就是右填0,右移就是左填零,按位或就是置1,按位與就是清零(取位),按位取反就是字面意思,
#include "gpio.h"
//pin_num: 0~31,選擇引腳號
void gpio0_seH(u16 pin_num){
	if(pin_num >= 16 && pin_num <= 31){
		PINSEL1 = PINSEL1 & (~(0x00000003 << (2 * (pin_num - 16))));//設定引腳為GPIO模式
	}
	else{
		PINSEL0 = PINSEL0 & (~(0x00000003 << (2 * pin_num)));//設定引腳為GPIO模式
	}
	IO0DIR = IO0DIR | (0x00000001 << pin_num);//方向控制暫存器,1位輸出,0位輸入
	IO0SET = IO0SET | (0x00000001 << pin_num);//高電平輸出暫存器
}
void gpio0_seL(u16 pin_num){
	if(pin_num >= 16 && pin_num <= 31){
		PINSEL1 = PINSEL1 & (~(0x00000003 << (2 * (pin_num - 16))));//設定引腳為GPIO模式
	}
	else{
		PINSEL0 = PINSEL0 & (~(0x00000003 << (2 * pin_num)));//設定引腳為GPIO模式
	}
	IO0DIR = IO0DIR | (0x00000001 << pin_num);
	IO0CLR = IO0CLR | (0x00000001 << pin_num);//低電平輸出暫存器
}
u32 gpio0_geN(u16 pin_num){
	if(pin_num >= 16 && pin_num <= 31){
		PINSEL1 = PINSEL1 & (~(0x00000003 << (2 * (pin_num - 16))));//設定引腳為GPIO模式
	}
	else{
		PINSEL0 = PINSEL0 & (~(0x00000003 << (2 * pin_num)));//設定引腳為GPIO模式
	}
	IO0DIR = IO0DIR & (~(0x00000001 << pin_num));
	return ((IO0PIN & (0x00000001 << pin_num)) >> pin_num);//回傳指定管腳上的電平值
}
void gpio1_seH(u16 pin_num){
	if(16 <= pin_num <= 25){
		PINSEL2 = PINSEL2 & (~(0x00000008));//設定引腳為GPIO模式
	}
	else{
		PINSEL2 = PINSEL2 & (~(0x00000004));//設定引腳為GPIO模式
	}
	IO1DIR = IO1DIR | (0x00000001 << pin_num);
	IO1SET = IO1SET | (0x00000001 << pin_num);
}
void gpio1_seL(u16 pin_num){
	if(16 <= pin_num <= 25){
		PINSEL2 = PINSEL2 & (~(0x00000008));
	}
	else{
		PINSEL2 = PINSEL2 & (~(0x00000004));
	}
	IO1DIR = IO1DIR | (0x00000001 << pin_num);
	IO1CLR = IO1CLR | (0x00000001 << pin_num);
}
u32 gpio1_geN(u16 pin_num){
	if(16 <= pin_num <= 25){
		PINSEL2 = PINSEL2 & (~(0x00000008));
	}
	else{
		PINSEL2 = PINSEL2 & (~(0x00000004));
	}
	IO1DIR = IO1DIR & (~(0x00000001 << pin_num));
	return ((IO1PIN & (0x00000001 << pin_num)) >> pin_num);
}
  1. 在main.c中添加下面的代碼,
/*********************************/
//本程式僅供學習科研使用
//單片機型號:LPC2124
//作者:哈哈我是HH
//修改日期:2021.4.6
//版本:V1.0
//Copyright(C) 哈哈我是HH 2021-2031
//All rights reserved
/*********************************/
#include "sys.h"
#include "gpio.h"
u32 flag1 = 0;
int main(void){
	while (1)  
	{
		gpio0_seH(0);
		delay_ms(200);
		gpio0_seL(0);
		delay_ms(200);
		flag1 = gpio1_geN(16);
		if(flag1 == 1){
			gpio0_seH(1);
		}
		if(flag1 == 0){
			gpio0_seL(1);
		}
	}
}

GPIO的操作是非常簡單的,這里就不添加proteus中的仿真圖,大家可以自己修改main.c中的代碼進行實驗,接下來就要是介紹外部中斷的使用了,

LPC2124之EINT(外部中斷)

EINT簡介

中斷學得好不好,可以說是任何一款單片機有沒有入門的試金石(感覺定時器和串口都是試金石,算了算了,想想還是中斷更加基礎),單片機的程式執行都是main函式開始的(排除一些上電片內資源的呼叫),因為c語言的順序執行原因,導致main函式的所有步驟都是要一步一步順序執行的,所以既然你寫了,那都要執行,這樣的效率簡直太低了,設想一下如果你的main函式里面寫了100條操作陳述句,結果只有最后一條陳述句才真正去實際操作的,前面的99條都是當前不必執行的,可能100條對于單片機來說還是小意思,那更多的呢?這時候如果引入了中斷,那么完全不用都在main函式里面去書寫,全部放到中斷中,哪條回應中斷,哪條才去執行,這樣單片機的效率真正的提高了!
網上比較形象的例子就是如果你在打游戲但是隨時都有可能女朋友(假設你有女朋友)的微信要回,你不可能打1s的游戲看1s的手機訊息(相當于main函式里面while(1)的操作,但是如果你真的這么去做,我只能說你是好男人,博主不配擁有女朋友),你一定是一直在打游戲,只有手機來訊息了你才會去看(相當于中斷操作)!
LPC2124的外部中斷總共有4個,為P0.1、P0.3、P0.7、P0.9、P0.14、P0.15、P0.16、P0.20引腳,因此是需要設定PINSEL暫存器的值為EINT,
在這里插入圖片描述
在這里插入圖片描述

下圖給出了外部中斷的暫存器,
在這里插入圖片描述
EXTINT是設定中斷標志的,8位,高電平有效,
在這里插入圖片描述

EXTMODE是設定外部信號的中斷回應是電平有效(0)還是邊沿有效(1),同樣也是8位,
在這里插入圖片描述
EXTPOLAR是設定外部信號的中斷回應如果是電平有效,那么這個信號是低電平有效(0)還是高電平有效(1),中斷回應如果是邊沿有效,那么這個信號是下降沿有效(0)還是上升沿有效(1),同樣也是8位,
在這里插入圖片描述
在這里插入圖片描述

下圖給出了向量中斷暫存器,向量中斷暫存器是所有中斷(包括外部中斷、定時器中斷、串口中斷等等)都需要設定的,主要是設定中斷的型別,中斷函式的地址以及中斷的優先級,在這里插入圖片描述
在這里插入圖片描述
我們在配置向量中斷暫存器主要是設定四個暫存器,
VICIntSelect配置中斷型別,FIQ是快速中斷請求,一般我們選擇的是IRQ(向量中斷請求),
在這里插入圖片描述
VICIntEnable是使能中斷,我們配置為1就行,
在這里插入圖片描述
VICVectCntl設定中斷優先級,第5位給1使能,4:0位設定為對應中斷的中斷源編號(見下圖),實際中VICVectCntl對應的暫存器是VICVectCntl0~15,也就是對應16個優先級,數字越大優先級越低,數字越小優先級越高,這樣的話在中斷都回應的情況下,優先級越高越先回應,值得注意的是不能給不同中斷設定相同的優先級,
在這里插入圖片描述
中斷源編號
在這里插入圖片描述
在這里插入圖片描述
VICVectAddr是設定中斷服務函式的地址,因為優先級的原因,所以這里也是有16個,即暫存器是VICVectAddr0~15,而優先級和地址的標號是要相同的,
在這里插入圖片描述
以上就是外部中斷需要配置的暫存器,看上去比較多,但是實際上手還是比較容易的,配置比較簡單,

代碼撰寫

在撰寫撰寫前,我們需要在GPIO的程式上繼續撰寫,首先在RESOURSE檔案下添加兩個檔案eint.c和eint.h,并在工程中將eint.c添加到RESOURSE分組下,

  1. 添加eint.h的代碼,是一些外部中斷函式的申明,
#ifndef __EINT_H
#define __EINT_H
#include "sys.h"

void eint_st0(u32 pin_num);//外部中斷0,pin_num:1或者16
void eint_st1(u32 pin_num);//外部中斷1,pin_num:3或者14
void eint_st2(u32 pin_num);//外部中斷2,pin_num:7或者15
void eint_st3(u32 pin_num);//外部中斷3,pin_num:9或者20

#endif
  1. 添加eint.c的代碼,主要是外部中斷函式的撰寫設計我之前說的一些暫存器的操作,需要說明的是,如果中斷服務函式不需要要的是需要寫個框架的,代碼最下面我給了模板,直接去掉//就行,
#include "eint.h"
__irq void IRQ_Eint0(void);//外部中斷0中斷服務函式宣告
__irq void IRQ_Eint1(void);//外部中斷1中斷服務函式宣告
__irq void IRQ_Eint2(void);//外部中斷2中斷服務函式宣告
__irq void IRQ_Eint3(void);//外部中斷3中斷服務函式宣告
//外部中斷0只能選擇1或者16
void eint_st0(u32 pin_num){
	if(pin_num == 1){
		PINSEL0 = PINSEL0 | 0x0000000C; //P0.1管腳功能選擇為外部中斷
	}
	else{
		PINSEL1 = PINSEL1 | 0x00000003; //P0.16管腳功能選擇為外部中斷
	}
		VICIntSelect = VICIntSelect & (~0x00004000); //將外部中斷0設定為IRQ模式
		VICIntEnable = VICIntEnable | 0x00004000; //使能外部中斷0
		VICVectCntl0 = 0x2E; //將14號中斷外部中斷0優先級設定為0
		VICVectAddr0 = (int)IRQ_Eint0; //設定中斷服務子程式
		EXTINT = EXTINT | 0x01;
		EXTMODE = EXTMODE & (~0x01); //0為電平激活,1為邊沿激活
		EXTPOLAR = EXTPOLAR & (~0x01); //0為低電平產生中斷,1位高電平產生中斷
}
//外部中斷1只能選擇3或者14
void eint_st1(u32 pin_num){
	if(pin_num == 3){
		PINSEL0 = PINSEL0 | 0x000000C0; //P0.3管腳功能選擇為外部中斷
	}
	else{
		PINSEL0 = PINSEL0 | 0x30000000; //P0.14管腳功能選擇為外部中斷
	}
		VICIntSelect = VICIntSelect & (~0x00008000); //將外部中斷1設定為IRQ模式
		VICIntEnable = VICIntEnable | 0x00008000; //使能外部中斷1
		VICVectCntl1 = 0x2F; //將15號中斷外部中斷1優先級設定為1
		VICVectAddr1 = (int)IRQ_Eint1; //設定中斷服務子程式
		EXTINT = EXTINT | 0x02;
		EXTMODE = EXTMODE & (~0x02); //0為電平激活,1為邊沿激活
		EXTPOLAR = EXTPOLAR & (~0x02); //0為低電平產生中斷,1位高電平產生中斷
}
//外部中斷2只能選擇7或者15
void eint_st2(u32 pin_num){
	if(pin_num == 7){
		PINSEL0 = PINSEL0 | 0x0000C000; //P0.7管腳功能選擇為外部中斷
	}
	else{
		PINSEL0 = PINSEL0 | 0xC0000000; //P0.15管腳功能選擇為外部中斷
	}
		VICIntSelect = VICIntSelect & (~0x00010000); //將外部中斷2設定為IRQ模式
		VICIntEnable = VICIntEnable | 0x00010000; //使能外部中斷2
		VICVectCntl2 = 0x30; //將16號中斷外部中斷2優先級設定為2
		VICVectAddr2 = (int)IRQ_Eint2; //設定中斷服務子程式
		EXTINT = EXTINT | 0x04;
		EXTMODE = EXTMODE & (~0x04); //0為電平激活,1為邊沿激活
		EXTPOLAR = EXTPOLAR & (~0x04); //0為低電平產生中斷,1位高電平產生中斷
}
//外部中斷3只能選擇9或者20
void eint_st3(u32 pin_num){
	if(pin_num == 9){
		PINSEL0 = PINSEL0 | 0x000C0000; //P0.9管腳功能選擇為外部中斷
	}
	else{
		PINSEL1 = PINSEL1 | 0x00000300; //P0.20管腳功能選擇為外部中斷
	}
		VICIntSelect = VICIntSelect & (~0x00020000); //將外部中斷3設定為IRQ模式
		VICIntEnable = VICIntEnable | 0x00020000; //使能外部中斷3
		VICVectCntl3 = 0x31; //將17號中斷外部中斷3優先級設定為3
		VICVectAddr3 = (int)IRQ_Eint3; //設定中斷服務子程式
		EXTINT = EXTINT | 0x08;
		EXTMODE = EXTMODE & (~0x08); //0為電平激活,1為邊沿激活
		EXTPOLAR = EXTPOLAR & (~0x08); //0為低電平產生中斷,1位高電平產生中斷
}
//外部中斷0中斷服務函式
// __irq void IRQ_Eint0(void){
// 	
// }
//外部中斷1中斷服務函式
// __irq void IRQ_Eint1(void){
// 	
// }
//外部中斷2中斷服務函式
// __irq void IRQ_Eint2(void){
// 	
// }
//外部中斷3中斷服務函式
// __irq void IRQ_Eint3(void){
// 	
// }
  1. 添加main.c的代碼,這里需要說明的是一般外部中斷的中斷服務函式是進行標志位操作的,一般不會進行大量的回圈之類,
/*********************************/
//本程式僅供學習科研使用
//單片機型號:LPC2124
//作者:哈哈我是HH
//修改日期:2021.4.6
//版本:V1.0
//Copyright(C) 哈哈我是HH 2021-2031
//All rights reserved
/*********************************/
#include "sys.h"
#include "gpio.h"
#include "eint.h"
u32 flag = 0;
__irq void IRQ_Eint0(void){
	flag = 1;
	while((EXTINT&0x01)!=0){  //等待外部中斷信號恢復為高電平
  	EXTINT = 0x01; //清除EINT0中斷標志
  }
  VICVectAddr=0;
}
__irq void IRQ_Eint1(void){
	flag = 2;
	while((EXTINT&0x02)!=0){  //等待外部中斷信號恢復為高電平
  	EXTINT = 0x02; //清除EINT1中斷標志
  }
  VICVectAddr=0;
}
__irq void IRQ_Eint2(void){
	flag = 3;
	while((EXTINT&0x04)!=0){  //等待外部中斷信號恢復為高電平
  	EXTINT = 0x04; //清除EINT2中斷標志
  }
  VICVectAddr=0;
}
__irq void IRQ_Eint3(void){
	flag = 4;
	while((EXTINT&0x08)!=0){  //等待外部中斷信號恢復為高電平
  	EXTINT = 0x08; //清除EINT3中斷標志
  }
  VICVectAddr=0;
}
int main(){
	eint_st0(16);
	eint_st1(3);
	eint_st2(7);
	eint_st3(20);
	while(1){
		if(flag == 1){
			gpio1_seL(23);
			delay_ms(100);
			gpio1_seH(23);
			delay_ms(100);		
		}
		else if(flag == 2){
			gpio1_seL(23);
			delay_ms(500);
			gpio1_seH(23);
			delay_ms(500);
		}
		else if(flag == 3){
			gpio1_seL(23);
			delay_s(1);
			gpio1_seH(23);
			delay_s(1);
		}
		else if(flag == 4){
			gpio1_seL(23);
			delay_s(2);
			gpio1_seH(23);
			delay_s(2);
		}
		else{
			gpio1_seH(23);
		}
	}
}

編譯之后就可以電路仿真了,這里使用的是proteus(這軟體真就一言難盡),

電路仿真

在這里插入圖片描述
實驗現象:
按下第一個按鍵,led以100ms進行閃爍,
按下第二個按鍵,led以500ms進行閃爍,
按下第三個按鍵,led以1s進行閃爍,
按下第四個按鍵,led以2s進行閃爍,

LPC2124之TIMER(定時器)

TIMER簡介

定時器的概念其實非常簡單就是單片機內部的一個精確計數(定時)的資源,細心的讀者不難發現之前我在撰寫sys.c的代碼就有寫到delay函式,這是粗延時,簡單的理解就是單片機在一個地方死回圈,而定時器往往搭配中斷組成定時器中斷的功能來使用,比如在經過一段時間后定時器產生中斷回應單片機去執行,當然了定時器最基本的功能就是計時,其衍生功能還有輸入捕獲和pwm波輸出,
LPC2124有兩個定時器TIMER0和TIMER1,其時鐘來源于外部晶振,我們也同樣是進行暫存器的操作來實作相應的功能,下圖給出了定時器的相關暫存器,
在這里插入圖片描述
在這里插入圖片描述
實際上我們在操作定時器時不需要都配置上面全部的暫存器,有些是輸入捕獲實驗的,僅僅拿來計時的話只有四個暫存器需要配置,
MR暫存器是設定定時器的計數值,記一次相當于時鐘的一個周期,實際配置我們設定的是T0/1MR0~3,
在這里插入圖片描述
MCR暫存器的配置主要是如果計數器和MR0~3的值匹配后會產生中斷或者復位或者停止,這里是需要和MR暫存器的編號相同,實際操作中我們需要配置的是T0MCR或者T1MCR,
在這里插入圖片描述
在這里插入圖片描述
TCR暫存器的作用是使能定時器,置1就行,實際操作需要配置的是T0TCR或者T1TCR,
在這里插入圖片描述
IR暫存器的配置是如果將MCR暫存器設定了中斷模式,那么這里是需要匹配中斷通道的,例如MCR設定了MR0的中斷模式,那么IR暫存器就要匹配通道0的中斷標志,
在這里插入圖片描述既然上文博主提到了定時器一般是需要中斷的,那么也就是說除了上面的四個暫存器需要配置,還需要中斷的四個暫存器VICIntSelect、VICIntEnable、VICVectAddr、VICVectCntl,這一部分的知識如果不太清楚的話就請查看一下上文的外部中斷暫存器配置的講解,
接下來就是代碼的撰寫了,

代碼撰寫

同樣我們是需要在外部中斷實驗的基礎再添加代碼的,首先在RESOURSE檔案下添加兩個檔案timer.c和timer.h,并在工程中將timer.c添加到RESOURSE分組下,

  1. 添加timer.h的代碼,主要是函式的申明,
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
void timer_st0(void);
void timer_st1(void);
#endif
  1. 添加timer.c的代碼,撰寫了定時器初始化函式,需要說明的是中斷優先級和中斷服務函式需要和外部中斷的區別開,不能設定相同的中斷優先級和中斷服務函式,
#include "timer.h"
__irq void IRQ_timer0 (void);//定時器0中斷服務函式
__irq void IRQ_timer1 (void);//定時器1中斷服務函式
void timer_st0(void){ 
  T0MR0 = 1199999; //設定匹配值,1200000-1,12000000=1s
  T0MCR = T0MCR | 0x003; //匹配后復位TC,并產生中斷
  T0TCR = 0x1;//啟動定時器0,T0TCR計數控制暫存器
  VICIntSelect = VICIntSelect & (~0x00000010); //將定時器0設定為IRQ模式
  VICIntEnable = VICIntEnable | 0x00000010; //使能定時器0
  VICVectAddr2 = (int)IRQ_timer0; //設定定時器0的中斷服務程式地址  
  VICVectCntl2 = 0x24; //將4號中斷定時器0優先級設定為2
}
void timer_st1(void){ 
  T1MR0 = 1199999; //設定匹配值,1200000-1,12000000=1s
  T1MCR = T1MCR | 0x003; //匹配后復位TC,并產生中斷
  T1TCR = 0x1;//啟動定時器1,T1TCR計數控制暫存器
  VICIntSelect = VICIntSelect & (~0x00000020); //將定時器1設定為IRQ模式
  VICIntEnable = VICIntEnable | 0x00000020; //使能定時器1
  VICVectAddr3 = (int)IRQ_timer1; //設定定時器1的中斷服務程式地址  
  VICVectCntl3 = 0x25; //將5號中斷定時器1優先級設定為1
}
// __irq void IRQ_timer0 (void){
// 	
// }
__irq void IRQ_timer1 (void){
	
}
  1. 添加main.c的代碼,需要說明的是需要在main函式開始的時候初始化外部中斷(本實驗用到了外部中斷)和定時器,
/*********************************/
//本程式僅供學習科研使用
//單片機型號:LPC2124
//作者:哈哈我是HH
//修改日期:2021.4.6
//版本:V1.0
//Copyright(C) 哈哈我是HH 2021-2031
//All rights reserved
/*********************************/
#include "sys.h"
#include "gpio.h"
#include "timer.h"
#include "eint.h"
u32 timer0Times = 0;
u32 times_flag = 0;	
__irq void IRQ_Eint2(void){
	times_flag = 1;
	while((EXTINT&0x04)!=0){		//中斷標志清零
		EXTINT=0x04;
	}
  VICVectAddr=0;					//通知中斷處理結束
}	
__irq void IRQ_Eint3(void){
	times_flag = 2;
	while((EXTINT&0x08)!=0){		//中斷標志清零
		EXTINT=0x08;
	}
  VICVectAddr=0;					//通知中斷處理結束
}
__irq void IRQ_timer0(void){ //定時器中斷處理函式
	if(times_flag == 1){
		timer0Times++;
		if(timer0Times == 1){								
			gpio0_seH(0);
			gpio0_seL(1);
			gpio0_seH(2);
			gpio0_seL(3);
		}
		if(timer0Times == 2){	
			gpio0_seL(0);
			gpio0_seH(1);
			gpio0_seL(2); 
			gpio0_seH(3);
		}
		if(timer0Times == 3){	
			gpio0_seH(0);
			gpio0_seL(1);
			gpio0_seH(2); 
			gpio0_seL(3);
		}
		if(timer0Times == 4){	
			gpio0_seL(0);
			gpio0_seH(1);
			gpio0_seL(2); 
			gpio0_seH(3);
			timer0Times = 0;
		}
		T0IR = 1;						//中斷標志清零
		VICVectAddr = 0;    //通知中斷處理結束
	}
	else if(times_flag == 2){
		timer0Times++;
		if(timer0Times == 1){								
			gpio0_seH(0);
			gpio0_seH(1);
			gpio0_seL(2);
			gpio0_seL(3);
		}
		if(timer0Times == 2){	
			gpio0_seL(0);
			gpio0_seL(1);
			gpio0_seH(2);
			gpio0_seH(3);
		}
		if(timer0Times == 3){	
			gpio0_seH(0);
			gpio0_seH(1);
			gpio0_seL(2);
			gpio0_seL(3);
		}
		if(timer0Times == 4){	
			gpio0_seL(0);
			gpio0_seL(1);
			gpio0_seH(2);
			gpio0_seH(3);
			timer0Times = 0;
		}
		T0IR = 1;						//中斷標志清零
		VICVectAddr = 0;    //通知中斷處理結束
	}
	else{
		T0IR = 1;						//中斷標志清零
		VICVectAddr = 0;    //通知中斷處理結束
	}
}
int main(void){
	gpio0_seH(0);
	gpio0_seH(1);
	gpio0_seH(2);
	gpio0_seH(3);
	eint_st2(15);
	eint_st3(20);		//按鍵中斷初始化
	timer_st0();		//定時器初始化
	while (1)  
	{
		if(times_flag == 1){
			gpio1_seL(27);
		}
		if(times_flag == 2){
			gpio1_seH(27);
		}
	}
}

電路仿真

在這里插入圖片描述
實驗說明:需要將LPC2124的時鐘設定為12MHZ,
實驗現象:
按下第一個按鍵,led1、led3和led2、led4交替閃爍,D5亮,
按下第二個按鍵,led1、led2和led3、led4交替閃爍,D5滅,

LPC2124之UART(串口)

UART簡介

串口主要是用來做串口通信的,而通信正是人機互動、多機互聯的基礎,只有學好了uart串口通信才能夠更加深入的去學習其他的通信方式,比如說IIC、SPI等等,
在介紹UART暫存器之前還是需要了解一些串口的基本知識,比如波特率,還有就是其資料傳輸結構,當然了有一點是需要說明的是通常意義上的UART串口通信應該是半雙工異步通信,何為半雙工,簡單的理解就是收發不能同步,何為異步,簡單的理解就是不存在同步時鐘,因此才會需要波特率去匹配資料收發速度,與之對應的USART才是全雙工異步通信,
波特率更深刻的理解可以自行百度,這里大家只需要知道波特率是代替時鐘的作用,否則兩邊資料“理解”無法做到匹配,舉個簡單的理解我傳輸了一個1去2號機,那2號機怎么知道這是1個1還是2個1還是n個1,如果我們約定好波特率了,就不會存在問題,我只要以和發送方相同的發送步長(波特率)去讀就不會出錯了,
資料傳輸結構指的是一次傳輸的資料格式,通常設定的是8位資料,無校驗位,一個停止位,
LPC2124總共有兩組串口分別為UART0——RXD0(接收P0.1)、TXD0(發送P0.0)和UART1——RXT0(接收P0.9)、TXD0(發送P0.8),接下來給出串口的所有暫存器(以串口0介紹,串口1同理),
在這里插入圖片描述
以上的暫存器我們也并不是都用到,
LCR暫存器是用來配置資料傳輸結構,這里就設定為8個字符長度、1個停止位,不使能奇偶校驗,禁止間隔發送,第一次需要使能訪問除數鎖存,
在這里插入圖片描述
在這里插入圖片描述
DLLDLM是設定除數鎖存暫存器的即為波特率的系數,計算公式為:15000000/(16*波特率),15000000是時鐘為15MHZ,波特率常用的有9600,19200,38400,而DLL表示低八位,DLM表示高八位,在設定完除數鎖存暫存器之后需要將LCR暫存器的最高位置0,以禁止訪問除數鎖存,
在這里插入圖片描述
IER暫存器只需要使能RDA就行,即為接收到資料就產生中斷,
在這里插入圖片描述
以上暫存器設定完之后同樣我們需要使能中斷的相關暫存器以及引腳功能復用的暫存器,

代碼撰寫

需要說明的是本次實驗我們用到了雙機通信,因此主程式main.c有兩套,

  1. 添加uart.h的代碼,主要是函式的申明,
#ifndef __UART_H
#define __UART_H
#include "sys.h"
void uart_st0(u32 baud_rate); //不要設定波特率低于4800,不穩,常用9600,19200,38400
void uart_st1(u32 baud_rate); //不要設定波特率低于4800,不穩,常用9600,19200,38400
u32 putchar0(u32 ch);
void serialPuts0(u8 *p);
u32 putchar1(u32 ch);
void serialPuts1(u8 *p);
__irq void IRQ_uart0 (void);//串口0中斷服務函式

#endif
  1. 添加uart.c的代碼,主要是一些串口初始化以及發送字串的函式的撰寫,
#include "uart.h"
__irq void IRQ_uart0 (void);//串口0中斷服務函式
void uart_st0(u32 baud_rate){ //串口0初始化
	PINSEL0 = PINSEL0 | 0x00000005; //打開串口功能
  U0LCR = 0x83; //8位資料,無校驗位,一個停止位,禁止間隔發送,使能訪問除數鎖存
	if(15000000/(16 * baud_rate) <= 255){
		U0DLM = 0; //設定除數鎖存高八位
		U0DLL = 15000000/(16 * baud_rate);//設定除數鎖存低八位,時鐘15MHz設定波特率為38400,計算公式15000000/(16*波特率)
	}else{
		U0DLM = (floor)(15000000/(16 * baud_rate) - 255); //設定除數鎖存高八位
		U0DLL = 255;//設定除數鎖存低八位,時鐘15MHz設定波特率為38400,計算公式15000000/(16*波特率)
	}
  U0LCR = 0x03; //禁止訪問除數鎖存
// 	U0IIR = 0x04; //中斷標識暫存器為接收資料可用
	U0IER = 0x01; //使能RDA中斷
	VICIntSelect = VICIntSelect & (~0x00000040); //將串口0設定為IRQ模式
	VICIntEnable = VICIntEnable | 0x00000040; //使能串口0中斷
  VICVectAddr0 = (int)IRQ_uart0; //設定串口0的中斷服務程式地址  
  VICVectCntl0 = 0x26; //將6號中斷串口0優先級設定為0
}
void uart_st1(u32 baud_rate){ //串口1初始化
	PINSEL0 = PINSEL0 | 0x00050000; //打開串口功能
  U1LCR = 0x83; //8位資料,無校驗位,一個停止位,禁止間隔發送,使能訪問除數鎖存
	if(15000000/(16 * baud_rate) <= 255){
		U1DLM = 0; //設定除數鎖存高八位
		U1DLL = 15000000/(16 * baud_rate);//設定除數鎖存低八位,時鐘15MHz設定波特率為38400,計算公式15000000/(16*波特率)
	}else{
		U1DLM = (floor)(15000000/(16 * baud_rate) - 255); //設定除數鎖存高八位
		U1DLL = 255;//設定除數鎖存低八位,時鐘15MHz設定波特率為38400,計算公式15000000/(16*波特率)
	}
  U1LCR = 0x03; //禁止訪問除數鎖存
}
u32 putchar0(u32 ch){ //向串口0發送一個字符
  if(ch == '\n'){
    while (!(U0LSR & 0x20)); //幀錯誤狀態激活(停止位錯誤)
    U0THR = 0x0D; //回車
		U0THR = 0x0A; //換行
  }
  while (!(U0LSR & 0x20)); //幀錯誤狀態激活(停止位錯誤)
  return (U0THR = ch);
}
void serialPuts0(u8 *p){ //向串口0發送字串
  while (*p != '\0'){
  	putchar0(*p++);
  }
}
u32 putchar1(u32 ch){ //向串口1發送一個字符
  if(ch == '\n'){
    while (!(U1LSR & 0x20)); //幀錯誤狀態激活(停止位錯誤)
    U1THR = 0x0D; //回車
		U1THR = 0x0A; //換行
  }
  while (!(U1LSR & 0x20)); //幀錯誤狀態激活(停止位錯誤)
  return (U1THR = ch);
}
void serialPuts1(u8 *p){ //向串口1發送字串
  while (*p != '\0'){
  	putchar1(*p++);
  }
}
// __irq void IRQ_uart0 (void){
// 	
// }
  1. 將sys.h修改一下,
#ifndef __SYS_H
#define __SYS_H	 
#include "LPC21xx.H"
#include "math.h"
#include "string.h"
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
void delay_ms(u32 num); //ms級粗延遲,最小單位為1ms,無法小數延遲
void delay_s(u32 num); //s級粗延遲,建議最小單位為s,可以小數延遲,最小小數點后三位
#endif
  1. 添加主機main.c的代碼,
/*********************************/
//本程式僅供學習科研使用
//單片機型號:LPC2124
//作者:哈哈我是HH
//修改日期:2021.3.29
//版本:V1.0
//Copyright(C) 哈哈我是HH 2021-2031
//All rights reserved
/*********************************/
#include "sys.h"
#include "gpio.h"
#include "timer.h"
#include "eint.h"
#include "uart.h"
u8 ledDown[]={"The LED is down!\n"};
u8 ledUp[]={"The LED is up!\n"};
char ledon[] = "dt1"; //盡量輸入數字,字母在proteus中不穩定
char ledoff[] = "dt0"; //盡量輸入數字,字母在proteus中不穩定
char buff[] = "";
u32 timesflag = 0;
__irq void IRQ_uart0 (void){
	if(U0RBR != '!'){
		buff[timesflag] = U0RBR;
		timesflag++;
	}else{
		if(strcmp(ledon,buff) == 0){
			gpio0_seL(25);
		}else{
			gpio0_seH(25);
		}
		timesflag = 0;
	}
	VICVectAddr=0;
}
int main (void){
	uart_st0(38400);
	uart_st1(38400);
  while(1){
		gpio0_seL(18);
		serialPuts1(ledUp);
		delay_ms(200);
  	gpio0_seH(18);
		serialPuts1(ledDown);
		delay_ms(200);
  }
}
  1. 添加從機main.c的代碼,
/*********************************/
//本程式僅供學習科研使用
//單片機型號:LPC2124
//作者:哈哈我是HH
//修改日期:2021.3.29
//版本:V1.0
//Copyright(C) 哈哈我是HH 2021-2031
//All rights reserved
/*********************************/
#include "sys.h"
#include "gpio.h"
#include "timer.h"
#include "eint.h"
#include "uart.h"
u8 ledUp[]={"dt1!"}; //盡量輸入數字,字母在proteus中不穩定,結尾以!區分
u8 ledDown[]={"dt0!"}; //盡量輸入數字,字母在proteus中不穩定,結尾以!區分
u32 key_flag = 0;
__irq void IRQ_Eint2(void){
	if(key_flag == 0){
		serialPuts0(ledUp);
	}else{
		serialPuts0(ledDown);
	}
	key_flag = !key_flag;
	while((EXTINT&0x04)!=0){		//中斷標志清零
		EXTINT=0x04;
	}
  VICVectAddr=0;					//通知中斷處理結束
}
int main (void){
	uart_st0(38400);
	eint_st2(15);
  while(1){
// 		serialPuts0(ledDown);
// 		delay_ms(200);
// 		serialPuts0(ledUp);
// 		delay_ms(200);
  }
}

電路仿真

在這里插入圖片描述
實驗現象:
D1閃爍的同時會伴隨virtual terminal上面的字符提醒,同時每按一下從機的按鍵,主機的D1會改變一下狀態,
在這里插入圖片描述

感謝各位讀者的閱讀,如有錯誤望指出,歡迎討論!

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/273773.html

標籤:其他

上一篇:【C語言基礎學習筆記】一、初始C語言(3)

下一篇:【硬核】23種設計模式娓娓道來,助你優雅的撰寫出漂亮代碼!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more