嵌入式实战(一)| GPIO实验 跑马灯效果实现 寄存器及其代码全解析

news2025/5/24 8:46:28

文章目录

  • 1 GPIO编程用到的寄存器介绍
    • 1.1 PxSEL寄存器
    • 1.2 PxDIR寄存器
    • 1.3 PxINP寄存器
  • 2 按键消抖
    • 2.1 软件消抖
  • 3 经典任务代码解析

硬件图如下
在这里插入图片描述

实际上他们在端口命名的时候进行了分组

如上所示,P和点号之间的我认为他就是代表一个组,用某个寄存器控制,所以有0,1,2组

1 GPIO编程用到的寄存器介绍

1.1 PxSEL寄存器

基本介绍

端口功能选择,用来设置端口为通用I/O还是外设I/O功能

关于这两个功能区别如下

通用I/O功能,可以输出高低电平,在本实验中我们只需要给LED灯高低电平即可,因而设置为通用的

外设I/O功能 一般的外部设备,例如摄像头或者打印机他们具体实现某些功能(拍照或打印文档),单片机要控制这些外部设备,一般的来说单片机的I/O口与这些外设的引脚相连,通过I/O引脚实现对外部设备的控制,让它们完成我们要求的功能

使用方法

PxSEL中的x代表几号端口组

比如上面的按键1KEY1对应的是P0.1 所以就应该控制P0SEL寄存器

那么每一位上面含义呢,对于位位0代表是通用I/O,1代表外设I/O

例如:将P1_0、P1_1、P1_3和P1_4设置成通用I/O,即相应的bit置0

P1SEL &=~0x1B; //0001 1011

注意这里有取反操作,

设0用取反与,设1用或

1.2 PxDIR寄存器

基本介绍

端口方向选择,是输入还是输出

注意这里的输入还是输出都是站在单片机角度的

比如:对于LED灯是单片机输出信号到灯,所以对应端口设置为输出,按键是外部给单片机输入,所以设置为输入

使用方法

PxDIR中的x代表几号端口组

将P1_0、P1_1、P1_3和P1_4设置成输出口,即相应的bit置1

P1DIR |=0x1B; //0001 1101

设置了传输方向为输出后,比如输出给LED灯,然后我们通过在端口设置高电平直接就可以控制灯的亮暗了

例如:

 P1_0=1; P1_1=0;

1.3 PxINP寄存器

基本介绍

当端口设置为输入模式的时候,即上面的PxDIR对应位设置为0的时候,可以进一步设置输入

具体有三种,上拉和下拉和三态

上拉是指单片机的引脚通过一个电阻连接到电源(高电平),当外界没有信号输入到引脚时,引脚被上拉电阻固定在高电平(逻辑值1)。相当于初始给引脚一个高电平

下拉是指单片机的引脚通过一个电阻连接到地(低电平),当外界没有信号输入到引脚时,引脚被下拉电阻固定在低电平(逻辑值0)。相当于初始给引脚一个低电平

三态也称高阻,即I/O引脚既没有上拉到电源,也没有下拉到地,呈现高阻值状态。三态模式一般用于引脚的输出功能,特别当单片机的引脚接在多个设备公用的通信总线上时。当单片机不发送信号时,采用三态工作模式可以保证不干扰其他设备之间的通信。三态模式用于输入引脚时,引脚必须外接其他器件,此时不存在上拉或下拉电阻,还能降低单片机的功耗。

使用方法

P0INP,P1INP寄存器每一位含义如下

在这里插入图片描述

P2INP寄存器每一位含义如下

在这里插入图片描述

可以在输入端口读取电平值

比如

if(P1_2 == 0) //判断按键被按下

2 按键消抖

2.1 软件消抖

最简单的消抖原理,就是当检测到按键状态变化后,先等待一个10ms左右的延时时间,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。

if(SW1 == 0) //判断按键被按下
{
	DelayMS (10); //为消抖进行延时
	if(SW1 == 0 ) //经过延时后按键仍处在按下状态
	{
	...
	while(!SW1); //等待按键松开
	}
}

3 经典任务代码解析

三个LED灯跑马灯效果,采用软件消抖

注意InitKey的初始化函数

/****************************************************************************
* 文 件 名: main.c
* 描    述: 按下按键KEY1控制LED1.LED2.LED3实现跑马灯效果
****************************************************************************/
#include <ioCC2530.h>

typedef unsigned char uchar;
typedef unsigned int  uint;


#define LED1 P1_0       //定义P1.0口为LED1控制端
#define LED2 P1_1       //定义P1.1口为LED2控制端
#define LED3 P1_4       //定义P1.4口为LED3控制端

#define KEY1 P0_1       // P0.1口控制按键KEY1
#define KEY2 P2_0       // P2.0口控制按键KEY2
#define KEY3 P0_7       // P0.7口控制按键KEY3

#define ON      1    
#define OFF     0


/****************************************************************************
* 名    称: DelayMS()
* 功    能: 以毫秒为单位延时,系统时钟不配置时默认为16M(用示波器测量相当精确)
* 入口参数: msec 延时参数,值越大,延时越久
* 出口参数: 无
****************************************************************************/
void DelayMS(uint msec)
{ 
    uint i,j;
    static int DelayCallCount=0;
    
    for (i=0; i<msec; i++)
        for (j=0; j<535; j++);
    DelayCallCount++;
}

/****************************************************************************
* 名    称: LedOnOrOff()
* 功    能: 点亮或熄灭所有LED灯    
* 入口参数: mode为0时LED灯亮  mode为1时LED灯灭
* 出口参数: 无
****************************************************************************/
void LedOnOrOff(uchar mode)
{
    LED1 = mode;
    LED2 = mode;
    LED3 = mode; 
}

/****************************************************************************
* 名    称: InitLed()
* 功    能: 设置LED相应的IO口
* 入口参数: 无
* 出口参数: 无
****************************************************************************/
void InitLed(void)
{

  P1DIR |= 0x01;               //P1.0定义为输出口  
  P1DIR |= 0x02;               //P1.1定义为输出口 
  P1DIR |= 0x10;               //P1.4定义为输出口 
  asm("NOP");
  
  LedOnOrOff(0);  // 使所有LED灯默认为熄灭状态  
}

/****************************************************************************
* 名    称: InitKey()
* 功    能: 设置按键相应的IO口
* 入口参数: 无
* 出口参数: 无
****************************************************************************/
void InitKey(void)
{
  
    P0SEL &= ~0x02;     //设置P0.1为普通IO口  
    P0DIR &= ~0x02;     //按键接在P0.1口上,设P0.1为输入模式 
    P0INP &= ~0x02;     //打开P0.1上拉电阻
    
    P2SEL &= ~0x01;     //设置P2.0为普通IO口
    P2DIR &= ~0x01;     //按键接在P2.0口上,设P2.0为输入模式 
    P2INP &= ~0x01;     //打开P2.0上拉电阻
    
    P0SEL &= ~0x80;     //设置P0.7为普通IO口  
    P0DIR &= ~0x80;     //按键接在P0.7口上,设P0.7为输入模式 
    P0INP &= ~0x80;     //打开P0.7上拉电阻
  
}

/****************************************************************************
* 名    称: KeyScan()
* 功    能: 读取按键状态
* 入口参数: 无
* 出口参数: 0为抬起   1为按键按下
****************************************************************************/
uchar KeyScan_1(void)   //检测按键key1
{
    if (KEY1 == 0)
    {
        DelayMS(10);      //延时10MS去抖
        if (KEY1 == 0)
        {
            while(!KEY1); //松手检测
            return 1;     //有按键按下
        }
    }
    
    return 0;             //无按键按下
}

uchar KeyScan_2(void)   //检测按键key2
{
    if (KEY2 == 0)
    {
        DelayMS(10);      //延时10MS去抖
        if (KEY2 == 0)
        {
            while(!KEY2); //松手检测
            return 1;     //有按键按下
        }
    }
    
    return 0;             //无按键按下
}


uchar KeyScan_3(void)   //检测按键key3
{
    if (KEY3 == 0)
    {
        DelayMS(10);      //延时10MS去抖
        if (KEY3 == 0)
        {
            while(!KEY3); //松手检测
            return 1;     //有按键按下
        }
    }
    
    return 0;             //无按键按下
}

/****************************************************************************
* 程序入口函数
****************************************************************************/
void main(void)
{
    InitLed();		      //设置LED灯相应的IO口
    InitKey();                //设置按键KEY1相应的IO口
    int flow_1=1;             //初始设置
    int flow_2=0;
    int flow_3=0;
    while(1)
    {
        DelayMS(2);
        if(KeyScan_1())
        {
          flow_1=!flow_1;  
          if(flow_1==1)  //判断如果此时flow1按下,则把其余按键置零,防止干扰
            flow_2=0;
            flow_3=0;
        }
        if(KeyScan_2())  
        {
          flow_2=!flow_2; 
          if(flow_2==1)  //判断如果此时flow2按下,则把其余按键置零,防止干扰
            flow_1=0;
            flow_3=0;
        }
        if(KeyScan_3())
        {
          flow_3=!flow_3;  //判断如果此时flow2按下,则把其余按键置零,防止干扰
          if(flow_3==1)  
            flow_1=0;
            flow_2=0;
        }
        //扫描按键当前状态,按下抬起一次改变LED显示效果,在跑马灯效果从左到右,从右到左,与LED2灯闪烁效果间切换
        if (flow_1)    //依次点亮 LED1  LED2 LED3 实现跑马灯效果
        {   LED1 = ON;    //点亮LED1      
            DelayMS(500); 
            LED1 = OFF;   //熄灭LED1 
            LED2 = ON;                
            DelayMS(500); 
            LED2 = OFF;            
            LED3 = ON;           
            DelayMS(500); 
            LED3 = OFF;
        }
        if (flow_2)     //依次点亮 LED3  LED2 LED1 实现跑马灯效果  
        {   LED3 = ON;    //点亮LED1      
            DelayMS(500); 
            LED3 = OFF;   //熄灭LED1 
            LED2 = ON;                
            DelayMS(500); 
            LED2 = OFF;            
            LED1 = ON;           
            DelayMS(500); 
            LED1 = OFF;
        }               
        if (flow_3)     //依次点亮 LED2 实现亮灯是灭灯时长的2倍效果 
        {   LED2 = ON;    //点亮LED1      
            DelayMS(1000); 
            LED2 = OFF;   //熄灭LED1 
            DelayMS(500); 
        }
        
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1356022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

当hashCode相同时,equals是否也相同?

目录 hashCode方法 equals方法 String类的hashCode和equals 用String为例 当hashCode相同时 总结 在Java中&#xff0c;理解对象的这两个基本方法—hashCode和equals对于编码是至关重要的&#xff0c;尤其是在处理集合类如HashMap和HashSet时。然而&#xff0c;一个常见的…

CV必备的15个多尺度模型分享,涵盖特征融合、多尺度预测等4种网络结构

在卷积神经网络中&#xff0c;感受野的大小会影响到模型能够捕捉到的特征的尺度&#xff0c;从而影响模型的性能。因此我们在设计网络时&#xff0c;需要合理地控制感受野的大小。 那么问题来了&#xff1a;怎样才能合理控制&#xff1f; 到目前为止&#xff0c;已有很多学者…

Leetcode11-快乐数(202)

1、题目 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。 如果这个过程 结果为 1…

银行家算法c++

银行家算法 1. 银行家算法1.1 银行算法家的目的1.2 银行算法家的作用2. 设计原理2.1 银行家算法的数据结构2.2 银行家算法介绍2.3 安全性算法 3. 实验要求4. 银行家算法实例5. 完整代码和运行测试5.1 测试结果5.2 完整代码 1. 银行家算法 1.1 银行算法家的目的 银行家算法是避…

奇技淫巧:如何给项目中的RabbitMQ添加总开关

本文主要分享了如何给项目中的RabbitMQ添加总开关&#xff0c;通过简单配置开/关RabbitMQ。 一、需求背景 SpringBoot项目里使用了RabbitMQ&#xff0c;但某些场景下&#xff0c;不希望项目启动时自动检查RabbitMQ连接 例如&#xff1a; 在开发不需要RabbitMQ的功能过程中&…

python的课后练习总结4(for循环)

1&#xff0c;for循环 for 临时变量 in 序列: 重复执行的代码1 重复执行的代码2 ........... 遍历序列 字符串 我是中国人 列表 [‘星期一,星期二,星期三,星期四] 元组 (‘星期一,星期二,星期三,星期四&#xff09; 一&#xff0c;break 终止循环 二&#xff0c;con…

【C初阶——指针2】鹏哥C语言系列文章,基本语法知识全面讲解——指针(2)

崩刃的剑&#xff0c;依旧致命&#xff0c;锈蚀的盾&#xff0c;屹立如初&#xff08;王者荣耀李信&#xff09; 本文由睡觉待开机原创&#xff0c;转载请注明出处。 本内容在csdn网站首发 欢迎各位点赞—评论—收藏 如果存在不足之处请评论留言&#xff0c;共同进步&#xff0…

能翻页的电子图册怎么做

​随着科技的进步&#xff0c;电子图册已经成为了越来越多企业宣传和展示产品的重要工具。相比于传统的纸质图册&#xff0c;电子图册具有更多的优点&#xff0c;如方便携带、易于分享、可交互性强等。那么&#xff0c;如何制作一款能翻页的电子图册呢&#xff1f; 一、确定主题…

INT201各种题型收集

汇总一下 FA 有穷自动机 - RL正则语言 DFA M (Q, Σ, δ, q, F) Q 是有限状态集合&#xff08;Finite Set of States&#xff09;&#xff1a; 这表示自动机中存在一个有限数量的不同状态。每个状态代表了自动机在某个特定时刻的内部状态。这些状态可以用符号或名称表示。 …

基于多反应堆的高并发服务器【C/C++/Reactor】(中)Buffer的创建和销毁

TcpConnection:封装的就是建立连接之后得到的用于通信的文件描述符&#xff0c;然后基于这个文件描述符&#xff0c;在发送数据的时候&#xff0c;需要把数据先写入到一块内存里边&#xff0c;然后再把这块内存里边的数据发送给客户端&#xff0c;除了发送数据&#xff0c;剩下…

内存的基础知识-第四十天

目录 什么是内存&#xff1f;内存的作用 常用的数量单位 指令的工作原理 思考 三种装入方式 绝对装入 可重定位装入&#xff08;静态重定位&#xff09; 动态运行时装入&#xff08;动态重定位&#xff09; 写程序到程序运行 编译和链接 链接的三种方式 本节思维导…

代码随想录27期|Pthon|Day31|贪心算法|理论基础|455.分发饼干|376. 摆动序列|53. 最大子序和

理论基础 首先&#xff0c;贪心算法基本靠“做题感觉”&#xff0c;所以没有规范的总结和做题技巧&#xff0c;只能说见到过之后还能想起来。 一般情况可以看成是对于一个大的问题的子问题的局部最优的求解&#xff0c;然后可以推导出全局的最优。 这个过程没有证明&#xf…

数据库中的几种锁

数据库锁 1.数据库锁的种类 以 mysql innoDB 为例&#xff0c;数据库的锁有 排他锁&#xff0c;共享锁&#xff0c;意向锁&#xff0c;自增锁&#xff0c;间隙锁&#xff0c;锁的范围有包括&#xff0c;行锁&#xff0c;表锁 &#xff0c;区间锁。 从应用研发的视角&#xff…

Gromacs WARNING问题

上述示例中&#xff0c;NA 是对系统净电荷进行中和的阳离子。请根据您的系统特性和仿真需求调整这些值。 总体而言&#xff0c;这个警告是为了提醒您关于电荷中性化的问题&#xff0c;确保您的模拟结果更加物理可信。 收敛性未达到预期精度&#xff1a; 警告指出&#xff0c;优…

普中STM32-PZ6806L开发板(HAL库函数实现-访问多个温度传感器DS18B20)

简介 我们知道多个DS18B20的DQ线是可以被挂在一起的, 也就是一根线上可以访问不同的DS18B20而不会造成数据错乱, 怎么做到的&#xff0c;其实数据手册都有说到&#xff0c; 就是靠64-bit ROM code 进行识别, 也可以理解成Serial Number进行识别, 因为主要差异还是在Serial Numb…

成为一名合格的软件测试工程师,得掌握什么技能?

在这个信息时代&#xff0c;软件行业的需求空前增长&#xff0c;而软件测试工程师作为软件开发过程中的重要角色&#xff0c;也越来越受企业的重视。那么&#xff0c;成为一名合格的软件测试工程师需要掌握什么技能呢&#xff1f;我结合多年的教学经验为大家总结出以下几点。 …

Fast and flexible X-ray tomography using the ASTRA toolbox

使用ASTRA工具箱进行快速灵活的X射线断层扫描 论文链接&#xff1a;http://dX.doi.org/10.1364/OE.24.025129 项目链接&#xff1a;https://astra-toolboX.com/indeX.html Abstract 从一系列投影图像中重建物体&#xff0c;如在计算机断层扫描(CT)中&#xff0c;是许多不同应…

nuxt3 env文件、全局变量处理

有两种方向 通过配置nuxt.config.ts Nuxt提供的钩子函数&#xff0c;实现全局变量的获取 runtimeconfig env文件往runtimeconfig放入内容 useAppConfig 通过env文件配置来获取服务端全局变量&#xff0c;客户端通过vite.define实现 nuxt.config.ts Nuxt钩子 1. runtim…

Unity ab包如何加密

「ab包」全称为 AssetBundle &#xff0c;是Unity提供的一种资源存储压缩包。其中储存了游戏的资源&#xff0c;如图片、模型、纹理、音视频、代码等文件。 由于ab包具有灵活储存、支持热更、包体较小且便于管理等优势&#xff0c;已经成为了市面上主流的游戏资源压缩方式。 …

李沐机器学习系列4---全连接层到卷积

1 从全连接到卷积 1.1 平移不变性 从概率分布的角度来看卷积的定义, f ( τ ) f(\tau) f(τ)是概率密度&#xff0c; g ( t − τ ) g(t-\tau) g(t−τ)是在这个分布下的均值 ( f ∗ g ) ( t ) ∫ − ∞ ∞ f ( τ ) g ( t − τ ) d τ (f*g)(t)\int_{-\infin}^{\infin}f(\t…