打印
[程序源码]

串口通讯环形缓冲区应用代码分享

[复制链接]
1035|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
blust5|  楼主 | 2020-3-14 12:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下代码是我自己写的自己用过的,串口通讯的话加上环形缓冲区之后,很方便处理协议和帧结构相关的逻辑。

uart.c

/*
* uart.c
*
*  Created on: 2018年1月24日
*      Author: blust
*/

#include"uart.h"

unsigned char UartTxBuffer[UART_TX_RX_SIZE];    // 发送数组
unsigned char UartRxBuffer[UART_TX_RX_SIZE];    // 接收数组

unsigned char UartRxCircleBuffer[UART_RX_BUFF_SIZE];    // 接收环形缓冲区
volatile unsigned char uart_rx_head = 0;    // 环形缓冲区头,缓冲区头尾重合有两种情况,一种是接收溢出,头覆盖了尾;一种是缓冲区空,所有数据都被读取处理了
volatile unsigned char uart_rx_tail = 0;    // 环形缓冲区尾
volatile unsigned char uart_tx_num = 0;     // 需发送数据长度
volatile unsigned char uart_tx_cnt = 0;     // 发送数据计数

// 初始化函数
void UART_Init(void) //ACLK=32.678K
{
    //Select the IO's function to uart.
    P1DIR  |=  BIT2;             //P1.2  UART_TX
    P1DIR  &= ~BIT1;             //P1.1  UART_RX
    P1SEL  |=  BIT1 + BIT2;        //select P1.1 as UART port
    P1SEL2 |=  BIT1 + BIT2;
    //Set the bus as uart.
    UCA0CTL1 |= UCSWRST;         //reset UART module,as well as enable UART module
    UCA0CTL1 |= UCSSEL1; // CLK = SMCLK  8MHz
    UCA0BR0   = 0x41; // 8MHz/9600 = 833.33   833 = 0x0341
    UCA0BR1   = 0x03;
    UCA0MCTL  = UCBRS1; // UCBRSx = 0.33×8=2.64取整
    UCA0CTL1 &= ~UCSWRST;        //UART reset end
    IE2 |= UCA0RXIE ;  //Open the UART receive interrupt
}

// 读取函数
// 环形缓冲区为空则返回-1
// 读取长度超出数组上限返回-1
// 正常读取则返回数据长度
signed char UART_Read(void)
{
    unsigned char i = 0;

    if(uart_rx_tail == uart_rx_head)
    {
        return -1;
    }

    do{
        if(i >= UART_TX_RX_SIZE)
        {
            return -1;
        }
        UartRxBuffer[i++] = UartRxCircleBuffer[uart_rx_tail++];
        if (uart_rx_tail >= UART_RX_BUFF_SIZE)
        {
            uart_rx_tail = 0;
        }
    }
    while(uart_rx_tail != uart_rx_head);

    return i;
}

#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)   //接收中断
{
//    IFG2 &=~UCA0RXIFG;         //clear RX interrupt flag
    timer_comm_stick = 0;                // 用来超时判断帧接收完成的计数变量,定时器里累加和判断超时

    UartRxCircleBuffer[uart_rx_head ++] = UCA0RXBUF;
    if (uart_rx_head >= UART_RX_BUFF_SIZE)
    {
        uart_rx_head = 0;
    }
}

// 发送函数
// 传递参数为要发送的数据长度
// 发送数组采用全局变量UartTxBuffer[],下标从0开始
// 待发送长度为0或超出数组长度,返回-1,正常发送则返回0
signed char UART_Transmit(unsigned char length)
{
    if((length == 0)||(length > UART_TX_RX_SIZE))
    {
        return -1;
    }

    IE2 &= ~UCA0RXIE;   // 关闭接收中断
    IFG2 &= ~UCA0TXIFG; // 清发送中断标志
    IE2 |= UCA0TXIE;    // 打开发送中断
    delay_ms(1);
    uart_tx_cnt = 0;
    uart_tx_num = length;
    UCA0TXBUF = UartTxBuffer[uart_tx_cnt ++];
   
    return 0;
}

// 发送中断
void uart_transmit_isr(void)
{
    if(uart_tx_cnt < uart_tx_num)
    {
        UCA0TXBUF = UartTxBuffer[uart_tx_cnt ++];
    }
    else
    {
        memset(UartTxBuffer, 0, sizeof(UartTxBuffer));
        IFG2 &= ~UCA0TXIFG;  // 清发送中断标志
        IE2  &= ~UCA0TXIE;   // 关闭发送中断
        IFG2 &= ~UCA0RXIFG;  // 清接收中断标志
        IE2  |= UCA0RXIE;    // 开接收中断
    }
}

#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
    if(UART_TXIF)
    {
        uart_transmit_isr();
    }
}



使用特权

评论回复

相关帖子

沙发
blust5|  楼主 | 2020-3-14 12:13 | 只看该作者
uart.h

/*
* uart.h
*
*  Created on: 2018年1月24日
*      Author: blust
*
* 对外接口:
* 初始化函数                UART_Init();
* 发送函数                        UART_Transmit(length);
* 读取函数                        UART_Read();
* 发送数组                        UartTxBuffer[]
* 接收数组                        UartRxBuffer[]
*/

#ifndef UART_H_
#define UART_H_

#include <msp430.h>
#include "stdint.h"
#include <stdio.h>
#include <string.h>


#define UART_RX_BUFF_SIZE   64  // 接收环形缓冲区长度

#define UART_TX_RX_SIZE   64  // 发送接收数组长度
extern unsigned char UartTxBuffer[UART_TX_RX_SIZE];     // 发送数组
extern unsigned char UartRxBuffer[UART_TX_RX_SIZE];     // 接收数组

extern volatile unsigned char uart_rx_head;    // 环形缓冲区头
extern volatile unsigned char uart_rx_tail;    // 环形缓冲区尾


#define UART_TXIF  (IFG2&UCA0TXIFG)
#define UART_RXIF  (IFG2&UCA0RXIFG)

extern void UART_Init(void);
extern signed char UART_Read(void);
extern signed char UART_Transmit(unsigned char length);


#endif /* UART_H_ */

使用特权

评论回复
板凳
Prry| | 2020-3-16 09:17 | 只看该作者
参考抽象成模块的:
https://blog.csdn.net/qq_20553613/article/details/78902689

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:业精于勤荒于嬉,行成于思毁于随。

72

主题

2829

帖子

11

粉丝