目录
- 硬知识
- 一、MSP430单片机端口概述
- 二、通用IO端口输出特性
- 三、端口P1和P2
- 1.输入寄存器PxIN
- 2.输出寄存器PxOUT
- 3.方向寄存器PxDIR
- 4.上拉/下拉电阻使能寄存器PxREN
- 5.输出驱动能力调节寄存器PxDS
- 6.功能选择寄存器PxSEL
- 7.中断使能寄存器PxIE
- 8.中断触发边沿选择寄存器PxIES
- 9 .中断标志寄存器PxIFG
- 四、端口P3~P11
- 五、端口的应用
- GPIO API
- GPIO管脚配置
- 处理GPIO中断
- 访问GPIO引脚值
- 上机实战
- 扫描输入
- 外部中断输入
平台:Code Composer Studio 10.3.1
MSP430F5529 LaunchPad™ Development Kit
(MSP‑EXP430F5529LP)
硬知识
一、MSP430单片机端口概述
通用I/O端口是MSP430单片机最重要也是最常用的外设模块。通用I/O端口不仅可以直接用于输入/输出,而且可以为MSP430单片机应用系统提供必要的逻辑控制信号。
MSP430F5xx/6xx系列单片机最多可以提供12个通用I/O端口(P1~P11和PJ),大部分端口有8个引脚,少数端口引脚数少于8个。每个I/O引脚都可以被独立地设置为输入或者输出引脚,并且每个I/O引脚都可以被独立地读取或者写入,所有的端口寄存器都可以被独立地置位或者清零。
P1和P2引脚具有中断能力。从P1和P2端口的各个I/O引脚引入的中断可以独立地被使能,并且被设置为上升沿或者下降沿触发中断。所有P1端口的I/O引脚的中断都来源于同一个中断向量P1IV。同理,P2端口的中断源都来源于另一个中断向量P2IV。
可以对每个独立的端口进行字节访问,或者将两个结合起来进行字访问。端口组合P1和P2、P3和P4、P5和P6、P7和P8可结合起来称为PA、PB、PC和PD端口。当进行字操作写入PA口时,所有的16位数据都被写入这个端口;利用字节操作写入PA端口低字节时,高字节保持不变;利用字节指令写入PA端口的高字节时,低字节保持不变。其他端口也是一样。当写入的数据长度小于端口的最大长度时,那些没有用到的位保持不变。应用这个规则来访问所有端口,除了中断向量寄存器P1IV和P2IV,它们只能进行字节操作。
二、通用IO端口输出特性
MSP430单片机在默认输出驱动(PxDS.y=0,即欠驱动强度)且单片机供电电压VCC为3V条件下,端口低电平和高电平的输出特性分别如下两图所示,其中,电流输入为正,输出为负。
当PxDS.y控制位被配置为1时,即单片机端口被配置为强驱动模式。在强驱动模式下,端口的低电平和高电平输出特性分别如下两图所示。
三、端口P1和P2
端口P1和P2具有输入/输出、中断和外部模块功能,可以通过设置它们各自的9个控制寄存器来实现这些功能。下面所述Px代表P1和P2。
1.输入寄存器PxIN
输入寄存器是CPU扫描I/O引脚信号的只读寄存器,用户不能对其写入,只能通过读取该寄存器的内容获取I/O端口的输入信号,此时引脚的方向必须选定为输入。输入寄存器中某一位为0,表明该位输入为低;某一位为1,表明该位输入为高。
2.输出寄存器PxOUT
该寄存器为I/O端口的输出缓冲寄存器。其内容可以像操作内存数据一样写入,以达到改变I/O口输出状态的目的。在读取时,输出缓存的内容与引脚方向定义无关。改变方向寄存器的内容,输出缓存的内容不受影响。
0:输出为低; 1:输出为高。
3.方向寄存器PxDIR
相互独立的8位分别定义了8个引脚的输入/输出方向。8位在PUC之后都被复位。使用输入或输出功能时,应先定义端口的方向,输入/输出才能满足设计者的要求。作为输入时,只能读;作为输出时,可读可写。
0:输入模式; 1:输出模式。
4.上拉/下拉电阻使能寄存器PxREN
该寄存器的每一位可以使能相应I/O引脚的上拉/下拉电阻。该寄存器需和输出寄存器配合使用,才能完成上拉/下拉电阻的配置。
0:上拉/下拉电阻禁止; 1:上拉/下拉电阻使能。
5.输出驱动能力调节寄存器PxDS
PxDS寄存器的每一位可使相关引脚选择全驱动模式和次驱动模式(减弱驱动能力)。默认的是次驱动模式。
0:次驱动模式; 1:全驱动模式。
6.功能选择寄存器PxSEL
P1和P2端口还有其他片内外设功能,为了减少引脚,将这些功能与芯片外的联系通过复用P1和P2引脚的方式来实现。PxSEL用来选择引脚的I/O端口功能与外围模块功能。
0:选择引脚为普通I/O功能; 1:选择引脚为外围模块功能。
7.中断使能寄存器PxIE
该寄存器的8位与该端口的8个引脚一一对应,其中每一位用以控制相应引脚的中断允许。
8.中断触发边沿选择寄存器PxIES
如果允许Px口的某个引脚中断,还需定义该引脚的中断触发沿。该寄存器的8位分别定义了Px口的8个引脚的中断触发沿。
9 .中断标志寄存器PxIFG
该寄存器有8个标志位,它们含有相应引脚是否有待处理中断的信息,即相应引脚是否有中断请求。如果Px的某个引脚允许中断,同时选择上升沿,则当该引脚发生由低电平向高电平跳变时,PxIFG的相应位就会置位,表明该引脚上有中断事件发生。
四、端口P3~P11
这些端口没有中断能力,其余功能与P1、P2端口一样,能实现输入/输出功能和外围模块功能。每个端口有6个寄存器供用户使用,用户可通过这6个寄存器对它们进行访问和控制。每个端口的6个寄存器分别为:输入寄存器(PxIN)、输出寄存器(PxOUT)、方向选择寄存器(PxDIR)、输出驱动能力调节寄存器(PxDS)、上拉/下拉电阻使能寄存器(PxREN)和功能选择寄存器(PxSEL)。具体用法同P1和P2端口。
五、端口的应用
端口是单片机中最经常使用的外设资源。一般在程序的初始化阶段对端口进行配置。配置时,先配置功能选择寄存器PxSEL,若为I/O端口功能,则继续配置方向寄存器PxDIR;若为输入,则继续配置中断使能寄存器PxIE;若允许中断,则继续配置中断触发沿选择寄存器PxIES。
需要注意的是,P1和P2端口的中断为多源中断,即P1端口的8位共用一个中断向量P1IV,P2端口的8位也共用一个中断向量P2IV。当Px端口上的8个引脚中的任何一个引脚有中断触发时,都会进入同一个中断服务程序。在中断服务程序中,首先应该通过PxIFG判断是哪一个引脚触发的中断,再执行相应的程序,最后还要用软件清除相应的PxIFG标志位。
GPIO API
GPIO APl被分成三组功能:
处理配置GPIO引脚的功能,
处理中断的功能,
以及访问引脚值的功能。
GPIO管脚配置
GPIO_setAsOutputPin(uint8_t selectedPort, uint16_t selectedPins);
GPIO_setAsInputPin(uint8_t selectedPort, uint16_t selectedPins);
GPIO_setAsInputPinWithPullDownResistor(uint8_t selectedPort, uint16_t selectedPins);
GPIO_setAsInputPinWithPullUpResistor(uint8_t selectedPort, uint16_t selectedPins);
GPIO_setDriveStrength(uint8_t selectedPort, uint16_t selectedPins, uint8_t
driveStrength);
GPIO_setAsPeripheralModuleFunctionOutputPin(uint8_t selectedPort, uint16_t
selectedPins);
GPIO_setAsPeripheralModuleFunctionInputPin(uint8_t selectedPort, uint16_t
selectedPins);
selectedPort
//is the selected port. Valid values are:
GPIO_PORT_P1
GPIO_PORT_P2
GPIO_PORT_P3
GPIO_PORT_P4
GPIO_PORT_P5
GPIO_PORT_P6
GPIO_PORT_P7
GPIO_PORT_P8
GPIO_PORT_P9
GPIO_PORT_P10
GPIO_PORT_P11
GPIO_PORT_PA
GPIO_PORT_PB
GPIO_PORT_PC
GPIO_PORT_PD
GPIO_PORT_PE
GPIO_PORT_PF
GPIO_PORT_PJ
selectedPins
/*
is the specified pin in the selected port. Mask value is the logical OR of any of
the following:
*/
GPIO_PIN0
GPIO_PIN1
GPIO_PIN2
GPIO_PIN3
GPIO_PIN4
GPIO_PIN5
GPIO_PIN6
GPIO_PIN7
GPIO_PIN8
GPIO_PIN9
GPIO_PIN10
GPIO_PIN11
GPIO_PIN12
GPIO_PIN13
GPIO_PIN14
GPIO_PIN15
GPIO_PIN_ALL8
GPIO_PIN_ALL16
driveStrength
//specifies the drive strength of the pin Valid values are:
GPIO_REDUCED_OUTPUT_DRIVE_STRENGTH
GPIO_FULL_OUTPUT_DRIVE_STRENGTH
处理GPIO中断
GPIO_enableInterrupt(uint8_t selectedPort, uint16_t selectedPins);
GPIO_disableInterrupt(uint8_t selectedPort, uint16_t selectedPins);
GPIO_clearInterrupt(uint8_t selectedPort, uint16_t selectedPins);
GPIO_getInterruptStatus(uint8_t selectedPort, uint16_t selectedPins);
GPIO_selectInterruptEdge(uint8_t selectedPort, uint16_t selectedPins, uint8_t
edgeSelect);
edgeSelect
//specifies what transition sets the interrupt flag Valid values are:
GPIO_HIGH_TO_LOW_TRANSITION
GPIO_LOW_TO_HIGH_TRANSITION
访问GPIO引脚值
GPIO_setOutputHighOnPin(uint8_t selectedPort, uint16_t selectedPins);
GPIO_setOutputLowOnPin(uint8_t selectedPort, uint16_t selectedPins);
GPIO_toggleOutputOnPin(uint8_t selectedPort, uint16_t selectedPins);
GPIO_getInputPinValue(uint8_t selectedPort, uint16_t selectedPins);
上机实战
扫描输入
用户按键为P2.1、P1.1,LED为P4.7、P1.0
将P2.1设为内部上拉输入,P1.0设为输出,当按下S1时,反转LED1
GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P2, GPIO_PIN1);GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);while(1){if(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1)){delay_ms(20);if(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1)){GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);while(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1));}}}
整个main文件为
#include "driverlib.h"#define MCLK_IN_HZ 25000000#define delay_us(x) __delay_cycles((MCLK_IN_HZ/1000000*(x)))
#define delay_ms(x) __delay_cycles((MCLK_IN_HZ/1000*(x)))int main(void)
{WDT_A_hold(WDT_A_BASE);GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);UCS_turnOnXT2 (UCS_XT2_DRIVE_4MHZ_8MHZ);PMM_setVCore(PMM_CORE_LEVEL_3);UCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);UCS_initFLLSettle(25000, 50);UCS_initClockSignal(UCS_MCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P2, GPIO_PIN1);GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);while(1){if(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1)){delay_ms(20);if(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1)){GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);while(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1));}}}
}
按下S1,LED1成功反转。
外部中断输入
GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P2, GPIO_PIN1);//P2.1 interrupt enabledGPIO_enableInterrupt(GPIO_PORT_P2, GPIO_PIN1); //使能中断//P2.1 Hi/Lo edgeGPIO_selectInterruptEdge(GPIO_PORT_P2, GPIO_PIN1, GPIO_HIGH_TO_LOW_TRANSITION); //设置中断类型//P2.1 IFG clearedGPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN1); //清除中断标志位__bis_SR_register(GIE); //启用可屏蔽中断while(1){}
//******************************************************************************
//
//This is the PORT2_VECTOR interrupt vector service routine
//
//******************************************************************************
#pragma vector=PORT2_VECTOR // P2口中断源
__interrupt
void Port_2 (void) // 声明一个中断服务程序,名为Port_2()
{if(GPIO_getInterruptStatus(GPIO_PORT_P2, GPIO_PIN1)){delay_ms(20);if(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1)){//P1.0 = toggleGPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);while(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1));}//P2.1 IFG clearedGPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN1);}
}
经烧录检验,外部中断输入配置成功。