STM32F103C8T6外设
一、GPIO
1. 基本结构

2. 位结构

输入驱动器部分
保护二极管对输入电压进行限幅。Vdd是数字电源,为3.3V,Vss是数字地。
当输入电压大于3.3V时,上方保护二极管导通,电流流入Vdd,避免过大的电流对内部电路产生影响。
同理,当输入小于-3.3V的负压时,下方二极管导通。当输入电压在0~3.3V之间时,两二极管均不导通。
上拉电阻和下拉电阻处的开关由寄存器的相应位控制,分为上拉输入模式,下拉输入模式和浮空输入模式。
浮空输入:浮空输入是输入端口未连接任何信号源时,其输入端口处于一种“悬空”状态,即没有明确的电平值。2.上拉输入:“上拉输入”是指在数字电路中,将一个输入端口连接至高电平信号(通常为Vdd)的电路拓扑。在这种情况下,当输入端口不接任何信号源时(悬空)其输入端口处于高电平状态。3.下拉输入:同理
TTL肖特基触发器:当输入波形大于上限电压时,输出高电平,即使后续波形在上限电压上下反复横跳,在上限和下限之间波动,仍输出高电平,只有当输入波形小于下限电压时,输入低电平。有效避免了信号波动造成的电平不定现象。所以经过整形后的输入波形就是一个标准的数字信号。
输出部分
输出数据寄存器不可位寻址,但可以使用位设置或位清除寄存器对其上的位进行单独操作。
如果要对输出数据寄存器某位置1,只需要在位设置寄存器对应位置1即可,写0的对应位保持不变,同理,位清除寄存器某位置1,在输出数据寄存器中的对应位清零。
开漏模式下,P-MOS恒定断开,当N-MOS闭合时,低电平驱动,当N-MOS断开,输出端口处于高阻模式。
开漏模式下,要输出高电平,N-MOS断开,pin处于高阻态,再外接一个上拉电阻,上拉电阻接Vdd为5V。GPIO输出端口被拉到5V。
关闭模式:两个mos管均断开,端口电平由外部信号控制,流向输入模块。
3. 模式总结

EXTI基
二、EXTI
1. EXTI基本结构

1.输入源:GPIO 引脚
每个 GPIO 端口(GPIOA/GPIOB/GPIOC等所有GPIO口)都有 16 个通用 IO 引脚(编号0~15),均可作为外部中断的输入信号源。
关键限制:EXTI 线 0~15(一共16条线),每条EXTIx线只能连接到一个 GPIO 端口的第x个引脚(如EXTI0只能选PA0/PB0/PC0.....中的一个,无法同时连接多个),因此需要 AFIO 模块做 “选择开关”。
2. 选择开关:AFIO(复用功能 IO)模块
全称Alternate Function I/O,核心作用是为每条 EXTI 线选择对应的 GPIO 引脚,解决多引脚共用 EXTI 线的冲突。例如:EXTI1只能选通PA1/PB1/PC1.....中的一个。
注意:必须先开启 AFIO 时钟(RCC_APB2Periph_AFIO),否则无法配置该模块。
| EXTI 线号 | 对应功能 |
|---|---|
| EXTI0~EXTI15 | GPIO 引脚外部中断 |
| PVD | PVD(可编程电压检测器)中断 |
| RTC | RTC 闹钟事件中断 |
| USB | USB 唤醒事件中断 |
| ETH | 以太网唤醒事件中断(大容量型号) |
2. EXTI 线号与NVIC 中断通道的对应关系
| EXTI 线号 | 对应 NVIC 中断通道 |
|---|---|
| EXTI0 | EXTI0_IRQn (外部中断0的中断通道命名) |
| EXTI1 | EXTI1_IRQn |
| EXTI2 | EXTI2_IRQn |
| EXTI3 | EXTI3_IRQn |
| EXTI4 | EXTI4_IRQn |
| EXTI5~EXTI9 | EXTI9_5_IRQn(共用同一个中断通道) |
| EXTI10~EXTI15 | EXTI15_10_IRQn(共用) |
3.示例代码
#include "stm32f10x.h"
// LED状态标志位
uint8_t led_state = 0;
/**
* @brief 配置GPIO:PA0为按键输入,PC13为LED输出
*/
void GPIO_EXTI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 1. 开启GPIOA和GPIOC的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
// 2. 配置PA0为上拉输入(按键默认高电平,按下时拉低)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输入模式速度可忽略,配置也无妨
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 3. 配置PC13为推挽输出(LED)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);
// 初始化LED为熄灭状态(PC13输出高电平)
GPIO_SetBits(GPIOC, GPIO_Pin_13);
led_state = 0;
}
/**
* @brief 配置AFIO和EXTI:PA0映射到EXTI0,下降沿触发
*/
void EXTI_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
// 1. 开启AFIO时钟(EXTI配置必须开启!否则无法映射引脚)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// 2. 将PA0映射到EXTI0线(AFIO配置)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
// 3. 配置EXTI0线参数
EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 选择EXTI0线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 模式:中断(不是事件)
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 触发方式:下降沿(按键按下时)
EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能该EXTI线
EXTI_Init(&EXTI_InitStructure);
}
/**
* @brief 配置NVIC:设置EXTI0中断优先级并使能
*/
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 配置中断优先级分组:2位抢占优先级,2位响应优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 配置EXTI0中断通道
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 选择EXTI0对应的中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; // 抢占优先级:1(0为最高)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; // 响应优先级:1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能该中断通道
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief EXTI0中断服务函数:中断触发时自动调用
* @note 函数名必须与启动文件中定义的一致,不能写错!
*/
void EXTI0_IRQHandler(void)
{
// 确认是EXTI0触发的中断(防止其他中断误触发)
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
// 翻转LED状态
led_state = !led_state;
if(led_state == 0)
{
GPIO_SetBits(GPIOC, GPIO_Pin_13); // 熄灭LED(PC13高电平)
}
else
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 点亮LED(PC13低电平)
}
// 关键:清除EXTI0的中断挂起位,否则会一直触发中断!
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
/**
* @brief 主函数:初始化模块,循环等待中断
*/
int main(void)
{
// 初始化GPIO、EXTI、NVIC
GPIO_EXTI_Config();
EXTI_Config();
NVIC_Config();
// 主循环:空转,所有操作在中断服务函数中完成
while(1)
{
// 可在此添加其他任务,不影响中断响应
}
}
注:EXTI 线共用问题:EXTI5~EXTI9共用EXTI9_5_IRQn中断通道,EXTI10~EXTI15共用EXTI15_10_IRQn通道,如果使用这几个外部中断线,需在中断服务函数中用EXTI_GetITStatus()轮询判断具体触发的线。
更多推荐


所有评论(0)