以下代码是我自己写的自己用过的,串口通讯的话加上环形缓冲区之后,很方便处理协议和帧结构相关的逻辑。
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();
}
}
|