51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 单片机技术文章 > MSP430单片机 > 详细内容
MSP430中Timer_A and Timer_B的UART运用
发布时间:2009/7/28  阅读次数:752  字体大小: 【】 【】【

作者:丁鹏飞   徐国军 西安邮电学院044#

摘 要
自1996年MSP430十六位单片机问世以来,它的低功耗性能及丰富的片内资源受到各方面的好评,本文针对MSP430F13x及MSP43014X 系列单片机中的定时器进行介绍,利用定时器A(Timer_A)和定时器B(Timer_B)中的捕获比较寄存器来开发多个串行通信口,使十六位单片机在通信领域发挥更大的潜力。

一、 概述

MSP430具有丰富的外围模块,如MSP430F149就包含:12位A/D,精密模拟比较器,硬件乘法器,2组频率可达8MHZ的时钟模块,2个可以实现异步、同步及多址访问的串行通行接口,采用了超低功耗技术,可以进行在线调试与编程,其指令周期可达125ns。MSP430F14X系列目前在市场的售价大约为60元人民币,与其它单片机相比,MSP430具有更高的性价比和优越性,适合做测控、通讯等嵌入系统。本文介绍利用 MSP430中的定时器解决多串口通信。

目前美国德州仪器所出的所有FLASH 单片机都含有Timer_A,而在MSP430F13X系列和MSP43014X系列中既含有Timer_A也含有Timer_B,在F13X中有一个带有3个捕获/比较模块的Timer_B,在F14X中有一个带有7个捕获/比较模块的Timer_B,它们均是扩展UART口的核心。

Timer_A和Timer_B都是非常有用的定时器,Timer_A具有以下特点:

(1) 十六位计数器,有四种工作模式(停止、增计数、连续、增/减计数)
(2) 可以选择计数器时钟源(外设的,内置的快慢速均可)
(3) 三个具有可配置输入端的捕获/比较寄存器(具有自动锁存功能)
(4) 可用于串行通信

与Timer_A相比,Timer_B可进行8、10、12、16位计数,但在Timer_B中未实现锁存功能。Timer_A和Timer_B可支持同时进行的多时序控制、多个捕获/比较功能、多种输出波形(PWM波形),也可以是上述功能的组合。

二、 可行性分析

首先,收和发是针对不同的定时器,它们的中断源不同,中断标志会记住不同中断。其次,同一定时器的不同捕获寄存器(不包括CCR0)的中断标志有优先级、共用一个中断向量的中断标志,中断向量寄存器(TAIV或TBIV)用于确定产生中断请求的中断源,所以当出现同发或者同收现象时,可以根据中断向量寄存器中的内容来确定具体的中断操作,在进入一个中断后,中断向量寄存器会保存另外中断源的中断向量,直到前一中段结束而执行该中断,即不会丢失另外的中断。

三、 系统原理

计算机进行串行通信的高电平为-5~-15V,低电平为5~15V,而从MSP430单片机输出的信号的高电平为3V,低电平0V,要实现MSP430与计算机通信必须进行电平转换。实现这一转换,可以利用MAX202E来实现。

发送特性的实现是用比较功能将数据从输出单元的引脚移出,波特率是用定时器定时产生中断来实现的。

接收特性的实现是利用定时器的捕获功能实现接收数据的检测,当检测到起始位时,将定时器设置为比较模式,接收的位被EQUx信号自动锁存。这样就不会因CPU无法及时响应而造成接收错,提高了接收控制的灵活性,从而CPU因不需等待接收而提高其利用率。

以MSP430F149为例,Timer_A的捕捉/比较寄存器具有将输入信号锁存的功能,故利用它实现输入信号的准确接收;而Timer_B捕捉/比较寄存器不具有将输入信号锁存的功能,不宜将其作为串口的输入,本例利用它控制串口的输出。因Timer_A只有三个捕捉/比较寄存器,故利用它们可以开发出三个UART口,加上其本身的两个UART口,MSPF149最终可有五个UART口,硬件电路简图如图(1)(其中,UTXD1、URXD1的电平转换与其它几个UART的 硬件连接 一样)

四、主程序工作过程及软件框图

用Timer_A和Timer_B要实现多个UART口,合理选取Timer_A和Timer_B的工作模式非常重要。经分析,我们选取Timer_A和Timer_B工作在连续记数模式。在主程序中,需要发送数据时,由主程序调用发送子程序(其主要作用是初始化用于发送数据的Timer_B,经过初始化以后,由定时器定时产生中断来发送数据)。而接收模块初始化以后,接收数据的起始位的检测由定时器的捕获功能自动实现,不需软件控制,当捕获器检测到起始位以后由接收中断服务子程序实现数据的接收,其软件框图如下:

以Timer_A的CCR0的接收、Timer_B的CCR0的发送为例,其中断服务子程序分别如下:

1、 发送中断服务子程序:

TX_LOOP
         ADD    #Bitime,&TBCCR0      
         BIT      #0001H,R5
         JNZ      TX1
         BIC      #OUT,&TBCCTL0
         JMP      TX2
TX1   BIS       #OUT,&TBCCTL0      
TX2   SUB      #01H,R6                
         JNZ      TX3
         BIC      #CCIE,&TBCCTL0
TX3   RRA      R5
RETI

2、 接收中断服务子程序:

RX_LOOP
        CMP    #0009H,R8   
        JNZ      RX_START      
        BIC      #CAP,&CCTL0   
        MOV    &TAR,&CCR0
        ADD    #Bitime1_5,&CCR0        
        MOV    #0000H,R7      
        DEC      R8
        JMP      RXEND
RX_START
        BIT      #SCCI,&CCTL0
        RRC.B   R7
        SUB      #01H,R8
        JNZ      RXEND1
        BIC      #CCIE,&CCTL0
RXEND1      
        ADD    #Bitime,&CCR0   
RXEND
        RETI   

利用Timer_A和Timer_B实现UART功能的完整调试程序见附页:(在程序中,考虑到接收与发送的多个UART的中断具有相似之处,我们在程序中仅对两个发送口和两个接收口进行了调试,经调试,证实了利用Timer_A和Timer_B可以实现多个UART口功能。

五、对Timer_A和Timer_B实现的UART口的实时性、误差分析:

1. 接收和发送的实时性:

在发送数据时,如果定时器的计数时钟频率比较高,例如,当定时器的计数时钟频率为8MHZ,波特率为9600时,接收/发送相邻比特的间隔为833个时钟周期,即使延时几十个时钟周期(按理论,只要小于250个时钟周期即可)发送下一个比特也能正确接收该字节。在接收数据时,由于定时器具有自动锁存功能,对数据位的接收只要在下一位数据到来之前接收即可。由此可见,用定时器实现的UART口完全可以实现实时性,这完全可以用于对实时性要求比较高的系统。

2. 接收和发送一个字节的CPU占用率:

由于是利用中断来唤醒接收和发送中断服务的,在接收和发送的位间隔时间中CPU可以继续执行其他程序。CPU占用率可用以下公式计算:

CPU占用率=(发送或接收一位总的占用时钟周期*波特率)/CPU频率

经计算,发送和接收一个字节的CPU占用率(以最高时钟频率8MHZ、波特率为9600为例)分别约为:3.31%和3.39%。

3. 时间误差分析:

对于一般的UART口来说,由于字节间存在累积误差,因此,对波特率的要求较高,需要时钟频率非常接近波特率的整数倍。而实际波特率往往是通过时钟分频得到,无法产生精确的波特率,不可避免地会扩大累积误差。对于利用定时器实现的UART口来说,在发送或接收下一个字节时,定时器重新开始该字节内的计数,因此,字节之间不存在累积误差,仅存在字节内的累积误差,因此,这大大降低了时钟接近波特率的整数倍的要求,在定时器的计数时钟频率比较高(为波特率的几百倍时)时,时钟的选择将不受限制。

在定时器实现的UART口中,当定时器的计数时钟频率比较高时,字节内产生的累积误差也非常小。例如,当定时器的计数时钟频率为8MHZ,波特率为9600时,要求定时器每计数833.333时发送一个比特,然而,定时器只能计整数,因此选择每计数833时发送一个比特。在这种情况下,每一位所产生的误差只有千之几,这样的误差较一般的UART口来说是非常小的。

4. 与一般的UART口的性能比较:

UART口的实现在各种不同类型的微处理机系统中都不同,可能是用通用的I/O端口以等待的方式用软件实现位的处理,这样的处理方式需要极大的CPU开销,因此增大了功耗,也降低了CPU的可用性。而用定时器实现的UART口,在发送或接收时的位间隔期间,CPU可以继续执行其他的程序,加上MSP430单片机自身的特点,它甚至可以在超低功耗模式下接收和发送。

六、结束语

MSP430单片机的定时器功能强大,中断源较多,可以任意嵌套,它给工程开发人员提供了较多的选择余地。上面仅介绍了用TIMER_A、TIEMR_B来扩充UART口,开发人员只要熟悉定时器的工作原理,就可以根据自己的需要,从多种方法中选出最优方案。MSP430单片机所具有的较高性价比及优越性必将使其成为众多单片机中出色的一员。

参考文献

胡大可.《MSP430系列FLASH型超低功耗16位单片机》.北京航空航天大学出版设,2001

《MSP430系列软件用户指南》.利尔达(中国)电子有限公司

《MSP430 ASSERMBLER,LINKER,AND LIBRARIAN PROMGRAMING》.利尔达(中国)电子有限公司

邬宽明.《单片机外围器件使用手册-数据传输接口器件分册》.北京航空航天大学出版设
完整的调试程序源代码

#include   "msp430x14x.h"
        ORG    0FFFEH      
        DW      MAIN            /*设置上电起始地址*/
        RSEG   UDATA0
        DS      0                  
Bitime       EQU   209H    /*发送比特的时间间隔,时钟平率为5.030MHZ,波特率为9600比特/秒*/
Bitime1_5   EQU   30EH    /*起始位与第一个比特的时间间隔*/
TX_Count    EQU   000AH   /*发送数据的计数值*/
RX_Count    EQU   0009H   /*接收数据的计数值*/
CHECKDATA   EQU   0300H   /*存储通道1(CCR0)接收数据的起始地址*/
CHECKDATA1 EQU   0500H   /*存储通道1(CCR1)接收数据的起始地址*/
        RSEG   CSTACK         /*定义堆栈段*/
        DS      0
        RSEG   CODE            /*代码段开始*/
        DS      0
MAIN
      MOV      #(WDTPW+WDTHOLD),&WDTCTL   /* 关闭看门狗*/
INITSYS
        MOV      #SFE(CSTACK),SP
        MOV.B   #(RSEL2+RSEL1+RSEL0),&BCSCTL1    /*设置基础时钟模块*/
        MOV.B   #(DCO2+DCO1+DCO0),&DCOCTL        
        BIC.B   #OSCOFF,SR                                    
        PUSH    #0FFFFH                                         /*基础时钟的调整时钟*/
LOOP                
        DEC      0(SP)
        JNZ      LOOP
        MOV.B   #SELM_1,&BCSCTL2                          /* 选择系统时钟源*/
SetupTA         MOV   #(TASSEL_2+MC1),&TACTL      /*设置定时器A的时钟源及工作模式*/      
                     MOV   #(TBSSEL_2+MC1),&TBCTL      /*设置定时器B的时钟源及工作模式*/      
SetupC0         MOV   #OUT,&TBCCTL0                     /*通道1发送空闲数据*/
                     MOV   #OUT,&TBCCTL1                     /*通道2发送空闲数据*/
Setupp1_2      MOV.B   #00H,&P1DIR   /*设置定时器A和定时器B输入/出数据的管脚*/
                     BIS.B   #06H,&P1SEL   /*P1.1和P1.2用于接收数据*/
                     BIS.B   #03H,&P4DIR   /*P4.0和P4.1用于发送数据*/
                     BIS.B   #03H,&P4SEL                                                                                   
Delay            PUSH    #00FFH         /*用于延时*/
Delay2           DEC      0(SP)   
                     JNZ      Delay2
                     INCD    SP
                     MOV      #GIE,SR       /*开中断*/
/*--------------调试发送、接受模块的功能-----------------------*/
         MOV      #CHECKDATA,R14      /*设置接收通道1数据的起始地址*/
         MOV      #CHECKDATA1,R4      /*设置接收通道2数据的起始地址*/
         MOV      #35H,R5                 /*R5、R9用于存储发送的数据*/
         MOV      #39H,R9                 /*发送数据可以放于RAM中,或用变量代替R5,R9*/
         MOV      #00H,R10
         CALL    #RX_Ready              /*开启接收端口*/   
         CALL    #TX_Byte                /*发送2个通道的可以同时开启,但这里先开启通道1*/
TEST_TX12
         CMP      #00H,R6                /*判断通道1发送是否完毕,可以在中断服务程序中设置发送完标志*/
         JNZ      TEST_TX22
         MOV      #0035H,R5           /*发送的数据没有设置奇偶校验位,但可以根据情况设置*/
         CALL    #TX_Byte            /*发送完毕继续发送以便于调试发送数据是否正确*/
TEST_TX22
         CMP      #00H,R10            /*判断通道2发送是否完毕,可以在中断服务程序中设置发送完标志*/
         JNZ      TEST_RX12
         MOV      #0039H,R9           /*发送完毕继续发送以便于调试发送数据是否正确*/
         CALL    #TX_Byte1
         JMP      TEST_RX12
TEST_RX12                            
         CMP      #00H,R8              /*判断通道1数据是否接收完*/
         JNZ      TEST_RX22
         MOV      R7,R15                /*将接暂时数据存储于R15中,也可以利用RAM来存储*/
         MOV      #RX_Count,R8      /*接收控制*/
         MOV      #(CCIE+CAP+CCIS_0+CM_2+OUT),&CCTL0   /*准备接受下一个数据*/
LOAD   MOV.B   R15,0(R14)    /*将接收数据存储在RAM中,用于调试接收是否正确,可以奇偶校验来判断*/
         INC      R14                /*R14用于存储接收数据存放的地址,可以用变量代替*/
TEST_RX22        
         CMP      #00H,R12           /*判断通道2数据是否接收完*/
         JNZ      TEST_TX12        
         MOV      R11,R13            /*将接暂时数据存储于R13中,也可以利用RAM来存储*/
         MOV      #RX_Count,R12   /*接收控制*/
         MOV      #(CCIE+CAP+CCIS_0+CM_2+OUT),&CCTL1
LOAD1 MOV.B   R13,0(R4)       /*将接收数据存储在RAM中,用于调试接收是否正确,可以奇偶校验来判断*/
         INC      R4                   /*R4用于存储接收数据存放的地址,可以用变量代替*/
         JMP      TEST_TX12
/*------------调试代码段结束------*/                          

/************发送数据子程序*****************/
TX_Byte                                               /*通道1的发送中断服务子程序*/
        MOV      #TX_Count,R6                   /*R6用于存放发送的比特数,可以用变量代替*/
        BIS      #0FF00H,R5                      /*用于设置停止位*/
        MOV      #(CCIE+CLLD_3),&TBCCTL0   /*设置定时器B的CCR0的工作模式*/
        MOV      #Bitime,&TBCCR0                /*设置第一位的中断时间*/
        ADD      &TBR,&TBCCR0
        BIC      #OUT,&TBCCTL0                   /*发送起始位*/
        ADD      #Bitime,&TBCCR0                /*下一位的接收时间*/
        RET
/*CCR1,CCR2的中断共用一个地址,如果CCR2用于模块功能,必须首先判断是否为CCR1产生的中断*/      
TX_Byte1                                                 /*通道2的发送中断服务子程序*/
         MOV      #TX_Count,R10                   /*发送控制,R10用于存储通道2的发送比特位的个数*/
         BIS      #0FF00H,R9   
         MOV      #(CCIE+CLLD_3),&TBCCTL1       /*设置定时器B的CCR1的工作模式*/
         MOV      #Bitime,&TBCCR1                     /*设置第一位的中断时间*/   
         ADD      &TBR,&TBCCR1
         BIC      #OUT,&TBCCTL1                        /*发送起始位*/
         ADD      #Bitime,&TBCCR1                   /*下一位的接收时间*/
         RET   
/*---------准备接受数据-----------------------------*/
RX_Ready
         MOV      #(TASSEL_2+MC_2),&TACTL   /*设置定时器A的工作模式*/
         MOV      #RX_Count,R8       /*R8,R12用于存储接收的比特数,可以用变量代替*/
         MOV      #RX_Count,R12                                     /*接受控制*/
         MOV      #(CCIE+CAP+CCIS_0+CM_2+OUT),&CCTL0 /* 设置定时器A的CCR0的工作模式*/
         MOV      #(CCIE+CAP+CCIS_0+CM_2+OUT),&CCTL1   /* 设置定时器A的CCR1的工作模式*/
         MOV      #0000H,R11                                          /* R11 用于存储CCR1接受的数据*/
         MOV      #0000H,R7                                            /* R7用于存储通道1接受的数据*/
         RET           
/*----------------发送中断服务子程序(CCR0)---------------------*/
TX_LOOP                                  /*通道1的发送中断服务子程序*/
        ADD    #Bitime,&TBCCR0   
        BIT    #0001H,R5            /*判断发送位为1还是0*/
        JNZ    TX1
        BIC    #OUT,&TBCCTL0    /*发送起始位*/
        JMP    TX2
TX1   BIS    #OUT,&TBCCTL0      
TX2   SUB    #01H,R6              /*发送比特数减1*/
        JNZ    TX3
        BIC    #CCIE,&TBCCTL0
TX3   RRA      R5                     /*发送数据存储于R5中,可以用变量代替,必须与主程序中的设置一致*/
        RETI
/*----------------发送中断服务子程序(CCR1)---------------------*/
TX_LOOP1                               /*通道2的发送中断服务子程序*/
        ADD    #Bitime,&TBCCR1
        BIT    #0001H,R9           /*判断发送位为1还是0*/
        JNZ    TX11
        BIC    #OUT,&TBCCTL1    /*发送起始位*/
        JMP    TX21
TX11 BIS    #OUT,&TBCCTL1      
TX21 SUB    #01H,R10            /*发送比特数减1*/
        JNZ    TX31
        BIC    #CCIE,&TBCCTL1
TX31 RRA      R9                     /*发送数据存储于R9中,可以用变量代替,必须与主程序中的设置一致*/
        BIC    #CCIFG,&TBCCTL1 /*中断完,关闭中断标志位*/
        RETI
/*----------------接受中断服务子程序(CCR0)---------------------*/
RX_LOOP                           /*通道1的接收中断服务子程序*/
        CMP    #0009H,R8      /*判断接收位数*/
        JNZ    RX_START      
        BIC    #CAP,&CCTL0   /*接收到起始位,将定时器设置为比较模式*/
        MOV    #Bitime1_5,&CCR0 /*设置第一位的接收时间*/
        ADD    &TAR,&CCR0        
        MOV    #0000H,R7      /*将接收存储器清除,准备接收数据*/
        DEC    R8
        JMP    RXEND
RX_START
        BIT      #SCCI,&CCTL0 /*判断接收位为是0还是1*/
        RRC.B   R7
        SUB      #01H,R8
        JNZ      RXEND1
        BIC      #CCIE,&CCTL0 /*接收完,关闭中断允许位,开启在主程序*/
        JMP      RXEND
RXEND1      
        ADD    #Bitime,&CCR0   /*设置下一位的接收时间*/
RXEND
        RETI   
/*----------------接受中断服务子程序(CCR1)---------------------*/
RX_LOOP1                      /*通道1的接收中断服务子程序*/
        CMP    #0009H,R12 /*判断接收位数*/
        JNZ    RX_START1   
        BIC    #CAP,&CCTL1 /*接收到起始位,将定时器设置为比较模式*/
        MOV    #Bitime1_5,&CCR1   /*设置第一位的接收时间*/
        ADD    &TAR,&CCR1        
        MOV    #0000H,R11              /*将接收存储器清除,准备接收数据*/
        DEC    R12
        JMP    RXEND10
RX_START1
        BIT      #SCCI,&CCTL1         /*判断接收位为是0还是1*/
        RRC.B   R11
        SUB      #01H,R12
        JNZ      RXEND11
        BIC      #CCIE,&CCTL1    /*接收完,关闭中断允许位,开启在主程序*/
RXEND11           
        ADD    #Bitime,&CCR1    /*设置下一位的接收时间*/
RXEND10
        BIC    #CCIFG,&CCTL1    /*中断完,关闭中断标志位*/
        RETI   
/*-----------列中断向量表-----------------*/   
        COMMON INTVEC                          
         ORG   TIMERB0_VECTOR             
           DW    TX_LOOP                          
         ORG   TIMERB1_VECTOR
           DW    TX_LOOP1
         ORG   TIMERA0_VECTOR
           DW    RX_LOOP
         ORG   TIMERA1_VECTOR
           DW    RX_LOOP1
         END


说明:该程序用于测试利用定时器实现UART口的可行性,接收数据直接通过存储器所接收的数据来判断接收的正确性,在整个调试过程中,我们用超级终端随机发送数据,利用示波器观察UART发送的数据,通过在线调试来观察接收的数据是否正确。因此,没有考虑寄存器的有限性、数据的奇偶位。在实际运用系统中,可以用存储器来代替某些寄存器,也可以扩充存储空间和判断奇偶位。

通过反复的调试,用定时器扩充的UART口可以正确无误的进行接收/发送。由于该程序仅用于调试用定时器扩充的UART口的可行性,在实际运用中可以根据具体情况做相应改动。

利用定时器扩充的另外的一个UART口与其它两个类似,在扩充另外一个UART口时,必须考虑CCR1与CCR2共用一个中断向量的中断标志。

我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号