定时器模拟串口

yqstop   2006-12-11 14:47 楼主
请教:芯片本身无串口通信功能(如F2001),P1.1用于发送和接收,每次8字节,该如何通信?

回复评论 (6)

#define RXD 0x02 // RXD on P1.1
#define TXD 0x20 // TXD on P1.5

// 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

unsigned int RXTXData;
unsigned char BitCnt;

void TX_Byte (void);
void RX_Ready (void);

// Built with IAR Embedded Workbench Version: 3.40A
//******************************************************************************

#include <msp430x20x3.h>


void main (void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
CCTL0 = OUT; // TXD Idle as Mark
TACTL = TASSEL_1 + MC_2; // ACLK, continuous mode
P1SEL = TXD + RXD; //
P1DIR = TXD; //

// Mainloop
for (;;)
{
RX_Ready(); // UART ready to RX one Byte
_BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr until char RXed
TX_Byte(); // TX Back RXed Byte Received
}
}


// Function Transmits Character from RXTXData Buffer
void TX_Byte (void)
{
BitCnt = 0xA; // Load Bit counter, 8data + ST/SP
while (CCR0 != TAR) // Prevent async capture
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
CCTL0 = CCIS0 + OUTMOD0 + CCIE; // TXD = mark = idle
while ( CCTL0 & CCIE ); // Wait for TX completion
}


// Function Readies UART to Receive Character into RXTXData Buffer
void RX_Ready (void)
{
BitCnt = 0x8; // Load Bit counter
CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE; // Sync, Neg Edge, Cap
}

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

// TX
if (CCTL0 & CCIS0) // TX on CCI0B?
{
if ( BitCnt == 0)
CCTL0 &= ~ CCIE; // All bits TXed, disa××e interrupt
else
{
CCTL0 |= OUTMOD2; // TX Space
if (RXTXData & 0x01)
CCTL0 &= ~ OUTMOD2; // TX Mark
RXTXData = RXTXData >> 1;
BitCnt --;
}
}
// RX
else
{
if( CCTL0 & CAP ) // Capture mode = start bit edge
{
CCTL0 &= ~ CAP; // Switch from capture to compare mode
CCR0 += Bitime_5;
}
else
{
RXTXData = RXTXData >> 1;
if (CCTL0 & SCCI) // Get bit waiting in receive latch
RXTXData |= 0x80;
BitCnt --; // All bits RXed?
if ( BitCnt == 0)
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
{
CCTL0 &= ~ CCIE; // All bits RXed, disa××e interrupt
_BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR)
}
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
}
点赞  2006-12-11 15:25
请教斑竹,我现在是一个IO口既具有发送又具有接收功能,上述代码该如何修改?
点赞  2006-12-11 15:37
无论如何要两个口线,否则你无法控制应答时序的。最简单办法可以用口线模拟IIC
点赞  2006-12-13 08:34
我在软件中不断改变IO口的输入和输出方向不就可以了吗?见下!
#define RXD 0x02 // RXD on P1.1
#define TXD 0x02 // TXD on P1.1
...
TACTL = TASSEL_2 + MC_2; // MCLK, continuous mode
P1SEL = 0x02; //outside function
P1DIR = TXD;
......
void TX_Byte (void)
{
P1DIR |= BIT1;
BitCnt = 0x0A; // Load Bit counter, 8data + ST/SP
RXTXData=0x2a;
while (CCR0 != TAR) // Prevent async capture
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
CCTL0 = OUTMOD0 + CCIE; // TXD = mark = idle
while ( CCTL0 & CCIE ); // Wait for TX completion
}

void RX_Ready (void)
{
P1DIR &=~BIT1; //input direct
for(int i = 0;i<8;i++)
{
BitCnt = 0x08; // Load Bit counter
CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE; // Sync,PWM output mode,Capture mode 1 , Neg Edge, Cap
while(CCTL0&CCIE);
}

}

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

// TX
//if (CCTL0 & CCIS_0) // TX on CCI0B?
if(!(P1DIR&0X02))
{

if(BitCnt == 0)
CCTL0 &= ~ CCIE; // All bits TXed, disa××e interrupt
else
{
CCTL0 |= OUTMOD2; // TX Space
if (RXTXData & 0x01)
CCTL0 &= ~ OUTMOD2; // TX Mark
RXTXData = RXTXData >> 1;
BitCnt --;
}
}
// RX
else
{
P1DIR &= ~TXD;
if( CCTL0 & CAP ) // Capture mode = start bit edge
{
CCTL0 &= ~ CAP; // Switch from capture to compare mode
CCR0 += Bitime_5;
}
else
{
RXTXData = RXTXData >> 1;
if (CCTL0 & SCCI) // Get bit waiting in receive latch
RXTXData |= 0x80;
BitCnt --; // All bits RXed?
if ( BitCnt == 0)
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
{
CCTL0 &= ~ CCIE; // All bits RXed, disa××e interrupt
cStr[0] = RXTXData;
_BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR)
}
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
}
点赞  2006-12-14 14:30
可以是可以的,我以前也做过相关的东西,主要是机械结构上限制死了,没办法。只要在时序上做好分配就好了,一个送的时候另一个肯定已经在等好接收了。然后再反过来这样的双向传输就解决了应答问题。但这样的东西总是差一点的
点赞  2006-12-17 23:22
谢谢.但是我的产品由于体积所限,只能用一个接口通信.假如我用两个IO口,接到同一个通信脚上,通过判断信号线的高低电平来判断是发送还是接收,不知道是否行得通?这样发送和接受是否会比较可靠些?我现在接收和发送的都不全对,还不知道是不是时序没分配好的原因.
点赞  2006-12-18 11:31
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复