C语言模拟C++方式读取串口操作实现

在使用C++编程对串口操作时,经常有用到serialport.read(),serialport.print()之类的函数,而且系统自带接收buf,不用考虑数据漏失的问题,那么在C语言环境下,怎么做呢?特别是51或STM32编程,或者要将C++代码转换成C代码时对这一块也不好移植,下面提供一个API,方便大家使用。

首先看接口文件,也就是头文件:

serialpoortAPI.h

#ifndef __SERIALPORT_H__
#define __SERIALPORT_H__

#define _SS_MAX_RX_BUFF 96

#define INT_TYPE 0
#define STRING_TYPE 1

void UartBegin(unsigned int bps,void (*uart_init)(unsigned int),void (*uart_send)(unsigned char));
void SerialPrint(void const *send_data,int type);
void SerialPrintln(void const *send_data,int type);
void SerialWrite(char send_data);
int SerialRead(void);
int SerialAvailable(void);
int SerialInt(unsigned char rec_data);
void ClearRxBuf(void);

#endif

头文件里提供了对串口的基本操作,在设置好之后,直接调用就好了。注意_SS_MAX_RX_BUFF设置的是接收缓存的buf,如果一帧数据量比较大,建议设置大一点。

然后就是实现文件了,serialpoortAPI.c

变量定义:

//serialportAPI
#include  
#include 
#include "serialportAPI.h"

static char _receive_buffer[_SS_MAX_RX_BUFF]; 
static volatile unsigned char _receive_buffer_tail = 0;
static volatile unsigned char _receive_buffer_head = 0;
unsigned char _buffer_overflow = 0;//溢出标志位

static void (*UartInit)(unsigned int);
static void (*UartSend)(unsigned char);
这里定义了一个数据接收缓存buf,还有_receive_buffer_tail和_receive_buffer_head,分别对应_receive_buffer的可用数据的终点和起点,如果起点和终点发生了相逢,就发生了溢出,设置标志位_buffer_overflow。

注意这里有两个函数指针,分别为数据初始化UartInit 和数据发送UartSend , 这两个函数需要在外面使用到,在函数初始化时需要对这两个函数指针赋值:

void UartBegin(unsigned int bps,void (*uart_init)(unsigned int),void (*uart_send)(unsigned char))
{
	UartInit = uart_init;
	UartSend = uart_send;
	UartInit(bps);
}

下面实现函数的发送部分功能,实现方法比较简单:

//发送
//调用的时候如果是整数,传入的必须是int型,并加上&符
void SerialPrint(void const *send_data,int type)
{
	if(type == STRING_TYPE)
	{
		char *data_temp = (char *)send_data;//强制类型转换
		while(*data_temp != '\0')
		{
			UartSend(*data_temp++);
		}
	}
	else if(type == INT_TYPE)
	{	
		char str[7];
		char *index = str;
		int data_temp = (int)(*(int *)send_data);
		sprintf(index, "%d" , data_temp);
		while(*index != '\0')
		{
			UartSend(*index++);
		}		
	}
}

//带换行的发送
//调用的时候如果是整数,传入的必须是int型,并加上&符
void SerialPrintln(void const *send_data,int type)
{
	SerialPrint(send_data,type);
	UartSend('\r');
	UartSend('\n');
}

void SerialWrite(char send_data)
{
	UartSend(send_data);
}

int SerialRead(void)
{
	unsigned char d;
	  // Empty buffer?
  if (_receive_buffer_head == _receive_buffer_tail)
    return -1;

  // Read from "head"
  d = _receive_buffer[_receive_buffer_head]; // grab next byte
  _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
  return (int)d;
}

然后是接收部分,这里需要将下面的函数放在外面串口中断中运行:

//call by UART interrupt
int SerialInt(unsigned char rec_data)
{
    // if buffer full, set the overflow flag and return
    if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) 
    {
      // save new data in buffer: tail points to where byte goes
      _receive_buffer[_receive_buffer_tail] = rec_data; // save new byte
      _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
    } 
    else 
    {
      _buffer_overflow = 1;
    }	
		return 1;
}

然后就是几个常用的接收函数:

int SerialRead(void)
{
	unsigned char d;
	  // Empty buffer?
  if (_receive_buffer_head == _receive_buffer_tail)
    return -1;

  // Read from "head"
  d = _receive_buffer[_receive_buffer_head]; // grab next byte
  _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
  return (int)d;
}

int SerialAvailable(void)
{
	return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
}
在使用时一般是先使用SerialAvailable()判断有没有数据,然后用SerialRead()读取,可以看到,很多操作是基于_receive_buffer_tail和_receive_buffer_head这两个值的。

最后就是清除接收缓存的操作,也很简单,只要设置_receive_buffer_tail和_receive_buffer_head这两个值就好了

void ClearRxBuf(void)
{
	_receive_buffer_tail = 0;
	_receive_buffer_head = 0;
	_buffer_overflow = 0;
}



你可能感兴趣的:(C,算法,嵌入式开发)