回顧自己之前寫的LED的亮燈程序,短短的幾行代碼就實現了。
#include <reg52.h>
void main(void){
P0 = 0x11;
while(1);
}
以上代碼就可以點亮與P0口相連的陰極LED了。
但是這個燈是怎麼亮的呢?
關鍵在於頭文件
void PORT_init(PTXn_e ptxn, uint32 cfg )
{
SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK << PTX(ptxn)); //開啓PORTx端口 1.使能PORT時鐘
//系統時鐘門控寄存器控制A,B,C,D,E的時鐘源
PORT_ISFR_REG(PORTX_BASE(ptxn)) = (1<<PTn(ptxn)); // 清空標誌位 2.清空中斷標誌位
PORT_PCR_REG(PORTX_BASE(ptxn), PTn(ptxn)) = cfg; // 複用功能 實現中斷觸發方式,帶無源濾波器,複用功能口,上拉或下拉電阻 3.配置port的各種屬性
}
程序分析:
SIM_SCGC5的宏定義爲:
typedef struct SIM_MemMap {
uint32_t SOPT1; /**< System Options Register 1, offset: 0x0 */
uint32_t SOPT1CFG; /**< SOPT1 Configuration Register, offset: 0x4 */
uint8_t RESERVED_0[4092];
uint32_t SOPT2; /**< System Options Register 2, offset: 0x1004 */
uint8_t RESERVED_1[4];
uint32_t SOPT4; /**< System Options Register 4, offset: 0x100C */
uint32_t SOPT5; /**< System Options Register 5, offset: 0x1010 */
uint8_t RESERVED_2[4];
uint32_t SOPT7; /**< System Options Register 7, offset: 0x1018 */
uint8_t RESERVED_3[8];
uint32_t SDID; /**< System Device Identification Register, offset: 0x1024 */
uint8_t RESERVED_4[12];
uint32_t SCGC4; /**< System Clock Gating Control Register 4, offset: 0x1034 */
uint32_t SCGC5; /**< System Clock Gating Control Register 5, offset: 0x1038 偏移量直接偏到SCGC5*/
uint32_t SCGC6; /**< System Clock Gating Control Register 6, offset: 0x103C */
uint32_t SCGC7; /**< System Clock Gating Control Register 7, offset: 0x1040 */
uint32_t CLKDIV1; /**< System Clock Divider Register 1, offset: 0x1044 */
uint8_t RESERVED_5[4];
uint32_t FCFG1; /**< Flash Configuration Register 1, offset: 0x104C */
uint32_t FCFG2; /**< Flash Configuration Register 2, offset: 0x1050 */
uint8_t RESERVED_6[4];
uint32_t UIDMH; /**< Unique Identification Register Mid-High, offset: 0x1058 */
uint32_t UIDML; /**< Unique Identification Register Mid Low, offset: 0x105C */
uint32_t UIDL; /**< Unique Identification Register Low, offset: 0x1060 */
uint8_t RESERVED_7[156];
uint32_t COPC; /**< COP Control Register, offset: 0x1100 */
uint32_t SRVCOP; /**< Service COP Register, offset: 0x1104 */
} volatile *SIM_MemMapPtr;
//這個結構體內保存的是SIM存儲映射的各個寄存器的名稱和地址,地址是通過結構體指針的偏移來決定,後面的註釋表明裏地址偏移量
#define SIM_BASE_PTR ((SIM_MemMapPtr)0x40047000u) //SIM模塊的絕對地址 0x4004 7000u
//其中(SIM_MemMapPtr)爲一個結構體指針,這個結構體的絕對地址爲0x4004 7000u
//因爲地址總線爲32根,所以用8位的16進制數來代表32位2進制,數據類型爲unsigned int
#define SIM_SCGC5_REG(base) ((base)->SCGC5) //這裏的BASE指的是SIM模塊的絕對地址,在結//構體中SCGC5代表偏移量0x1038,直接偏移到SCG5寄存器上
uint32_t SCGC5; /**< System Clock Gating Control Register 5, offset: 0x1038 偏移量直接偏到SCGC5*/
#define SIM_SCGC5 SIM_SCGC5_REG(SIM_BASE_PTR) //括號裏爲SIM的絕對地址,這裏指的是SCG5寄存器的內存位置0x4004 8038
後面的還是不大懂
二:PORT的中斷復位函數:
1.進行port端口複用
2.寫入中斷號
3.根據中斷標誌位判斷對應引腳是否進入中斷
4.寫1清除對應引腳的中斷標誌位
5.執行處理函數
具體實現:
port_init(PTC9, ALT1 | IRQ_FALLING | PULLUP ); //初始化 PTC9 管腳,複用功能爲GPIO ,下降沿觸發中斷,上拉電阻
set_vector_handler(PORTC_PORTD_VECTORn ,PORTC_PORTD_IRQHandler); //設置PORTC和PORTD的中斷服務函數爲 PORTC_PORTD_IRQHandler
enable_irq (PORTC_PORTD_IRQn); //使能
void PORTC_PORTD_IRQHandler(void)
{
#if 0 // 條件編譯,兩種方法可供選擇
uint8 n = 0; //引腳號
n = 9;
if(PORTC_ISFR & (1 << n)) //PTC9 觸發中斷
{
PORTC_ISFR = (1 << n); //寫1清中斷標誌位
/* 以下爲用戶任務 */
/* 以上爲用戶任務 */
}
#else
PORT_FUNC(C,9,key_handler);
#endif
}