学习了MSP430单片机的一些基础操作,如I/O口和看门狗的使用,以及低功耗模式。
1. 逻辑操作
I/O和寄存器需要涉及到很多运算符的操作,先简要复习一下C语言中运算符的使用方法做个备忘。
与、& 、AND:1 & 1 = 1,1 & 0 = 0
,有0为0
或、| 、OR:1 | 1 = 1
,1 | 0 = 1
,有1为1
异或、^ 、XOR:1 ^ 0 = 1,0 ^ 1 = 1, 1 ^ 1 = 0, 0 ^ 0 = 0
,不同为1
取反、~ ** : ~ 1 = 0, ~ 0 = 1
, **01互换
2. GPIO口概述
在前面的示例程序中我们发现对单片机进行编程实际上就是改写寄存器的值。单片机各个外设的功能其实是预先固定的,而寄存器就像是这些功能的控制接口,通过改变寄存器的值就可以在这些功能中进行选择。还有一些寄存器直接对应引脚的状态,例如GPIO的输入/输出寄存器。像以下语句:
P1OUT = 0x01
;这句话其实就是赋值给P1OUT这个寄存器,这个寄存器是GPIO的输出寄存器,赋值之后对应引脚的输出状态就会发生改变。
P1OUT寄存器共有8位,分别是从P1.0-P1.7。要给这个寄存器赋值,其实就是写入一个8位的二进制数值,例如00000001。在C语言中,为了尽量精简代码,一般把这个8位二进制数换算成2位16进制数,前面加上“0x”表示这是一个16进制的值。这样二进制的00000001也可以表示为0x01,那么上面一句P1OUT =0x01实际上是把P1.0赋值为1,P1.1-P1.7赋值为0。
单片机最基础的功能是通过引脚来控制或者采集外部电路的接口,这是我们知道的单片机最基础的功能。
不同的单片机可以提供一个或多个8位I/O口,引脚的数量越多,芯片提供的I/O口就越多,相应的功能也更丰富一点;
例如 8051 提供了 P0、P1、P2、P3这四组IO:
I/O口 | 引脚 | 第一功能 | 第二功能 |
---|---|---|---|
P0口 | P0.0~P0.7 | 输入与输出 | 分时的传送地址低8位与数据线 |
P1口 | P1.0~P1.7 | 输入与输出 | 无第二功能 |
P2口 | P2.0~P2.7 | 输入与输出 | 传送地址的高八位 |
P3口 | P3.0~P3.7 | 输入与输出 | P3.0——RXD:串行口输入端 |
P3.1——TXD:串行口输出端 | |||
P3.2——INT0 :外部中断0中断请求输入端 | |||
P3.3——INT1 :外部中断1中断请求输入端 | |||
P3.4——T0:定时器/计数器0外部输入端 | |||
P3.5——T1:定时器/计数器1外部输入端 | |||
P3.6——WR:外部数据存储器写选通信号 | |||
P3.7——RD:外部数据存储器读选通信号 |
MSP430特点:
类型丰富:MSP430提供了12组IO口,分别是 P1-P11,PJ.,以及S、COM端口。其中除了第十一P11的宽度是3位,其他的端口全是8为宽度;
相邻的端口可以组合成端口对,分别命名为 PA、PB、PC、PD等,通过字节(byte)形式访问
单独端口
,通过字(word)的形式访问端口对
;功能丰富:P1和P2具有9个(或7个)寄存器,其他有6个(或4个)寄存器
- 每个I/O口可单独编程
- 输入和输出可任意组合
- P1、P2所有I/O口都具有边沿可选的输入中断功能
- 能使用指令对寄存器操作
- 可设置I/O口上拉或者下拉
- 配置I/O驱动能力
输出特性:MSP430只有数据端口,可用端口的某一位或几位来传送状态信息来确定外设状态;
MSP430输入端口的最大漏电流为50na,输入端口的漏电流对系统的耗电影响很大;
每个端口的输出晶体管都能够限制输出电流(最大约为25mA)
MSP430的I/O口功能:
- PxDIR输入/输出方向寄存器:作为输入时,只能读,作为输出时,可读可写
- PxIN输入寄存器:是只读寄存器,用户不能对其写入
- PxOUT输出寄存器:可读可写
- PxREN上拉或下拉电阻使能寄存器(提高信号的驱动能力):该寄存器的每一位可以使能或禁用I/O引脚的上拉/下拉电阻——0为禁止,1为使能
- PxSEL功能选择寄存器:P1和P2端口还具有其他片内外设功能,0-选择引脚为I/O端口,1-选择引脚为外围模块功能
- PxDS输出驱动强度寄存器:每位设置引脚的输出强度为高驱动强度(“1”)或低驱动强度(“0”),默认值为低驱动强度
- PxIE中断使能寄存器:该寄存器的8位与该端口的8个引脚一一对应,某一位置位表示允许对应的引脚在电平变化(上升沿或下降沿)时产生中断
- PxIES中断触发沿选择寄存器:如果允许Px口某个引脚中断,还需定义该引脚的中断触发方式,该寄存器8位对应Px口的8个引脚(”0:上升沿使相应标志置位,1:下降沿使相应标志置位“)
- PxIFG中断标志寄存器:用来表示对应引脚是否产生了有PxIES设定的电平跳变,如果GIE置位,引脚对应的中断使能寄存器PxIE位置位,则会向CPU请求中断处理
3. I/O寄存器
(1)PxDIR:输入/输出方向寄存器
相互独立的8位分别定义了8个引脚的输入/输出方向。8位在PUC后都被复位。使用输入和输出功能时,应该先定义端口的方向,输入/输出才能满足设计者的要求。
0:输入模式;
1:输出模式。
(2)PxIN:输入寄存器
输入寄存器是 只读寄存器。用户不能对它进行写入,只能通过该寄存器内容知道I/O端口的输入信号。此时引脚方向必须选定为输入。
(3) PxOUT:输出寄存器
该寄存器为I/O端口的输出缓冲寄存器,在读取时输出缓存内容与引脚方向定义无关。
(4) PxIFG:中断标志寄存器
该寄存器有8个标志位,标志相应引脚是否有待处理中断的信息,即相应引脚是否有中断请求。寄存器定义如下:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
PxIFG | PxIFG.6 | PxIFG.5 | PxIFG.4 | PxIFG.3 | PxIFG.2 | PxIFG.1 | PxIFG.0 |
0:没有中断请求;
1:有中断请求。
(5) PxIES:中断触发沿选择寄存器
如果允许Px口的某个引脚中断,还需定义该引脚的中断触发方式。该寄存器的8位分别对应Px口的8个引脚。
0:上升沿使相应标志置位
1:下降沿使相应标志置位
(6) PxIE:中断使能寄存器
Px口的每一个引脚都有一位用以控制该引脚是否允许中断。该寄存器定义如下:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
PxIE.7 | PxIE.6 | PxIE.5 | PxIE.4 | PxIE.3 | PxIE.2 | PxIE.1 | PxIE.0 |
0:禁止中断;
1:允许中断。
(7) PxSEL:功能选择寄存器
P1和P2俩端口还具有其他片内外设功能,这些功能与芯片外的联系通过复用P1和P2引脚的方式来实现。P1SEL和P2SEL用来选择引脚的I/O端口功能与外围模块功能。
0:选择引脚位I/O模式;
1:选择引脚为外围模块功能。
端口P3、P4、P5和P6没有中断能力,其余功能同P1和P2,可以实现输入/输出功能和外围模块功能。四个寄存器可以对它们进行访问和控制,这四个寄存器分别是PxDIR,PxIN,PxOUT,PxSEL,定义和用法同P1、P2端口。
4. I/O口操作
430不支持直接对位操作,需要使用屏蔽符和掩码来实现修改寄存器的某一位而不影响其他位的目的。BIT0~F分别对16位寄存器操作。
配置MSP430的寄存器可以用两种方法来实现:
最直接的方式,直接给寄存器赋值,如
P1DIR = 0x81
;利用msp430官方库文件中宏定义,更直观地表示要操作地寄存器:
1 |
PxDIR = 0x81
就可以改写成 PxDIR = BIT0 + BIT7
,可以省去计算寄存器换算16进制的值;
- 驱动库中提供了一个函数GPIO_setAsInputPin()来将I/O口配置为输出。
4.1 PxDIR
设置IO口方向,0-输入,1-输出。如P1.5、P1.6、P1.7 接有按键,P1.1、P1.3、P1.4接有LED,那么P1.5、P1.6、P1.7 要设为输入,P1.1、P1.3、P1.4 要设为输出:
1 | P1DIR|=BIT1+BIT3+BIT4; // P1.1、P1.3、P1.4设为输出 |
PxDIR 寄存器在复位过程中会被清0,没有被设置的IO口方向均为输入状态,因此第二句可以被省略。
4.2 PxOUT和PxIN
对于所有已经设成输出状态的IO口,可以通过 PxOUT
寄存器设置其输出电平(当IO口配置为输入模式并且置高/置低使能时, PxOUT
寄存器:0置低1置高);
对于所有已经被设成输入状态的IO口,可以通过 PxIN
寄存器读回其输入电平。
如判断P1.5口上的开关状态,若低电平则从P1.1口输出高电平点亮LED:
1 | if(( P1IN & BIT5) ==0 ) P1OUT|=BIT1; //若P1.5为低电平则P1.1输出高电平 |
4.3 PxSEL
用于设置每一位IO的功能: 0=普通IO口 1=第二功能。
例如MSP4305418A中P5.6和P5.7和串口的TXD、RXD公用引脚,如果需要将两个引脚配置成串口收发脚,需将P5SEL的6,7位置高:
1 | P5SEL |= BIT6 + BIT7; // P2.4,5 设为串口收发引脚 |
4.4 PxIE和PxIES
PxIE寄存器用于设置每一位IO的中断允许: 0=不允许 1=允许
PxIES寄存器用于选择每一位IO的中断触发沿: 0=上升沿 1=下降沿
使用方法: 使用IO口中断之前,需要先将IO 口设为输入状态,并允许该位IO的中断,再通过PxIES寄存器选择触发方式为上升沿触发或者下降沿触发。
例如将P1.5、P1.6、P1.7 口设为中断源,下降沿触发:
1 | P1DIR &=~(BIT5 + BIT6 + BIT7); // P1.5、P1.6、P1.7设为输入(可省略) |
4.5 PxIFG
PxIFG寄存器是IO中断标志寄存器:0=中断条件不成立1=中断条件曾经成立过.
这个寄存器存在的目的是为了尽可能地不漏掉每一次中断。
例如P1.5、P1.6、P1.7 发生中断后执行不同的代码:
1 |
|
PxIFG
的中断操作比较灵活,既可以被动执行中断判断,也可以通过主动向写 PxIFG
寄存器相应位写“1”。
因此,更改 PxIES
应该在关闭中断后进行,并在打开中断之前及时清除中断标志。
5. 例程
使用TI官方提供的点亮LED的程序来进行430的入门操作——操作I/O口。
1 | //******************************************************************************* |
程序流程
1.关看门狗;2.设置I/O口;3.延时、循环输出
源码解释
- 关看门狗
1 | WDTCTL = WDTPW + WDTHOLD; // 停止看门狗 |
这句话实现了关开门狗的功能,要想理解这句话需要先查看官方的芯片手册:
WDTPW
:读取时必须是069h
,写的时候必须是05Ah
,否则就会出现一个PUC信号导致单片机复位
WDTHOLD
:置为1
时看门狗被停止
在头文件msp430x14x.h
中查看WDTPW
、WDTHOLD
的宏定义
430的库文件对这两个“变量”的宏定义如下:
1 |
WDTPW
为5A表示写入,WDTHOLD
为80,高位为1,地位为0,表示关闭看门狗。
将两个数相加,送入WDTCTL
实现关门狗;如果缺失其中一个会导致产生一个PUC信号使单片机复位。
2. 设置I/O口
P1DIR |= 0x01; // 提取01口,设置P1.1为输出
如上图,端口(Port)P1和P2具有输入/输出、中断和外部模块功能,这些功能可以通过它们各自的7个控制寄存器的设置来实现。
这里P1.1端口默认无输出,而P1.3-1.6,P1.7-1.8都是默认输入(00h)
1 | P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR |
- 延时、循环输出
1 | P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR |
这句指令又可写成 P1OUT = P1OUT ^ 0x01;
每次对第四位进行异或,改为输出。0 ^ 1,循环之后又变成1 ^ 1,实现闪烁。