入门STM32F103-GPIO输入
2025-10-31 来源:elecfans
上一次完成了端口引脚的输出,今天开始做引脚的输入。
每个引脚有四种输入模式,这里简单讲一下。第一个是模拟输入,就是输入量为模拟信号,浮空输入,就是输入量为数字信号高低电平,上拉/下拉输入,就是把不确定的信号统一拉高/低。因为我的硬件电路可以出入确定的高低电平,这里我就配置成浮空输入。
这次的实验功能是通过两个按键完成流水灯的流向和启停,两个按键分别连接到PA0和PC13
PA0控制流向,PC13控制启停。流水灯连接方式沿用上次实验的接法。
讲一下编程顺序:
打开端口时钟总线->配置各个端口的输入输出方式->在主函数中判断启停标志->若为启动标志,则点亮相应的小灯,并延时等待同时读取按键信息->若为停止标志,则将小灯熄灭或点亮。
下面是用到的寄存器 由于是承接上一次的实验,有些上次用到的我就不在详细描述了。
RCC->APB2ENR :APB2 外设时钟使能寄存器 图1为寄存器位描述,因为用到PA、PB、PC,需将相应的位置1.

图1为外设时钟使能寄存器(RCC_APB2ENR)的位描述
GPIOA->CRL :PA端口配置低寄存器 跟PB的一样,之前提到过就不放图片了,这里是要把它配置成浮空输入模式,因此需要配制成0x4。PC口同理,但要注意的是由于PC13属于属于高8位引脚,因此应在CRH中进行配置,这点需要注意。
讲完寄存器后还有一个知识点,就是按键的检测问题。
我们都知道按键在按下是由于器件接触的原因在波形上产生一段连续的抖动,在检测中就会产生误判,这是我们不希望出现的。对此产生了两种解决方案,第一种也是我们经常用到的,叫延时去抖。但这里的去是躲过去的意思,并非消去。第二种方法是硬件去抖,这里通过在按键两端并联电容,通过对电容充放电来实现去抖,是真正的消去了抖动。这里我采用的是第二种方法,因此程序中就没有延时判断了。
我们在刚学习按键时会写这样的一句话 while(按键是否抬起?);这句话很好理解,因为我们只希望执行一次键函数,即使按键一直被按,所以就有了这句检测按键是否抬起。这句话的本质是CPU一直询问按键是否抬起,若按键一直被按着,那么CPU将一直执行这句话,这极大的浪费了系统资源。
因此在我将使用另一种按键检测方法,起名为键标志法。这个方法是在判断按键按下后在判断这个键标志是否为有效,若为真则会执行键函数,若为假,则不会执行键函数。这样CPU就不用一直检测按键是否抬起了。达到优化程序的目的。
下面是本次实验的程序
#include "stm32f10x.h"
unsigned char box[]={0xff,0x22,0x20,0x21,0x01,0x03,0x02}; //这里放的是流水灯的控制字
unsigned char sx,p,mark1,mark2,j=1;
//这里声明了流水灯方向控制字,启停控制字以及两个键标志。
void keybord(void) //按键检测函数
{
if(GPIOA->IDR & 0x1) //如果按键PA0被按下
{
if(mark1==0) //判断键标志是否为0
{
sx ^= 1; // 若为0则执行键函数,取反流水灯控制字。
mark1=1; //将键标志置1,实现按键的一次相应
}
}
else mark1=0; //在没有按键按下时将键标志置0为下一次按键按下做准备
if(GPIOC->IDR & (1<<13)) //按键PC13键函数
{
if(mark2==0)
{
p ^=1; // 将启停控制字取反
mark2=1;
if(p==1) //判断当前状态 为1时关闭灯
GPIOB->ODR |= 0X23;
else //不然恢复显示。
GPIOB->ODR =box[j];
}
}
else mark2=0;
}
void delay(void) //延时函数
{
unsigned int i,x;
for(x=0;x<200;x++)
for(i=0;i<6000;i++)
{
keybord(); //这里加入键函数是为随时捕捉按键信息
}
}
int main(void)
{
RCC->APB2ENR |= (1<<2) |(1<<3) |(1<<4) ; //打开端口时钟总线
GPIOA->CRL |= 0X04; //配置各个端口的输入输出方式
GPIOB->CRL |= 0X3 |(3<<4) | (3<<20);
GPIOC->CRH |= (0X04) <<24;
GPIOB->ODR |= 0X23; //关闭流水灯
keybord(); //读取一下按键信息
while(1)
{
if(p==1) //启停情况
{
keybord(); //若为停止则循环读取按键信息
}
else //若为启动
{
GPIOB->ODR =box[j]; //则执行相应的灯光
delay(); //延时等待
if(p==0) // 这里又判断了一遍是因为按键信息有可能发生改变
{
if(sx==0) //判断流水灯方向是正向流水还是反向流水
{
if(j==6)
j=1;
else j++;
}
else
{
if(j==1)
j=6;
else j--;
}
}
}
}
}
- 车联网安全入门——CAN总线模糊测试
- Nordic Semiconductor 扩展 nRF54L 系列,推出入门级低功耗蓝牙 SoC
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 线性稳压器的电压输入至输出控制——第一部分:快速入门和优势
- 全场景工控与网关解决方案:从入门到旗舰的一站式选型
- 51单片机快过时了?为什么高手总推荐51入门?
- 广州易显5寸串口触摸屏工程开发快速入门
- 广州易显VGA卡编程快速入门教程
- 迅为RK3588开发环境搭建三步曲:从零到一轻松入门
- 铠侠推出全新EXCERIA BASIC SSD系列 兼具PCIe@4.0性能与高性价比的全新入门级SSD系列
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 蓝牙信道探测技术原理与开发套件实践
- Microchip 推出生产就绪型全栈边缘 AI 解决方案,赋能MCU和MPU实现 智能实时决策
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析




