单片机
返回首页

入门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--;

}

}

}

}

}


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 家用电器遥控器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外开关

  • DS1669数字电位器

  • HA1377 桥式放大器 BCL 电容 17W(汽车音频)

    相关电子头条文章