端口結(jié)構(gòu)介紹 無論使用MCU實(shí)現(xiàn)什么功能,只要是有意義的功能必然會(huì)涉及到IO口的操作。IO口的操作也是MCU的入門操作,按國(guó)際慣例一般上手MCU的第一個(gè)程序點(diǎn)燈程序就是通過IO口的輸出來實(shí)現(xiàn)的。 華大M0+系列單片機(jī)的端口電路有兩種結(jié)構(gòu),這兩種電路結(jié)構(gòu)大體相同,只是存在三個(gè)微小的差別。HC32F(L)x3x、HC32F(L)x7x和HC32F(L)x9x系列芯片的端口電路是一種結(jié)構(gòu),為了便于說明我們稱這種結(jié)構(gòu)為結(jié)構(gòu)一,框圖如下: HC32F003、HC32F005和HC32L110芯片是一種結(jié)構(gòu),我們稱這種結(jié)構(gòu)為結(jié)構(gòu)二,框圖如下: 由上面兩個(gè)構(gòu)圖我們可以很清楚地知道兩種結(jié)構(gòu)的區(qū)別如下: 1.結(jié)構(gòu)一的PxOUT(寄存器中出現(xiàn)的x=A,B,C,D,E,F(xiàn)代表芯片含有的端口組,后面的亦是同樣的意思)可以通過操作位寄存器(PxBSET、PxBCLR、PxBSETCLR)來直接控制某一位的輸出,而不會(huì)影響這組寄存器中的其余的位,結(jié)構(gòu)二沒有相關(guān)的位操作。 2.結(jié)構(gòu)一輸出/輸入數(shù)據(jù)寄存器(PxOUT/PxIN)支持AHB/FAST IO總線訪問(通過寄存器 GPIO_CTRL2.ahb_sel 位控制),其他寄存器支持AHB總線訪問。結(jié)構(gòu)二端口輸入值/輸出值寄存器(PxIN/PxOUT)只支持 AHB 總線讀寫。對(duì)于這兩種不同的總線,系統(tǒng)時(shí)鐘(HCLK)對(duì)這兩種總線的處理周期并不相同。下面兩幅圖為對(duì)于兩種總線端口翻轉(zhuǎn)的最快時(shí)序: 對(duì)于 AHB 總線,每?jī)蓚€(gè) HCLK 周期,IO 翻轉(zhuǎn)一次,而對(duì)于 FAST IO 總線,每個(gè) HCLK周期,IO 翻轉(zhuǎn)一次。 3.結(jié)構(gòu)二對(duì)應(yīng)芯片的RST引腳可以復(fù)用成帶有內(nèi)部上拉電阻的數(shù)字輸入引腳,結(jié)構(gòu)一對(duì)應(yīng)的芯片RST引腳不可以復(fù)用為IO引腳。 重點(diǎn)來了,說完兩種結(jié)構(gòu)的差別后進(jìn)入正題,說下兩種結(jié)構(gòu)和共性。 每個(gè)端口都可以配置成數(shù)字或模擬端口,并且可以實(shí)現(xiàn)內(nèi)部上拉(pull up)/下拉(pull down)的輸入,高阻輸入(floating input),推挽輸出(CMOS output),開漏輸出(open drain output),兩檔驅(qū)動(dòng)能力輸出。 數(shù)字端口被配置成模擬端口后,數(shù)字功能被隔離,不能輸出數(shù)字“1”和“0”,CPU 讀取端口輸入值寄存器的結(jié)果為“0”。 每個(gè)數(shù)字端口被配置為輸入時(shí),都可以提供外部中斷,中斷類型可以配置成高電平觸發(fā)、低電平觸發(fā)、上升沿觸發(fā)、下降沿觸發(fā) 4 種,查詢 Px_STAT[n]的中斷標(biāo)志位即可知道相應(yīng)的中斷觸發(fā)端口。另外,每個(gè)數(shù)字端口的中斷都可以把芯片從睡眠模式/深度睡眠模式喚醒到工作模式。 芯片復(fù)位后端口為高阻輸入(floating input),目的是防止芯片被異常復(fù)位時(shí),對(duì)外部器件產(chǎn)生異常動(dòng)作。 當(dāng)端口配置為數(shù)字端口的時(shí)候可以通過設(shè)置Px_SEL寄存器接受各功能模塊(如 SPI,UART,I2C,Timer 等)的輸入輸出信號(hào),此內(nèi)容放到相應(yīng)外設(shè)模塊內(nèi)容來講解。 端口相關(guān)配置介紹 端口相關(guān)配置如下: 數(shù)字端口(PxADS對(duì)應(yīng)位為0); 模擬端口(PxADS對(duì)應(yīng)位為1); 端口引腳為輸入(PxDIR對(duì)應(yīng)位為1); 端口引腳為輸出(PxDIR對(duì)應(yīng)位為0); 輸入電平狀態(tài)(PxIN 對(duì)應(yīng)引腳獲得高電平對(duì)應(yīng)位為1,獲得低電平對(duì)應(yīng)位為0); 輸出電平選擇(PxOUT 對(duì)應(yīng)位為1相應(yīng)引腳輸出高電平,為0相應(yīng)引腳輸出低電平); 內(nèi)部上拉(PxPU對(duì)應(yīng)位為1); 內(nèi)部下拉(PxPD對(duì)應(yīng)位為1); 高阻(PxPU對(duì)應(yīng)位為0且PxPD對(duì)應(yīng)位為0); 推挽輸出(PxOD對(duì)應(yīng)位為0); 開漏輸出(PxOD對(duì)應(yīng)位為1); 低驅(qū)動(dòng)能力輸出(PxDR對(duì)應(yīng)位為1); 高驅(qū)動(dòng)能力輸出(PxDR對(duì)應(yīng)位為0); 端口高電平中斷使能(PxHIE對(duì)應(yīng)位為1); 端口低電平中斷使能(PxLIE對(duì)應(yīng)位為1); 端口上升沿中斷使能(PxRIE對(duì)應(yīng)位為1); 端口下降沿中斷使能(PxFIE對(duì)應(yīng)位為1); 對(duì)于結(jié)構(gòu)一的芯片特有寄存器 端口置位(PxBSET對(duì)應(yīng)位為1置位,為0保持); 端口清零(PxBCLR對(duì)應(yīng)位為1清零,為0保持); 端口置位清零(PxBSETCLR (PxBSET對(duì)應(yīng)位為1置位,為0保持;PxBCLR對(duì)應(yīng)位為1清零,為0保持))。PxBSET 和 PxBCLR 相同位同時(shí)置 1 時(shí),PxBCLR 具有高優(yōu)先級(jí)。即該端口被清零。 端口配置操作流程 端口復(fù)用配置為模擬端口操作流程 a)設(shè)置寄存器 PxADS[n]為 1 端口復(fù)用配置為數(shù)字通用端口操作流程 a) 設(shè)置寄存器 PxADS[n]為 0 b) 設(shè)置寄存器 Px_SEL 為 0 c) 設(shè)置寄存器 PxDIR[n]為 1:端口方向?yàn)檩斎?,CPU 可以讀取端口的狀態(tài) PxIN[n]。 d) 設(shè)置寄存器 PxDIR[n]為 0:端口方向?yàn)檩敵?br> e) 設(shè)置寄存器 PxOUT[n]為 1:端口輸出高電平 f) 設(shè)置寄存器 PxOUT[n]為 0:端口輸出低電平 端口上拉使能配置操作流程 a)設(shè)置寄存器 PxPU[n]為 1 端口下拉使能配置操作流程 a) 設(shè)置寄存器 PxPU[n]為 0 b) 設(shè)置寄存器 PxPD[n]為 1 注:當(dāng) PxPU[n],PxPD[n]同時(shí)置 1 時(shí),PxPU[n]優(yōu)先級(jí)高,PxPD[n]無效。 端口增強(qiáng)驅(qū)動(dòng)配置操作流程 a)設(shè)置寄存器 PxDR[n]為 0 端口開漏輸出配置操作流程 a)設(shè)置寄存器 PxOD[n]為 1 配置代碼 無上下拉輸入配置 stc_gpio_cfg_t stcGpioCfg; Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //打開GPIO外設(shè)時(shí)鐘 stcGpioCfg.enDir = GpioDirIn; //端口方向配置-》輸入 stcGpioCfg.enDrv = GpioDrvL; //驅(qū)動(dòng)能力配置-》高驅(qū)動(dòng)能力 stcGpioCfg.enPu = GpioPuDisable; //端口上下拉配置-》無 stcGpioCfg.enPd = GpioPdDisable; stcGpioCfg.enOD = GpioOdDisable; //開漏輸出配置-》開漏輸出關(guān)閉 stcGpioCfg.enCtrlMode = GpioAHB; //總線控制模式配置-》AHB Gpio_Init(STK_USER_PORT, STK_USER_PIN, &stcGpioCfg); // GPIO IO USER KEY初始化 推挽輸出配置 stc_gpio_cfg_t stcGpioCfg; Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //打開GPIO外設(shè)時(shí)鐘 stcGpioCfg.enDir = GpioDirOut; //端口方向配置-》輸出 stcGpioCfg.enDrv = GpioDrvL; //驅(qū)動(dòng)能力配置-》高驅(qū)動(dòng)能力 stcGpioCfg.enPu = GpioPuDisable; //端口上下拉配置-》無 stcGpioCfg.enPd = GpioPdDisable; stcGpioCfg.enOD = GpioOdDisable; //開漏輸出配置-》開漏輸出關(guān)閉 stcGpioCfg.enCtrlMode = GpioAHB; //總線控制模式配置-》AHB Gpio_Init(STK_LED_PORT, STK_LED_PIN, &stcGpioCfg); // GPIO IO LED端口初始化 Gpio_ClrIO(STK_LED_PORT, STK_LED_PIN); // LED關(guān)閉 常用的端口操作庫函數(shù) 單端口操作 單個(gè)IO口輸出低電平 原型 en_result_t Gpio_ClrIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 Gpio_ClrIO(GpioPortA ,GpioPin1 ); //PA01端口輸出低電平 單個(gè)IO口輸出高電平 原型 en_result_t Gpio_SetIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 Gpio_SetIO(GpioPortA ,GpioPin1 ); //PA01端口輸出高電平 獲得IO口輸入值 原型 boolean_t Gpio_GetInputIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 u8PA1Stat = Gpio_GetInputIO(GpioPortA ,GpioPin1); //u8PA1Stat 為PA1端口輸入電平狀態(tài) 獲得IO口輸出值 原型 boolean_t Gpio_ReadOutputIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 u8PA1Stat = Gpio_ReadOutputIO(GpioPortA ,GpioPin1); //u8PA1Stat 為PA1端口輸出電平狀態(tài) 多端口操作 同時(shí)讓一組端口中的多個(gè)引腳輸出低電平 原型 en_result_t Gpio_ClrPort(en_gpio_port_t enPort, uint16_t u16ValMsk) 舉例 Gpio_ClrPort(GpioPortA , 0x000F); //PA0~PA3輸出低電平,其余保持 同時(shí)讓一組端口中的多個(gè)引腳輸出高電平 原型 en_result_t Gpio_SetPort(en_gpio_port_t enPort, uint16_t u16ValMsk) 舉例 Gpio_SetPort(GpioPortA , 0x000F); //PA0~PA3輸出高電平,其余保持 獲取一組IO口的輸入數(shù)據(jù) 原型 uint16_t Gpio_GetInputData(en_gpio_port_t enPort) 舉例 u16PAInputData = Gpio_GetInputData(GpioPortA ); //u16PAInputData的值為PA組輸入數(shù)據(jù) 同時(shí)讓一組端口輸出多個(gè)高低電平 原型 en_result_t Gpio_SetClrPort(en_gpio_port_t enPort, uint32_t u32ValMsk) 舉例 Gpio_SetClrPort(GpioPortA , 0x00f0000f); //PA4 ~ PA7輸出高電平PA0 ~ PA3輸出低電平
端口結(jié)構(gòu)介紹 無論使用MCU實(shí)現(xiàn)什么功能,只要是有意義的功能必然會(huì)涉及到IO口的操作。IO口的操作也是MCU的入門操作,按國(guó)際慣例一般上手MCU的第一個(gè)程序點(diǎn)燈程序就是通過IO口的輸出來實(shí)現(xiàn)的。 華大M0+系列單片機(jī)的端口電路有兩種結(jié)構(gòu),這兩種電路結(jié)構(gòu)大體相同,只是存在三個(gè)微小的差別。HC32F(L)x3x、HC32F(L)x7x和HC32F(L)x9x系列芯片的端口電路是一種結(jié)構(gòu),為了便于說明我們稱這種結(jié)構(gòu)為結(jié)構(gòu)一,框圖如下: HC32F003、HC32F005和HC32L110芯片是一種結(jié)構(gòu),我們稱這種結(jié)構(gòu)為結(jié)構(gòu)二,框圖如下: 由上面兩個(gè)構(gòu)圖我們可以很清楚地知道兩種結(jié)構(gòu)的區(qū)別如下: 1.結(jié)構(gòu)一的PxOUT(寄存器中出現(xiàn)的x=A,B,C,D,E,F(xiàn)代表芯片含有的端口組,后面的亦是同樣的意思)可以通過操作位寄存器(PxBSET、PxBCLR、PxBSETCLR)來直接控制某一位的輸出,而不會(huì)影響這組寄存器中的其余的位,結(jié)構(gòu)二沒有相關(guān)的位操作。 2.結(jié)構(gòu)一輸出/輸入數(shù)據(jù)寄存器(PxOUT/PxIN)支持AHB/FAST IO總線訪問(通過寄存器 GPIO_CTRL2.ahb_sel 位控制),其他寄存器支持AHB總線訪問。結(jié)構(gòu)二端口輸入值/輸出值寄存器(PxIN/PxOUT)只支持 AHB 總線讀寫。對(duì)于這兩種不同的總線,系統(tǒng)時(shí)鐘(HCLK)對(duì)這兩種總線的處理周期并不相同。下面兩幅圖為對(duì)于兩種總線端口翻轉(zhuǎn)的最快時(shí)序: 對(duì)于 AHB 總線,每?jī)蓚€(gè) HCLK 周期,IO 翻轉(zhuǎn)一次,而對(duì)于 FAST IO 總線,每個(gè) HCLK周期,IO 翻轉(zhuǎn)一次。 3.結(jié)構(gòu)二對(duì)應(yīng)芯片的RST引腳可以復(fù)用成帶有內(nèi)部上拉電阻的數(shù)字輸入引腳,結(jié)構(gòu)一對(duì)應(yīng)的芯片RST引腳不可以復(fù)用為IO引腳。 重點(diǎn)來了,說完兩種結(jié)構(gòu)的差別后進(jìn)入正題,說下兩種結(jié)構(gòu)和共性。 每個(gè)端口都可以配置成數(shù)字或模擬端口,并且可以實(shí)現(xiàn)內(nèi)部上拉(pull up)/下拉(pull down)的輸入,高阻輸入(floating input),推挽輸出(CMOS output),開漏輸出(open drain output),兩檔驅(qū)動(dòng)能力輸出。 數(shù)字端口被配置成模擬端口后,數(shù)字功能被隔離,不能輸出數(shù)字“1”和“0”,CPU 讀取端口輸入值寄存器的結(jié)果為“0”。 每個(gè)數(shù)字端口被配置為輸入時(shí),都可以提供外部中斷,中斷類型可以配置成高電平觸發(fā)、低電平觸發(fā)、上升沿觸發(fā)、下降沿觸發(fā) 4 種,查詢 Px_STAT[n]的中斷標(biāo)志位即可知道相應(yīng)的中斷觸發(fā)端口。另外,每個(gè)數(shù)字端口的中斷都可以把芯片從睡眠模式/深度睡眠模式喚醒到工作模式。 芯片復(fù)位后端口為高阻輸入(floating input),目的是防止芯片被異常復(fù)位時(shí),對(duì)外部器件產(chǎn)生異常動(dòng)作。 當(dāng)端口配置為數(shù)字端口的時(shí)候可以通過設(shè)置Px_SEL寄存器接受各功能模塊(如 SPI,UART,I2C,Timer 等)的輸入輸出信號(hào),此內(nèi)容放到相應(yīng)外設(shè)模塊內(nèi)容來講解。 端口相關(guān)配置介紹 端口相關(guān)配置如下: 數(shù)字端口(PxADS對(duì)應(yīng)位為0); 模擬端口(PxADS對(duì)應(yīng)位為1); 端口引腳為輸入(PxDIR對(duì)應(yīng)位為1); 端口引腳為輸出(PxDIR對(duì)應(yīng)位為0); 輸入電平狀態(tài)(PxIN 對(duì)應(yīng)引腳獲得高電平對(duì)應(yīng)位為1,獲得低電平對(duì)應(yīng)位為0); 輸出電平選擇(PxOUT 對(duì)應(yīng)位為1相應(yīng)引腳輸出高電平,為0相應(yīng)引腳輸出低電平); 內(nèi)部上拉(PxPU對(duì)應(yīng)位為1); 內(nèi)部下拉(PxPD對(duì)應(yīng)位為1); 高阻(PxPU對(duì)應(yīng)位為0且PxPD對(duì)應(yīng)位為0); 推挽輸出(PxOD對(duì)應(yīng)位為0); 開漏輸出(PxOD對(duì)應(yīng)位為1); 低驅(qū)動(dòng)能力輸出(PxDR對(duì)應(yīng)位為1); 高驅(qū)動(dòng)能力輸出(PxDR對(duì)應(yīng)位為0); 端口高電平中斷使能(PxHIE對(duì)應(yīng)位為1); 端口低電平中斷使能(PxLIE對(duì)應(yīng)位為1); 端口上升沿中斷使能(PxRIE對(duì)應(yīng)位為1); 端口下降沿中斷使能(PxFIE對(duì)應(yīng)位為1); 對(duì)于結(jié)構(gòu)一的芯片特有寄存器 端口置位(PxBSET對(duì)應(yīng)位為1置位,為0保持); 端口清零(PxBCLR對(duì)應(yīng)位為1清零,為0保持); 端口置位清零(PxBSETCLR (PxBSET對(duì)應(yīng)位為1置位,為0保持;PxBCLR對(duì)應(yīng)位為1清零,為0保持))。PxBSET 和 PxBCLR 相同位同時(shí)置 1 時(shí),PxBCLR 具有高優(yōu)先級(jí)。即該端口被清零。 端口配置操作流程 端口復(fù)用配置為模擬端口操作流程 a)設(shè)置寄存器 PxADS[n]為 1 端口復(fù)用配置為數(shù)字通用端口操作流程 a) 設(shè)置寄存器 PxADS[n]為 0 b) 設(shè)置寄存器 Px_SEL 為 0 c) 設(shè)置寄存器 PxDIR[n]為 1:端口方向?yàn)檩斎?,CPU 可以讀取端口的狀態(tài) PxIN[n]。 d) 設(shè)置寄存器 PxDIR[n]為 0:端口方向?yàn)檩敵?br> e) 設(shè)置寄存器 PxOUT[n]為 1:端口輸出高電平 f) 設(shè)置寄存器 PxOUT[n]為 0:端口輸出低電平 端口上拉使能配置操作流程 a)設(shè)置寄存器 PxPU[n]為 1 端口下拉使能配置操作流程 a) 設(shè)置寄存器 PxPU[n]為 0 b) 設(shè)置寄存器 PxPD[n]為 1 注:當(dāng) PxPU[n],PxPD[n]同時(shí)置 1 時(shí),PxPU[n]優(yōu)先級(jí)高,PxPD[n]無效。 端口增強(qiáng)驅(qū)動(dòng)配置操作流程 a)設(shè)置寄存器 PxDR[n]為 0 端口開漏輸出配置操作流程 a)設(shè)置寄存器 PxOD[n]為 1 配置代碼 無上下拉輸入配置 stc_gpio_cfg_t stcGpioCfg; Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //打開GPIO外設(shè)時(shí)鐘 stcGpioCfg.enDir = GpioDirIn; //端口方向配置-》輸入 stcGpioCfg.enDrv = GpioDrvL; //驅(qū)動(dòng)能力配置-》高驅(qū)動(dòng)能力 stcGpioCfg.enPu = GpioPuDisable; //端口上下拉配置-》無 stcGpioCfg.enPd = GpioPdDisable; stcGpioCfg.enOD = GpioOdDisable; //開漏輸出配置-》開漏輸出關(guān)閉 stcGpioCfg.enCtrlMode = GpioAHB; //總線控制模式配置-》AHB Gpio_Init(STK_USER_PORT, STK_USER_PIN, &stcGpioCfg); // GPIO IO USER KEY初始化 推挽輸出配置 stc_gpio_cfg_t stcGpioCfg; Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //打開GPIO外設(shè)時(shí)鐘 stcGpioCfg.enDir = GpioDirOut; //端口方向配置-》輸出 stcGpioCfg.enDrv = GpioDrvL; //驅(qū)動(dòng)能力配置-》高驅(qū)動(dòng)能力 stcGpioCfg.enPu = GpioPuDisable; //端口上下拉配置-》無 stcGpioCfg.enPd = GpioPdDisable; stcGpioCfg.enOD = GpioOdDisable; //開漏輸出配置-》開漏輸出關(guān)閉 stcGpioCfg.enCtrlMode = GpioAHB; //總線控制模式配置-》AHB Gpio_Init(STK_LED_PORT, STK_LED_PIN, &stcGpioCfg); // GPIO IO LED端口初始化 Gpio_ClrIO(STK_LED_PORT, STK_LED_PIN); // LED關(guān)閉 常用的端口操作庫函數(shù) 單端口操作 單個(gè)IO口輸出低電平 原型 en_result_t Gpio_ClrIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 Gpio_ClrIO(GpioPortA ,GpioPin1 ); //PA01端口輸出低電平 單個(gè)IO口輸出高電平 原型 en_result_t Gpio_SetIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 Gpio_SetIO(GpioPortA ,GpioPin1 ); //PA01端口輸出高電平 獲得IO口輸入值 原型 boolean_t Gpio_GetInputIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 u8PA1Stat = Gpio_GetInputIO(GpioPortA ,GpioPin1); //u8PA1Stat 為PA1端口輸入電平狀態(tài) 獲得IO口輸出值 原型 boolean_t Gpio_ReadOutputIO(en_gpio_port_t enPort, en_gpio_pin_t enPin) 舉例 u8PA1Stat = Gpio_ReadOutputIO(GpioPortA ,GpioPin1); //u8PA1Stat 為PA1端口輸出電平狀態(tài) 多端口操作 同時(shí)讓一組端口中的多個(gè)引腳輸出低電平 原型 en_result_t Gpio_ClrPort(en_gpio_port_t enPort, uint16_t u16ValMsk) 舉例 Gpio_ClrPort(GpioPortA , 0x000F); //PA0~PA3輸出低電平,其余保持 同時(shí)讓一組端口中的多個(gè)引腳輸出高電平 原型 en_result_t Gpio_SetPort(en_gpio_port_t enPort, uint16_t u16ValMsk) 舉例 Gpio_SetPort(GpioPortA , 0x000F); //PA0~PA3輸出高電平,其余保持 獲取一組IO口的輸入數(shù)據(jù) 原型 uint16_t Gpio_GetInputData(en_gpio_port_t enPort) 舉例 u16PAInputData = Gpio_GetInputData(GpioPortA ); //u16PAInputData的值為PA組輸入數(shù)據(jù) 同時(shí)讓一組端口輸出多個(gè)高低電平 原型 en_result_t Gpio_SetClrPort(en_gpio_port_t enPort, uint32_t u32ValMsk) 舉例 Gpio_SetClrPort(GpioPortA , 0x00f0000f); //PA4 ~ PA7輸出高電平PA0 ~ PA3輸出低電平 |
|