MSP430-IO模拟串口通讯实验[这个可学到很多知识]

楼主
MSP430-IO模拟串口通讯实验[这个可学到很多知识]
 <<MSP430F1121的Timer_A实现模拟串口功能例程>>
 [URL=http://www.microcontrol.cn/datasheet/MSP430/MSP430base/MSP430Timer_A_USART.pdf]http://www.microcontrol.cn/datasheet/MSP430/MSP430base/MSP430Timer_A_USART.pdf[/URL]

      [IMGA=0,absMiddle]../../upload/2006/06/16/023502.gif[/IMGA]
 
   为了加强你对MSP430的Timer A模块应用知识,新手门不防做做这个DIY实验。
      [IMGA=0,absMiddle]../../upload/2006/06/16/023150.jpg[/IMGA]
      
   上图是我当年初学MSP430单片机时自己动手制作的,图片右边的IC是一个485通讯驱动器,直接做成485通讯之用。现在想起来当年做的这个小玩意还是很有意思的,这当中可以让新手们可以学到TA和串口实验原理。看例子也许你能看得明白,但真正自己动起手来又是另外一回事了。建议在校的学生哥们多多动手,读大学并不是拿了文凭就那么回事。更重要的是理论结合实战动手能力,做到毕来后要文武双全。        
1楼
棒极了,我上次有release的帮忙汇编实验成功了.
下面是汇编程序,供大家参考!!
;主要函数及其功能:1."Set_DCO"校准(Calibrate) DCO
;                 2."TA0_ISR" TIME_A中断子程序
;                 3."RX_Ready"准备接收UART ready to RX one Byte
;                 4."TX_Byte"发送接收到的一个字节
;备注:可用串口调试助手2.2测试     
;******************************************************************************
;说明: 发送1个字节,接收1个字节,格式:TX:"01",RX:"01"
;   This program demonstrates a half-duplex 9600-baud UART using
;   Timer_A3 and a 32kHz crystal.  The program will wait in LPM3, echoing back
;   a received character using 8N1 protocol.  The Set_DCO subroutine will
;   calibrate the DCOCLK to ~2Mhz, which is used as the Timer_A clock.
;   ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
;   //*External watch crystal installed on XIN XOUT is required for ACLK*//       
;
;                MSP430F1121
;             -----------------
;         /|\|              XIN|-  
;          | |                 | 32k
;          --|RST          XOUT|-
;            |                 |
;            |   CCI0A/TXD/P1.1|-------->  
;            |                 | 9600 8N1
;            |   CCI0B/RXD/P2.2|<--------
;-------------------------------------------------------------
;   CPU registers used
#define      RXTXData R4                   
#define      BitCnt   R5
;Conditions for 9600 Baud HW/SW UART, SMCLK = DCOCLK ~ 2Mhz
Bitime_5     equ    0104                    ; ~ 0.5 bit length
Bitime       equ    0208                    ; ~ 9615 baud
Delta        equ    0488                    ; DCOCLK = (Delta)/(32768/8)

RXD          set    004h                    ; RXD on P2.2
TXD          set    002h                    ; TXD on P1.1
;
;   M.Buccini
;   Texas Instruments, Inc
;   January 2004
;******************************************************************************
#include  "msp430x11x1.h"
;------------------------------------------------------------------------------
            ORG     0FC00h                  ; Program Start
;------------------------------------------------------------------------------
RESET       mov.w   #300h,SP                ; Initialize Stackpointer
StopWDT     mov.w   #WDTPW+WDTHOLD,&WDTCTL  ; Stop WDT
SetupBC     bis.b   #DIVA_3,&BCSCTL1        ; ACLK=LFXT1CLK/8=4096
Setup_TA    mov.w   #TASSEL_2+MC_2,&TACTL   ; Timer_A输入信号为SMCLK, 连续增计数0H->0FFFFH->0H->0FFFFH
            call    #Set_DCO                ; 校准(Calibrate) DCO
SetupC0     mov.w   #OUT,&CCTL0             ; TXD Idle as Mark
SetupP1_2   bis.b   #TXD,&P1SEL             ; P1.1/TA0 for TXD function
            bis.b   #TXD,&P1DIR             ; TXD output on P1
            bis.b   #RXD,&P2SEL             ; P2.2/TA0 as RXD input
                                            ;
Mainloop    call    #RX_Ready               ; 准备接收UART ready to RX one Byte
            bis.w   #LPM3+GIE,SR            ; Enter LPM3 w/ int until Byte RXed
            call    #TX_Byte                ; 发送接收到的一个字节TX Back RXed Byte Received
            jmp     Mainloop                ;
                                            ;
;-----------------------------------------------------------------------------
TX_Byte   ; Subroutine that Transmit One Byte from RXTXData Buffer.
;-----------------------------------------------------------------------------
            bis.b   #04h,&P1DIR             ;打开端口方向
            bis.b   #04h,&P1OUT             ;定义使能端
            mov.w   &TAR,&CCR0              ; TA定时器值送CCR0(Current state of TA Counter)
            add.w   #Bitime,&CCR0           ; 加一个位时间(Some time till first bit)
            bis.w   #0100h, RXTXData        ; 置停止位Add mark stop bit to RXTXData
            rla.w   RXTXData                ; 算术左移Add space start bit
            mov.w   #10,BitCnt              ; 10位Load Bit Counter, 8data + ST/SP
            mov.w   #OUTMOD0+CCIE,&CCTL0    ; 输出模式,允许中断TXD = mark = idle
TX_Wait     bit.w   #CCIE,&CCTL0            ; 等待发送完成Wait for TX completion
            jnz     TX_Wait                 ;
            ret                             ;
                                            ;
;-----------------------------------------------------------------------------
RX_Ready  ; Subroutine that will Receive One Byte into RXTXData Buffer.
          ; !! Sync capture not possible as DCO=TACLK=SMCLK can be off !!
;-----------------------------------------------------------------------------
            bis.b   #08h,&P1DIR             ;打开端口方向
            bic.b   #08h,&P1OUT             ;定义使能端
            mov.w   #08,BitCnt              ; Load Bit Counter, 8 data bits
SetupRX     mov.w   #CM1+CCIS0+OUTMOD0+CAP+CCIE,&CCTL0  ;上升沿捕获,选择CCI0A为捕获的输入信号源,
                                  ;输出模式,捕获模式,允许中断(Neg Edge,Cap)          
            ret                             ;
                                            ;
;-----------------------------------------------------------------------------
TA0_ISR  ;  CCR0/UART ISR:   RXTXData Buffer holds UART Data.
;-----------------------------------------------------------------------------
            add.w   #Bitime,&CCR0           ; 1个位时间Time to Next Bit
            bit.w   #CCIS0,&CCTL0           ; RX on ISCCIB?
            jnz     UART_RX                 ; 为1跳(即选择CCI0B为捕获的输入信号源)Jump --> RX
                                        ; 为0(即选择CCI0A为捕获的输入信号源)
UART_TX     cmp.w   #00h,BitCnt             ; 10为是否发完
            jne     TX_Next                 ; 未完跳Next bit?
            bic.w   #CCIE,&CCTL0            ; 完了清除中断All Bits TX or RX, Disable Int.
            reti                            ;
TX_Next     bic.w   #OUTMOD2,&CCTL0         ; 清除TX Mark
            rra.w   RXTXData                ; 算术右移LSB is shifted to carry
            jc      TX_Test                 ; 为1跳Jump --> bit = 1
TX_Space    bis.w   #OUTMOD2,&CCTL0         ; 为0 PWM翻转/复位TX Space
TX_Test     dec.w   BitCnt                  ; 位计数减1位All bits sent (or received)?
            reti                            ;
                                            ;
UART_RX     bit.w   #CAP,&CCTL0             ; 是否为捕获模式Compare mode for start bit edge
            jz      RX_Bit                  ; 不是跳Start bit edge?
RX_Edge     bic.w   #CAP,&CCTL0             ; 是,清除捕获模式Switch to Compare mode
            add.w   #Bitime_5,&CCR0         ; 加半位时间First databit 1.5 bits from edge
            mov.w   #CPUOFF+GIE,0(SP)       ; !!! DCO needs to remain on !!!
            reti                            ;
RX_Bit      bit.w   #SCCI,&CCTL0            ; 为1时C=1,为0时C=0,Get bit waiting in receive latch
            rrc.b   RXTXData                ; 带进位右移Store received bit
RX_Test     dec.w   BitCnt                  ; 位计数减1 All bits sent (or received)?
            jnz     RX_Next                 ; 不位0继续接收Next bit?
;>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
RX_Comp     bic.w   #CCIE,&CCTL0            ; 为0清除中断使能All Bits RXed, Disable Interrupt
            mov.w   #GIE,0(SP)              ; Decode Byte= Active in Mainloop
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
RX_Next     reti                            ;
;
;-----------------------------------------------------------------------------
Set_DCO;    Subroutine: Sets DCO to selected frequency based on Delta.
;           R14 and R15 are used, ACLK = 32768/8 Timer_A clocked by DCOCLK
;-----------------------------------------------------------------------------
            clr.w   R15                     ;                                         
Setup_CC2   mov.w   #CM_1+CCIS_1+CAP,&CCTL2 ; 上升沿捕获,选择CCI2B为捕获的输入信号源,选择捕获模式
Test_DCO    bit.w   #CCIFG,&CCTL2           ; Test 捕获(capture) flag
            jz      Test_DCO                ; 未捕获继续查
            bic.w   #CCIFG,&CCTL2           ; Clear capture flag
                                            ;
AdjDCO      mov.w   &CCR2,R14               ; R14 = captured SMCLK
            sub.w   R15,R14                 ; R14 = capture difference,R14=R14-R15
            mov.w   &CCR2,R15               ; R15 = captured SMCLK
            cmp.w   #Delta,R14              ; Delta(488) = SMCLK/(32768/8)
            jlo     IncDCO                  ; R14<488跳
            jeq     DoneDCO                 ; R14=488跳
DecDCO      dec.b   &DCOCTL                 ; DCOCTL=DCOCTL-1(Slow DCO with DCO and MOD)
            jnz     Test_DCO                ; |=0跳(Slower?)
            cmp.b   #XT2OFF+DIVA_3,&BCSCTL1 ; Can RSEL.x be decremented?
            jz      DoneDCO                 ; 相等返回(jmp>DCO at slowest setting)
            dec.b   &BCSCTL1                ; BCSCTL1=BCSCTL1-1(Decrement RSEL.x)
            jmp     Test_DCO                ; 跳
IncDCO      inc.b   &DCOCTL                 ; DCOCTL=DCOCTL+1(Speed DCO with DCO and MOD)
            jnc     Test_DCO                ; 没有溢出跳(Faster?)
            cmp.b   #XT2OFF+DIVA_3+07h,&BCSCTL1 ; Can RSEL.x be increased?
            jz      DoneDCO                 ; 相等返回(jmp> DCO at fastest setting)
            inc.b   &BCSCTL1                ; BCSCTL1=BCSCTL1+1(Increment RSEL.x)
            jmp     Test_DCO                ; 跳
DoneDCO     clr.w   &CCTL2                  ; Stop CCR2
            ret                             ; Return from subroutine
                                            ;
;-----------------------------------------------------------------------------
;           Interrupt Vectors Used MSP430x11x1          
;-----------------------------------------------------------------------------
            ORG     0FFFEh                  ; MSP430 RESET Vector
            DW      RESET                   ;
            ORG     0FFF2h                  ; Timer_A0 Vector
            DW      TA0_ISR                 ;
            END
            
2楼
very good!  谢谢DC的分析!!
3楼
谢谢楼主了
4楼
CCR0加半位时间的原因是当捕获比较功能捕获到起始位后,再加上半位的时间产生中断。以后在读取每一位时间时都能采样到每的中间值。以确保读数的准备性。
                *
            |-------|
    --------         -------   相差半位时间,后面读数都是在每位的中间采样。这样就能准确点。
5楼
电路图好象标错了,P1.1------TXD
                 P2.2------RXD

电脑版 Page created in 0.1562 seconds width 3 queries.