单片机CC2530通用I/O端口(一)

文章详细介绍了CC2530单片机的I/O端口配置,包括功能、方向和工作模式寄存器,以及如何使用这些寄存器实现流水灯和按键控制。此外,还讨论了按键的高低电平、抖动处理和软件消抖方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

I/O 端口的基础知识

一、配置功能寄存器(PxSEL)

二、配置方向寄存器(PxDIR)

三、配置工作模式寄存器(PxINP)

I/O 端口的应用

(一)流水灯

main.c

sys_init.c

sys_init.h

运行结果

(二)按键 

1.按键与高低电平(灯的亮灭)

2.按键消抖

(1)按键抖动

(2)按键消抖

(3)软件消抖

(三)按键控制一个LED灯的亮灭

main.c

sys_init.c

sys_init.h

运行结果:

I/O 端口的基础知识

CC2530有40个引脚,21个可编程I/O引脚,其中P0、P1各有8个,P2有5个。

I/O 端口配置寄存器分别为:功能寄存器(PxSEL)、方向寄存器(PxDIR)、工作模式寄存器(PxINP),x表示0,1,2。

例如:如把P2所有端口改成输入。

解题:改成输入,从1到0,与非关系。P2DIR &= ~0xFF。

一、配置功能寄存器(PxSEL)

例如:要求将P0.4改成通用 I/O 口。

解题:外设改成通用,又是一个置零过程,与非关系。

1111 1111这是初始过程,1110 1111这是将P0.4置零。因为4,前面有0,1,2,3(按下标来算,类似数组),所以从后往前数第五个,1该成0。把前半段和后半段分成两个部分,每个部分与初始不同的位,按2的该位下标次方求和,分别填在 0x _ _ 的后两位上。

0+0+0+2.^0=1   0+0+0+0=0

所以,P0SEL &= ~ 0x10。

例2:将P0.4和P0.5设置成外设的 I/O 口。

解题: 0000 0000(初始)0011 0000(设成外设)0->1  => 或 

0+0+2.^0+2.^1=3   0+0+0+0=0

所以,P0SEL  |= 0x30。

二、配置方向寄存器(PxDIR)

例1:将P0.4和P0.5改成输入。

改输入=>置零=> 与非

1111 1111(初始)

1100 1111(改成输入,置零)

0+0+2.^1+2.^0=3  0+0+0+0=0

P0DIR &= ~0x30。

例2:将P1.0和P1.1改成输出。

改输出=> 0->1 =>或关系

0000 0000(初始)

0000 0011(改成输出)

0+0+0+0=0 0+0+2.^1+2.^0=3

P1DIR |= 0x03.

三、配置工作模式寄存器(PxINP)

例1:将P0.4和P0.5设置成三态

0->1 => 或关系

0000 0000(原来)

0011 0000(P0.4和P0.5设置成三态)

0+0+2.^1+2.^0=3 0+0+0+0=0

P0INP |= 0x30。

例2:P2.0和P2.1设置成上拉状态。

以第二张图,2端口0上拉,1下拉。1->0 置零。

P2INP &= ~ 0x03。

例3:设置所有P0端口为上拉输入。

参考本博客第一张图,0三态,1上拉,0->1 => 或关系。

通过另外一种写法

0可以用F替代

P0INP |= 0x80。(由本博客第一张图应该是0x8F,F换成0,得出)。

I/O 端口的应用

(一)流水灯

问题:间隔500ms,依次点亮 LED1,LED2,LED3,不停循环。

思路:先用P0.1,P0.2,P0.3分别控制LED1,LED2,LED3。然后定义一个延时函数,主程序中,定义一个while(1)永真循环,然后循环内按照LED1亮,LED2灭,LED3灭。间隔500ms。LED1灭,LED2亮,LED3灭。间隔500ms。LED1灭,LED2灭,LED3亮。为一次的过程,循环,即实现了LED1,LED2,LED3间隔500ms,依次闪烁,不停循环。

函数需求:初始化函数,流水灯函数(循环),延时函数。

注意:灯 1==灭 ,0==亮。

main.c
#include<ioCC2530.h>
#include"sys_init.h"

void main()
{
       xtal_init();  //晶振初始化函数
       
       Init_LED();  //LED初始化函数
       
       while(1)
       {
       LED_RUN();   //流水灯函数
       }
}

/*系统时钟初始化
-------------------------------------------------------*/
void xtal_init(void)
{
  SLEEPCMD &= ~0x04;              //都上电
  while(!(CLKCONSTA & 0x40));     //晶体振荡器开启且稳定
  CLKCONCMD &= ~0x47;             //选择32MHz晶体振荡器
  SLEEPCMD |= 0x04;
}
/*  xtal_init 放在main.c无 warn,放在sys_init.c有警告  */ 
sys_init.c
#include <ioCC2530.h>
#include"sys_init.h"


void Delay(uint ms) //延时函数
{
    uint i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 535; j++)
            ;
}

void Init_LED() //LED初始化函数
{
    P1SEL &= ~0x13; //初始化P1.0,P1.1,P1.4为通用 I/O 端口,通用(0),外设(1)

    P1DIR |= 0x13; //初始化P1.0,P1.1,P1.4为输出端口,输入(0),输出(1)

    LED1 = 1; //先关灯。灯的亮灭:1表示灭 0表示亮
    LED2 = 1;
    LED3 = 1;
}

void LED_RUN() //流水灯函数
{
    LED1 = ~LED1;
    Delay(500); // 添加分号
    LED2 = ~LED2;
    Delay(500); // 添加分号
    LED3 = ~LED3;
    Delay(500); // 添加分号
}
sys_init.h
#include<ioCC2530.h>
/*----------------------------------------------------------------------------*/
/*                            macro declaration 	                      */
/*----------------------------------------------------------------------------*/
#define LED1    P1_0              //定义LED1为P1_0口控制
#define LED2    P1_1              //定义LED2为P1_1口控制
#define LED3    P1_4              //定义LED3为P1_4口控制

#define uint   unsigned  int
#define uchar  unsigned  char

#define CLKSPD  ( CLKCONCMD & 0x07 )    //getting the clock division factor

void xtal_init();
void Init_LED(); 
void LED_RUN(); 
void Delay(uint ms);
运行结果

(二)按键 

1.按键与高低电平(灯的亮灭)

       按键松开,通过电阻上拉为高电平。按键按下,通过电阻上拉为低电平。即低电平时,灯亮(以按键控制LED灯的亮灭为例)。

2.按键消抖
(1)按键抖动

       机械弹性开关的按键,开关在闭合时不会马上稳定地接通,在断开时不会一下子断开。在闭合或断开瞬间伴随着一系列抖动。

(2)按键消抖

        按键消抖就是为了防止按键抖动。

        按键消抖有硬件消抖软件消抖两种。

(3)软件消抖

基础思想:当电平变化时,延迟一段时间后,再读取电压。

按键松开:端口为0。按键按下:端口为1

(三)按键控制一个LED灯的亮灭

P0.1控制LED1,P0.4控制按键,当按键按下,LED灯取反,则改变了LED灯的亮灭。

main.c
#include<ioCC2530.h>
#include"sys_init.h"

void main()
{
       xtal_init();  //晶振初始化函数
       
       InitLed();   //LED初始化函数
         
       InitKey();     //按键初始化函数
        
       while(1)
       {
            if(KeyScan())   //按键扫描函数
              
              LED1 = ~LED1;  //按键按下则改变LED状态
            
       }
}


/*系统时钟初始化
-------------------------------------------------------*/
void xtal_init(void)
{
  SLEEPCMD &= ~0x04;              //都上电
  while(!(CLKCONSTA & 0x40));     //晶体振荡器开启且稳定
  CLKCONCMD &= ~0x47;             //选择32MHz晶体振荡器
  SLEEPCMD |= 0x04;
}
/*  xtal_init 放在main.c无 warn,放在sys_init.c有警告  */ 
sys_init.c
#include <ioCC2530.h>
#include"sys_init.h"


void Delay(uint ms) //延时函数
{
    uint i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 535; j++)
            ;
}

void InitLed() //LED初始化函数
{
    P0SEL &= ~0x02; //初始化P0.1为通用 I/O 端口,通用(0),外设(1)

    P0DIR |= 0x02; //初始化P0.1为输出端口,输入(0),输出(1)

    LED1 = 1; //先关灯。灯的亮灭:1表示灭 0表示亮
    
}

void InitKey()  //KEY初始化函数
{
    P0SEL |= 0x10;  //初始化P0.4为通用 I/O 端口,通用(0),外设(1)
      
    P0DIR &= ~0x10; //初始化P0.4为输入端口,输入(0),输出(1)
      
    KEY =  0;     //设一开始按键松开,松开(0),按下(1)
}

uchar KeyScan(void)
{
       if(KEY == 1)
       {
         Delay(10);     //延迟10ms防抖动
         
         if(KEY == 1)   //按键确实按下
           
         {
           while(KEY);  //等待按键松开,走完while,表示按键按下且释放
           
           return 1;    //表示按键按下去了
         }
       }
       
       return 0; //无按键按下
}

sys_init.h
#include<ioCC2530.h>
/*----------------------------------------------------------------------------*/
/*                            macro declaration 	                      */
/*----------------------------------------------------------------------------*/
#define LED1    P0_1             //定义LED1为P0.1控制

#define KEY     P0_4             //定义KEY为P0.4口控制


#define uint   unsigned  int
#define uchar  unsigned  char

#define CLKSPD  ( CLKCONCMD & 0x07 )    //getting the clock division factor

void xtal_init();
void InitLed(); 
uchar KeyScan(void);
void Delay(uint ms);
void InitKey();
运行结果:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值