MSP430程序库UART异步串口

发布者:快乐心跳最新更新时间:2020-06-17 来源: eefocus关键字:MSP430  程序库  UART  异步串口 手机看文章 扫描二维码
随时随地手机看文章

硬件介绍:

MSP单片机的USART模块可以配置成SPI(同步通信)模式或UART(异步通信)模式,这里只讨论UART方式。UART数据传输格式如下:

image

起始位,数据位由高到低7/8位,地址位 0/1位,奇偶校验位 奇偶或无,停止位1/2位。数据位位数、地址位、奇偶校验位、停止位均可由单片机内部寄存器控制;这两款单片机都有两个USART模块,有两套独立的寄存器组;以下寄存器命中出现x代表0或是1,0代表对应0模块的寄存器,1代表对应1模块的寄存器;其中,与串口模式设置相关的控制位都位于UxCTL寄存器,与接收相关的控制位都位于UxRCTL寄存器,与发送相关的控制位都位于UxTCTL寄存器;波特率设置用UxBR0、UxBR1、UxMCTL三个寄存器;接收与发送有独立的缓存UxRXBUF、UxTXBUF,并具有独立的移位寄存器和独立的中断;中断允许控制位位于IE1/2寄存器,中断标志位位于IFG1/2寄存器。


波特率设置:430的波特率设置用三个寄存器实现,

UxBR0:波特率发生器分频系数低8位。

UxBR1:波特率发生器分频系数高8位。

UxMCTL:波特率发生器分频系数的小数部分实现。

设置波特率时,首先要选择合适的时钟源:USART模块可以设置的时钟源有UCLK引脚、ACLK、SMCLK;对于较低的波特率(9600以下),可选ACLK作为时钟源,这样,在LPM3(低功耗3)模式下,串口仍能正常发送接收数据;另外,由于串口接收过程有一个三取二判决逻辑,这至少需要三个时钟周期,因此分频系数必须大于3;波特率高于9600时,将不能使用ACLK作为时钟源,要调为频率较高的SMCLK作为时钟源;另外还可以外部输入UCLK时钟。分频系数计算公式如下:

image

小数分频是MSP430单片机的串口特色之一,UxMCTL寄存器的作用就是控制小数的分频,控制方法如下:对应位是1,则分频系数加一,0则分频系数减一;小数分频器会自动依次取出每一位来调整分频系数。其计算方法:可以先计算小数部分一的个数,然后把1均匀的放入UxMCTL的8位中,这样计算比较简单,分频系数的小数部分乘以8即得到1的位数,查表得到对应的UxMCTL值;另外一种通过计算每一位的错误率,交互计算,直到得到最小错误率的UxMCTL值,这种方法比较复杂,但得到的小数分频误差更小,这种方法也是TI给的计算方法,详细参考UserGuide。


另外,有关寄存器,以及其他单片机硬件有关知识请参考德州仪器提供的用户指南和数据手册等资料。


程序实现:

宏定义:是程序具有更好的移植性。

对模块的寄存器进行宏定义,把0/1换成x,使用时,只需更改宏定义即可更改程序是使用哪个模块;这样程序就具有了比较好的移植性。


/***********************************宏定义*********************************/

#define UxCTL   U0CTL

#define UxRCTL  U0RCTL

#define UXTCTL  U0TCTL


#define UxBR0   U0BR0

#define UxBR1   U0BR1

#define UxMCTL  U0MCTL


#define UxRXBUF U0RXBUF

#define UxTXBUF U0TXBUF


#define UxME    U0ME

#define UxIE    U0IE

#define UxIFG   U0IFG


#define UTXEx   UTXE0

#define URXEx   URXE0


#define URXIEx  URXIE0

#define UTXIEx  UTXIE0


#define UARTON  P3SEL |= 0X30           // P3.4,5 = USART0 TXD/RXD

/**************************************************************************/

程序改为UART1时,只需把宏定义中的0改为1  UARTON改为对应端口的即可

异步串口初始化(UartInit):完成波特率,停止位以及其他相关的设置。

串口初始化,首先是波特率寄存器值的计算和设置:本程序选用第二种:通过运算,选取误差最小的寄存器所需值进行设置。


波特率寄存器值根据所选时钟频率和所需波特率值进行设置,计算方法:从m0(UxMCTL最低位)开始计算,根据这一位的误差(0或1时)误差较小的bit值,直到计算完成。


为了更好的写这个程序,我先用C语言写了一个简单的波特率计算软件,为了让设置波特率的函数能够在单片机程序中复用,程序用宏定义模拟的MSP430单片机的波特率寄存器。完整程序如下:


#include

#include


//函数声明

void SetBaudRateRegisters(long clk,int baud);


/************************宏定义***********************/

#define UxBR1    a[0]

#define    UxBR0    a[1]

#define    UxMCTL    a[2]


unsigned char a[3];                     //数组模拟寄存器

void main()

{

    long clk;                           //时钟

    long baud;                           //波特率

    printf("t---波特率计算软件!---n");

    printf("n请输入时钟频率(Hz):");

    scanf("%ld",&clk);                    

    printf("n请输入波特率:");

    scanf("%ld",&baud);

    getchar();                          //读取多余回车符


    SetBaudRateRegisters(clk,baud);     //设置寄存器值


    //显示寄存器值

    printf("nUxBR1:0x%xtUxBR0:0x%xtUxMCTL:0x%xn",UxBR1,UxBR0,UxMCTL);

    

    getchar();

}


/****************************************************************************

* 名    称:SetBaudRateRegisters

* 功    能:根据时钟 波特率设置对应寄存器

* 入口参数:

*           clk:        所选时钟频率(如:32768)

            baud        波特率      (300~115200)

* 出口参数:无

* 范    例: SetBaudRateRegisters(32768,9600) //用时钟频率32768产生9600的波特率

****************************************************************************/

void SetBaudRateRegisters(long clk,long baud)

{

    int n = clk / baud;     //整数波特率

    char mSum = 0;            //Σmi

    int txEr0;              //对应位为0时错误率

    int txEr1;              //对应位为1时错误率

    char i = 0;             //循环计数


    UxBR1 = n >> 8;         //高8位

    UxBR0 = n & 0xff;       //低8位

    UxMCTL = 0;

    

    //循环 比较错误率大小 设置UxMCTL

    for(;i < 8;i++)

    {

        txEr0 = 100 * baud * ((i + 1) * n + mSum) / clk - 100 * (i + 1);

        txEr1 = 100 * baud * ((i + 1) * n + mSum + 1) / clk - 100 * (i + 1);

        if(abs(txEr1) < abs(txEr0))

        {

            mSum++;

            UxMCTL |= (1<        }

    }

}

程序可以使用任何的C语言编译器编译运行,可供网友们复用此程序。我使用vs2010编译运行的,运行结果如下:

image

运行效果很好,和官方给出的值一样,但是也不全都是这样,4800的波特率(时钟:32768)时就不一样,可能是我计算式只是用了发送时的误差计算,没有用接收误差,计算结果稍有出入,如果有兴趣,网友可以自行添加接收误差,判断;应该就和官方给出的数值完全一样了。


初始化函数:初始化函数完成串口时钟源选择,波特率初始化,奇偶校验,数据位,停止位,以及其他相关设置。


时钟源选择:根据波特率选取时钟源,波特率大于9600,选1M的SMCLK时钟(需要初始化时钟系统对应函数参考使用示例),小于9600,选ACLK(32768)以使功耗降低(低功耗3仍能正常收发数据)


UxTCTL &=~ (SSEL0+SSEL1);       //清除之前的时钟设置

if(baud<=9600)                  //brclk为时钟源频率

{

  UxTCTL |= SSEL0;              //ACLK,降低功耗

  brclk = 32768;                //波特率发生器时钟频率=ACLK(32768)

}

else

{

  UxTCTL |= SSEL1;              //SMCLK,保证速度

  brclk = 1000000;              //波特率发生器时钟频率=SMCLK(1MHz)

}

波特率设置:直接调用之前实现的设置寄存器函数即可,当波特率在正常范围外时,返回0。


    //------------------------设置波特率-------------------------   

    if(baud < 300||baud > 115200)   //波特率超出范围

    {

        return 0;

    }

    SetBaudRateRegisters();         //设置波特率寄存器

奇偶校验、数据位位数、停止位数设置:比较简单,直接根据参数值设置对应寄存器即可。


//------------------------设置校验位-------------------------  

switch(parity)

{

    case 'n':case'N': UxCTL &=~ PENA;               break;  //无校验

    case 'p':case'P': UxCTL |= PENA + PEV;          break;  //偶校验

    case 'o':case'O': UxCTL |= PENA; UxCTL &=~ PEV; break;  //奇校验  

    default :         return(0);                            //参数错误

}


//------------------------设置数据位-------------------------    

switch(dataBits)

{

    case 7:case'7': UxCTL &=~ CHAR; break;      //7位数据

    case 8:case'8': UxCTL |= CHAR;  break;      //8位数据

    default :       return(0);                  //参数错误

//------------------------设置停止位-------------------------    

switch(stopBits)

{

    case 1:case'1': UxCTL &= ~SPB;  break;      //1位停止位

    case 2:case'2': UxCTL |= SPB;   break;      //2位停止位

    default :       return(0);                  //参数错误

}

其他:包括串口收发使能,串口接收和发送中断设置,第二功能打开等。


    UARTON;                     //端口使能

    UxME |= UTXEx + URXEx;      //发送 接收使能

    

    UCTL0 &= ~SWRST;            // Initialize USART state machine

    

    UxIE |= URXIEx + UTXIEx;    // Enable USART0 RX interrupt 

到此,MSP430异步串行口的初始化工作全部完成,如果需要其他的方式,只需对应设置寄存器即可。


写字符(UartxWriteChar):向UARTx模块写(发送)一个字符。

写字符:向串口写入一个字符,通过串口向终端发送一个字符。


void UartWriteChar(char c)

  while (TxFlag==0) UartLpm();  // 等待上一字节发完,并休眠

  TxFlag=0;                     //

  UxTXBUF=c;

}

这个函数根据程序标志TxFlag判断上一字符是否发送完成,此标志位将在发送中断中被置位,表示本字符发送完成。发送中断程序如下:


#pragma vector=UARTxTX_VECTOR

__interrupt void UartTx ()

{

  TxFlag=1;

  __low_power_mode_off_on_exit();

}

发送字符时,先等待上一字符发送完成,然后把字符放入发送缓冲区,待发送完成,中断置标志位,指示发送完成。


读取字符(UartxReadChar):从UARTx模块读取(获取)一个字符。

读取字符和写字符类似:调用读取函数后,等待标志位,接收到字符后,读出来。


char UartReadChar()

  while (RxFlag==0) UartLpm(); // 收到一字节?

  RxFlag=0;

  return(UxRXBUF);

}

同样,RxFlag指示收到一个字符,并且在中断中被置位。中断程序如下:


#pragma vector=UARTxRX_VECTOR

__interrupt void UartRx()

{

  RxFlag=1;

  /*在这里添加用户中断服务程序代码,如将数据压入接收缓冲等*/

  __low_power_mode_off_on_exit();

}

读取函数将阻塞,如果收不到字符,CPU将一直处于低功耗状态。


写字符串(UartxWriteStr):向UARTx模块写(发送)一个字符串。

写字符串只需调用写字符函数即可,比较简单,程序如下:


void UartWriteStr(char *s)

{

    while(*s)

    {

        UartWriteChar(*s++);

    }

}

这样,即可调用这个函数通过串口发送字符串。

头文件:头文件把要调用的函数声明放进去,需要使用函数时只需包含此文件,不需要再进行函数声明。

头文件内容如下:


#ifndef __UART_H

#define __UART_H


char UartInit(long baud,char parity,char dataBits,char stopBits);

void UartWriteChar(char c);

void UartWriteStr(char *s);

char UartReadChar();


#endif /* __UART_H */

其中#ifndef 等预编译用来防止重复包含。


程序调用示例:

要调用这个函数库,首先要包含Uart.h头文件;把Uart.h拷到对应文件夹中,然后在要调用程序的源程序文件中添加文件包含:


#include "msp430x16x.h"   //430寄存器头文件

#include "Uart.h"         //串口通讯程序库头文件

然后,在项目中加入Uart.c,把Uart.c拷入项目文件夹中,在项目中添加文件,加入后文件结构大致如下图:

image

如果要用9600以上的波特率,需要把SMCLK设为1M,我的程序调用了以下的这个函数,把MCLK设为8MHz,SMCLK设为1MHz:


void ClkInit()

{

    char i;

    BCSCTL1 &= ~XT2OFF;             //打开XT2振荡器

[1] [2]
关键字:MSP430  程序库  UART  异步串口 引用地址:MSP430程序库UART异步串口

上一篇:MSP430平台下实现Si4432的收发数据
下一篇:MSP430F149小系统开发板实现RS232串口通信

推荐阅读最新更新时间:2024-11-18 19:06

MSP430-定时器的寄存器介绍以及测试应用
本文介绍的是MSP430内部的定时器1 测试代码如下: #include io430.h #include in430.h //demo,led闪烁 void Init_TimeA(void); int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; Init_TimeA(); P2DIR = 0XFF; P2OUT = 0XFF; return 0; } void Init_TimeA(void) { TACTL = T
[单片机]
MSP430-定时器的寄存器介绍以及测试应用
LCD1602动态显示--基于MSP430F149单片机
main.c /*************************************************** 程序功能:动态显示文字“welcome!” ---------------------------------------------------- 测试说明:观察液晶显示 ****************************************************/ #include msp430.h #include Cry1602.h #define uchar unsigned char uchar *s1 = welcome! ; void main( void ) {
[单片机]
MSP430f149使用XT2的8M晶振输出PWM
由于需要将PWM保持在20khz来控制BUCK电路降压,同时又需要步进改动占空比,故需要TA利用8M晶振输出PWM,经测试,最大占空比频率可达4M,将频率定为20khz时,有200个步进点,BUCK输入电压为18V,每次改变占空比输出电压约变化0.1V可达到要求。 系统版XT2IN与XT2O直接连接高频晶振8M晶振,TI官方例程所给程序无使用XT2的程序(但是有开启HF XTAL的:BCSCTL1 |= XTS;)由于我们的板子8M晶振被接在了XT2IN和XT2O上,所以只能使用(BCSCTL1 &= ~XT2OFF; //打开XT2高频晶体振荡器)来打开8M晶振,之后通过(BCSCTL2 |= SELM_2 + SELS;
[单片机]
STM32 UART 初始化
因为想用串口3,但配置了很长时间还是不行,为什么UART1,2行,UART3就不行的,最后原因是:使能GPIOB,端口时钟 USART3时钟,我只使能了UART3时钟,没有使能UART3所在端口GPIOB的时钟,所以导致无法正常启动串口3。 下面具体写下串口配置过程: 1:系统时钟初始化,包括系统时钟和要开放的IO口和串口的时钟配置。 2:IO口初始化,包括引脚,速率,输入输出模式等。 3:配置USART的波特率,数据位等。 对应的3个函数,相当有条理 /--------------——————--------------------------------------------------------------
[单片机]
MSP430单片机各种寄存器总结(1)——CPU 寄存器
参考资料: 王宏波老师的PPT MSP430F6638用户手册 王宏波老师实验教程 第一章 CPU 寄存器 1.1 PC——程序计数器 取完指令后CPU根据该指令的字节数自动增量PC,因此20位的PC(R0)的值总是指向下一条要执行的指令。 PC总是指向偶地址(bit0=0) 1.2 SP——堆栈指针 CPU使用20位堆栈指针(SP,也称为R1)来存储子例程调用和中断的返回地址。 【作用】:保护现场和恢复现场。 它使用先进后出方案。 SP由用户初始化为RAM,并且始终与偶数地址对齐。 堆栈分两种: 向上增长,栈底占用较低地址,栈顶占用较高地址 : 8051 向下增长,栈底占用较高地址,栈顶占用较低地址: MS
[单片机]
<font color='red'>MSP430</font>单片机各种寄存器总结(1)——CPU 寄存器
MSP430F249UART
//****************************************************************************** // MSP430x24x Demo - USCI_A0, 9600 UART Echo ISR, DCO SMCLK // // Description: Echo a received character, RX ISR used. Normal mode is LPM0. // USCI_A0 RX interrupt triggers TX Echo. // Baud rate divider with 1MHz = 1MHz/9600 = ~104.2
[单片机]
MSP430汇编指令
指 令 操作数位置及执行过程 说 明 状 态 位 代 码 源操作数 目的操作数 指令执行过程详述 VNZC ADC 或ADC.B dst dst+C- dst 进位C 加至目的操作数目的操作数以前的内容丢失 **** ADD 或ADD.B src,dst src+dst- dst 源操作数加至目的操作数源操作数不受影响目的操作数以前的内容丢失 **** ADDC 或ADDC.B src,dst src+dst+C- dst 源操作数和进位C 加至目的操作数源操作数不受影响目的操作数以前
[单片机]
基于MSP430的智能仪表与组态王的通讯设计
1 引言   目前组态王与单片机的通信多是通过动态数据交换或自己开发通讯驱动程序的方式进行的 。动态数据交换(DDE)是Windows平台上一个完整的通讯协议,通过DDE使应用程序之间彼此能交换数据和发送指令。但使用DDE会带来一些额外的开销,如会降低系统实时性、增加系统的不可靠性,特别在多参数传送时不太稳定,易出现数据丢失现象。而自己开发通讯驱动程序又有一定的难度,且开发周期较长。最近,在为九江石化燃运输煤皮带监控系统的设计中,基于MSP430单片机的智能仪表作为下位机,研华公司的工控机作为上位机,采用ADAM-5000的协议,实现了数据的实时采集、处理和显示。 2 系统结构   燃运皮带监控系统整体结构如图1所示。现场的
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved