其實(shí)現(xiàn)在也沒(méi)心情介紹了,直接說(shuō)一下有什么實(shí)用的功能
第一點(diǎn)哈,支持位帶操作
//IO口操作宏定義#defineBITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))#defineMEM_ADDR(addr)? *((volatile unsigned long? *)(addr))#defineBIT_ADDR(addr, bitnum)? MEM_ADDR(BITBAND(addr, bitnum))//IO口地址映射#defineGPIO0_PIN_Addr? ? (LPC_GPIO0_BASE+20)#defineGPIO1_PIN_Addr? ? (LPC_GPIO1_BASE+20)#defineGPIO2_PIN_Addr? ? (LPC_GPIO2_BASE+20)#defineGPIO3_PIN_Addr? ? (LPC_GPIO3_BASE+20)#defineGPIO4_PIN_Addr? ? (LPC_GPIO4_BASE+20)#defineGPIO5_PIN_Addr? ? (LPC_GPIO5_BASE+20)#defineP0out(n)? BIT_ADDR(GPIO0_PIN_Addr,n)//輸出#defineP0in(n)? ? BIT_ADDR(GPIO0_PIN_Addr,n)//輸入#defineP1out(n)? BIT_ADDR(GPIO1_PIN_Addr,n)//輸出#defineP1in(n)? ? BIT_ADDR(GPIO1_PIN_Addr,n)//輸入#defineP2out(n)? BIT_ADDR(GPIO2_PIN_Addr,n)//輸出#defineP2in(n)? ? BIT_ADDR(GPIO2_PIN_Addr,n)//輸入#defineP3out(n)? BIT_ADDR(GPIO3_PIN_Addr,n)//輸出#defineP3in(n)? ? BIT_ADDR(GPIO3_PIN_Addr,n)//輸入#defineP4out(n)? BIT_ADDR(GPIO4_PIN_Addr,n)//輸出#defineP4in(n)? ? BIT_ADDR(GPIO4_PIN_Addr,n)//輸入#defineP5out(n)? BIT_ADDR(GPIO5_PIN_Addr,n)//輸出#defineP5in(n)? ? BIT_ADDR(GPIO5_PIN_Addr,n)//輸入
好處就不言而喻了,,簡(jiǎn)直太方便了和實(shí)用了
第二點(diǎn)
voidGPIO_Conf_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint32_t mode);//配置指定引腳的模式voidGPIO_Conf_Bits(uint8_t GPIOx, uint32_t StartPinx,uint32_t PinNum,uint32_t mode);//配置多個(gè)連續(xù)引腳的模式voidGPIO_Init_Bit(GPIO_InitTypeDef * GPIO_InitStruct);//初始化一個(gè)引腳的模式--內(nèi)部調(diào)用,用戶不使用voidGPIO_Init_Bits(GPIO_InitTypeDef *GPIO_InitStruc,uint32_t PinNum);//初始化多個(gè)連續(xù)引腳的配置--內(nèi)部調(diào)用,用戶不使用voidGPIO_Dir_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t Dir);//設(shè)置指定引腳的輸入輸出方向voidGPIO_Dir_Bits(uint8_t GPIOx, uint32_t StartPinx,uint32_t PinNum,uint8_t Dir);//設(shè)置多個(gè)連續(xù)引腳的輸入輸出方向voidGPIO_Write_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t BitVal);//設(shè)置指定引腳輸出高低電平voidGPIO_Write_Bits(uint8_t GPIOx,uint32_t BitVal);//將數(shù)據(jù)寫(xiě)入指定的GPIO數(shù)據(jù)端口uint8_t GPIO_Read_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx);//讀取指定引腳的電平狀態(tài)uint32_t GPIO_Read_Bits(uint8_t GPIOx);//讀取指定的GPIO端口的電平狀態(tài)voidGPIO_Mask_Bit(uint8_t GPIOx,uint32_t GPIO_Pinx,uint8_t Mask);//屏蔽或清除屏蔽引腳voidGPIO_Mask_Bits(uint8_t GPIOx, uint32_t StartPinx,uint32_t PinNum,uint8_t Mask);//屏蔽或清除屏蔽多個(gè)連續(xù)引腳
其實(shí)有了位帶操作自己感覺(jué)應(yīng)該去掉上面的設(shè)置一個(gè)引腳的電平,,,不過(guò)呢!位帶操作我是訪問(wèn)的PIN寄存器,而函數(shù)里面用的是SET和CLR
先說(shuō)第一個(gè)函數(shù)的實(shí)現(xiàn)過(guò)程
先看內(nèi)部
/**
* @brief? 配置指定引腳的模式
* @param? GPIOx:設(shè)置的端口0-5
* @param? GPIO_Pinx:設(shè)置的引腳0-32
* @param? mode:引腳的模式
GPIO_Mode_IFT? ? ? ? //無(wú)上下拉
GPIO_Mode_IPD? ? ? ? //內(nèi)部下拉
GPIO_Mode_IPU? ? ? ? //內(nèi)部上拉
GPIO_Mode_TRA? ? ? ? //轉(zhuǎn)發(fā)模式
GPIO_Mode_HYS? ? ? ? //遲滯模式
GPIO_Mode_INV? ? ? ? //輸入反向
GPIO_Mode_SWI? ? ? ? //轉(zhuǎn)換速率
GPIO_Mode_OOD? ? ? ? //開(kāi)漏輸出
* @retval None
* @example GPIO_Conf_Bit(GPIO0,1,GPIO_Mode_IPD);//P0_1下拉*/voidGPIO_Conf_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint32_t mode)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIOx=GPIOx;
GPIO_InitStruct.mode=mode;
GPIO_InitStruct.Pinx=GPIO_Pinx;
GPIO_Init_Bit(&GPIO_InitStruct);
}
我定義了一個(gè)結(jié)構(gòu)體
/*端口初始化結(jié)構(gòu)體*/typedefstruct{
uint8_t? ? ? GPIOx;//引腳端口號(hào)uint32_t? ? mode;//工作模式uint32_t? ? Pinx;//引腳號(hào)0~31}GPIO_InitTypeDef;
/**
* @brief? 初始化一個(gè)引腳的配置--用戶不使用
* @param? *GPIO_InitStruc:端口初始化結(jié)構(gòu)體指針
* @param
* @param
* @retval None
* @example GPIO_Init_Bit(&GPIO_InitStruc);*/voidGPIO_Init_Bit(GPIO_InitTypeDef *GPIO_InitStruc)
{switch(GPIO_InitStruc->GPIOx)
{case0:GPIO_Type->GPIO0_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case1:GPIO_Type->GPIO1_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case2:GPIO_Type->GPIO2_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case3:GPIO_Type->GPIO3_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case4:GPIO_Type->GPIO4_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case5:GPIO_Type->GPIO5_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;default:break;
}
}
然后呢
/*引腳初始化結(jié)構(gòu)體*/typedefstruct{
__IO uint32_t GPIO0_Table[32];
__IO uint32_t GPIO1_Table[32];
__IO uint32_t GPIO2_Table[32];
__IO uint32_t GPIO3_Table[32];
__IO uint32_t GPIO4_Table[32];
__IO uint32_t GPIO5_Table[4];
}GPIO_Type_Config;
LPC_ICON_BASE這個(gè)地址到LPC_ICON_BASE+32+32+32+32+32+4這個(gè)地址分別對(duì)應(yīng)P0,P1,P2,P3,P4,P5的各個(gè)引腳的配置寄存器
那么
GPIO_Type->GPIO0_Table[0] 就是配置P0_0引腳
GPIO_Type->GPIO1_Table[1] 就是配置P1_1引腳
GPIO_Type->GPIO2_Table[2] 就是配置P2_2引腳
其實(shí)寫(xiě)成數(shù)組也是為了便于區(qū)分是哪個(gè)端口
因?yàn)槲覀魅氲氖?/p>
端口號(hào) ?還有 ?引腳號(hào)后面的 ?模式(mode) ?一開(kāi)始用的枚舉,后來(lái)一想為了能一下子寫(xiě)入多種配置,所以就宏定義的,這樣的話模式或運(yùn)算寫(xiě)入就好啦
/*宏定義引腳的所有配置*/#defineGPIO_Mode_IFT? (0x0000)? ? ? /* 無(wú)上下拉 */#defineGPIO_Mode_IPD? (0x0008)? ? ? /* 內(nèi)部下拉 */#defineGPIO_Mode_IPU? (0x0010)? ? ? /* 內(nèi)部上拉 */#defineGPIO_Mode_TRA? (0x0018)? ? ? /* 轉(zhuǎn)發(fā)模式*/#defineGPIO_Mode_HYS? (0x0020)? ? ? /* 遲滯模式*/#defineGPIO_Mode_INV? (0x0040)? ? ? /* 輸入反向*/#defineGPIO_Mode_SWI? (0x0200)? ? ? /* 轉(zhuǎn)換速率*/#defineGPIO_Mode_OOD? (0x0400)? ? ? /* 開(kāi)漏輸出 */
看最后一個(gè)函數(shù)
/**
* @brief? 設(shè)置指定引腳輸出高低電平
* @param? GPIOx:設(shè)置的端口0-5
* @param? GPIO_Pinx:設(shè)置的引腳0-32
* @param? BitVal:0-輸入低電平,1-輸出高電平
* @retval None
* @example GPIO_Write_Bit(GPIO0,1,1);//P0_1輸出高電平*/voidGPIO_Write_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t BitVal)
{if(BitVal)
{
PORT_Table[GPIOx]->SET |= (1<
}else{
PORT_Table[GPIOx]->CLR |= (1<
}
}
#defineGPIO_BASES {LPC_GPIO0,LPC_GPIO1,LPC_GPIO2,LPC_GPIO3,LPC_GPIO4,LPC_GPIO5}//存儲(chǔ)地址staticLPC_GPIO_TypeDef *constPORT_Table[] = GPIO_BASES;
這個(gè)呢我是利用的他自帶的結(jié)構(gòu)體實(shí)現(xiàn)的
LPC_GPIO_TypeDef
/*------------- General Purpose Input/Output (GPIO) --------------------------*//** @brief General Purpose Input/Output (GPIO) register structure definition*/typedefstruct{
__IO uint32_t DIR;
uint32_t RESERVED0[3];
__IO uint32_t MASK;
__IO uint32_t PIN;
__IO uint32_t SET;
__O? uint32_t CLR;
} LPC_GPIO_TypeDef;
原先的程序
#defineLPC_GPIO0? ? ? ? ? ? ((LPC_GPIO_TypeDef? ? ? *) LPC_GPIO0_BASE? ? )#defineLPC_GPIO1? ? ? ? ? ? ((LPC_GPIO_TypeDef? ? ? *) LPC_GPIO1_BASE? ? )#defineLPC_GPIO2? ? ? ? ? ? ((LPC_GPIO_TypeDef? ? ? *) LPC_GPIO2_BASE? ? )#defineLPC_GPIO3? ? ? ? ? ? ((LPC_GPIO_TypeDef? ? ? *) LPC_GPIO3_BASE? ? )#defineLPC_GPIO4? ? ? ? ? ? ((LPC_GPIO_TypeDef? ? ? *) LPC_GPIO4_BASE? ? )#defineLPC_GPIO5? ? ? ? ? ? ((LPC_GPIO_TypeDef? ? ? *) LPC_GPIO5_BASE? ? )
這樣的話
如果把P0_12置一只需要
LPC_GPIO0->SET |= 1<<12;
我為了讓前面這個(gè)LPC_GPIO0是個(gè)可變的,,,因?yàn)榉奖憧刂坡?/p>
所以才有了
#defineGPIO_BASES {LPC_GPIO0,LPC_GPIO1,LPC_GPIO2,LPC_GPIO3,LPC_GPIO4,LPC_GPIO5}//存儲(chǔ)地址staticLPC_GPIO_TypeDef *constPORT_Table[] = GPIO_BASES;
這樣的話PORT_Table[0]正好是LPC_GPIO0 ,
PORT_Table[1]正好是LPC_GPIO1
這個(gè)函數(shù)就誕生了....
voidGPIO_Write_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t BitVal)
{if(BitVal)
{
PORT_Table[GPIOx]->SET |= (1<
}else{
PORT_Table[GPIOx]->CLR |= (1<
}
}
還有一個(gè)地方,我為了可以直接設(shè)置某些引腳的高低電平狀態(tài)呢,,,,由于SET和CLR實(shí)現(xiàn)起來(lái)需要做判斷,耽誤時(shí)間,我看了下直接PIN就可以,所以就直接用的PIN
/**
* @brief? 將數(shù)據(jù)寫(xiě)入指定的GPIO數(shù)據(jù)端口
* @param? GPIOx:設(shè)置的端口0-5
* @param? BitVal:指定端口的值寫(xiě)入輸出數(shù)據(jù)寄存器
* @param
* @param
* @retval? None
* @example GPIO_Write_Bits(GPIO0,0xffffffff);//P0_0--P0_31輸出高電平*/voidGPIO_Write_Bits(uint8_t GPIOx,uint32_t BitVal)
{
PORT_Table[GPIOx]->PIN =BitVal;
}
讀取呢
/**
* @brief? 讀取指定引腳的電平狀態(tài)--如果不先設(shè)置引腳方向,讀出來(lái)一直是1
* @param? GPIOx:初始化的端口0-5
* @param? GPIO_Pinx:讀取的引腳0-32
* @param
* @retval 1-狀態(tài)高,0-狀態(tài)低
* @example Value = GPIO_Read_Bit(GPIO0,1,1);//讀取P0_1的電平狀態(tài)*/uint8_t GPIO_Read_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx)
{return((PORT_Table[GPIOx]->PIN >>GPIO_Pinx)&0x01);
}
/**
* @brief? 讀取整個(gè)端口的電平狀態(tài)--如果不先設(shè)置引腳方向,讀出來(lái)一直是1
* @param? GPIOx:初始化的端口0-5
* @param
* @param
* @retval bit=1--狀態(tài)高,bit=0--狀態(tài)低
* @example Value = GPIO_Read_Bits(GPIO0);//讀取GPIO0的電平狀態(tài)*/uint32_t GPIO_Read_Bits(uint8_t GPIOx)
{return(PORT_Table[GPIOx]->PIN);
}
其余的就沒(méi)有什么說(shuō)的了....可惜....我可能以后再也用不到了
工程呢為了方便,把Keil和IAR建到了一塊,文件的.c和.h共用,,也是為了方便實(shí)用
對(duì)于程序的風(fēng)格還是走的當(dāng)年學(xué)操作系統(tǒng)時(shí)的代碼風(fēng)格,沒(méi)說(shuō)的,程序大了提高方便性
結(jié)束....老感覺(jué)傷感,,,,,,,,竟然寫(xiě)了一篇就寫(xiě)到頭了
源碼
鏈接:密碼:78ic
評(píng)論