CC2541蓝牙学习——I/O口
2015-04-25 18:39阅读:
学习目标:I/O口的配置,掌握寄存器“PxSEL”和“PxDIR”
CC2541有21个数字I/O引脚,P0、P1 各8个数字I/O端口,P2
5个数字I/O端口。
1.访问模式
| 符号 |
访问模式 |
| R/W |
可读写 |
| R |
只读 |
| R0 |
读0 |
| R1 |
读1 |
| W |
只写 |
| W0 |
写0 |
| W1 |
写1 |
| H0 |
硬件清除 |
| H1 |
硬件设置
|
2.端口寄存器(P0,P1,P2)
| 端口 |
Bit位 |
名称 |
初始化 |
读写 |
描述 |
| P0 |
7:0 |
P0[7:0] |
0XFF |
R/W |
|
端口0,通用I/O端口,可以位寻址。
XDATA
(0x7080).
| P1 |
7:0 |
P1[7:0] |
0XFF |
R/W |
端口1,通用I/O端口,可以位寻址。 XDATA (0x7090). |
| P2 |
7:5 |
--- |
000 |
R0 |
未使用 |
| P2 |
4:0 |
P2[4:0] |
0x1F |
R/W |
端口2,通用I/O端口,可以位寻址。 XDATA (0x70A0).
|
这些引脚可以用作通用的I/O端口,同时通过独立编程还可以作为特殊功能的I/O(例如串口、ADC等),这21个引脚都可以作外部中断源输入口以产生中断,这个不同于普通51单片机,只有P3.2、P3.3两个外部中断源,外部中断功能可以唤醒睡眠模式。I/O口通过独立编程以选择作为数字输入还是数字输出,P0、P1、P2端口既可以字节寻址也可以位操作,其中P1.0和P1.1具备20mA的输出驱动能力,其他所有端口只具备4mA的输出驱动能力,所以P1.0和P1.1可以用来驱动大功率的LED等。
这21个引脚用作输入时,可以设置为上拉、下拉或三态操作模式,其中P1.0和P1.1引脚没有上拉和下拉功能。上拉和下拉功能或三态操作模式由寄存器“PxINP”设置(其中x为端口标号0~2)。注意配置为外设I/O信号的引脚没有上拉/下拉功能,即使外设功能是一个输入
这21个I/O口具体的功能和输入还是输出由功能选择寄存器“PxSEL”和方向寄存器“PxDIR”配置。
注意:复位后,所有引脚默认的模式为:带上拉的输入通用I/O口
3.功能选择寄存器(P0SEL,P1SEL,P2SEL)
| 端口 |
Bit位 |
名称 |
初始化 |
读写 |
描述 |
| P0SEL |
7:0 |
SELP0_[7:0] |
0x00 |
R/W |
P0.7--P0.0的功能选择(0:通用I/O 1:外设功能) |
| P1SEL |
7:0 |
SELP1_[7:0] |
0x00 |
R/W |
P1.7--P1.0的功能选择(0:通用I/O 1:外设功能) |
| P2SEL |
7 |
--- |
0 |
R0 |
未使用 |
| P2SEL |
6 |
PRI3P1 |
0 |
R/W |
端口1外设优先级控制,当PERCFG分配USART0和USART1相同引脚的时候,这些位将确定优先级。0:USART
0 优先; 1:USART 1 优先 |
| P2SEL |
5 |
PRI2P1 |
0 |
R/W |
端口1外设优先级控制,当PERCFG分配USART1和TIMER3相同引脚的时候,这些位将确定优先级。0:USART
1 优先; 1:TIMER 3 优先 |
| P2SEL |
4 |
PRI1P1 |
0 |
R/W |
端口1外设优先级控制,当PERCFG分配TIMER1和TIMER4相同引脚的时候,这些位将确定优先级。0:TIMER
1 优先; 1:TIMER 4 优先 |
| P2SEL |
3 |
PRI0P1 |
0 |
R/W |
端口1外设优先级控制,当PERCFG分配USART0和TIMER1相同引脚的时候,这些位将确定优先级。0:USART
0 优先; 1:TIMER 1 优先 |
| P2SEL |
2:0 |
SELP2_[2:0] |
000 |
R/W |
P2.2--P2.0的功能选择(0:通用I/O 1:外设功能) |
这三个寄存器,P0SEL和P1SEL的每一位控制P0、P1的8个I/O口的功能,P2SEL的低三位控制P2端口的P2.2--P2.0功能,其他高P2SEL
6:3是用来控制端口1外设的优先级的,具体的在后面再说明。
4.方向寄存器(P0DIR,P1DIR,P2DIR)
| 端口 |
Bit位 |
名称 |
初始化 |
读写 |
描述 |
| P0DIR |
7:0 |
DIRP0_[7:0] |
0x00 |
R/W |
P0.7--P0.0的方向(0:输入 1:输出) |
| P1DIR |
7:0 |
DIRP1_[7:0] |
0x00 |
R/W |
P1.7--P1.0的方向(0:输入 1:输出) |
| P2DIR |
7:6 |
PRIP0[1:0] |
00 |
R/W |
端口0外设优先级控制,当PERCFG分配给一些外设相同引脚的时候,这些位将确定优先级。优先级从前到后如下:00:USART
0,USART 1,Timer 1; 01:USART
1,USART 0,Timer 1; 10:Timer 1
channels 0-1,USART 1,USART 0,Timer
1 channels 2-3; 11:Timer 1
channels 2-3,USART 0,USART 1,Timer
1 channels 0-1 |
| P2DIR |
5 |
--- |
0 |
R0 |
未使用 |
| P2DIR |
4:0 |
DIRP2_[4:0] |
00000 |
R/W |
P2.4—P2.0的方向(0:输入 1:输出) |
5.输入模式寄存器(P0INP,P1INP,P2INP)
| 端口 |
Bit位 |
名称 |
初始化 |
读写 |
描述 |
| P0INP |
7:0 |
MDP0_[7:0] |
0x00 |
R/W |
P0.7--P0.0的输入模式: 0:上拉/下拉(具体看PDUP0设置); 1:三态 |
| P1INP |
7:2 |
MDP1_[7:2] |
000000 |
R/W |
P1.7—P1.2的输入模式:0:上拉/下拉(具体看PDUP1设置);1:三态 |
| P1INP |
1:0 |
--- |
00 |
R0 |
未使用 |
| P2INP |
7 |
PDUP2 |
0 |
R/W |
端口2上拉/下拉选择,对所有端口2引脚设置为上拉/下拉输入:0:上拉;1:下拉 |
| P2INP |
6 |
PDUP1 |
0 |
R/W |
端口1上拉/下拉选择,对所有端口1引脚设置为上拉/下拉输入:0:上拉;1:下拉 |
| P2INP |
5 |
PDUP0 |
0 |
R/W |
端口0上拉/下拉选择,对所有端口0引脚设置为上拉/下拉输入:0:上拉;1:下拉 |
| P2INP |
4:0 |
MDP2_[4:0] |
00000 |
R/W |
P2.4—P2.0的输入模式: 0:上拉/下拉(具体看PDUP2设置);1:三态
|
总结:I/O口用做输出口时配置过程
- 选择I/O口功能为通用I/O口
- 配置I/O口方向为输入
例程:LED1~4流水灯
#include
typedef unsigned char uchar;
typedef unsigned int
uint;
#define LED1 P1_0
#define LED2 P1_1
#define LED3 P1_4
#define LED4 P0_1
void InitClock(void)
{
CLKCONCMD &= ~0x40;
//选择32MHz晶振
while(CLKCONSTA & (1<< 6));
//等待时钟稳定
CLKCONCMD &= ~0x47;
//TICKSPD 128分频:250kHz,CLKSPD不分频
}
void InitLED(uchar mode)
{
P1SEL &= ~0x13;
//P1.0,P1.1,P1.4设置为通用I/O口
P1DIR |=
0x13;
//P1.0,P1.1,P1.4设置为输出
P0SEL &= ~0x02;
//P0.1设置为通用I/O口
P0DIR |= 0x02;
//P0.1设置为通用I/O口
LED1 = mode;
//LED灯亮熄控制
LED2 = mode;
LED3 = mode;
LED4 = mode;
}
void Delay1ms(unsigned int uiDelay)
{
unsigned int i,j;
for(i = 0; i < uiDelay; i++)
{
for(j = 0;j < 1322; j++);
}
}
int main(void)
{
InitClock();
//系统时钟初始化,32Mhz
InitLED(0);
//熄灭所有LED灯
while(1)
{
LED1 = !LED1;
Delay1ms(500); //延时500ms
LED2 = !LED2;
Delay1ms(500);
LED3 = !LED3;
Delay1ms(500);
LED4 = !LED4;
Delay1ms(500);
}
}