搜索
bottom↓
回复: 7

TimerA模拟Uart,接收不正确

[复制链接]

出0入0汤圆

发表于 2013-9-24 20:32:13 | 显示全部楼层 |阅读模式
芯片型号是Msp430F4250
参考一些样例程序做了个模拟Uart,现在调试时发现接收不正确(发送还未调试),具体来说:用串口调试软件发送几字节数据,然后用仿真器设置断点,查看接收数据是否正确。波特率定为9600。每次接收的数据只有第一个字节正确,后面全错;发送字节数超过三个时,接收字节数也不正确,比如发送8个字节,程序中显示收到6个字节。主要程序如下:

程序的大体思路:用TimerA 的 CCR0收发数据 用CCR1作接收超时判断(长时间没有收到数据时,认为数据接收完毕,开始处理数据)
                        单字节接收缓存到变量intData,每接收完一字节,存放到uchRcvBuf[]数组中,变量uchMsgLen指示已经接收的字节数

今天弄了一天也没有进展,缺失方向。恳请大家帮忙!

#define Bitime_5                0x30            //半位时长
#define Bitime                  0x6C            //一位时长

//------------------------------------------------------------------------------
// Timer_A CCR0中断服务函数
// 用于UART功能
//
#pragma vector=TIMERA0_VECTOR
__interrupt void TimerA_CCR0_ISR(void)
{
  CCR0 += Bitime;
  //CCTL0&=~CCIFG;
  if(CCTL0 & CCIS0)     //-----逐位接收-----------------------------------------
  {
    if(CCTL0 & CAP )                    // Capture mode = start bit edge
    {
      CCTL0 &= ~ CAP;                   // Capture to compare mode
      CCR0 += Bitime_5;
      CCTL1=0x0;                        // 停止接收超时检查
    }
    else
    {
      intData=intData>>1;
      if(CCTL0 & SCCI) intData|=0x80;       // Get bit waiting in receive latch
      uchBitCnt--;                            // All bits RXed?
      if(uchBitCnt==0)
      {
        uchRcvBuf[uchMsgLen]=(unsigned char)intData;    //保存数据
        uchMsgLen=(uchMsgLen+1)%cst_MaxMsgLen;          //
        uchBitCnt=8;                    //准备接收下一字节
        //CCTL0|=CAP;                     //恢复为捕获模式
        CCTL0 = SCS + CCIS0 + OUTMOD0 + CM1 + CAP + CCIE;  // Sync, Neg Edge, Capture
        TACCR1=TAR+Bitime*50;           //设置CCR1,定时4个字节的传输时间
        CCTL1=CCIE;                     //启用CCR1中断
      }
    }
  }
  else                  //-----逐位发送-----------------------------------------
  {
    if(uchBitCnt==0)
      CCTL0&=~CCIE;                     
    else
    {
      if (intData & 0x01)
        CCTL0 &= ~ OUTMOD2;                     //输出1
      else
        CCTL0|=OUTMOD2;                         //输出0
      intData=intData>>1;
      uchBitCnt--;
    }
  }
}

//******************************************************************************
// Timer_A CCR1\CCR2\TA中断服务
// 睡眠唤醒
//
#pragma vector=TIMERA1_VECTOR
__interrupt void TimerA_CCR1_ISR(void)
{
  switch(__even_in_range(TAIV,4))
  {
  case 2:        //CCR1中断---------------------------------------------串口等待
    CCTL0=0;                                    //
    CCTL1=0;                                    //
    UART_ISR(uchRcvBuf,uchMsgLen);              //处理串口消息------在此处设置断点,查看接收到的数据
    uchMsgLen=0;
    uchBitCnt=8;                                //恢复TimerA CCR0设置(接收功能)
    CCTL0=SCS+CCIS0+OUTMOD0+CM1+CAP+CCIE;       // Sync, Neg Edge, Capture
    break;
   
  case 10:       //TA中断-----------------------------------------------睡眠唤醒
    TACTL=0x0;
    __low_power_mode_off_on_exit();
  }
}

出0入0汤圆

发表于 2013-9-24 20:36:22 | 显示全部楼层
我以前写的
  1. /*
  2. * 看了很久才发现这个是软件
  3. * 模拟UART.所以用不到UART
  4. * 控制器.基本思想是定时器根据
  5. * 波特率来产生中断,每次中断的
  6. * 时候I/O根据发送内容来翻转.
  7. */

  8. #include<msp430.h>

  9. #define RED_LED BIT0
  10. #define GRN_LED BIT6

  11. #define BUTTON BIT3

  12. #define TXD BIT1
  13. #define RXD BIT2

  14. /*
  15. * 2400 bps -> 52
  16. */

  17. #define TPB 52

  18. int TXWord;
  19. unsigned char bitcnt = 0;

  20. void inituart(void);
  21. void sendbyte(unsigned char b);
  22. void sendstring( const char *str);

  23. void main(void)
  24. {
  25.     /*关闭看门狗*/
  26.         WDTCTL = WDTPW + WDTHOLD;
  27.    
  28.         /*LED设置为输出模式*/
  29.         P1DIR |= RED_LED + GRN_LED;
  30.         P1OUT &= ~(RED_LED + GRN_LED);
  31.    
  32.         /*初始化UART*/
  33.         inituart();
  34.    
  35.         /*
  36.          * 初始化按键
  37.          * 输入模式
  38.          */
  39.         P1DIR &= ~BUTTON;
  40.         /*中断标志清零*/
  41.         P1IFG &= ~BUTTON;
  42.         /*中断标志使能*/
  43.         P1IE |= BUTTON;
  44.    
  45.         for(;;)
  46.         {
  47.                 /*全局中断开,进入低功耗模式LPM3*/
  48.                 _BIS_SR(LPM3_bits + GIE);
  49.                 /*发送字符串*/
  50.                 sendstring("XIAO JB\r\n");
  51.         }
  52. }

  53. void inituart(void)
  54. {
  55.     /*I/O初始化*/
  56.         P1OUT |= TXD;
  57.         P1DIR |= TXD;
  58.    
  59.         /*时钟初始化*/
  60.         BCSCTL1 = CALBC1_1MHZ;
  61.         DCOCTL = CALDCO_1MHZ;
  62.         /*SMCLK4分频,SMCLK=1000KHz/4=500KHz*/
  63.         BCSCTL2 &= ~(DIVS_3);

  64.     /*定时器初始化,SMCLK,向上计数,500KHz/8=62.5KHz,计数器清零*/
  65.         TACTL = TASSEL_2 + MC_1 + ID_3 + TACLR;
  66.         TACCR0 = TPB;
  67. }

  68. void sendbyte(unsigned  char b)
  69. {
  70.         TXWord = b;
  71.         TXWord |= 0x100;
  72.         TXWord <<= 1;

  73.         bitcnt = 10;
  74.    
  75.     /*清零计数器*/
  76.         TACTL |= TACLR;
  77.         /*清零中断标志位*/
  78.         TACCTL0 &= ~CCIFG;
  79.         /*中断使能*/
  80.         TACCTL0 |= CCIE;

  81.     /*等待中断发生*/
  82.         while(TACCTL0 & CCIE)
  83.         {
  84.                 _BIS_SR(LPM0_bits + GIE);
  85.         }
  86. }

  87. /*发送一个字符串*/
  88. void sendstring(const char *str)
  89. {
  90.         char *c = str;
  91.         for(; *c; c++)
  92.         {
  93.                 sendbyte(*c);
  94.         }
  95. }

  96. /*定时器中断函数声明*/
  97. void TimerA0(void) __attribute__((interrupt(TIMER0_A0_VECTOR)));
  98. void TimerA0(void)
  99. {
  100.     /*中断标志位清零*/
  101.         TACCTL0 &= ~CCIFG;
  102.    
  103.         /*如果位计数器为零,发送完毕,返回*/
  104.         if(!bitcnt)
  105.         {
  106.                 TACCTL0 &= ~CCIE;
  107.                 __bic_SR_register_on_exit(LPM0_bits);
  108.                 return;
  109.         }
  110.         else
  111.         {   
  112.             /*判断要发送的字节的第一位*/
  113.                 if(TXWord & 0x01)
  114.                 {
  115.                         P1OUT |= TXD;
  116.                         P1OUT |= RED_LED;
  117.                         P1OUT &= ~GRN_LED;
  118.                 }
  119.                 else
  120.                 {
  121.                         P1OUT &= ~TXD;
  122.                         P1OUT |= GRN_LED;
  123.                         P1OUT &= ~RED_LED;
  124.                 }
  125.                
  126.                 /*左移,继续发送,直至bitcnt==0*/
  127.                 TXWord >>= 1;
  128.                 bitcnt --;
  129.         }
  130. }

  131. /*按键中断函数声明*/
  132. void Port_1(void) __attribute__((interrupt(PORT1_VECTOR)));
  133. void Port_1(void)
  134. {   
  135.     /*清零中断标志位*/
  136.         P1IFG &= ~BUTTON;
  137.         /*退出低功耗模式LPM3*/
  138.         __bic_SR_register_on_exit(LPM3_bits);
  139. }
复制代码

出0入0汤圆

 楼主| 发表于 2013-9-24 21:09:39 | 显示全部楼层
笑笑我笑了 发表于 2013-9-24 20:36
我以前写的

这是模拟发送,有接收部分吗?

出0入0汤圆

发表于 2013-9-24 22:09:30 | 显示全部楼层
接收结束的时候判断1.5个停止位就可以了!你上BAIDU文库搜搜把!

出0入0汤圆

 楼主| 发表于 2013-9-25 11:15:29 | 显示全部楼层
activeleo 发表于 2013-9-24 22:09
接收结束的时候判断1.5个停止位就可以了!你上BAIDU文库搜搜把!

百度文库没有找到有用的信息,也偿试了接收停止位(在收到第8位数据后,又执行了一个1.5位的等待--通过定时器的比较模式实现),情况与之前一模一样。

出0入0汤圆

 楼主| 发表于 2013-9-25 18:21:27 | 显示全部楼层
接收已经正常了,呵呵,心情不错。原因是主系统时钟频率比较低,中断处理程序的运行时间稍长,再次打开捕获时,错过了正确的起始位。

出0入0汤圆

 楼主| 发表于 2013-9-25 18:23:16 | 显示全部楼层
波特率降到2400,或者仍然使用9600,但是发送采用两个停止位,这两种方式都正确接收数据。

出0入13汤圆

发表于 2013-9-25 20:53:29 | 显示全部楼层
//******************************************************************************
//  MSP430F20xx Demo - Timer_A, Ultra-Low Pwr UART 2400 Echo, 32kHz ACLK
//
//  Description: Use Timer_A CCR0 hardware output modes and SCCI data latch
//  to implement UART function @ 2400 baud. Software does not directly read and
//  write to RX and TX pins, instead proper use of output modes and SCCI data
//  latch are demonstrated. Use of these hardware features eliminates ISR
//  latency effects as hardware insures that output and input bit latching and
//  timing are perfectly synchronised with Timer_A regardless of other
//  software activity. In the Mainloop the UART function readies the UART to
//  receive one character and waits in LPM3 with all activity interrupt driven.
//  After a character has been received, the UART receive function forces exit
//  from LPM3 in the Mainloop which echo's back the received character.
//  ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO
//  //* An external watch crystal is required on XIN XOUT for ACLK *//       
//
//               MSP430F20xx
//            -----------------
//        /|\|              XIN|-
//         | |                 | 32kHz
//         --|RST          XOUT|-
//           |                 |
//           |   CCI0B/TXD/P1.5|-------->
//           |                 | 2400 8N1
//           |   CCI0A/RXD/P1.1|<--------
//
#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

volatile unsigned int RXTXData;
volatile unsigned char BitCnt;

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

//  M. Buccini / L. Westlund
//  Texas Instruments Inc.
//  October 2005
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.40A
//******************************************************************************

#include <msp430.h>
/* main.c */
#include <stdio.h>
#include "linkedlist.h"
void print_item(link p)
{
  printf("%d\n", p->item);
}

int 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;                              //
  P1DIR |= 0x01;                            // Set P1.0 to output direction
//LPM3;
// Mainloop
  for (;;)
  {
  P1OUT ^= 0x01;                            // LED Flash
  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
  
link p = make_node(10);
insert(p);
p = make_node(5);
insert(p);
p = make_node(90);
insert(p);
p = search(5);
delete(p);
free_node(p);
traverse(print_item);
destroy();
p = make_node(100);
push(p);
p = make_node(200);
push(p);
p = make_node(250);
push(p);
while (p = pop())
{
  print_item(p);
  free_node(p);
}
  
  
  
  }
}


// Function Transmits Character from RXTXData Buffer
void TX_Byte (void)
{
  unsigned char Tar = 0;                   // Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
  unsigned char Ccr = 0;                   //
  
  BitCnt = 0xA;                             // Load Bit counter, 8data + ST/SP
  Tar = TAR;
  Ccr = CCR0;
  //while ( CCR0 != TAR )                       // Prevent async capture
  //  CCR0 = TAR;                             // Current state of TA counter
  while ( Ccr != 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, disable 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, disable interrupt
      _BIC_SR_IRQ(LPM3_bits);               // Clear LPM3 bits from 0(SR)
      }
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    }
  }
}

/*------------------------------------------------------------------------------
    if ((0x10 & P1IN)) P1OUT |= 0x01;       // if P1.4 set, set P1.0
    else P1OUT &= ~0x01;                    // else reset
------------------------------------------------------------------------------*/
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-11 05:50

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表