硬件图如下
实际上他们在端口命名的时候进行了分组
如上所示,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
注意这里有取反操作,
设0用取反与,设1用或
1.2 PxDIR寄存器
基本介绍
端口方向选择,是输入还是输出
注意这里的输入还是输出都是站在单片机角度的
比如:对于LED灯是单片机输出信号到灯,所以对应端口设置为输出,按键是外部给单片机输入,所以设置为输入
使用方法
PxDIR中的x代表几号端口组
将P1_0、P1_1、P1_3和P1_4设置成输出口,即相应的bit置1
设置了传输方向为输出后,比如输出给LED灯,然后我们通过在端口设置高电平直接就可以控制灯的亮暗了
例如:
1.3 PxINP寄存器
基本介绍
当端口设置为输入模式的时候,即上面的PxDIR对应位设置为0的时候,可以进一步设置输入
具体有三种,上拉和下拉和三态
上拉是指单片机的引脚通过一个电阻连接到电源(高电平),当外界没有信号输入到引脚时,引脚被上拉电阻固定在高电平(逻辑值1)。相当于初始给引脚一个高电平
下拉是指单片机的引脚通过一个电阻连接到地(低电平),当外界没有信号输入到引脚时,引脚被下拉电阻固定在低电平(逻辑值0)。相当于初始给引脚一个低电平
三态也称高阻,即I/O引脚既没有上拉到电源,也没有下拉到地,呈现高阻值状态。三态模式一般用于引脚的输出功能,特别当单片机的引脚接在多个设备公用的通信总线上时。当单片机不发送信号时,采用三态工作模式可以保证不干扰其他设备之间的通信。三态模式用于输入引脚时,引脚必须外接其他器件,此时不存在上拉或下拉电阻,还能降低单片机的功耗。
使用方法
P0INP,P1INP寄存器每一位含义如下
P2INP寄存器每一位含义如下
可以在输入端口读取电平值
比如
2 按键消抖
2.1 软件消抖
最简单的消抖原理,就是当检测到按键状态变化后,先等待一个10ms左右的延时时间,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。
1 2 3 4 5 6 7 8 9
| if(SW1 == 0) //判断按键被按下 { DelayMS (10); //为消抖进行延时 if(SW1 == 0 ) //经过延时后按键仍处在按下状态 { ... while(!SW1); //等待按键松开 } }
|
3 经典任务代码解析
三个LED灯跑马灯效果,采用软件消抖
注意InitKey的初始化函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
#include <ioCC2530.h>
typedef unsigned char uchar; typedef unsigned int uint;
#define LED1 P1_0 #define LED2 P1_1 #define LED3 P1_4
#define KEY1 P0_1 #define KEY2 P2_0 #define KEY3 P0_7
#define ON 1 #define OFF 0
void DelayMS(uint msec) { uint i,j; static int DelayCallCount=0; for (i=0; i<msec; i++) for (j=0; j<535; j++); DelayCallCount++; }
void LedOnOrOff(uchar mode) { LED1 = mode; LED2 = mode; LED3 = mode; }
void InitLed(void) {
P1DIR |= 0x01; P1DIR |= 0x02; P1DIR |= 0x10; asm("NOP"); LedOnOrOff(0); }
void InitKey(void) { P0SEL &= ~0x02; P0DIR &= ~0x02; P0INP &= ~0x02; P2SEL &= ~0x01; P2DIR &= ~0x01; P2INP &= ~0x01; P0SEL &= ~0x80; P0DIR &= ~0x80; P0INP &= ~0x80; }
uchar KeyScan_1(void) { if (KEY1 == 0) { DelayMS(10); if (KEY1 == 0) { while(!KEY1); return 1; } } return 0; }
uchar KeyScan_2(void) { if (KEY2 == 0) { DelayMS(10); if (KEY2 == 0) { while(!KEY2); return 1; } } return 0; }
uchar KeyScan_3(void) { if (KEY3 == 0) { DelayMS(10); if (KEY3 == 0) { while(!KEY3); return 1; } } return 0; }
void main(void) { InitLed(); InitKey(); 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) flow_2=0; flow_3=0; } if(KeyScan_2()) { flow_2=!flow_2; if(flow_2==1) flow_1=0; flow_3=0; } if(KeyScan_3()) { flow_3=!flow_3; if(flow_3==1) flow_1=0; flow_2=0; } if (flow_1) { LED1 = ON; DelayMS(500); LED1 = OFF; LED2 = ON; DelayMS(500); LED2 = OFF; LED3 = ON; DelayMS(500); LED3 = OFF; } if (flow_2) { LED3 = ON; DelayMS(500); LED3 = OFF; LED2 = ON; DelayMS(500); LED2 = OFF; LED1 = ON; DelayMS(500); LED1 = OFF; } if (flow_3) { LED2 = ON; DelayMS(1000); LED2 = OFF; DelayMS(500); } } }
|