2.1 GPIO的8种工作模式
GPIO工作图如下:
4种输入模式
结构图的上半部分分为输入模式结构, 分为上拉模式,下拉模式,浮空模式和模拟输入模式.
上/下拉模式:通过设置配置寄存器(CRL,CRH)来控制1和2开关,于是得到GPIO的上拉输入模式(GPIO_Mode_IPU)和下拉输入模式(GPIO_Mode_IPD).
浮空输入模式(GPIO_Mode_IN_FLOATING):没有接上下拉电阻,经由TTL施密特触发器输入. 配置成这个模式直接用电压表测量其引脚电压为1点几伏,这个值不确定,由于其输入阻抗较大,一般把这种模式用于标准的通信协议如I2C,USART的接收到
模拟输入模式(GPIO_Mode_AIN):关闭了施密特触发器,不接上下拉电阻,经由另一路线路把电压信号传送到片上外设模块(如ADC模块)
4种输出模式
结构图的下半部分为输出模式结构,分为推挽输出模式(GPIO_Mode_Out_PP),开漏输出模式(GPIO_Mode_Out_OD),复用推挽输出模式()GPIO_Mode_AF_PP和复用开漏输出模式(GPIO_Mode_AF_OD).
推挽输出模式:在输出高电平时,P_MOS管导通;输出低电平时,N_MOS管导通. 其负载能力和开关速度都比普通的方式较好.推挽输出低电平为0V,高电平为3.3V
开漏输出模式:若控制输出为0V,N_MOS导通,使输出接地;若控制输出1,则为高阻态(无法直接输出高电平).为正常使用时必须外接一个上拉电阻,它具有”线与”特性,即当有多个开漏模式引脚连接到一起时,只有当所有引脚都输出高阻态才能由上拉电阻提供高电平,此高电平的电压为外部上拉电阻所接电源的电压.
对于复用模式是根据GPIO的复用功能来选择的,如GPIO引脚用作串口的输出,使用复用推挽输出模式,若用在IC ,SMBUS这些需要线与功能的复用场合则使用复用开漏输出模式
2.2 外部中断/事件控制器(EXTI)
2.2.1 EXTI寄存器描述
a) 中断屏蔽寄存器(EXTI_IMR)
MRx:x为0-18, (1)开放x线上的中断请求
b) 事件屏蔽寄存器(EXTI_EMR)
MRx:x为0-18, (1)开放x线上的事件请求
c) 上升沿触发选择寄存器(EXTI_RTSR)
TRx:x为0-18, (1)允许输入线x上的上升沿触发(中断和事件)
d) 下降沿触发选择寄存器(EXTI_FISR)
TRx:x为0-18, (1)允许输入线x上的下降沿触发(中断和事件)
注意:外部唤醒线是边沿触发的,这些线上不能出现毛刺信号.在写EXTI_FTSR寄存器时,在外部中断线上的下降沿信号不能被识别,挂起位不会被置位.(这个对EXTI_RTSR也是一样的)
在同一中断线上,可以同时设置上升沿和下降沿触发.即任一边沿都可触发中断.
e) 软中断事件寄存器(EXTI_SWIER)
SWIERx:x为0-18, 设置线x上的软件中断.当该位为0时,写1将设置EXTI_PR中相应的挂起位.如果在EXTI_IMR和EXTI_EMR中允许产生该中断,则此时将产生一个中断.
注:通过清除EXTI_PR的对应位(写入1),可以清除该位为0.
f) 挂起寄存器(EXTI_PR)
PRx:x为0-18,当在外部中断线上发生了选择的边沿事件,该位被置1.在该位中写入1可以清除它,也可以通过改变边沿检测的极性清除.
2.2.2 外部中断配置寄存器2(AFIO_EXTICR2)
参考<STM32参考手册>7.4 AFIO寄存器描述
2.2.3 外部中断/事件线路映像
PAx~PGx端口的中断事件都连接到了EXTIx,即同一时刻EXTx只能相应一个端口的事件触发,不能够同一时间响应所有GPIO端口的事件,但可以分时复用。它可以配置为上升沿触发,下降沿触发或双边沿触发。
另外还有其他三种外部中断/事件控制器的连接如下:
EXTI线16连接到PVD输出
EXTI线17连接到RTC闹钟事件
EXTI线18连接到USB唤醒事件
2.3 NVIC中断控制器
NVIC(Nested Vectored Interrupt Controller)是属于Cortex内核的器件,不可屏蔽中断(NMI)和外部中断都由它来处理,而SYSTICK不是由NVIC来控制的.
2.3.1 NVIC结构成员(NVIC_InitTypeDef)
NVIC_IRQChannel 需要配置的中断向量 (参考)
NVIC_IRQChannelCmd 使能或关闭相应中断向量的中断响应
NVIC_IRQChannelPreemptionPriority 配置相应中断向量抢占优先级
NVIC_IRQChannelSubPriority 配置相应中断向量的响应优先级
2.3.2 抢占优先级和响应优先级
STM32的中断向量具有两个属性,一个为抢占属性,另一个为响应属性,其属性编号越小,表明它的优先级别越高.
抢占,是指打断其它中断的属性,即因为具有这个属性,会出现嵌套中断(在执行中断服务函数A的过程中被中断B打断,执行完中断服务函数B再继续执行中断服务函数A).
响应属性是应用在抢占属性相同的情况下,当两个中断向量的抢占优先级相同时,如果两个中断同时到达,则先处理响应优先级高的中断.
2.3.3 NVIC的优先级组
在配置优先级的时候,还要注意一个很重要的问题,中断种类的数量.NVIC只可以配置16种 中断向量的优先级,也就是说,抢占优先级和响应优先级的数量由一个4位的数字来决定,把这个4位数字的位数分配成抢占优先级部分和响应优先级部分.有5种分配方式,可采用库函数NVIC_PriorityGroupConfig()配置
2.4 外部中断程序编写
/*配置GPIO##group的##pin为EXTI中断,并设置优先级*/ #define DEFINE_PIN_EXTI(group, pin, IRQn, SubPriority) void init_P##group##pin##_as_EXTI(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /*使能EXTIx线的时钟和第二功能AFIO时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO##group|RCC_APB2Periph_AFIO, ENABLE); /*配置EXTI中断线I/O*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /*上拉输入*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIO##group, &GPIO_InitStructure); /*选择GPIO##group##pin管脚为外部中断源和配置IO口的工作模式*/ GPIO_EXTILineConfig(GPIO_PortSourceGPIO##group, GPIO_PinSource##pin); EXTI_InitStructure.EXTI_Line = EXTI_Line##pin; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /*设置为下降沿触发*/ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /*设置NVIC优先级组为第一组*/ NVIC_InitStructure.NVIC_IRQChannel = IRQn; /*该参数的设置参考<STM32固件库>中NVIC_Init()函数的用法和<STM32参考手册>中8.1.2中断和异常向量*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /*这里配置PC5为EXTI为外部中断源,NVIC结构体中.NVIC_IRQChannel=EXTI9_5_IRQn表示要配置的是EXTI第5-9线的中断向量,EXTI5-EXTI9使用同一个中断向量,所以只能写入EXTI5_9_IRQn.这些参数可在stm32f10x.h中的IRQn类型定义中找到.*/ DEFINE_PIN_EXTI(C, 5, EXTI9_5_IRQn, 1) /*中断服务函数的编写*/ /*stm32f10x_it.c文件是专门用来存放中断服务函数的.中断服务函数的名字必须要与启动文件startup_stm32f10x_hd.s中的中断向量表一致.*/ /* PC5 Key1 interrupt handler */ void EXTI9_5_IRQHandler(void) { static uint8_t led1_status = OFF; if(EXTI_GetITStatus(EXTI_Line5) != RESET) //确保是否产生了EXTI LINE中断 { led1_status ^= 1; turn_led(LED1, led1_status); // EXTI_ClearITPendingBit(EXTI_Line5); //清除中断标志 } }
2.5 AFIO时钟
AFIO是指GPIO端口的复用功能,GPIO除了可以用作普通的输入输出,还可以用作片上外设的复用输入输出口(如串口,ADC等).大多数GPIO有一个默认复用功能,有的还有重映射功能.重映射功能是指把原来属于A引脚的默认复用功能,转移到B引脚进行试验,前提是B引脚有这个重映射功能.使用GPIO_PinRemapConfig()函数进行重映射.
当把GPIO用作EXTI外部中断或使用重映射功能的时候,必须开启AFIO时钟,而在使用默认复用功能的时候不用开启AFIO时钟.
参考连接:
http://blog.csdn.net/huangyidong6718/article/details/21640849