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);