<br />GPIO功能描述<br />每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。<br /> <br />GPIO端口的每个位可以由软件分别配置成多种模式。<br />─输入浮空<br />─输入上拉<br />─输入下拉<br />─模拟输入<br />─开漏输出<br />─推挽式输出<br />─推挽式复用功能<br />─开漏复用功能<br /> <br />每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问(不允许半字或字节访问)。GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的独立访问;这样,在读和更改访问之间产生IRQ时不会发生危险。<br /> <br />下图给出了一个I/O端口位的基本结构。<br /> <br /><br /> <br /> <br /> <br />复位期间和刚复位后,复用功能未开启,I/O端口被配置成浮空输入模式(CNFx[1:0]=01b,MODEx[1:0]=00b)。<br />复位后,JTAG引脚被置于输入上拉或下拉模式:<br />─PA15:JTDI置于上拉模式<br />─PA14:JTCK置于下拉模式<br />─PA13:JTMS置于上拉模式<br />─PB4: JNTRST置于上拉模式<br /> <br />当作为输出配置时,写到输出数据寄存器上的值(GPIOx_ODR)输出到相应的I/O引脚。可以以推挽模式或开漏模式(当输出0时,只有N-MOS被打开)使用输出驱动器。<br />输入数据寄存器(GPIOx_IDR)在每个APB2时钟周期捕捉I/O引脚上的数据。<br />所有GPIO引脚有一个内部弱上拉和弱下拉,当配置为输入时,它们可以被激活也可以被断开。<br /> <br />当对GPIOx_ODR的个别位编程时,软件不需要禁止中断:在单次APB2写操作里,可以只更改一个或多个位。<br />这是通过对“置位/复位寄存器”(GPIOx_BSRR,复位是 GPIOx_BRR)中想要更改的位写’1’来实现的。没被选择的位将不被更改。<br /> <br /> <br />复用功能(AF)<br />使用默认复用功能前必须对端口位配置寄存器编程。<br />●<br />对于复用的输入功能,端口必须配置成输入模式(浮空、上拉或下拉)且输入管脚必须由外部驱动<br />注意:也可以通过软件来模拟复用功能输入管脚,这种模拟可以通过对GPIO控制器编程来实现。此时,端口应当被设置为复用功能输出模式。显然,这时相应的管脚不再由外部驱动,而是通过GPIO控制器由软件来驱动。<br />●<br />对于复用输出功能,端口必须配置成复用功能输出模式(推挽或开漏)。<br />●<br />对于双向复用功能,端口位必须配置复用功能输出模式(推挽或开漏)。这时,输入驱动器被配置成浮空输入模式。<br />如果把端口配置成复用输出功能,则引脚和输出寄存器断开,并和片上外设的输出信号连接。<br />如果软件把一个GPIO脚配置成复用输出功能,但是外设没有被激活,它的输出将不确定。<br /> <br />软件重新映射I/O复用功能<br />为了使不同器件封装的外设I/O功能的数量达到最优,可以把一些复用功能重新映射到其他一些脚上。这可以通过软件配置相应的寄存器来完成(参考AFIO寄存器描述)。这时,复用功能就不再映射到它们的原始引脚上了。<br /> <br />输入配置<br />当I/O端口配置为输入时:<br />●输出缓冲器被禁止<br />●施密特触发输入被激活<br />●根据输入配置(上拉,下拉或浮动)的不同,弱上拉和下拉电阻被连接<br />●出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器<br />●对输入数据寄存器的读访问可得到I/O状态<br /> <br /> <br /> <br /> <br /> <br />输出配置<br />当I/O端口被配置为输出时:<br />●输出缓冲器被激活<br />─开漏模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将端口置于高阻状态(P-MOS从不被激活)。<br />─推挽模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将激活P-MOS。<br />●施密特触发输入被激活<br />●弱上拉和下拉电阻被禁止<br />●出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器<br />●在开漏模式时,对输入数据寄存器的读访问可得到I/O状态<br />●在推挽式模式时,对输出数据寄存器的读访问得到最后一次写的值。<br /> <br /> <br /> <br /> <br />模拟输入配置<br />当I/O端口被配置为模拟输入配置时:<br />●输出缓冲器被禁止;<br />●禁止施密特触发输入,实现了每个模拟I/O引脚上的零消耗。施密特触发输出值被强置为’0’;<br />●弱上拉和下拉电阻被禁止;<br />●读取输入数据寄存器时数值为’0’。<br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br />例程(1)<br /> <br /> <br />本例展示了如何通过设置GPIO BSRR寄存器(Port bit set/reset registe)和GPIO BRR寄存器 (Port bit reset register)来翻转IO的状态。<br /> <br />通过设置这两个寄存器,可以利用单比特操作(single atomic write access)来改变一个或者几个IO端口的状态。<br /> <br />#include "stm32f10x_lib.h"<br /> <br />/* Private typedef -----------------------------------------------------------*/<br />/* Private define ------------------------------------------------------------*/<br />/* Private macro -------------------------------------------------------------*/<br />/* Private variables ---------------------------------------------------------*/<br />GPIO_InitTypeDef GPIO_InitStructure;<br />ErrorStatus HSEStartUpStatus;<br /> <br />/* Private function prototypes -----------------------------------------------*/<br />void RCC_Configuration(void);<br />void NVIC_Configuration(void);<br />void Delay(vu32 nCount);<br /> <br />/* Private functions ---------------------------------------------------------*/<br /> <br />/*******************************************************************************<br />* Function Name : main<br />* Description : Main program.<br />* Input : None<br />* Output : None<br />* Return : None<br />*******************************************************************************/<br />int main(void)<br />{<br />#ifdef DEBUG<br /> debug();<br />#endif<br /> <br /> /* Configure the system clocks */<br /> RCC_Configuration();<br /> <br /> /* NVIC Configuration */<br /> NVIC_Configuration();<br /> <br /> /* Enable GPIOC clock */<br /> RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能APB2外设(GPIOC)时钟<br /> <br /> /* Configure PC.04-PC.07 as Output push-pull */<br /> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;<br /> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br /> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;<br /> GPIO_Init(GPIOC, &GPIO_InitStructure);<br /> <br /> while (1)<br /> {<br /> /* Turn on led connected to PC.04pin */<br /> GPIO_SetBits(GPIOC, GPIO_Pin_4);<br /> /* Insert delay */<br /> Delay(0xAFFFF);<br /> <br /> /* Turn on led connected to PC.05 and PC.06 pins */<br /> GPIO_SetBits(GPIOC, GPIO_Pin_5 | GPIO_Pin_6);<br /> /* Turn off led connected to PC.04 pin */<br /> GPIO_ResetBits(GPIOC, GPIO_Pin_4);<br /> /* Insert delay */<br /> Delay(0xAFFFF);<br /> <br /> /* Turn on led connected to PC.07 pin */<br /> GPIO_SetBits(GPIOC, GPIO_Pin_7);<br /> /* Turn off led connected to PC.05 and PC.06 pins */<br /> GPIO_ResetBits(GPIOC, GPIO_Pin_6 | GPIO_Pin_5);<br /> /* Insert delay */<br /> Delay(0xAFFFF);<br /> <br /> /* Turn off led connected to PC.07 pin */<br /> GPIO_ResetBits(GPIOC, GPIO_Pin_7);<br /> }<br />}<br /> <br />/*******************************************************************************<br />* Function Name : RCC_Configuration<br />* Description : Configures the different system clocks.<br />* Input : None<br />* Output : None<br />* Return : None<br />*******************************************************************************/<br />void RCC_Configuration(void)<br />{<br /> /* RCC system reset(for debug purpose) */<br /> RCC_DeInit();<br /> <br /> /* Enable HSE */<br /> RCC_HSEConfig(RCC_HSE_ON);<br /> <br /> /* Wait till HSE is ready */<br /> HSEStartUpStatus = RCC_WaitForHSEStartUp();<br /> <br /> if(HSEStartUpStatus == SUCCESS)<br /> {<br /> /* Enable Prefetch Buffer */<br /> FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);<br /> <br /> /* Flash 2 wait state */<br /> FLASH_SetLatency(FLASH_Latency_2);<br /> <br /> /* HCLK = SYSCLK */<br /> RCC_HCLKConfig(RCC_SYSCLK_Div1); <br /> <br /> /* PCLK2 = HCLK */<br /> RCC_PCLK2Config(RCC_HCLK_Div1); <br /> <br /> /* PCLK1 = HCLK/2 */<br /> RCC_PCLK1Config(RCC_HCLK_Div2);<br /> <br /> /* PLLCLK = 8MHz * 9 = 72 MHz */<br /> RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);<br /> <br /> /* Enable PLL */ <br /> RCC_PLLCmd(ENABLE);<br /> <br /> /* Wait till PLL is ready */<br /> while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)<br /> {<br /> }<br /> <br /> /* Select PLL as system clock source */<br /> RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);<br /> <br /> /* Wait till PLL is used as system clock source */<br /> while(RCC_GetSYSCLKSource() != 0x08)<br /> {<br /> }<br /> }<br />}<br /> <br />/*******************************************************************************<br />* Function Name : NVIC_Configuration<br />* Description : Configures Vector Table base location.<br />* Input : None<br />* Output : None<br />* Return : None<br />*******************************************************************************/<br />void NVIC_Configuration(void)<br />{<br />#ifdef VECT_TAB_RAM <br /> /* Set the Vector Table base location at 0x20000000 */ <br /> NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); <br />#else /* VECT_TAB_FLASH */<br /> /* Set the Vector Table base location at 0x08000000 */ <br /> NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); <br />#endif<br />}<br /> <br />/*******************************************************************************<br />* Function Name : Delay<br />* Description : Inserts a delay time.<br />* Input : nCount: specifies the delay time length.<br />* Output : None<br />* Return : None<br />*******************************************************************************/<br />void Delay(vu32 nCount)<br />{<br /> for(; nCount != 0; nCount--);<br />}<br /> <br />#ifdef DEBUG<br />/*******************************************************************************<br />* Function Name : assert_failed<br />* Description : Reports the name of the source file and the source line number<br />* where the assert_param error has occurred.<br />* Input : - file: pointer to the source file name<br />* - line: assert_param error line source number<br />* Output : None<br />* Return : None<br />*******************************************************************************/<br />void assert_failed(u8* file, u32 line)<br />{ <br /> /* User can add his own implementation to report the file name and line number,<br /> ex: printf("Wrong parameters value: file %s on line %d
", file, line) */<br /> <br /> /* Infinite loop */<br /> while (1)<br /> {<br /> }<br />}<br />#endif<br /> <br />例程2要用到JTAG ,没有那个接口,所以不能演示。<br /> <br /> <br /> <br /><br /> |
|