基于msp430串口接收中断
- 格式:docx
- 大小:12.11 KB
- 文档页数:1
MSP430I/O口中断引脚设置PxDIR输入/输出方向寄存器PxIN输入寄存器PxOUT输出寄存器PxIFG中断标志寄存器PxIE中断使能寄存器PxSEL功能选择寄存器(1)若使用P1口的部分引脚作为中断方式,在开总中断之前务必设置好P1IFG、P1IES、P1IE寄存器的相应位,并确保相应引脚为输入方向。
(2)为了尽量降低功耗,对连接引脚应设定为IO功能并设为输出。
(3)中断标志需要软件清除!可以用软件置位产生中断。
MSP430的IO中断由P1口和P2口输入变化的电平触发,P1和P2各有八个输入IO,P1的八个IO共用一个中断向量,P2的八个IO共用另一个中断向量。
在中断服务程序中判断到底是哪个IO口触发中断。
#include <msp430g2553.h>void Key_init(void){P1REN |= BIT3; //打开上拉,电路板上没有上拉电阻,触发边沿是从高电平到低电平P1IES |= BIT3; //选择触发边沿,下降沿触发P1IE |= BIT3; //打开P1.3的中断P1IFG &= 0x00;}void main(void){WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗P1DIR |= BIT0; //P1.0管脚设置为输出P1OUT |= BIT0; //P1.0管脚输出低电平Key_init(); //调用IO中断初始化函数_EINT(); //开启总中断,这一步没有的话,所有的中断都不能触发while(1); //死循环}#pragma vector = PORT1_VECTOR //中断向量声明__interrupt void Key_interrput(void){unsigned int i;for(i=0;i<12000;i++); //消抖必不可少啊!!if(P1IFG&BIT3) //判断是不是P1.3这个IO口产生了中断{ //若产生中断P1IFG.3置1P1OUT ^= BIT0; //LED2取反P1IFG &= 0x00; //中断标志位需要软件清除!!!P1REN |= BIT3;}}。
MSP430单片机实用技术讲座(13) 第9讲 简单的端口、显示、中断综合应用・南京航空航天大学 魏小龙・本讲将结合定时器、端口、中断等430资源进行综合应用。
具体要求如下:1.硬件连接 硬件连接(如图1)很简单,在P4端口连接了8只发光二极管LED0 ̄LED7,在P1端口连接了4×4键盘(16键)。
P1同时通过138、164扩展了8位数码显示器。
2.软件要求a)编写扫描键盘软件;b)编写数码管显示程序;c)键盘使用中断编写;d)P4连接的发光二极管的发光强度通过键盘控制,共分16亮度等级;e)分别控制单个发光二极管(可对LED0到LED7进行分别控制其亮度);f)在数码管上显示每只发光二极管的亮度,对应关系为:第一只数码管显示的数值对应第一只发光二极管的亮度,后面依次类推,第八只数码管显示的数值对应第八只发光二极管的亮度。
3.分析首先编写基本硬件程序,键盘与数码管显示已经在上一讲说清楚了,这里只管调用就可以了。
发光二极管显示也很简单,高电平亮,低电平熄。
那么如何实现发光二极管LED0 ̄ LED7显示的亮暗调节呢。
先看看图2所示的4个不同信号a、b、c、d。
假设它们的周期都是100Hz,则这些信号送发光二极管后,我们看不到发光二极管的亮与熄,我们看到的都是亮,只不过亮度不一样而已(因为人眼睛的视觉暂停缘故)。
很显然,信号a驱动发光二极管最暗,信号d驱动发光二极管最亮。
本讲所使用的硬件有16只扫描键盘,我们定义按0号按键显示最暗,按F号按键显示最亮。
根据软件要求e要求分别控制单个发光二极管(可对LED0到LED7进行分别控制其亮度),那么如何实现呢?我们可以将亮度数据存放在显示缓存里,则disbuffer[0]的数据表示LED0的亮度, 则disbuffer[1]的数据表示LED1的亮度......这样只要在显示缓存中取对应的亮度数值去控制发光二极管的显示就可以了。
数码管的显示方法为:在显示缓存中取数据移位到驱动对应数码管的74HC164,并延时显示一会儿。
你参考一下别人的代码看看注释很详细#include <msp430x14x.h>unsigned char RxData;//全局变量,保存接收到的数据。
void BasicClockSet(){/*下面将片外高速晶体设为MCLK分四步:(1) 起动高晶体(2) 清除OFIFG 标志位(3) 至少等待50us。
(4) 查看震荡器失效标志位OFIFG是否清0,如果没有清0,则重复1至4步直到震荡器失效标志位OFIFG清0。
与之相关寄存器为:1.BCSCTL1和BCSCTL2(基础系统时钟控制寄存器)2.IE1中断使能寄存器的第二位OFIE,振荡器失效中断使能位。
3.IFG1中断标志寄存器的第二位OFIFG,振荡器失效标志位。
4.DCOCTL数字震荡器控制寄存器。
一. BCSCTL1设置(基础系统时钟控制寄存器1):1.XT2OFF=0,外部高速晶体开。
2.XTS=0,片外低速晶体的频率,0为低频模式。
3.DIVAx=00B,不将其进行分频,即分频比为14.XT5V不使用设为0。
5.RSELx=111,DOC的电阻选择,此时DOC震荡频率达到最大10000MHZ(理想状态)。
因此BCSCTL1=0000 0111B=0x47。
二.BCSCTL2设置(基础系统时钟控制寄存器2):1.SELMx=10B,选择片外高速晶体作为MCLK。
这两位应等到振荡器失效标志位清0后才置位2.DIVMx=00B,不将其进行分频,即分频比为13.SELS=0B,选择子系统时钟为DCO4.DIVSx=00B,不将其进行分频,即分频比为15.DCOR=0B,选择芯片内部电阻。
三.DCOCTL(数字震荡器控制寄存器)1.DCOx=111,DCO频波段选择,此时诜择最大2.MODx=000,调制选择,当DCOx=111B时MODx无效。
*//*下面将片外高速晶体设为主系统时钟。
*///(1) 起动片外高速晶体BCSCTL1&=~XT2OFF;//XT2OFF的宏为0x80。
端口1中断函数多中断中断源:P1IFG.0~P1IFG7进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断#pragma vector=PORT1_VECTOR__interrupt void Port1(){ //以下为参考处理程序,不使用的端口应当删除其对于中断源的判断。
if((P1IFG&BIT0) == BIT0){ //处理P1IN.0中断P1IFG &= ~BIT0; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT1) ==BIT1){//处理P1IN.1中断P1IFG &= ~BIT1; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT2) ==BIT2){//处理P1IN.2中断P1IFG &= ~BIT2; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT3) ==BIT3){//处理P1IN.3中断P1IFG &= ~BIT3; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT4) ==BIT4){//处理P1IN.4中断P1IFG &= ~BIT4; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT5) ==BIT5){//处理P1IN.5中断P1IFG &= ~BIT5; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT6) ==BIT6){//处理P1IN.6中断P1IFG &= ~BIT6; //清除中断标志//以下填充用户代码}else{//处理P1IN.7中断P1IFG &= ~BIT7; //清除中断标志//以下填充用户代码}}端口2中断函数多中断中断源:P2IFG.0~P2IFG7进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断*****************************************************************************/ #pragma vector=PORT2_VECTOR__interrupt void Port2(){//以下为参考处理程序,不使用的端口应当删除其对于中断源的判if((P2IFG&BIT0) == BIT0){//处理P2IN.0中断P2IFG &= ~BIT0; //清除中断标志//以下填充用户代码}else if((P2IFG&BIT1) ==BIT1){//处理P2IN.1中断P2IFG &= ~BIT1; //清除中断标志//以下填充用户代码 }else if((P2IFG&BIT2) ==BIT2){//处理P2IN.2中断 P2IFG &= ~BIT2; //清除中断标志//以下填充用户代码 }else if((P2IFG&BIT3) ==BIT3){//处理P2IN.3中断 P2IFG &= ~BIT3; //清除中断标志//以下填充用户代码}else if((P2IFG&BIT4) ==BIT4){//处理P2IN.4中断P2IFG &= ~BIT4; //清除中断标志//以下填充用户代码 }else if((P2IFG&BIT5) ==BIT5){//处理P2IN.5中断P2IFG &= ~BIT5; //清除中断标志//以下填充用户代码}else if((P2IFG&BIT6) ==BIT6){//处理P2IN.6中断P2IFG &= ~BIT6; //清除中断标志//以下填充用户代码}else{//处理P2IN.7中断P2IFG &= ~BIT7; //清除中断标志//以下填充用户代码}}USART0发送中断函数******************************************************************************/ #pragma vector=USART0TX_VECTOR__interrupt void Usart0Tx(){//以下填充用户代码}USART0接收中断函数******************************************************************************/ #pragma vector=USART0RX_VECTOR__interrupt void Usart0Rx(){//以下填充用户代码}USART1发送中断函数******************************************************************************/ #pragma vector=USART1TX_VECTOR__interrupt void Usart1Tx(){//以下填充用户代码}SART1接收中断函数******************************************************************************/ #pragma vector=USART1RX_VECTOR__interrupt void Ustra1Rx(){//以下填充用户代码}基本定时器中断函数******************************************************************************/ #pragma vector=BASICTIMER_VECTOR__interrupt void BasTimer(){//以下填充用户代码}定时器A中断函数多中断中断源:CC1~2 TA******************************************************************************/#pragma vector=TIMER0_A1_VECTOR__interrupt void TimerA1(){//以下为参考处理程序,不使用的中断源应当删除switch (__even_in_range(TAIV, 10)){case 2: //捕获/比较1中断//以下填充用户代码break;case 4: //捕获/比较2中断//以下填充用户代码break;case 10: //TAIFG定时器溢出中断//以下填充用户代码break;}}定时器A中断函数中断源:CC0******************************************************************************/ #pragma vector=TIMERA0_VECTOR__interrupt void TimerA0(){//以下填充用户代码}多中断源:CC1~6 TB******************************************************************************/ #pragma vector=TIMERB1_VECTOR__interrupt void TimerB1(){//以下为参考处理程序,不使用的中断源应当删除switch (__even_in_range(TBIV, 14)){case 2: //捕获/比较1中断//以下填充用户代码break;case 4: //捕获/比较2中断//以下填充用户代码break;case 6: //捕获/比较3中断//以下填充用户代码break;case 8: //捕获/比较4中断//以下填充用户代码break;case 10: //捕获/比较5中断//以下填充用户代码break;case 12: / /捕获/比较6中断//以下填充用户代码break;case 14: //TBIFG定时器溢出中断//以下填充用户代码break;}}中断源:CC0******************************************************************************/ #pragma vector=TIMERB0_VECTOR__interrupt void TimerB0(){//以下填充用户代码}AD转换器中断函数多中断源:摸拟0~7、VeREF+、VREF-/VeREF-、(AVcc-AVss)/2 没有处理ADC12TOV和ADC12OV中断标志******************************************************************************/ #pragma vector=ADC_VECTOR__interrupt void Adc(){//以下为参考处理程序,不使用的中断源应当删除if((ADC12IFG&BIT0)==BIT0){ //通道0//以下填充用户代码}else if((ADC12IFG&BIT1)==BIT1){ //通道1//以下填充用户代码}else if((ADC12IFG&BIT2)==BIT2){ //通道2//以下填充用户代码}else if((ADC12IFG&BIT3)==BIT3){ //通道3//以下填充用户代码}else if((ADC12IFG&BIT4)==BIT4){ //通道4//以下填充用户代码}else if((ADC12IFG&BIT5)==BIT5){ //通道5//以下填充用户代码}else if((ADC12IFG&BIT6)==BIT6){ //通道6//以下填充用户代码}else if((ADC12IFG&BIT7)==BIT7){ //通道7//以下填充用户代码 }else if((ADC12IFG&BIT8)==BIT8){ //VeREF+//以下填充用户代码 }else if((ADC12IFG&BIT9)==BIT9){ //VREF-/VeREF-//以下填充用户代码}else if((ADC12IFG&BITA)==BITA){ //温度//以下填充用户代码}else if((ADC12IFG&BITB)==BITB){ //(A Vcc-A Vss)/2//以下填充用户代码}}看门狗定时器中断函数******************************************************************************/ #pragma vector=WDT_VECTOR__interrupt void WatchDog(){//以下填充用户代码}比较器A中断函数******************************************************************************/ #pragma vector=COMPARA TORA_VECTOR__interrupt void ComparatorA(){//以下填充用户代码}不可屏蔽中断函数******************************************************************************/ #pragma vector=NMI_VECTOR__interrupt void Nmi(){//以下为参考处理程序,不使用的中断源应当删除if((IFG1&OFIFG)==OFIFG){ //振荡器失效IFG1 &= ~OFIFG;//以下填充用户代码}else if((IFG1&NMIIFG)==NMIIFG){ //RST/NMI不可屏蔽中断IFG1 &= ~NMIIFG;//以下填充用户代码}else //if((FCTL3&ACCVIFG)==ACCVIFG){ //存储器非法访问FCTL3 &= ~ACCVIFG;//以下填充用户代码}}中断优先级:优先级顺序从高到低为:PORT2_VECTOR (1 * 2u) /* 0xFFE2 Port 2 */PORT1_VECTOR (4 * 2u) /* 0xFFE8 Port 1 */TIMER0_A1_VECTOR (5 * 2u) /* 0xFFEA Timer A CC1-2, TA */TIMER0_A0_VECTOR (6 * 2u) /* 0xFFEC Timer A CC0 */ADC_VECTOR (7 * 2u) /* 0xFFEE ADC */USART0TX_VECTOR (8 * 2u) /* 0xFFF0 USART 0 Transmit */USART0RX_VECTOR (9 * 2u) /* 0xFFF2 USART 0 Receive */WDT_VECTOR (10 * 2u) /* 0xFFF4 Watchdog Timer */ COMPARATORA_VECTOR (11 * 2u) /* 0xFFF6 Comparator A */TIMERB1_VECTOR (12 * 2u) /* 0xFFF8 Timer B CC1-2, TB */TIMERB0_VECTOR (13 * 2u) /* 0xFFFA Timer B CC0 */NMI_VECTOR (14 * 2u) /* 0xFFFC Non-maska××e */RESET_VECTOR (15 * 2u) /* 0xFFFE Reset [Highest Priority] */。
[1] 中断服务程序的格式
// P2 中断服务子程序
#pragma vector = PORT2_VECTOR
__interrupt void P2_IRQ(void)
{
switch(P1IFG)
{
case 0x01: // 引脚0
case 0x02: // 引脚1
case 0x04: // 引脚2
case 0x08: // 引脚3
case 0x10: // 引脚4
case 0x20: // 引脚5
case 0x40: // 引脚6
case 0x80: // 引脚7
}
}
中断服务程序最主要的是中断向量的设置
[2] 用P2.0~P2.3 的引脚中断,控制P4.0~P4.3 的LED闪烁
设置P2.0~P2.3 为输入状态
设置P2.0~P2.3 开中断
设置P2.0~P2.3 中断为上升沿中断
开全局中断_EINT();
设置P4.0~P4.3 为输出模式
写P2 中断服务子程序,如果某引脚有中断,则改变相对应的LED状态。
实验注意事项
[1] 在中断服务程序里面不要占用大量的时间,如果有大量的数据需要处理,则可以使
用在中断服务程序中设置标志变量,然后在主程序里面判断标志变量值,然后处理的方法。
[2] 中断服务程序只有在模块中断允许开启和全局中断开启时才有效
[3] 有的多个中断源使用一个中断向量,则需要在进中断的时候用switch~case语句判断
相关寄存器到底是哪个中断源发出的中断请求。
[4] I/O 口里面只有P1和P2口能响应中断,设计硬件电路的时候需要注意。
msp430的中断优先级和中断嵌套第一篇:msp430的中断优先级和中断嵌套msp430的中断优先级和中断嵌套MSP430的中断优先级按所在的向量的大小排列,中断向量地址越高优先级就越大,但是默认的MSP430是不能中断嵌套的,要想在执行某一中断时能够响应更高优先级的中断,需要在低优先级的中断程序中手动打开全局中断使能位,因为在进入中断服务子程序时全局中断使能位被清零,即禁止响应其它中断。
msp430的指令中,DINT 和EINT分别指关和开所有中断,也就是包涵P1IE、P2IE、WDTIE、TAIE、TBIE、ADC12IE、串口中断允许的所有中断允许位为“0”和为“1”。
当同时有多个中断来的时候才有优先级的考虑(优先级顺序可查看向量表)有中断响应以后自动关闭总中断,这个时候即使来更高优先级的中断都不会响应。
要中断嵌套的话,就必须在中断中打开总中断。
实现中断嵌套需要注意以下几点:1)430默认的是关闭中断嵌套的,除非你在一个中断程序中再次开总中断EINT;2)当进入中断程序时,只要不在中断中再次开中断,则总中断是关闭的,此时来中断不管是比当前中断的优先级高还是低都不执行;3)若在中断A中开了总中断,则可以响应后来的中断B(不管B 的优先级比A高还是低),B执行完再继续执行A。
注意:进入中断B 后总中断同样也会关闭,如果B中断程序执行时需响应中断C,则此时也要开总中断,若不需响应中断,则不用开中断,B执行完后跳出中断程序进入A程序时,总中断会自动打开;4)若在中断中开了总中断,后来的中断同时有多个,则会按优先级来执行,即中断优先级只有在多个中断同时到来时才起做用。
5)对于单源中断,只要响应中断,系统硬件自动清中断标志位,对于TA/TB定时器的比较/捕获中断,只要访问TAIV/TBIV,标志位被自动清除;对于多源中断(多个中断源共用一个中断向量)要手动清标志位,比如P1/P2口中断,要手工清除相应的标志,如果在这种中断用“EINT();”开中断,而在打开中断前没有清标志,就会有相同的中断不断嵌入,而导致堆栈溢出引起复位,所以在这类中断中必须先清标志再打开中断开关.特别注意:正是这段说明容易让人上当。
第6章并行数字输入输出端口中断的使用——按键电路的设计目标通过本章的学习,应掌握以下知识●中断的概念和工作过程●MSP430微控制器芯片支持的中断类型●Embedded Workbench for MSP430开发软件的中断服务程序结构●按键开关●独立式键盘的原理电路●MSP430微控制器芯片的并行输入/输出端口涉及中断的相关寄存器●字节操作运算符●条件语句●多个数据的输入方法引言信号处理是电子线路的一项主要的工作。
处理信号必须具有一个被处理的对象,也就是需要使用某种方式将被处理的信号引入电路。
在数字系统中,键盘是一种常见的信息输入工具。
组成键盘的按键开关具有两种工作状态,因此通过按键开关的断开,或者接通,就能够完成数字量0,或者1,两种取值的输入。
组成电路以后,按键开关的断开和接通可以用高电平和低电平这2种数字电路的工作状态反映出来。
这样将按键电路与MSP430微控制器芯片的输入/输出管脚连接起来,通过读取管脚的状态就能够判断按键开关是否动作,从而接收外部输入的信息。
按键开关组成键盘的电路形式常用的有独立式键盘电路和矩阵式键盘电路两种。
独立式键盘电路无论电路结构,还是它的识别程序结构,都比较简单。
矩阵式键盘电路的优点是对微控制器芯片的输入/输出管脚的占用数量较少。
作为一本入门书籍,本章只涉及独立式键盘电路。
键盘电路的处理时间只占用微控制器工作时间非常少的部分,同时键盘的使用还是随机的,这样让微控制器不断地读取按键的工作状态,显然降低了系统对信号的处理速度。
中断的概念非常适合按键工作状态的识别。
16.1按键开关当需要向微控制器传送命令,或者输入数据时,键盘通常被使用。
键盘是一组按键开关的集合。
像数码管一样,键盘也是应用系统的一个重要组成部分。
按键开关具有2个状态,闭合或者断开。
组成合适的电路,这2个状态反映在电压上就是按键开关分别呈现出高电平,或者低电平。
在数字电路中,这两个电平分别用来表示数据1,或者0。
关于MSP430中断、中断嵌套的一些注意
事项
1、MSP430默认的是关闭中断嵌套的,除非在一个
中断程序里面再次开启了总中断EINT();2、当进入中断程序时,只要不在中断中再次开中断,则总中断总是
关闭的,此时如果来中断,不管中断的优先级高还是低,都不执行。
3、如果在中断A中开放了总中断,则可以响应之后
到来的中断B(无论B的优先级是高还是低),B执行完了,再继续执行A。
这里,进入中断B之后,总中断同样也会关闭的。
如果中断B执行的过程中,还需要执行中断C,则此时也要在中断B中开放总中断。
若不需要响应中断,则不用开放总中断。
B执行完以后,跳出中断程序,进入A程序执行的时候,总中断会
自动打开。
4、若在中断之中开放了总中断,那么后来的中断同
时发生多个的话,则会按照优先级的顺序来执行,即
MSP430的中断优先级只有在
多个中断同时到来的时候才会起作用。
5、对于单中断源的中断,
只要响应中断,系统的硬件会自动的清除中断标志位。
对于TA、TB这样的定时器的比较、捕获中断,只要
访问TAIV/TBIV标志位就会被自动清除。
对于多源中断,需要手动清除标志位。
比如:P1、P2的中断,需要手动清楚相应的标志位。
如果在这种中断中使用“_EINT();”,开中断,而在打开中断之前,没有进行原来中断标识位
的清除工作,就会有相同的中断
不断的进行嵌套。
而导致堆栈溢出引起复位,所以在这类中断中,必须先清除标志位,再打开中断开关。
要
不然等着死机吧。