2.1 MSP430 GPIO概述
通用输入/输出接口(General Purpose Input/Output,简称GPIO)是单片机通过引脚来控制或者采集外部电路的接口,是单片机最基础的功能之一。
不同型号的MSP430可以提供一个或者多个8位I/O口。一般来说引脚越多的芯片提供的I/O口也越多。每8位I/O口会被分为一组(port),在每组当中再给每位编号(bit)。例如Port1中的第一位I/O口就命名为P1.0。
#define BIT0 (0x0001)
#define BIT1 (0x0002)
#define BIT2 (0x0004)
#define BIT3 (0x0008)
#define BIT4 (0x0010)
#define BIT5 (0x0020)
#define BIT6 (0x0040)
#define BIT7 (0x0080)
那么P1DIR = 0x81就可以改写为P1DIR = BIT0 + BIT7;这样就不用每次都将想要写入寄存器的值换算成16进制了。
3)另外图中的 MSP430wareexample是调用了MSP430驱动库来实现同样的功能。驱动库中提供了一个函数GPIO_setAsInputPin()来将I/O口配置为输出。
2.2.2 输出寄存器(PxOUT)
利用方向寄存器将I/O口配置为输出以后,就可以通过写输出寄存器PxOUT来给端口赋值了。例如要将P1.7设为高电平,直接写
P1OUT|= 0x80;
或者
P1OUT |= BIT7;
就可以了。
P1DIR &=~ BIT7; // Set P1.7 as input
P1OUT |= BIT7; // Set pull-up resistor for P1.7
P1REN |= BIT7; // Enable internal pull-up resistor
编译并下载程序,开始运行后按下S2按键,如果一切正常,绿色LED会亮起,松开S2后绿色LED会熄灭。
思考题:本实验中按键的状态检测是通过不断读取P1IN来实现的,这种方式叫做轮询。轮询是一种比较消耗CPU资源的方式,因为CPU需要不断读取GPIO的状态,就好像主人在家等快递,但家里没有门铃(也不能敲门),主人只能一遍又一遍的打开门看看外面有没有人。有没有另一种方式能够帮主人节省精力呢?下一章我们将介绍中断,中断就好像装上了门铃,可以提醒主人有人来了,大大节省主人(也就是单片机CPU)的精力和时间。
2.3 GPIO引脚复用
现在的单片机集成的功能越来越多,例如串口、定时器、ADC等,这些外设都需要引脚,但如果为每个外设都留下单独的引脚,单片机的引脚数量将会巨大,这既不经济也不实用。另外这些外设并一定会同时使用,因此单片机提供了引脚复用的功能,将GPIO和其他外设放在一个引脚上,使用的时候通过寄存器来选择用哪一个功能。
例如下图中,MSP430G2553的引脚8,它既可以作为GPIO模块中的P2.0,也可以作为定时器的TA1.0端口。其他引脚也是类似。具体每一个引脚有哪些功能请见MSP430G2553的datasheet。
P1DIR &=~ BIT0; // Set P1DIR
P1SEL |= BIT0; // Set P1SEL and P1SEL2
P1SEL2 ^=~ BIT0;
2.4 GPIO实验
下面我们将用两个实验来熟悉GPIO的两种基本应用场景——LED闪烁和读取按键。这两个应用场景分别对应GPIO的输出和输入,也是最经典的应用。通过这两个实验也可以进一步熟悉单片机GPIO的寄存器操作。
在实验开始之前需要清楚MSP430G2 LaunchPad板上LED和按键的硬件电路。板上共有2个LED灯和2个按键,P1.0连接红色LED,P1.6连接绿色LED。这两个LED都是通过跳线帽连接的,如果想断开LED,只需拔掉跳线帽即可。P1.3连接左边的按键,这个按键可以由用户自定义功能。右边的按键是Reset键,按下之后单片机会复位。
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
// Add your code below to initialize the GPIO
// End of your code
3)LED闪烁
初始化完成后,就要通过编程让LED开始闪烁了。闪烁的过程是通过一个while循环完成的,每个循环中先将LED对应I/O口的电平置高,再置低,中间添加延时就可以实现LED闪烁。程序中已经设置好了延时的时间,请自行添加改变GPIO状态的语句。如果一切正常,代码执行后绿色LED将以1s左右为周期闪烁。
while(1)
{
// Add your code below to set P1.6 high
// End of your code
_delay_cycles(500000);
//
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』