msp430f4152 TimerA模拟UART

2019-07-22 13:11发布

本程序主要特点是发送与接收所用的是不同定时器的不同通道,刚接触到这个问题,在网上没有找着例程,连官网的也是发送与接收用的同一定时器,就自己开始编写调试了  现把调通的代码贴上
/*
由于此处发送为P5.0/TA1.1,接收引脚为P7.6/TA0.2,发送接收是不同的定时器,可同时用接收产生捕获和定时,故发送接收可以进同一个中断
标志位Flag_RX是由于发送接收产生中断方式不同,故用标志位来判断是发送还是接收
*/
//利用捕捉比较功能实现异步串行通信。   
//芯片型号:MSP430F4152   p7.6---RX    P5.0--TX
//Timer_A TACLK=ACLK   
//波特率为 2400BIT/S TBIT1=14 TBIT0_5=6  
//帧格式:(0)XXXXXXXX(1),0为起始位,1为结束位,XXXXXXXXX为8位数据

#include  <msp430f4152.h>  
#define TBIT1 14;                      //TBIT1 为1 位时间   
#define TBIT0_5 6;                    //TBIT0_5 为半位时间  
#define TBIT1_5 20;

#define TXD BIT0                      //使用P1.0作为发送,特殊功能脚,用CCI0A做比较输出  
#define TXD_DIR P5DIR
#define TXD_SEL P5SEL
#define TXD_OUT P5OUT

#define RXD BIT6                     //使用P1.1作为接收,特殊功能脚,用CCI0B做捕获输入  
#define RXD_DIR P7DIR
#define RXD_SEL P7SEL

unsigned char Flag_RX;
unsigned int TR_COUNT;                   //发收计数器   
unsigned int T_DATA=0x00;              //发送缓冲器   
unsigned int R_DATA=0x00;             //接收缓冲器   
void init(void);                                  //初始化   
void txd (unsigned char byte);          //发送一字节数据   
void rxd(void);                                 //接收准备子程序   

main()   
{   
    init();  
    while(1)  
    {  
      rxd();                                 //准备接收   
      LPM3;                               //进入休眠状态,收到数据后在唤醒  
      txd(R_DATA);                 //把收到的数据重发  
    }  
}   

void init(void)                           
{   
    WDTCTL=WDTPW+WDTHOLD;                  //停止WDT   
    RXD_SEL|=RXD;  //选择为外部模块功能
    RXD_DIR&=~RXD; //设置接收引脚为输入模式

    TXD_SEL&=~TXD; //   关键点1:此处发送用的是定时器的比较功能,在发送阶段使其输出数据,所以需要设为I/O功能
    TXD_DIR|=TXD;     

    Flag_RX = 1;        //关键点2:由于不需要用发送的捕获,所以不能用CCISx来判断是发送接收,故需要一个标志位

    TACTL|=TASSEL_1+MC_2;                          //设定时器A 时钟源ACLK,设定时器为连续模式   
    _EINT();                                                            //开中断允许   
}   
//******************************************************  
//发送一字节数据子程序   
//输入参量:unsigned char 类型字节   
// *****************************************************  
void txd(unsigned char byte)   
{      
    T_DATA=byte;
    CCR2=TAR;                        //将TAR 时间存入CCR2,确定第一位 长度。   
    CCR2+=TBIT1;                  //将每1 位时间周期加入CCR2。   
    TR_COUNT=0x0A;                     //发送计数器。   
    CCTL2=CCIE;
    while(CCIE&CCTL2);               //等待CCIE 是否为0?为0 则表示发送完数据。   
}   
// *****************************************************  
//接收准备子程序   
//依赖TA0 中断来接收一字节数据。   
// *****************************************************  
void rxd(void)   
{  
    TR_COUNT=8;                             //接收数据位 位数
    CCTL2 = SCS + CCIS_0 + CM_2 + CAP + CCIE;
    // 比较捕获为输出模式+比较捕获模块为中断允许+下降沿捕获+设置为捕获模式   
    //+选择CCI2A 为捕获源+同步捕获   
}   
//*******************************************************************************   
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER0_A1(void)
{   
   switch(TA0IV)
  {
  case TA0IV_TACCR1:  break;   
  case TA0IV_TACCR2:
    if(Flag_RX == 1)    //发送和接收用的分别是TA1和TA0的中断    //接收处理
//   if(((CCTL2 & CCIS0)||(CCTL2 & CCIS1)) == 0) //是处于接收中还是发送中?   关键点3:发送不用捕获,不用此语句判断
    {  
        if(CCTL2&CAP)                   //是捕获模式还是比较模式?   
        {           
          CCTL2&=~CAP;                //是-开始捕获,将捕获功能改为比较功能   
          CCR2+=TBIT1_5;           //开始捕获位再加半位时间   
        }  
        else   
        {  
          R_DATA=R_DATA>>1;            //处于比较功能,将前面 那位向低位移.  
          if(CCTL2&SCCI)                        //这句等效于(P1IN&RXD)==1,如果RXD管脚是高电平  
          {  
            R_DATA|=BIT7;                    //则R_DATA的最高位置1  
          }  
          TR_COUNT--;                        //计数器减1  
          CCR2+=TBIT1;
          if(TR_COUNT==0)              //是否接收完8 位?   
          {   
            CCTL2&=~CCIE;           //是接收完,捕获/ 比较块停止中断充许   
            Flag_RX = 0;
            LPM3_EXIT;             //退出低功率模式(一般,在进入LPM3 时才使用)   
          }   
        }   
    }                              //接收结束   
    //----------------------------------------------------------------   
    else                           //发送处理
    {   
      switch(TR_COUNT)
      {
      case 0x0a:  TA0CCR2+=TBIT1;                                     TXD_OUT&=~TXD;   TR_COUNT--; break;  //起始位
      case 0x09:  TA0CCR2+=TBIT1; if(T_DATA&0x01){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;  
      case 0x08:  TA0CCR2+=TBIT1; if(T_DATA&0x02){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;      
      case 0x07:  TA0CCR2+=TBIT1; if(T_DATA&0x04){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;  
      case 0x06:  TA0CCR2+=TBIT1; if(T_DATA&0x08){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;
      case 0x05:  TA0CCR2+=TBIT1; if(T_DATA&0x10){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;
      case 0x04:  TA0CCR2+=TBIT1; if(T_DATA&0x20){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;
      case 0x03:  TA0CCR2+=TBIT1; if(T_DATA&0x40){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;
      case 0x02:  TA0CCR2+=TBIT1; if(T_DATA&0x80){TXD_OUT|=TXD;} else{TXD_OUT&=~TXD;}  TR_COUNT--; break;
      case 0x01:  TA0CCR2+=TBIT1;                                     TXD_OUT|=TXD;    TR_COUNT--;   break;  //停止位
      case 0x00:  CCTL2&=~CCIE;       Flag_RX = 1;                                                                    break;
        }
    }
  break;
  }
}  
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
dirtwillfly
1楼-- · 2019-07-22 17:49
感谢分享
i1mcu
2楼-- · 2019-07-22 21:42
定时器模拟uart
i1mcu
3楼-- · 2019-07-23 02:18
 精彩回答 2  元偷偷看……
vibra2016
4楼-- · 2019-07-23 07:27
这个模拟的程序非常不错的,参考的。
lzbf
5楼-- · 2019-07-23 11:48
定时器模拟的波特率不准
lzbf
6楼-- · 2019-07-23 15:52
而且最大的波特率还不是很高。

一周热门 更多>