实际上他们在端口命名的时候进行了分组
如上所示,P和点号之间的我认为他就是代表一个组,用某个寄存器控制,所以有0,1,2组
基本介绍
端口功能选择,用来设置端口为通用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用或
基本介绍
端口方向选择,是输入还是输出
注意这里的输入还是输出都是站在单片机角度的
比如:对于LED灯是单片机输出信号到灯,所以对应端口设置为输出,按键是外部给单片机输入,所以设置为输入
使用方法
PxDIR中的x代表几号端口组
将P1_0、P1_1、P1_3和P1_4设置成输出口,即相应的bit置1
P1DIR |=0x1B; //0001 1101
设置了传输方向为输出后,比如输出给LED灯,然后我们通过在端口设置高电平直接就可以控制灯的亮暗了
例如:
P1_0=1; P1_1=0;
基本介绍
当端口设置为输入模式的时候,即上面的PxDIR对应位设置为0的时候,可以进一步设置输入
具体有三种,上拉和下拉和三态
上拉是指单片机的引脚通过一个电阻连接到电源(高电平),当外界没有信号输入到引脚时,引脚被上拉电阻固定在高电平(逻辑值1)。相当于初始给引脚一个高电平
下拉是指单片机的引脚通过一个电阻连接到地(低电平),当外界没有信号输入到引脚时,引脚被下拉电阻固定在低电平(逻辑值0)。相当于初始给引脚一个低电平
三态也称高阻,即I/O引脚既没有上拉到电源,也没有下拉到地,呈现高阻值状态。三态模式一般用于引脚的输出功能,特别当单片机的引脚接在多个设备公用的通信总线上时。当单片机不发送信号时,采用三态工作模式可以保证不干扰其他设备之间的通信。三态模式用于输入引脚时,引脚必须外接其他器件,此时不存在上拉或下拉电阻,还能降低单片机的功耗。
使用方法
P0INP,P1INP寄存器每一位含义如下
P2INP寄存器每一位含义如下
可以在输入端口读取电平值
比如
if(P1_2 == 0) //判断按键被按下
最简单的消抖原理,就是当检测到按键状态变化后,先等待一个10ms左右的延时时间,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。
if(SW1 == 0) //判断按键被按下
{
DelayMS (10); //为消抖进行延时
if(SW1 == 0 ) //经过延时后按键仍处在按下状态
{
...
while(!SW1); //等待按键松开
}
}
三个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);
}
}
}