Hi Chris,

Am Sonntag, 12.09.04 um 22:13 Uhr schrieb Chris Liechti

your code ;-) it's rather difficult to make guesses without seeing any code.

------------ here is a code fragment i used successfully:

;variables
.data
        .comm   rxdata,1,1              ;char var
        .comm   rxshift,1,1             ;char var
        .comm   rxbit,2,2               ;short var, aligned

.text

interrupt(TIMERA1_VECTOR)
tax_int:
        add     &TAIV, r0               ; Add TA interrupt offset to PC
        reti                            ; CCR0 - no source
        jmp     Xccr1                   ; CCR1
        jmp     Xccr2                   ; CCR2
        reti                            ; CCR3 - no source
        reti                            ; CCR4 - no source
taover:                                 ; TAOVER (follows directly)
        reti

Xccr2:   reti   ;could be used for something else

;interrupt handler to receive as Timer_A UART
.global ccr1                            ;place a label afterwards so
Xccr1: ;that it is used in the listing
        add     rxbit, r0
        jmp     .Lrxstart               ;start bit
        jmp     .Lrxdatabit             ;D0
        jmp     .Lrxdatabit             ;D1
        jmp     .Lrxdatabit             ;D2
        jmp     .Lrxdatabit             ;D3
        jmp     .Lrxdatabit             ;D4
        jmp     .Lrxdatabit             ;D5
        jmp     .Lrxdatabit             ;D6
;        jmp     .Lrxlastbit             ;D7 that one follows anyway

.Lrxlastbit:                            ;last bit, handle byte
        bit     #SCCI, &CCTL1           ;read last bit
        xor     #BIT0, r2               ; XXX inverted input
        rrc.b   rxshift                 ;and save it
        clr     rxbit                   ;reset state
        mov     #CCIE|CAP|CM_1|CCIS_0|SCS, &CCTL1   ;restore cap mode
        mov.b   rxshift, rxdata         ;copy received data
br #swuartrx_interrupt ;call user function, must be an interrupt function that ends with a reti

.Lrxstart:                              ;startbit, init
        clr     rxshift                 ;clear input buffer
add #(BAUD/2), &CCR1 ;startbit + 1.5 bits -> first bit
        mov     #CCIE|CCIS_0|SCS, &CCTL1;set compare mode, sample bits
        jmp     .Lrxex                  ;set state,...

.Lrxdatabit:                            ;save databit
        bit     #SCCI, &CCTL1           ;measure databit
        xor     #BIT0, r2               ; XXX inverted input
        rrc.b   rxshift                 ;rotate in databit
.Lrxex: add     #BAUD, &CCR1            ;one bit delay
        incd    rxbit                   ;setup next state
        reti

; void serPutc(char)
;use an other Capture/Compare than for receiving (full duplex).
;this one is without interrupts and OUTMOD, because only
;this way P1.1 can be used. P1.1 is prefered because the
;BSL is on that pin too.
.global putchar
        .type putchar, @function
putchar:                                ;send a byte
        mov     #0, &CCTL2              ;select compare mode
        and     #0xff, r15              ;make sure its a byte
        mov     #10, r13                ;ten bits: Start, 8 Data, Stop
        rla     r15                     ;shift in start bit (0)
bis #0x0200, r15 ;set tenth bit (1), thats the stop bit
        mov     &TAR, &CCR2             ;set up start time
.Lt1lp: add     #BAUD, &CCR2            ;set up for one bit
        rrc     r15                     ;shift data trough carry
        jc      .Lt1                    ;test carry bit
//~ .Lt0:   bic.b   #TX, &P1OUT             ;generate pulse
.Lt0:   bis.b   #TX, &P1OUT             ;generate pulse
        jmp     .Ltc                    ;
//~ .Lt1:   bis.b   #TX, &P1OUT             ;generate pause
.Lt1:   bic.b   #TX, &P1OUT             ;generate pause
        jmp     .Ltc                    ;
.Ltc:   bit     #CCIFG, &CCTL2          ;wait for compare
        jz      .Ltc                    ;loop until the bit is set
        bic     #CCIFG, &CCTL2          ;clear for next loop
        dec     r13                     ;decrement bit counter
        jnz     .Lt1lp                  ;loop until all bits are tx'ed
        mov     #1, r15                 ;signal success to the caller
        ret


This is what I've used. Why is there a high on tx just before the startbit?


//                MSP430F1121
//            -----------------
//        /|\|              XIN|-
//         | |                 | 32kHz
//         --|RST          XOUT|-
//           |                 |
//           |   CCI0A/TXD/P1.1|-------->
//           |                 | 2400 8N1
//           |   CCI0B/RXD/P2.2|<--------

#define RXD   0x04                      // RXD on P2.2
#define TXD   0x02                      // TXD on P1.1

//   Conditions for 2400 Baud SW UART, ACLK = 32768

#define Bitime_5 0x06 // ~ 0.5 bit length + small adjustment
#define Bitime  0x0E                    // 427us bit length ~ 2341 baud


// Function Transmits Character from RXTXData Buffer
void TX_Byte(void)
{
BitCnt = 0xA; // Load Bit counter, 8data + ST/SP
  CCR0 = TAR;                           // Current state of TA counter
  CCR0 += Bitime;                       // Some time till first bit
  RXTXData |= 0x100;                    // Add mark stop bit to RXTXData
  RXTXData = RXTXData << 1;             // Add space start bit
  RXTXData = 0xffff ^ RXTXData;         // Invert tx bits
  CCTL0 = OUTMOD0+CCIE;                 // TXD = mark = idle
  while (CCTL0 & CCIE);                 // Wait for TX completion
}


// Timer A0 interrupt service routine
interrupt (TIMERA0_VECTOR) Timer_A(void)
{
  CCR0 += Bitime;                       // Add Offset to CCR0

// RX
  if (CCTL0 & CCIS0)                    // RX on CCI0B?
  {
  }
  else // TX
  {
        if ( BitCnt == 0){
CCTL0 &= ~ CCIE; // All bits TXed, disable interrupt
        }
    else
    {
      CCTL0 |=  OUTMOD2;                  // TX Space
      if (RXTXData & 0x01)
              CCTL0 &= ~ OUTMOD2;                 // TX Mark
      RXTXData = RXTXData >> 1;
      BitCnt --;
    }
  }
}


and the init code

  CCTL0 = OUT;                          // TXD Idle as Mark
  TACTL = TASSEL0+MC1;                  // ACLK, continous mode
  P1SEL = TXD;                          // P1.1/TA0 for TXD function
  P1DIR = TXD;                          // TXD output on P1
  P2SEL = RXD;                          // P2.2/TA0 as RXD input
  _BIS_SR(GIE); 

Reply via email to