MSP430 Launchpad教程-第2部分-中断和计时器
什么是“打断这是一个信号,通知我们的MCU某个事件已经发生,从而导致主程序正常流程的中断和“中断例程”的执行,该例程处理该事件并采取指定的措施。
快速链接
- 第1部分: MSP430启动板教程-第1部分-基础
- 第2部分: MSP430 Launchpad教程-第2部分-中断和计时器
- 第3部分: MSP430 LaunchPad教程-第3部分-ADC
- 第4部分: MSP430 LaunchPad教程-第4部分-UART传输
中断对于避免在轮询循环中浪费处理器的宝贵时间,等待外部事件至关重要(实际上,它们用于实时操作系统, 实时操作系统)。
在MSP430架构中,有几种类型的中断:定时器中断,端口中断,ADC中断等等。它们中的每一个都需要启用并配置为工作,并且每个中断都有一个单独的“服务例程”。
在本教程中,我们将看到如何使用计时器和端口中断来刷新某些LED,在下一个教程中,我们将保留ADC中断。因此,让我们编写一些代码!
#包括"msp430g2231.h" void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT
您应该认识到这些行,我们在上一教程中使用了它们来为我们的MCU添加定义文件,声明主要功能并停止看门狗定时器。
CCTL0 = CCIE; // 使能CCR0中断 TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK / 8,向上模式 CCR0 = 10000; // 12.5 Hz
这是一些有趣的东西。这些行配置计时器中断。我们首先通过将CCTL0寄存器中的CCIE位置1来使能它。
然后我们在TimerA控制寄存器中设置定时器模块的时钟。
如果查看msp430g2231.h文件,可以看到:
- TASSEL_2选择SMCLK(由内部DCO提供,该内部DCO的运行频率约为1 MHz)。
- MC_1选择“ UP模式”,定时器递增到存储在CCR0寄存器中的数字;
- ID_3为提供的时钟选择一个内部8x分频器(在我们的情况下,我们为SMCLK / 8)。
最后,我们设置CCR0寄存器。我们将TimerA模块配置为在溢出和触发中断之前最多计数该寄存器中存储的数量。
通过将其设置为10000,我们得到的溢出频率为12,5 Hz。实际上,我们有(SMCLK / 8)/ 10000 = 12,5。
您可以通过更改此数字来获得多个频率(请记住,MSP430具有16位定时器,因此存储在CCR0寄存器中的值不得大于65535),更改分频器或使用计数器添加if-else块在中断程序中。让我们继续。
P1输出&= 0x00; // 关闭所有内容 P1DIR&= 0x00; P1DIR|= BIT0 + BIT6; // P1.0 和 P1.6 pins output the rest are input P1REN |= BIT3; // Enable internal pull-up/down resistors P1输出|= BIT3; // Select pull-up mode for P1.3
这些行也应该很熟悉,但是有一些补充:首先,我们清除PORT1输出和方向寄存器。然后,我们将P1.0和P1.6引脚设置为输出,其余设置为输入。最后两行启用开关(BIT3)上的上拉电阻,以便正常状态(未按下按钮)将为“ 1”。
P1IE |= BIT3; // P1.3 打断 enabled P1IES |= BIT3; // P1.3 Hi/lo edge P1IFG&= ~BIT3; // P1.3 IFG cleared
使用这些代码行,我们首先告诉MCU监听P1.3引脚的逻辑状态变化(有效地启用该特定引脚上的中断)。
然后我们在中断产生时选择边沿(从高到低或从低到高)。请记住,LaunchPad上的按钮在按下时将输入引脚连接到GND,而在未按下时将其连接到VCC。因此,我们选择高/低沿。
最后,我们清除该引脚的中断标志。中断标志程序P1IFG在中断发生时进行报告,应在中断服务程序结束时将其清除。
_BIS_SR(CPUOFF + GIE); // Enter LPM0 w/ 打断 while(1) // Loop forever, we do everything with 打断s! {} }
您可能还记得,通过这条线,我们在保持中断使能的同时关闭了CPU,以节省一些电源。然后我们进入一个循环,以确保MCU在执行中断工作时不执行其他操作。
// 定时器A0中断服务程序 #pragma vector = TIMERA0_VECTOR __interrupt void Timer_A(void) { P1输出^= BIT0; // Toggle P1.0 }
这是TimerA中断服务程序。每当TimerA溢出时,都会执行此例程中插入的代码(请注意特殊声明)。如您所见,我们仅切换P1.0引脚(LaunchPad上的红色指示灯),然后返回正常执行。
// 端口1中断服务程序 #pragma vector = PORT1_VECTOR __interrupt void Port_1(void) { P1输出^= BIT6; // Toggle P1.6 P1IFG&=~BIT3; // P1.3 IFG cleared }
这是Port1中断服务程序。每次我们按下P1.3按钮时,都会执行此例程中插入的代码(请注意特殊声明)。我们切换P1.6引脚(在LaunchPad上变为绿色),清除P1.3中断标志(非常重要),然后返回正常执行。
编译并编程LaunchPad时,按P1.3按钮时,应该看到红色的LED闪烁,绿色的LED切换。
这是完整的代码,请尽情享受!
#包括"msp430g2231.h" void main(void) { WDTCTL = WDTPW + WDTHOLD; // 停止WDT CCTL0 = CCIE; // 使能CCR0中断 TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK / 8,向上模式 CCR0 = 10000; // 12.5赫兹 P1输出&= 0x00; // 关闭所有内容 P1DIR&= 0x00; P1DIR| = BIT0 + BIT6; // P1.0和P1.6引脚输出,其余输入 P1REN | = BIT3; // 启用内部上拉/下拉电阻 P1输出| = BIT3; // 为P1.3选择上拉模式 P1IE | = BIT3; // 启用P1.3中断 P1IES | = BIT3; // P1.3高/低边缘 P1IFG&=〜BIT3; // P1.3 IFG已清除 _BIS_SR(CPUOFF + GIE); // 输入带有中断的LPM0 while(1)//永远循环,我们处理中断! {} } //定时器A0中断服务程序 #pragma vector = TIMERA0_VECTOR __interrupt void Timer_A(void) { P1输出^= BIT0; // Toggle P1.0 } //端口1中断服务程序 #pragma vector = PORT1_VECTOR __interrupt void Port_1(void) { P1输出^= BIT6; // Toggle P1.6 P1IFG&=〜BIT3; // P1.3 IFG已清除 }
恩里科·加兰特(Enrico Garante)的上一篇文章:
MSP430启动板教程-第1部分-基础
恩里科·加兰特(Enrico Garante)的下一篇文章:
MSP430 LaunchPad教程-第3部分-ADC
[-]
评论者 ●2015年7月22日

嗨!
我将示例转换为MSP-EXP430F5529LP,希望对您有所帮助!
#包括“ msp430F5529.h” // 包含寄存器和内置函数的定义
#包括
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 停止WDT
TA0CCTL0 = CCIE; // 使能CCR0中断
TA0CTL = TASSEL_2 | MC_1 | ID_3; // SMCLK / 8,向上模式
TA0CCR0 = 10000; // 我必须计算出来,但是我很懒
P1输出&= 0x00; // 关闭P1上的引脚
P1DIR&= 0x00; // 将P1引脚设置为输出
P1DIR| = BIT0; // P1.0引脚设置为输出,其余输入
P4OUT&= 0x00; // 关闭P4上的引脚
P4DIR&= 0x00; // 将P4引脚设置为输出
P4DIR| = BIT7; // P4.7引脚设置为输出,其余输入
P2REN | = BIT1; // 为P2启用内部上拉/下拉电阻
P2OUT | = BIT1; // 为P2.1选择上拉模式
P2IE | = BIT1; // 启用P2.1中断
P2IES | = BIT1; // P2.1高/低边缘
P2IFG&=〜BIT1; // P2.1 IFG已清除
_BIS_SR(CPUOFF + GIE); // 输入带有中断的LPM0
while(1)//永远循环,我们处理中断!
{}
}
// 定时器A0中断服务程序
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0(void)
{
P1输出^= BIT0; // Toggle P1.0
}
// 端口2中断服务程序
#pragma vector = PORT2_VECTOR
__interrupt void Port_2(void)
{
静态uint8_t反跳= 0;
一会儿<= 100)
{
如果(〜P2IN& BIT1) debounce++;
否则反跳= 0;
}
P4OUT^= BIT7; // Toggle P4.7
去抖动= 0;
P2IFG&=〜BIT1; // P2.1 IFG已清除
}
我将示例转换为MSP-EXP430F5529LP,希望对您有所帮助!
#包括“ msp430F5529.h” // 包含寄存器和内置函数的定义
#包括
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 停止WDT
TA0CCTL0 = CCIE; // 使能CCR0中断
TA0CTL = TASSEL_2 | MC_1 | ID_3; // SMCLK / 8,向上模式
TA0CCR0 = 10000; // 我必须计算出来,但是我很懒
P1输出&= 0x00; // 关闭P1上的引脚
P1DIR&= 0x00; // 将P1引脚设置为输出
P1DIR| = BIT0; // P1.0引脚设置为输出,其余输入
P4OUT&= 0x00; // 关闭P4上的引脚
P4DIR&= 0x00; // 将P4引脚设置为输出
P4DIR| = BIT7; // P4.7引脚设置为输出,其余输入
P2REN | = BIT1; // 为P2启用内部上拉/下拉电阻
P2OUT | = BIT1; // 为P2.1选择上拉模式
P2IE | = BIT1; // 启用P2.1中断
P2IES | = BIT1; // P2.1高/低边缘
P2IFG&=〜BIT1; // P2.1 IFG已清除
_BIS_SR(CPUOFF + GIE); // 输入带有中断的LPM0
while(1)//永远循环,我们处理中断!
{}
}
// 定时器A0中断服务程序
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0(void)
{
P1输出^= BIT0; // Toggle P1.0
}
// 端口2中断服务程序
#pragma vector = PORT2_VECTOR
__interrupt void Port_2(void)
{
静态uint8_t反跳= 0;
一会儿<= 100)
{
如果(〜P2IN& BIT1) debounce++;
否则反跳= 0;
}
P4OUT^= BIT7; // Toggle P4.7
去抖动= 0;
P2IFG&=〜BIT1; // P2.1 IFG已清除
}
[-]
评论者 ●2015年12月29日

基本相同的概念,但对于开关“ S2”
#包括
/ *
* main.c
* /
int main(void){
WDTCTL = WDTPW | WDTHOLD; // 停止看门狗定时器
TA0CCTL0 = CCIE; / * TA0CCTL0寄存器:如果您打算使用定时器,则需要设置的第一个寄存器是CCTL0。它是一个16位寄存器,该寄存器的设置会影响我们如何使用该寄存器。为了我们的目的,我们只是告诉它使用* /启用中断。
TA0CTL = TASSEL_2 + MC_1 + ID_3; / * TASSEL_2:使用SMCLK MC_1:递增ID_3:除以8 * /
TA0CCR0 = 10000; // 最多10000
P1输出= 0;
P1DIR= BIT0; // P0作为输出
P1REN | = BIT1; // 为P1启用上拉/下拉
P1输出|= BIT1; // pull up res for P1
P4OUT= 0;
P4DIR= 0;
P4DIR = BIT7;
P1IE |= BIT1; //P1.0 打断 enable
P1IES | = BIT1; // 高/低边
P1IFG&=〜BIT1; // 清除标志
_BIS_SR(CPUOFF + GIE); // 睡觉直到中断
while(1){}
return 0;
}
// 定时器A中断
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
P4OUT ^= BIT7;
}
#pragma vector = PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= BIT0;
P1IFG &= ~BIT1;
}
#包括
/ *
* main.c
* /
int main(void){
WDTCTL = WDTPW | WDTHOLD; // 停止看门狗定时器
TA0CCTL0 = CCIE; / * TA0CCTL0寄存器:如果您打算使用定时器,则需要设置的第一个寄存器是CCTL0。它是一个16位寄存器,该寄存器的设置会影响我们如何使用该寄存器。为了我们的目的,我们只是告诉它使用* /启用中断。
TA0CTL = TASSEL_2 + MC_1 + ID_3; / * TASSEL_2:使用SMCLK MC_1:递增ID_3:除以8 * /
TA0CCR0 = 10000; // 最多10000
P1输出= 0;
P1DIR= BIT0; // P0作为输出
P1REN | = BIT1; // 为P1启用上拉/下拉
P1输出|= BIT1; // pull up res for P1
P4OUT= 0;
P4DIR= 0;
P4DIR = BIT7;
P1IE |= BIT1; //P1.0 打断 enable
P1IES | = BIT1; // 高/低边
P1IFG&=〜BIT1; // 清除标志
_BIS_SR(CPUOFF + GIE); // 睡觉直到中断
while(1){}
return 0;
}
// 定时器A中断
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
P4OUT ^= BIT7;
}
#pragma vector = PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= BIT0;
P1IFG &= ~BIT1;
}
[-]
评论者 ●2014年5月22日

嗨,我在Energia IDE中使用了您的代码,它可以完美编译并上载,但是只有按钮中断有效,而定时器中断无效,这可能是什么问题?顺便说一句,我正在使用MSP430G2553。
非常感谢!
非常感谢!
[-]
评论者 ●2014年7月15日

看看前面的评论
[-]
评论者 ●2016年8月30日

你有解决方案了吗?当我运行相同的程序时,TAR寄存器不会递增,因此永远无法达到所需的值,并且执行保持在while(1)循环上。是否存在时钟问题或其他问题?
[-]
评论者 ●2015年5月10日

你好
不错的教程。我可以知道你从哪里得到材料吗?我的意思是指令集。谢谢!
不错的教程。我可以知道你从哪里得到材料吗?我的意思是指令集。谢谢!
[-]
评论者 ●2016年2月23日

感谢您的分享!
我有关于清除中断标志的问题。
为什么我们不需要在Timer的中断服务程序中清除中断标志,而需要在Port1中断服务程序中清除中断标志?
我有关于清除中断标志的问题。
为什么我们不需要在Timer的中断服务程序中清除中断标志,而需要在Port1中断服务程序中清除中断标志?
[-]
评论者 ●2016年2月24日

在端口IRQ上具有IV的MSP系列,您无需手动清除该标志,因为只需读取寄存器即可清除导致该标志的标志,并且一次只能设置一个标志,因此可以在其中使用开关/大小写。好像发生了两个IRQ,他们将排在队列中。
430x2xxx没有IV,并且一次可以设置多个IFG标志,并且如果仅通过读取就清除了所有标志,那么如果对IFG寄存器进行位测试,就不能有多个标志,因此您需要手动清除该位。
430x2xxx没有IV,并且一次可以设置多个IFG标志,并且如果仅通过读取就清除了所有标志,那么如果对IFG寄存器进行位测试,就不能有多个标志,因此您需要手动清除该位。
[-]
评论者 ●九月26,2016

在第一个教程中我对ISR的结束有疑问,请使我们的LED闪烁:
#pragma vector = PORT1_VECTOR
__interrupt void Port_1(void)
{
P1输出^= BIT6; // Toggle P1.6
P1IFG&=〜BIT3; // P1.3 IFG已清除
}
如果按下按钮1.3,则进入ISR,因为为此配置了P1IE和P1IES,然后在例程P1OUT XOR BIT6,P1IFG中将程序返回到“ main()”?我的意思是,ISR本身会结束并自动返回吗?如果很严格,我想如果再按一次该按钮,程序将再次进入ISR。我的意思是。
但是,当TimerA告诉MCU“去ISR_TimerA例程?_TimerA开始计数,并且在计数结束时,程序将转到ISR_TimerA?如果是的话,哪一行开始对TimerA进行计数。我们如何停止”例如,ISR_TimerA ...在5次相同的中断之后。
我认为我的问题不是那么荒谬。
#pragma vector = PORT1_VECTOR
__interrupt void Port_1(void)
{
P1输出^= BIT6; // Toggle P1.6
P1IFG&=〜BIT3; // P1.3 IFG已清除
}
如果按下按钮1.3,则进入ISR,因为为此配置了P1IE和P1IES,然后在例程P1OUT XOR BIT6,P1IFG中将程序返回到“ main()”?我的意思是,ISR本身会结束并自动返回吗?如果很严格,我想如果再按一次该按钮,程序将再次进入ISR。我的意思是。
但是,当TimerA告诉MCU“去ISR_TimerA例程?_TimerA开始计数,并且在计数结束时,程序将转到ISR_TimerA?如果是的话,哪一行开始对TimerA进行计数。我们如何停止”例如,ISR_TimerA ...在5次相同的中断之后。
我认为我的问题不是那么荒谬。
[-]
评论者 ●2015年6月28日

嗨,我正在用计时器打扰一下,但我需要将SMCLK的频率更改为8MHz,您能帮我吗?
[-]
评论者 ●2015年7月22日

第二个#include是stdint.h之间<>
我不知道为什么它不显示。
我不知道为什么它不显示。
[-]
评论者 ●2015年10月31日

您的教程很棒!非常感谢。
[-]
评论者 ●2016年3月15日

我正在尝试获取外部中断并使LED闪烁。但是我收到类似“ 语用 vector =接受数字参数或“ unused_interrupts”而不是PORT_VECTOR的错误”
int main(){
// 停止看门狗定时器
WDTCTL = WDTPW + WDTHOLD;
P1DIR&=〜BIT4; // 配置为输入
P1输出|= BIT4;
P3DIR | = BIT4;
P3OUT|= BIT4;
P1IES = 0x01;
P1IE = 0x01; // 1b =启用相应的端口中断
P1IFG= 0x01; // PxIFG标志设置为高到低过渡
P1REN = 0x01; // 启用上拉或下拉
}
#pragma vector = PORT_VECTOR
__interrupt void Port_1(void){
如果((P1IN& BIT4)==0 ){
// 将输入读取为GND
P3OUT|= BIT4;
}
否则if((P1IN& BIT4)==1 ){
P3OUT&= ~BIT4;
}
}
[-]
评论者 ●2016年6月19日

嗨,我正在使用MSP430F1491。编译时,它在使能电阻上拉/下拉线(P1REN | = BIT3;)上给出错误。表明它无效。但是在使用MSP430F2419进行编译时,它可以完美地进行编译。背后的原因是什么?
[-]
评论者 ●2016年8月30日

当我运行相同的程序时,TAR寄存器不会递增,因此永远无法达到所需的值,并且执行保持在while(1)循环上。是否存在时钟问题或其他问题?
[-]
评论者 ●2016年8月30日

当我运行相同的程序时,TAR寄存器不会递增,因此永远无法达到所需的值,并且执行保持在while(1)循环上。是否存在时钟问题或其他问题?
[-]
评论者 ●九月12,2016

你好
上面的例子效果很好。现在,如果我想使用timer_A以不同的频率闪烁2个LED,我该怎么办?
我已将TACCRO = 10000和TACCR1 = 60000
因此,通过TACCTLO = CCIE和TACCTL1 = CCIE允许中断
还提出了两个ISR:
#pragma vector = TIMERA0_VECTOR
__interrupt void ISR1(无效)
{}
和#pragma vector = TIMERA1_VECTOR
__interrupt void ISR2(无效)
{}
但它不能正常工作。一个LED指示灯完美闪烁,而另一个则不闪烁。任何人都可以建议。提前致谢。
上面的例子效果很好。现在,如果我想使用timer_A以不同的频率闪烁2个LED,我该怎么办?
我已将TACCRO = 10000和TACCR1 = 60000
因此,通过TACCTLO = CCIE和TACCTL1 = CCIE允许中断
还提出了两个ISR:
#pragma vector = TIMERA0_VECTOR
__interrupt void ISR1(无效)
{}
和#pragma vector = TIMERA1_VECTOR
__interrupt void ISR2(无效)
{}
但它不能正常工作。一个LED指示灯完美闪烁,而另一个则不闪烁。任何人都可以建议。提前致谢。
[-]
评论者 ●2017年5月12日

什么是#
vector = PORT1_VECTOR是什么意思?另外,如果我将2个交换机连接到端口1的2个不同的引脚,并希望为它们执行不同的例程,该如何实现?
[-]
评论者 ●2018年3月12日

大家好,
我为使FR5994的代码工作有点挣扎,所以我认为这可以帮助其他人使用基于fr5994的启动板
// **************************************************** *******************************************
// MSP430闪烁LED演示-软件切换P1.0
//
// MSP430x5994
// -----------------
// / / \\ |辛|-
// | | | |
// --| RST XOUT |-
// | | |
// | | P1.0 |->LED1
// P1.1 |->LED2
// P5.5 |<--P5.5
//
// 德州仪器(TI)
// 2013年7月
// **************************************************** *******************************************
#包括<msp430.h>
void main(void)
{
// 时钟设置
WDTCTL = WDTPW + WDTHOLD; // 停止WDT
PM5CTL0&=〜LOCKLPM5; // 禁用GPIO上电默认的高阻抗模式
TA0CCTL0 = CCIE; // 使能CCR0中断
TA0CTL = TASSEL_1 + MC_1 + ID_3; // ACLK = 32.768kHz / 8,升频
TA0CCR0 = 4096; // 1Hz赫兹
P1输出&= 0x00; // 关闭所有内容
P1DIR&= 0x00;
P1DIR| = BIT0 + BIT1; // P1.0和P1.1引脚输出,其余为输入。输出用于两个LED
P5REN | = BIT5; // 启用内部上拉/下拉电阻
P5OUT | = BIT5; // 需要设置上拉高电阻
P5IE | = BIT5; // 启用P5.5中断
P5IES | = BIT5; // P5.5高/低边缘
P5IFG&=〜BIT5; // 已清除P5.5 IFG
_BIS_SR(CPUOFF + GIE); // 输入带有中断的LPM0
while(1)永远循环,我们处理中断!
{}
}
// 定时器A0中断服务程序
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0(void)
{
P1OUT ^ = 0x01; // 切换P1.0
//TA0CTL &= ~TAIFG;
}
// 端口5中断服务程序
#pragma vector = PORT5_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^ = 0x02; // 切换P1.1
P5IFG &=〜BIT5; // 已清除P5.5 IFG
}
[-]
评论者 ●十月19,2018

谢谢,将时钟设置为1 Hz非常重要。我想在开发之前,我们应该先看一下时钟源。
[-]
评论者 ●十月28,2019

你好,恩里科。非常好的系列文章。似乎很多人都在错误:
#2580-D
pragma vector =接受数字参数或“ unused_interrupts”,但
PORT2_Vector”,因为他们尝试使用中断。我在许多论坛上都看过,而且没有一种建议的解决方案似乎真正解决了这个问题。我只是在尝试将端口2的一个引脚拉低时产生一个中断。我已经多次重写代码以尝试不同的端口和不同的引脚,但始终会收到相同的警告。
关于解决方案有什么建议吗?我正在使用CCS 9和MPS430 FR2355评估板。
真诚的,鲍勃
[-]
评论者 ●十月28,2019

鲍勃,你应该尝试 我们的论坛.
[-]
评论者 ●十月28,2019

谢谢。我会试一试。
[-]
评论者 ●2013年7月21日

你能告诉我为什么你的初始化代码中有P1OUT | = BIT3吗?我不明白为什么它在那里,但是没有它,代码将无法工作。
[-]
评论者 ●2013年7月31日

如《 MSP430x2xx系列用户指南》中所述:
“每个PxREN寄存器中的每个位均启用或禁用相应I / O引脚的上拉/下拉电阻。
PxOUT寄存器中的相应位选择是将引脚上拉(1)还是下拉(0)。”
我在代码中添加了注释,以使其更加清晰,感谢您的举报!
“每个PxREN寄存器中的每个位均启用或禁用相应I / O引脚的上拉/下拉电阻。
PxOUT寄存器中的相应位选择是将引脚上拉(1)还是下拉(0)。”
我在代码中添加了注释,以使其更加清晰,感谢您的举报!
[-]
评论者 ●2013年8月13日

您可以在每个端口上声明多个中断引脚,并为每个中断信号运行单独的代码吗?
[-]
评论者 ●2013年8月15日

当然!
您只需使用P1IE和P1IES寄存器启用引脚中断即可。然后,在PORT1中断例程中,可以使用P1IFG寄存器上的if语句为每个引脚执行不同的代码,这将使您知道已按下了哪个引脚。
您只需使用P1IE和P1IES寄存器启用引脚中断即可。然后,在PORT1中断例程中,可以使用P1IFG寄存器上的if语句为每个引脚执行不同的代码,这将使您知道已按下了哪个引脚。
[-]
评论者 ●2013年9月7日

感谢您的文章,这非常有帮助
[-]
评论者 ●2013年9月16日

嗨,大家好,
我正在使用MPS430g2553控制器,我想从具有5个按键的小键盘上设置时间,它的作用是什么?
我正在使用MPS430g2553控制器,我想从具有5个按键的小键盘上设置时间,它的作用是什么?
[-]
评论者 ●2013年9月30日

再次伟大,但不适用于2553,我无法修复它!
[-]
评论者 ●2013年10月15日

对于MSP430G2553,必须使用
#pragma vector = TIMER0_A0_VECTOR
代替
#pragma vector = TIMERA0_VECTOR
定时器中断服务程序,它应该工作。我在10分钟前测试过!
#pragma vector = TIMER0_A0_VECTOR
代替
#pragma vector = TIMERA0_VECTOR
定时器中断服务程序,它应该工作。我在10分钟前测试过!
[-]
评论者 ●九月22,2017

你好,
我想了解这行 #pragma vector = TIMER0_A0_VECTOR 何时编译?
[-]
评论者 ●2013年11月18日

请告诉我有关使用msp430的相量计算的信息
[-]
评论者 ●2014年2月27日

先生,我想将密钥与P1.0交互。作为输出,我想以1%的时间间隔以1%的步长将PWM波的占空比百分比从1%增加到99%。
[-]
评论者 ●2014年5月24日

您为什么不考虑按钮防抖的20毫秒?
[-]
评论者 ●2014年8月29日

很棒的向导,完美的解释!非常感谢。
[-]
评论者 ●2014年11月6日

你好
感谢您的教程。我们对代码的解释非常好,而且很容易将代码分解为更简单的理解方式,非常感谢。
我将行“ P1IES | = BIT3;”更改为“ P1IES&=〜BIT3; ,即从上升沿到下降沿。
它按预期工作,..
同时我也尝试过
我将“ P1输出| = BIT3;”行更改为“ P1OUT&= ~BIT3; ".
如果我是正确的,这是清除位,即。将该位设置为下拉电阻器模式。
输出没有变化。
它应该不起作用,对.. ???!
感谢您的教程。我们对代码的解释非常好,而且很容易将代码分解为更简单的理解方式,非常感谢。
我将行“ P1IES | = BIT3;”更改为“ P1IES&=〜BIT3; ,即从上升沿到下降沿。
它按预期工作,..
同时我也尝试过
我将“ P1输出| = BIT3;”行更改为“ P1OUT&= ~BIT3; ".
如果我是正确的,这是清除位,即。将该位设置为下拉电阻器模式。
输出没有变化。
它应该不起作用,对.. ???!
[-]
评论者 ●2015年4月1日

最初,P1.3被拉 上...那个 是,很高。
现在,当按下按钮时,它变低,在轮询中,它用(〜BIT2&P1IN)。使用中断编码如何完成?
现在,当按下按钮时,它变低,在轮询中,它用(〜BIT2&P1IN)。使用中断编码如何完成?
[-]
评论者 ●2015年4月2日

当您将此(按下按钮的过程)定义为中断时,则在等待程序时,程序还会继续寻找中断。现在,当您按下按钮时,将设置一个中断标志,并调用一个子例程……
[-]
评论者 ●2015年4月2日

你好
我正在g2553上使用此端口和计时器中断程序。
它显示错误为:“ Port”未识别为内部或外部命令。
我还按照g2553.h更改了中断名称,但仍然是相同的错误……
对于 参考...这里 代码是:::
#包括“ msp430g2553.h”
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 停止WDT
CCTL0 = CCIE; // 使能CCR0中断
TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK / 8,向上模式
CCR0 = 10000; // 12.5赫兹
P1输出&= 0x00; // 关闭所有内容
P1DIR&= 0x00;
P1DIR| = BIT0 + BIT6; // P1.0和P1.6引脚输出,其余输入
P1REN | = BIT3; // 启用内部上拉/下拉电阻
P1输出| = BIT3; // 为P1.3选择上拉模式
P1IE | = BIT3; // 启用P1.3中断
P1IES | = BIT3; // P1.3高/低边缘
P1IFG&=〜BIT3; // P1.3 IFG已清除
_BIS_SR(CPUOFF + GIE); // 输入带有中断的LPM0
while(1)//永远循环,我们处理中断!
{}
}
// 定时器A0中断服务程序
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A(void)
{
P1输出^= BIT0; // Toggle P1.0
}
// 端口1中断服务程序
#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR(无效)
{
P1输出^= BIT6; // Toggle P1.6
P1IFG&=〜BIT3; // P1.3 IFG已清除
}
我正在g2553上使用此端口和计时器中断程序。
它显示错误为:“ Port”未识别为内部或外部命令。
我还按照g2553.h更改了中断名称,但仍然是相同的错误……
对于 参考...这里 代码是:::
#包括“ msp430g2553.h”
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 停止WDT
CCTL0 = CCIE; // 使能CCR0中断
TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK / 8,向上模式
CCR0 = 10000; // 12.5赫兹
P1输出&= 0x00; // 关闭所有内容
P1DIR&= 0x00;
P1DIR| = BIT0 + BIT6; // P1.0和P1.6引脚输出,其余输入
P1REN | = BIT3; // 启用内部上拉/下拉电阻
P1输出| = BIT3; // 为P1.3选择上拉模式
P1IE | = BIT3; // 启用P1.3中断
P1IES | = BIT3; // P1.3高/低边缘
P1IFG&=〜BIT3; // P1.3 IFG已清除
_BIS_SR(CPUOFF + GIE); // 输入带有中断的LPM0
while(1)//永远循环,我们处理中断!
{}
}
// 定时器A0中断服务程序
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A(void)
{
P1输出^= BIT0; // Toggle P1.0
}
// 端口1中断服务程序
#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR(无效)
{
P1输出^= BIT6; // Toggle P1.6
P1IFG&=〜BIT3; // P1.3 IFG已清除
}
[-]
评论者 ●2015年6月16日

对于G2553,您必须使用:
TA0CTL = TASSEL_2 + MC_1 + ID_3;
TA0CCR0 = 10000;
TA0CCTL0 = CCIE
#pragma vector = TIMER0_A0_VECTOR
TA0CTL = TASSEL_2 + MC_1 + ID_3;
TA0CCR0 = 10000;
TA0CCTL0 = CCIE
#pragma vector = TIMER0_A0_VECTOR
[-]
评论者 ●2015年4月11日

可能的问题是ISR函数名称-您使用void PORT1_ISR(void),但更常用的是void Port_1(void)。
要发布对评论的回复,请单击每个评论所附的“回复”按钮。要发布新评论(而不是回复评论),请查看评论顶部的“写评论”标签。
注册后,您可以参加所有相关网站上的论坛,并获得所有pdf下载的访问权限。