当前位置: 首页 > news >正文

江协科技STM32课程笔记(一) —GPIO

STM32系统结构

一、GPIO

GPIO(General Purpose Input Output)通用输入输出口
可配置为8种输入输出模式
引脚电平:0V~3.3V,部分引脚可容忍5V
输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等

1、GPIO位结构

左边的三个为寄存器,中间的部分为驱动器,右边是引脚。

首先引脚处的两个二极管用于对输入电压进行限幅,当电压大于VDD,则电流会通过上面的二极管流入VDD,如果电压小于VSS,则电流通过VSS流出IO;而电压处于VSS和VDD之间时电流正常流入,用于保护内部电路。

其次输入驱动器中有两个电阻,对应上拉输入模式和下拉输入模式,如果两个开关均断开,则是浮空输入模式。上拉和下拉用于提供输入的默认值为1和0,浮空模式时根据引脚电压随意改变。为不影响输入操作,这两个电阻一般较大。TTL施密特触发器用于电压整形,当输入电压大于某个阈值则输出瞬间变为高电平,反之低于某个阈值时则瞬间变为低电平,相当于硬件消抖。模拟输入连接ADC,所以需要在施密特触发器前。

接着看输出驱动器。PMOS和NMOS组成推挽输出模式,数据为1时,pmos通,nmos断;数据为0时pmos断,nmos通,这种方式下的驱动能力较强;开漏模式,就是PMOS不存在,数据为1时引脚为高阻态,数据为0时nmos通为低电平,用于I2C通信(“线与”)和提供5v输出(引脚外部上拉电阻5v)

最后通过位设置/清除寄存器设置输出数据寄存器的某一位或某几位,来让引脚输出0或者1;

2、8种输入输出模式

浮空输入可在引脚不用时完全断开引脚,其他模式可能存在电流损耗或者短路,否则如果要使用,就需要接连续的驱动源,不能让引脚悬空。

3、LED和蜂鸣器硬件电路

硬件电路

左为低电平有效,右为高电平有效,R1用于限流,避免烧坏LED

左为PNP,低电平有效(带箭头的是发射极,需要左边的基极为低电平时,发射极与下面的集电极导通,电流从发射极流向基极和集电极);右边是NPN,高电平有效(类比上面,电流从基极和集电极流向发射极)。忘记了可以看看下文。

一篇文章将三极管讲透:三极管从原理到应用,从参数到特性,从入门到精通_晶体三极管耗最高振荡频率(fm)-CSDN博客

需要注意:但凡是用三极管做开关信号,驱动负载,一律把负载接到集电极回路。

  • 负载在集电极:

    • 当GPIO输入高电平时,三极管进入饱和区。此时集电极-发射极之间的压降 Vce 非常小,通常在0.2V ~ 0.3V(称为饱和压降 Vce(sat))。

    • 因此,负载(蜂鸣器)两端的电压为 Vload = Vcc - Vce(sat) ≈ Vcc蜂鸣器得到了几乎全部的电源电压,可以正常工作。

    • 这是一个理想的开关:导通时电阻极低,压降极小。

  • 负载在发射极(射极跟随器):

    • 在这种配置下,发射极电压 Ve 永远跟着基极电压 Vb 变化,且总是 Ve = Vb - 0.7V

    • 假设GPIO输出高电平为3.3V,那么发射极电压最高只能是 3.3V - 0.7V = 2.6V

    • 如果蜂鸣器的工作电压是5V,那么此时它最多只能获得2.6V的电压,无法达到额定电压,可能导致蜂鸣器不响、响声小或不稳定。

    • 三极管无法进入饱和区,始终工作在线性区,Vce 压降较大(Vce = Vcc - Ve),导致三极管自身功耗大、发热严重

  • 负载在集电极:

    • GPIO电压和负载电源电压 Vcc 可以完全不同。你可以用一个3.3V的微控制器GPIO去控制一个由5V、12V甚至24V供电的负载。只要三极管的耐压(Vceo)足够,且基极电阻设置正确即可。这是该电路最大的优势之一。

  • 负载在发射极:

    • GPIO的电压直接决定了负载能得到的最高电压。你必须使用一个比负载所需电压至少高0.7V的GPIO来控制它。这在实际应用中限制极大,几乎无法用于驱动高于逻辑电压的负载。

4、使用

输出以流水灯为例:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启时钟GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//GPIO_SetBits(GPIOA,GPIO_Pin_0);//GPIO_ResetBits(GPIOA,GPIO_Pin_0);//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);uint8_t offset = 0x1;while (1){GPIO_Write(GPIOA,~offset);offset = (offset << 1) | (offset >> 7);sysDelayms(500);}

输入以按键为例:

硬件电路采用下拉方式,引脚内部采用上拉输入

uint8_t Key_GetNum(void)
{uint8_t Key = 0;		//定义变量,默认键码值为0if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)			//读PB1输入寄存器的状态,如果为0,则代表按键1按下{sysDelayms(20);											//延时消抖while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);	//等待按键松手sysDelayms(20);											//延时消抖Key |= GPIO_Pin_1;												//置键码为1}if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)			//读PB11输入寄存器的状态,如果为0,则代表按键2按下{sysDelayms(20);											//延时消抖while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);	//等待按键松手sysDelayms(20);											//延时消抖Key |= GPIO_Pin_2;												//置键码为2}return Key;			//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}void ledTurn(uint8_t Key)
{uint8_t temp = 0,writeData = 0;if(Key & GPIO_Pin_1){temp = (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1));writeData = (~temp)&0x1;GPIO_WriteBit(GPIOA, GPIO_Pin_1,(BitAction)writeData);}if(Key & GPIO_Pin_2){temp = (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2));writeData = (~temp)&0x1;GPIO_WriteBit(GPIOA, GPIO_Pin_2,(BitAction)writeData);}
}int main(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);//打开GPIOA和B时钟GPIO_InitTypeDef ledGPIO_InitStructure;ledGPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;ledGPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;ledGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&ledGPIO_InitStructure);//初始化GPIOA ledGPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);GPIO_InitTypeDef keyGPIO_InitStructure;keyGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入keyGPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;keyGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&keyGPIO_InitStructure);//初始化GPIOA ledvolatile uint8_t KeyNum = 0x0;	while (1){KeyNum = Key_GetNum();		//获取按键键码if(KeyNum != 0x0){ledTurn(KeyNum);}}
}


文章转载自:

http://Qn0PGwFP.czqqy.cn
http://kNvcd6Q4.czqqy.cn
http://gQyp1yqR.czqqy.cn
http://SixUhlDC.czqqy.cn
http://BL59jbSb.czqqy.cn
http://QRApuc6a.czqqy.cn
http://jidbDPbK.czqqy.cn
http://JSQrkCNb.czqqy.cn
http://N90DiyUT.czqqy.cn
http://hPLcluIK.czqqy.cn
http://zEd4UJA0.czqqy.cn
http://5iD17OEx.czqqy.cn
http://aeTtMWVo.czqqy.cn
http://X0PyerQ4.czqqy.cn
http://ogMNEh31.czqqy.cn
http://g39A3Op4.czqqy.cn
http://wFSYbR11.czqqy.cn
http://1vu9y6i4.czqqy.cn
http://NoNZCAaj.czqqy.cn
http://Ub4uBhHB.czqqy.cn
http://fVvWgv8M.czqqy.cn
http://3o00GK2l.czqqy.cn
http://SK3jWfZ4.czqqy.cn
http://tlt94fkH.czqqy.cn
http://pZEfBVNX.czqqy.cn
http://425nBT2w.czqqy.cn
http://IC3JhA4Y.czqqy.cn
http://N0N3WEPW.czqqy.cn
http://wXHyZ2V3.czqqy.cn
http://fm23DPsE.czqqy.cn
http://www.dtcms.com/a/385683.html

相关文章:

  • 江协科技STM32课程笔记(二)—外部中断EXTI
  • 科技信息差(9.15)
  • 龙珠KS6 10.5T矿机评测:性能、功耗、噪音与冷却分析
  • 打工人日报#20250915
  • 新一代车载诊断框架简介
  • 05-索引-性能分析
  • 【数据工程】 2. Unix 基础与文件操作
  • 第四课、 TypeScript 中 Cocos 的生命周期
  • 联邦学习论文分享:DPD-fVAE
  • Pairwise排序损失:让机器学会排序的艺术
  • 硬件开发—IMX6ULL裸机—UART通信
  • 蓝牙上位机开发指南
  • 【课堂笔记】复变函数-1
  • 谈谈人大金仓数据库
  • C#调用钉钉API发送通知教程
  • 电子电气架构 --- 产线EOL为何需要智能升级?
  • 无人机姿态控制系统详解与实现
  • 7.Redis 主从复制(重在理解)
  • 从零搭建RAG应用:跳过LangChain,掌握文本分块、向量检索、指代消解等核心技术实现
  • 从0开始做一个完整项目 -- 软件跨平台编译打包全流程
  • comfyUI实战——使用openArt的工作流
  • linux 之 struct attribute
  • 强化学习PPO-分类任务
  • 决策树模型全解析:从分类到回归(基于鸢尾花数据集)
  • shell脚本部署lamp
  • c语言6:static 关键字控制变量/函数的 “生命周期” 与 “可见性”
  • MySQL 数据库对象与视图:从概念到实战,掌握虚拟表的核心价值
  • 【VPX361】基于3U VPX总线架构的XCZU47DR射频收发子模块
  • 消火栓设备工程量计算 -【图形识别】秒计量
  • 基于LangGraph的深度研究智能体技术解析