今天将要学习关于按键相关的两个点,一个是按键的输入,另一个是外部中端。话不多说进入今天的正题:

一、按键的输入

今天我们想要实现的是利用两个按键来控制板子上的LED的亮灭。当第一个按键按下时LED点亮,当另一个按键按下时LED关闭。要实现的功能清除了,接下来让我们来看看原理图(在一中有我黏贴的原理图)。在原理图中,查看两个按键所连接的引脚,在我的板子中是PC1和PC13,同时需要查看两个按键所连接的另一端连接的GND还是vcc,一会用来判断按键是否被按下。至于LED的开关在上一讲中已经讲过了。

下面就是迫不及待的源代码了:

#include<stm32f10x_rcc.h>
#include<stm32f10x_gpio.h>void Config_Key(void)
{GPIO_InitTypeDef gpio_struct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);gpio_struct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_13;gpio_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOC,&gpio_struct);
}void Config_Light(void)
{GPIO_InitTypeDef gpio_struct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);gpio_struct.GPIO_Pin = GPIO_Pin_8;gpio_struct.GPIO_Mode = GPIO_Mode_Out_PP;gpio_struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&gpio_struct);
}int KeyScan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == 0){return 1;}if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == 1){return 0;}return 0;
}int main()
{Config_Key();Config_Light();GPIO_SetBits(GPIOA,GPIO_Pin_8);while(1){if(KeyScan(GPIOC,GPIO_Pin_1) == 1){GPIO_ResetBits(GPIOA,GPIO_Pin_8);}if(KeyScan(GPIOC,GPIO_Pin_13) == 1){GPIO_SetBits(GPIOA,GPIO_Pin_8);}}
}

我们分函数模块来分析一下代码:

void Config_Key(void)
{GPIO_InitTypeDef gpio_struct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);gpio_struct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_13;gpio_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOC,&gpio_struct);
}

按键所连接的GPIO端口的配置,同样的定义GPIO的结构体变量gpio_struct同时开启端口C的时钟。接下来就是对结构变量中元素进行配置,首先两个按键的引脚所连接的为PC1和PC13,所以GPIO_Pin的值如上设置。因为读取按键的状态所以将引脚的模式设置为浮空输入。GPIO_Speed变量不需要进行配置。最后将配置应用到端口C上。

LED灯的配置,上节已经配置过了。

接下来是本节的重点按键扫描:

int KeyScan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == 0){return 1;}if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == 1){return 0;}return 0;
}

着重分析该函数,函数的返回类型是整型,返回0或者1.当返回1时表示按键按下,当按下0时表示按键没有被按下。函数中的形参有两个,分别为端口和引脚(这个地方可以去函数调用的地方看一下就会很清楚了)。接下来闪亮登场的是有标准库提供的函数GPIO_ReadInputDataBit(),两个参数分别为端口、引脚和KeyScan()传入的参数一致,该函数用来读取某个端口,某个引脚的电平高低,高为1,低为0.最后就是在主函数中各个函数的调用以及一个简单的逻辑。

二、按键作为外部中端的输入源

首先会51的一定明白中断的含义,可能在32不会实施。在51中简单粗暴,打开中断允许位,设置触发方式,最后书写中断服务函数即发生中断所执行的代码。在32中51中复杂了许多,刚开始感觉WTF,怎么和51比起来难了这么多。但这并不影响我们去掌握它。流程和51大致相似,先是配置,然后设置触发方式,最后是中断服务函数。说了这么多废话,赶紧上源代码:

#include<stm32f10x.h>
#include<stm32f10x_rcc.h>
#include<stm32f10x_gpio.h>
#include<stm32f10x_exti.h>void Config_Light(void)
{GPIO_InitTypeDef gpio_struct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);gpio_struct.GPIO_Pin = GPIO_Pin_8;gpio_struct.GPIO_Mode = GPIO_Mode_Out_PP;gpio_struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&gpio_struct);
}void Config_NVIC(void)
{NVIC_InitTypeDef nvic_struct;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);nvic_struct.NVIC_IRQChannel = EXTI1_IRQn;nvic_struct.NVIC_IRQChannelPreemptionPriority = 1;nvic_struct.NVIC_IRQChannelSubPriority = 1;nvic_struct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_struct);nvic_struct.NVIC_IRQChannel = EXTI15_10_IRQn;nvic_struct.NVIC_IRQChannelPreemptionPriority = 2;nvic_struct.NVIC_IRQChannelSubPriority = 1;nvic_struct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_struct);
}void Config_Exti(void)
{GPIO_InitTypeDef gpio_struct;EXTI_InitTypeDef exti_struct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);Config_NVIC();gpio_struct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_13;gpio_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOC,&gpio_struct);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource1);exti_struct.EXTI_Line = EXTI_Line1;exti_struct.EXTI_Mode = EXTI_Mode_Interrupt;exti_struct.EXTI_Trigger = EXTI_Trigger_Rising_Falling;exti_struct.EXTI_LineCmd = ENABLE;EXTI_Init(&exti_struct);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13);exti_struct.EXTI_Line = EXTI_Line13;exti_struct.EXTI_Mode = EXTI_Mode_Interrupt;exti_struct.EXTI_Trigger = EXTI_Trigger_Rising_Falling;exti_struct.EXTI_LineCmd = ENABLE;EXTI_Init(&exti_struct);
}int main()
{Config_Light();Config_Exti();while(1);
}void EXTI1_IRQHandler()
{if(EXTI_GetITStatus(EXTI_Line1) != RESET){GPIO_ResetBits(GPIOA,GPIO_Pin_8);EXTI_ClearITPendingBit(EXTI_Line1);}
}void EXTI15_10_IRQHandler()
{if(EXTI_GetITStatus(EXTI_Line13) != RESET){GPIO_SetBits(GPIOA,GPIO_Pin_8);EXTI_ClearITPendingBit(EXTI_Line13);}
}

接下来,让我们化作一个小小芯片,身心体会配置过程。

void Config_NVIC(void)
{NVIC_InitTypeDef nvic_struct;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);nvic_struct.NVIC_IRQChannel = EXTI1_IRQn;nvic_struct.NVIC_IRQChannelPreemptionPriority = 1;nvic_struct.NVIC_IRQChannelSubPriority = 1;nvic_struct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_struct);nvic_struct.NVIC_IRQChannel = EXTI15_10_IRQn;nvic_struct.NVIC_IRQChannelPreemptionPriority = 2;nvic_struct.NVIC_IRQChannelSubPriority = 1;nvic_struct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_struct);
}

无论我们使用哪种中断我们可能都无法逃离这段代码。这段代码主要用来配置某个中断通道的优先级,以及中断通道的使能。类似于51的中断标志位使能。(理解不一定准确)

接下来实触发方式的设置:

void Config_Exti(void)
{GPIO_InitTypeDef gpio_struct;EXTI_InitTypeDef exti_struct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);Config_NVIC();gpio_struct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_13;gpio_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOC,&gpio_struct);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource1);exti_struct.EXTI_Line = EXTI_Line1;exti_struct.EXTI_Mode = EXTI_Mode_Interrupt;exti_struct.EXTI_Trigger = EXTI_Trigger_Rising_Falling;exti_struct.EXTI_LineCmd = ENABLE;EXTI_Init(&exti_struct);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13);exti_struct.EXTI_Line = EXTI_Line13;exti_struct.EXTI_Mode = EXTI_Mode_Interrupt;exti_struct.EXTI_Trigger = EXTI_Trigger_Rising_Falling;exti_struct.EXTI_LineCmd = ENABLE;EXTI_Init(&exti_struct);
}

需要开启外部中断时钟RCC_APB2Periph_AFIO。两个按键引脚设置为输入模式利用函数GPIO_EXTILineConfig()来选择要作为中断输入的引脚,接下来在中断配置结构体中EXTI_Line用来设置中断源,EXTI_Mode设置是触发中断还是事件,此处可以直接设成中断,其他以后会慢慢遇到理解。EXTI_Trigger用来设置触发方式,上升沿,下降沿,边沿触发等三种模式,使能该中断源。最后初始化中断配置应用。

最后书写中断服务函数:

void EXTI1_IRQHandler()
{if(EXTI_GetITStatus(EXTI_Line1) != RESET){GPIO_ResetBits(GPIOA,GPIO_Pin_8);EXTI_ClearITPendingBit(EXTI_Line1);}
}void EXTI15_10_IRQHandler()
{if(EXTI_GetITStatus(EXTI_Line13) != RESET){GPIO_SetBits(GPIOA,GPIO_Pin_8);EXTI_ClearITPendingBit(EXTI_Line13);}
}

在中断服务函数中利用EXTI_GetITStatus()函数来得到中断标志位状态,当状态不为RESET时,中断触发成功,执行相关的操作,最后记得清楚中断标志位。利用库提供的函数EXTI_ClearITPendingBit()来清楚中断标志位,然后退出中断服务函数,等待下次触发进入。

受水平所限,很多地方没有分析清楚,内心实在惶恐。

STM32----摸石头过河系列(二)相关推荐

  1. oCPC实践录 | 摸石头过河,oCPC先跑起来再说

    oCPC才开始的实践基本上是摸着石头过河,不断测试实验.不过也可以参考已有的oCPC产品设计,oCPC首要需要解决的是转化目标和转化数据. 在解决转化数据之前,可以先看一下申探社:深入互联网广告中的出 ...

  2. 58同城如何摸石头过河?

    本文转自:http://www.huxiu.com/article/4397/1.html 这家典型"鼠标+水泥".不愿复制Cragslist模式的创业公司,摸爬滚打间的经验教训 ...

  3. STM32----摸石头过河系列(八)

    在STM32中定时器(TIM)是很重要的外设,具有相当多的作用,并且用法多样,内容多.今天来分析一下定时器的理论知识,没有实例. 在STM32中定时可以分为三类:基本定时器.通用定时器.高级定时器. ...

  4. STM32----摸石头过河系列(一)

    在学习stm32之前,我较为熟练的掌握了51单片机的开发,可以运用51中的输入.输出,以及定时器.中断等.今天第一天,学习stm32点亮LED灯. 在本次学习中使用的是stm32f103RC系列单片机 ...

  5. STM32----摸石头过河系列(六)

    今天了解一下ADC,stm32中的模数转换利用的是逐次逼近的方法,这个当时在考研时特别熟,现在又忘了,又去问了一下万能的百度.先是多少了解一下这个转换过程,在32的开发过程中用不到,但毕竟从事这个的, ...

  6. STM32----摸石头过河系列(四)

    今天分析STM32一个相当重要的外设--串口,在我使用的这款单片机中有三个串口分别为USART1,USART2,USART3.其中USART1挂载在总线APB2上,USART2,3挂载在APB1上.这 ...

  7. 中台,都他妈被你们说糊涂了,文内才是正宗解释,别摸石头过河了,石头早就有了

    (1)我们先说说技术架构分层 我们按技术架构通常是这样的: 1.UI交互层:Windows UI.PC Web UI.移动App UI.微信小程序UI.摄像头视觉识别人机界面.语音交互人机界面 2.逻 ...

  8. STM32----摸石头过河系列(七)

    今天练习了32中的SysTick定时器,通常叫做滴答定时器.定时器的作用,用过51的想必都知道.定时器主要用来处理一些周期性的,时间间隔固定的事件.同时定时器也可以用来得到一个事件所耗费的时间.下面来 ...

  9. STM32----摸石头过河系列(五)

    今天总结一下DMA(Direct Memory Access,直接存储器存储),在以往我们从串口读取数据到内存的流程是,cpu通过串口读取导数据,然后CPU再将数据写入固定的内存.这种读取方式占用了大 ...

最新文章

  1. python函数手册68_直接在python中检索68个内置函数?
  2. [公告] TechNet / MSDN 经理人博客上周移机整合暂断
  3. javascript:jquery.history.js使用方法
  4. 【四种解法】剑指 Offer 39. 数组中出现次数超过一半的数字
  5. 在centOS7中装mysql_在 CentOS7 上安装 MySQL5.7
  6. 学会阅读硬件的原理图、数据手册大全
  7. 垃圾收集算法,垃圾收集器_垃圾收集器准则和提示
  8. “四方定理”--蓝桥杯
  9. bzoj 1024 [SCOI2009]生日快乐——模拟
  10. 卷积为什么如此强大?理解深度学习中的卷积
  11. TypeScript 类(Class)
  12. 数据可视化之单属性(字段)
  13. Leetcode每日一题:53.maximum-subarray(最大子序和)
  14. [Scikit-learn教程] 03.02 文本处理:分类与优化
  15. linux 常用查看日志命令--more 命令
  16. Phython是什么?
  17. Excel如何删除指定区域中重复值只保留一个
  18. em模型补缺失值_缺失值的四种处理方法
  19. 典藏推荐:《乱世佳人》(《飘》)
  20. 给表格加上横向、纵向滚动条并对滚动条进行美化

热门文章

  1. 大规模异构数据并行处理系统的设计、实现与实践
  2. 2016年《大数据》高被引论文Top10
  3. 作者:周园春(1975-),男,博士,中国科学院计算机网络信息中心研究员、博士生导师...
  4. 作者:石磊,男,北京金信网银金融信息服务有限公司互联网金融行业数据分析师。...
  5. 《大数据》2015年第2期“动态”——大数据发现银行贷款风险
  6. 贪心的Mixing Milk(洛谷P1208题题解,Java语言描述)
  7. 好程序员web前端分享详细了解JavaScript函数
  8. CISO的真正挑战:密码管理、IoT安全合规性
  9. 《Python程序设计》——1.2 程序开发周期
  10. 20145223 杨梦云 《网络对抗》shellcode实验+return-to-libc实验