MSP430单片机UART_FIFO 发送 接受
[复制链接]
一共有2个程序
程序1发送:
#include <msp430x42x.h>
#define TXBUF_SIZE 32 /*发送FIFO的最大容量*/
unsigned char TX_BUFF[TXBUF_SIZE]; /*发送FIFO缓冲区数组*/
unsigned int UART_OutLen=0; /*发送FIFO内待发出的字节数*/
unsigned int TX_IndexR=0; /*发送FIFO内的读指针*/
unsigned int TX_IndexW=0; /*发送FIFO内的写指针*/
/*****************************************************************
* 名 称:UART0_PutChar()
* 功 能:从串口发送1字节数据(向缓冲队列内填入1字节待发送数据)
* 入口参数:Chr:待发送的字节
* 出口参数:返回1表示发送成功,
返回0表示发送失败。
* 说 明: 发送过程中,不阻塞CPU运行
*****************************************************************/
char UART0_PutChar(unsigned char Chr)
{
if(UART_OutLen == TXBUF_SIZE) //如果FIFO已满
{
return (0); // 不发送数据,返回发送失败标志
}
if(UART_OutLen==0) // 如果是第一个字节
{
IFG1|=UTXIFG0; // 人为制造第一次中断条件
}
_DINT(); // 涉及FIFO操作时不允许中断,以免数据错乱
UART_OutLen++; // 待发送字节数加1
TX_BUFF[TX_IndexW] = Chr; // 待发送数据通过写指针写入FIFO
if (++TX_IndexW >= TXBUF_SIZE)// 写指针递增,且判断是否下标越界
{
TX_IndexW = 0; // 如果越界则写指针归零(循环队列)
}
IE1 |= UTXIE0; // 允许UART0的发送中断,在中断内依次发送数据
_EINT(); // FIFO操作完毕,恢复中断允许
return (1); // 返回发送成功标志
}
#pragma vector=UART0TX_VECTOR
__interrupt void UART_TX (void) // 串口发送中断
{
if(UART_OutLen>0) // FIFO内是否有待发送的数据?
{
UART_OutLen--; // 待发送数据字节数减1
U0TXBUF=TX_BUFF[TX_IndexR]; // 从尾指针读取一个字节并发送
if (++TX_IndexR >= TXBUF_SIZE)// 读指针递增,且判断是否下标越界
{
TX_IndexR = 0; // 如果越界则写指针归零(循环队列)
}
}
else IE1 &=~ UTXIE0; // 如果数据已发完,则关闭UART0的发送中断,停止发送
}
/*****************************************************************
* 名 称:UART0_PutChar_Legacy()
* 功 能:传统的从串口发送1字节数据程序,供对比用
* 入口参数:Chr:待发送的字节
* 说 明: 发送过程中,会阻塞CPU运行
*****************************************************************/
void UART0_PutChar_Legacy(char Chr)
{
TXBUF0=Chr;
while ((IFG1 & UTXIFG0)==0); // 等待该字节发完
}
void main( void )
{
WDTCTL = WDTPW + WDTHOLD; // 停止看门狗
FLL_CTL0 |= XCAP18PF; // 配置晶振负载电容
U0CTL = CHAR; // 异步通讯模式,8位数据,无校验,1位停止位。
ME1 |= UTXE0 + URXE0; // 开启串口0收发模块
U0TCTL |= SSEL0; // 选择ACLK作为串口波特率时钟源。
U0BR1 = 0; //
U0BR0 = 13; // 分频系数整数部分=13
U0MCTL = 0x6B; // 分频系数小数部分调制=5/8。(2400bps)
P2SEL |= BIT4 + BIT5; // P2.4,5 开启第二功能,作为串口收发引脚(不同单片机有差别)
_EINT(); // 总中断允许
while(1)
{
TACTL = TASSEL_2 + MC_2 + TAIE + TACLR; // 用TA测量传统发送程序所需时间
UART0_PutChar_Legacy(0x01);
UART0_PutChar_Legacy(0x02);
UART0_PutChar_Legacy(0x03);
UART0_PutChar_Legacy(0x04);
UART0_PutChar_Legacy(0x05); //测试,发送8字节数据
UART0_PutChar_Legacy(0x06);
UART0_PutChar_Legacy(0x07);
UART0_PutChar_Legacy(0x08);
TACTL = TASSEL_2 + MC_0; // TA停止计时
_NOP(); // 在这一句设断点查看TAR值(29652个周期)
__delay_cycles(1000000);
TACTL = TASSEL_2 + MC_2 + TAIE + TACLR; // 用TA测量带FIFO的发送程序所需时间
UART0_PutChar(0x01);
UART0_PutChar(0x02);
UART0_PutChar(0x03);
UART0_PutChar(0x04);
UART0_PutChar(0x05); //测试,发送8字节数据
UART0_PutChar(0x06);
UART0_PutChar(0x07);
UART0_PutChar(0x08);
TACTL = TASSEL_2 + MC_0; // TA停止计时
_NOP(); // 在这一句设断点查看TAR值 (440个周期)
__delay_cycles(1000000); //约一秒发送一次
}
}
复制代码
程序2接受:
#include <msp430x42x.h>
#define RXBUF_SIZE 32 /*接收FIFO的最大容量*/
unsigned char RX_BUFF[RXBUF_SIZE]; /*接收FIFO缓冲区数组*/
unsigned int UART_InpLen=0; /*接收FIFO内待读取的字节数*/
unsigned int RX_IndexR=0; /*接收FIFO的读指针*/
unsigned int RX_IndexW=0; /*接收FIFO的写指针*/
/*****************************************************************
* 名 称:UART0_GetChar()
* 功 能:从串口读取1字节数据(从缓冲队列内读取1字节已接收的数据)
* 入口参数:*Chr:读取数据所存放的地址指针
* 出口参数:返回1表示读取成功,返回0表示读取失败。
* 说 明: 读取过程中,不阻塞CPU运行
*****************************************************************/
char UART0_GetChar(unsigned char *Chr)
{
if(UART_InpLen==0) return(0); // 如果FIFO内无数据,返回0
_DINT(); // 涉及FIFO操作时不允许中断,以免指针错乱
UART_InpLen--; // 待读取数据字节数减1
*Chr=RX_BUFF[RX_IndexR]; // 从尾指针读取一个字节作为返回值
if (++RX_IndexR >= RXBUF_SIZE) // 读指针递增,且判断是否下标越界
{
RX_IndexR = 0; // 如果越界则写指针归零(循环队列)
}
_EINT(); // FIFO操作完毕,恢复中断允许
return (1); // 返回发送成功标志
}
/*****************************************************************
* 名 称:UART0_GetCharsInRxBuf()
* 功 能:获取FIFO内已接收的数据字节数
* 入口参数:无
* 出口参数:待读取的字节数
*****************************************************************/
unsigned int UART0_GetCharsInRxBuf()
{
return (UART_InpLen); // 返回FIFO内数据的字节数
}
/*****************************************************************
* 名 称:UART0_ClrRxBuf()
* 功 能:清除接收FIFO区
* 入口参数:无
* 出口参数:无
*****************************************************************/
void UART0_ClrRxBuf()
{
_DINT(); // 涉及FIFO操作时不允许中断,以免指针错乱
UART_InpLen=0; // 接收的数据清空
RX_IndexR=0;
RX_IndexW=0; // 头尾指针复位
_EINT();
}
#pragma vector=UART0RX_VECTOR
__interrupt void UART0_RX (void) // 串口接收中断
{
UART_InpLen++; // 接收字节计数加1
RX_BUFF[RX_IndexW] =U0RXBUF; // 串口接收数据通过写指针写入FIFO
if (++RX_IndexW >= RXBUF_SIZE) // 写指针递增,且判断是否下标越界
{
RX_IndexW = 0; // 如果越界则写指针归零(循环队列)
}
}
void main( void )
{
unsigned char RxDataBuff[8];
unsigned char Addr;
unsigned char Func;
int i;
WDTCTL = WDTPW + WDTHOLD; // 停止看门狗
FLL_CTL0 |= XCAP18PF; // 配置晶振负载电容
U0CTL = CHAR; // 异步通讯模式,8位数据,无校验,1位停止位。
ME1 |= UTXE0 + URXE0; // 开启串口0收发模块
U0TCTL |= SSEL0; // 选择ACLK作为串口波特率时钟源。
U0BR1 = 0; //
U0BR0 = 13; // 分频系数整数部分=13
U0MCTL = 0x6B; // 分频系数小数部分调制=5/8。(2400bps)
P2SEL |= BIT4 + BIT5; // P2.4,5 开启第二功能,作为串口收发引脚(不同单片机有差别)
IE1 |= URXIE0; // 开启UART0的接收中断,在中断内接收数据
_EINT(); // 总中断允许
while(1)
{
__delay_cycles(1000000);//模拟一个长耗时的程序,使CPU暂时不能读取串口
if(UART0_GetCharsInRxBuf()>=10) //每收到10字节数据
{
UART0_GetChar(&Addr); //读取第1字节
UART0_GetChar(&Func); //读取第2字节
for(i=0;i<8;i++) UART0_GetChar(RxDataBuff+i); //依次读取后8字节
}
}
}
|