This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430I2041使用定时器模拟串口中遇到的问题,波特率出错

Other Parts Discussed in Thread: MSP430F4270

   根据MSP430F4270官网提供的例程:slac077h\MSP430F42x0_MSP430FG42x0_Code_Examples\C\msp430x42x0_ta_uart9600.c,修改适配I2041,单字节收发在波特率正常的时候是可以正常的。

   例程中多是使用的ACLK,2400波特率;我想提一下波特率,改用SMCLK,8分频,计数得到2400/4800/9600/115200。本来也是可以正常工作的,但是不知什么原因在调试过程中突然出现波特率对不上的情况,使用示波器看到MCU发出的波形波特率有一个1.5倍的偏差,将一位/半位定时计数除以1.5后,就可正常工作。

调试过程如下:

1、在排查无果后,我怀疑是不是芯片损坏,时钟不准了,重新烧写以前用过的程序,发现一切正常,片子是好的。

2、OK,我再调试模拟串口程序,这时就发现,之前的问题好了,波特率的计算不存在那个1.5的偏差了。。。

3、对比两个程序,在初始化部分,模拟串口的代码只是少了系统主时钟的设定,加上,也没出现问题。

4、我就以为找到问题所在并解决了,开始调试多字节收发的问题,结果经过一个周末,今天上班在继续调试的时候,那个问题又出现了!    -_-||

  没办法了,现将代码贴出来寻求大家的帮助!先谢谢了!!

#include <msp430.h>

#define RXD   BIT4                                 // RXD on P2.4      TA1.O  CCI0B
#define TXD   BIT0                                 // TXD on P2.0      TA1.O  CCI0A

#define TAUCRXIFG   BIT0                           // RXD on P2.4
#define TAUCTXIFG   BIT1                           // TXD on P2.0
unsigned char taUCIFG = 0;

unsigned char   uart_rx_len;                      //串口接收长度计数器
unsigned char   uart_rx_buff[20];                 //串口0接收缓冲
unsigned char   uart_tx_buff[20];
unsigned char   uart_tx_len;


//  Conditions for 9600 Baud SW UART, SMCLK = 16384000

unsigned int Bitime_5;                     // ~ 0.5 bit length + small adjustment
unsigned int Bitime;                       // ~ 9620 baud

unsigned int RXData = 0x00;
unsigned int TXData = 0x00;
unsigned int BitCnt;

void TimeA_Uart_Init(unsigned long Baud);
void TX_Byte (unsigned char byte);
void RX_Ready (void);
void Send_TimeA_Uart_len(unsigned char *buffer,unsigned char len);

int main (void)
{
  WDTCTL = WDTPW + WDTHOLD;                     // Stop watchdog timer
//  FLL_CTL0 |= XCAP14PF;                       // Configure load caps

  //CLK_INIT    后加为解决波特率偏差问题,结果发现没用。。。
  CSCTL0  = 0x00;                              // DCOBYP = 0;  DCOR = 0; Internal Resistor Mode
  CSCTL1 |= DIVM__1 | DIVS__1;                 // MCLK = DCO/1, SMCLK = DCO/1

  TimeA_Uart_Init(2400);
  __bis_SR_register(GIE);                       

  uart_rx_len = 0;
  unsigned char data[10] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99};
  Send_TimeA_Uart_len(data,10);
  // Mainloop
  for (;;)
  {
    RX_Ready();                                 // UART ready to RX one Byte
    __bis_SR_register(CPUOFF);                  // Enter LPM0 Until character RXed
    TX_Byte(RXData);                            // TX Back RXed Byte Received
  }
}

void TimeA_Uart_Init(unsigned long Baud)
{
  switch(Baud)
  {

    case 9600:
      TA1CCTL0 = OUT;                              // TXD Idle as Mark
      TA1CTL   = TASSEL_2 | MC_2 | ID_3;                  // SMCLK, continuous mode
      P2SEL0  |= TXD | RXD;                        // P1.0/1 TA0 for TXD/RXD function
      P2SEL1  &= ~(TXD | RXD);                        // P1.0/1 TA0 for TXD/RXD function
      P2DIR    = TXD;                              // TXD output on P1

      Bitime   = 213;    // 16384000/8/9600   ~9615 baud
      Bitime_5 = 107;     // Bitime/2         ~0.5 bit length + small adjustment
      break;
    

  case 2400:
      TA1CCTL0 = OUT;                              // TXD Idle as Mark
      TA1CTL   = TASSEL_2 | MC_2 | ID_3;                  // SMCLK, continuous mode
      P2SEL0   = TXD + RXD;                        // P1.0/1 TA0 for TXD/RXD function
      P2DIR    = TXD;                              // TXD output on P1

      Bitime   = 853;    // 16384000/8/2400   ~2401 baud
      Bitime_5 = 427;     // Bitime/2         ~0.5 bit length + small adjustment
      break;
    default:
      break;
  }
}

void Send_TimeA_Uart_len(unsigned char *buffer,unsigned char len)
{
    for(unsigned char i=0;i<len;i++) //检测最终是不是到了这么多位数据
    {
      TXData = *buffer++;
      TX_Byte(TXData);
    }
}

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


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


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

  // RX
  if (TA1CCTL0 & CCIS0)                        // RX on CCI0B?
  {
    if( TA1CCTL0 & CAP )                       // Capture mode = start bit edge
    {
      TA1CCTL0 &= ~CAP;                       // Capture to compare mode
      TA1CCR0 += Bitime_5;
    }
    else
    {
      RXData = RXData >> 1;
      if (TA1CCTL0 & SCCI)                     // Get bit waiting in receive latch
        RXData |= 0x80;
      BitCnt --;                            // All bits RXed?
      if ( BitCnt == 0)
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
      {
        TA1CCTL0 &= ~CCIE;                    // All bits RXed, disable interrupt
        taUCIFG |= TAUCRXIFG;
        uart_rx_buff[uart_rx_len++] = RXData;
        
        __bic_SR_register_on_exit(CPUOFF);  // Clear LPM0 bits from 0(SR)
      }
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    }
  }
  // TX
  else
  {
    if ( BitCnt == 0)
      TA1CCTL0 &= ~ CCIE;                      // All bits TXed, disable interrupt
    else
    {
      TA1CCTL0 |=  OUTMOD2;                    // TX Space
      if (TXData & 0x01)
        TA1CCTL0 &= ~ OUTMOD2;                 // TX Mark
      TXData = TXData >> 1;
      BitCnt --;
    }
  }
}

PS : 还想请教下,模拟串口要想收发多字节能不能做,怎么做?

  比如,如何将一个缓冲区的数据加起止位送中断发出?

  如何判断接收停止位,例程中在接收时,只收8位,而没有找停止位。