社区导航

 

搜索
查看: 203|回复: 1

[分享] MSP430g2553硬件UART(基于官方例程的修改)

[复制链接]

3015

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2020-2-10 21:03 | 显示全部楼层 |阅读模式

一开始官方例程的UART_Keyboard在电脑上老是运行不了,于是就自己上网学习了一下UART实现的具体过程,修改了一下官方的例程代码,在这里记录一下
其实官方例程有时候运行不起在于:
1.波特率设置
2.官方的Rx中断处理函数并不适用于所有串口调试程序
3.注意跳线帽!!!RX接TX,TX接RX!!

官方例程的UART程序流程
这里我用onenote大致画了一下
对于Tx和Rx中断:
当单片机内部的Rx_buf寄存器(一般来说8bits)收到了无符号字符型数据时,就会产生Rx中断,系统调用Rx中断处理函数,也就是说当收到一个字符串型数据时系统会产生多次Rx中断。
当单片机内部的Tx_buf寄存器(也是8bits)将数据发送完毕时,会产生Tx中断,同理,当发送一个字符串型数据时系统会产生多次Tx中断。
对于FIFO:
也就是申明的存储字符型数据的字符数组
RxFIFO用来读取Rx_buf传来的字符型数据,并供给CPU进行读取
TxFIFO用来存放CPU准备发送的数据,并让Tx_buf进行读取
所以每个FIFO要用三个变量来表示:读指针位置,写指针位置,已有的容量大小

image.png
代码分析
main.c
可以看出来主函数只起到了关闭看门狗的作用,精华都在初始化UART函数中


int main(void)
{
 WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
 USCI_A0_init();
}

USCI_A0_init()
void USCI_A0_init(void){
    //配置时钟
      DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_1MHZ;                    // Set DCO 实际时钟频率1048576Hz
      DCOCTL = CALDCO_1MHZ;
      //配置GPIO寄存器
      P1SEL = BIT1 + BIT2 ;                     // P1.1 = RXD, P1.2=TXD
      P1SEL2 = BIT1 + BIT2 ;                    // P1.1 = RXD, P1.2=TXD
    //配置串口寄存器
      UCA0CTL1 |= UCSSEL_2;                     // SMCLK
      UCA0BR0 = 104;                            // 1MHz 9600
      UCA0BR1 = 0;                              // 1MHz 9600
      UCA0MCTL =UCBRS_0;//UCBRS0;                        // Modulation UCBRSx = 1
      UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
     //开中断
      IE2 |= UCA0RXIE+UCA0TXIE;            //使能TX,RX中断
      _enable_interrupts();
     //设置单片机工作模式
      _bis_SR_register(LPM0_bits);        //单片机工作在LPM0功耗模式
 }

在这里有几个比较重要的寄存器需要说明:
UCA0CTL1:
时钟源选择和软件复位使能
UCSSEL_2:时钟源一般可以选择ACLK和SMCLK(官网例程选择了ACLK,这里选择SMCLK)
至于软件复位的那位UCSWRST:0被禁用。USCI复位被释放用于运行。1被启用。USCI逻辑保持在复位状态。意思就是说在单片机复位之后 如果 此位是0 那么串口可以正常工作 为1 即保持 复位状态 复位状态后 此位为1 就是说 复位后如果不清零 那么串口是不会工作的

UCA0BR0,UCA0BR1
波特率配置寄存器
给定一个BRCLK时钟源,波特率用来决定需要分频的因子N:
N = fBRCLK/Baudrate
分频因子N通常是非整数值,因此至少一个分频器和一个调制阶段用来尽可能的接近N。
所以:
UCA0BRX用来存放N的整数部分,其中BR0存放低位,BR1存放高位(这里的SMCLK时钟源频率大概为32khz)

UCA0MCTL
波特率调整控制器
有整数部分时不够的,还要有小数部分!
UCBRSx = round( ( N – INT(N) ) × 8 )
注意这个寄存器的最后一位时用来选择模式的!!我们这里用0模式!
给出一个计算列题:
例2:32768Hz频率下驱动以2400波特率异步通ACLK = REFO = ~32768Hz, MCLK = SMCLK = DCO ~1.045MHz
N = fBRCLK/Baudrate = 32768/2400 = ~13.65
UCBRx = INT(N) = INT(13.65) = 13
UCBRSx = round( ( N – INT(N) )×8 ) = round( ( 13.65 – 13) × 8 )=round(5.2)=5
UCA0CTL1 |= UCSSEL_1; // 选ACLK为时钟
UCAxBR0 = 13;
UCAxBR1 = 0 ;
UCAxMCTL = 0x0A;//7-4:
UCBRFx,3-1:UCBRSx,0:UCOS16
UCBRSx为寄存器UCAxMCTL的1-3位,所以写入0x0A(00001010)

定义中断处理函数
//====================================中断处理函数============================================
//TX中断处理函数
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
//    while(!(IFG2 & UCA0TXIFG));  //待发送为空
    IFG2&=~UCA0TXIFG;     // 手动清除标志位,标志位置零
    UART_OnTx();          // 调用Tx事件处理函数
}
//RX中断处理函数
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
//  while (!(IFG2&UCA0TXIFG));                // 等待发送完成
   IFG2&=~UCA0RXIFG;                // USCI_A0 TX buffer ready?
   UART_OnRx();                      //!!!!!!!EVENT.H函数!
//  UCA0TXBUF = UCA0RXBUF;                    // TX -> RXed character
}

这里改写了一下中断处理函数,想要试一试配置成功与否的话可以直接在Rx中断里面写:UCA0TXBUF = UCA0RXBUF;收到啥发啥

/******************************************************************************************************
 * 名       称:UART_OnRx()
 * 功       能:UART的Rx事件处理函数
 * 入口参数:无
 * 出口参数:无
 * 说       明:对接收到的数据,区别对待进行处理
 * 范       例:无
 ******************************************************************************************************/
void UART_OnRx()
{
    unsigned char Temp=0;           //定义读取的RX_buf中的8bits数
    Temp=UCA0RXBUF;                 //读取RX_buf中的数据
    //判断RXBUF中的收到的数据 1:回车,匹配数据 0:不是回车,放入FIFO中
    if(Temp==0x0d)                  //如果是回车
    {
        if(Rx_FIFO_DataNum>0)       //如果已经收到数据
        {
            Command_match();        //判断指令
//            Rx_FIFO_Clear();        //读取完一次指令,清零
        }
        else{
            UART_SendString(String1);       //没收到任何数据
        }
    }
    else                            //收到的不是回车,则读取数据
    {
        Rx_FIFO_WriteChar(Temp);    //写入数据到FIFO中
    }
}

/******************************************************************************************************
 * 名       称:UART_OnTx()
 * 功       能:UART的Tx事件处理函数
 * 入口参数:无
 * 出口参数:无
 * 说       明:Tx_FIFO里有数据就将数据移到Tx Buffer寄存器中去
 * 范       例:无
 ******************************************************************************************************/
void UART_OnTx(void)
{
 unsigned char Temp;
 if(Tx_FIFO_DataNum>0)           //数据量==0为结束条件
 {
  Tx_FIFO_ReadChar(&Temp); //调用FIFO库函数,返回8bit数据
  UCA0TXBUF= Temp;            //
 }
}


回复

使用道具 举报

1953

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

发表于 2020-2-12 08:55 | 显示全部楼层

不错的分享,必须顶一下啊

 


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 /5 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-2-21 10:15 , Processed in 0.101534 second(s), 18 queries , Gzip On, MemCache On.

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