欢迎来到我的博客https://www.cnblogs.com/veis/

https://www.cnblogs.com/veis/p/14182037.html

分享一个51单片机的串口结构

说明

  1. 目前主要封装了串口1的实例,采用可移植数据类型,可以同步移植到STM32、STM8等单片机;
  2. 需自行实现串口接收回调函数内容;
  3. 欢迎各位指正并分享;

头文件

#ifndef __SERIAL_H__
#define __SERIAL_H__

#include <reg52.h>

#ifndef uint8_t
typedef unsigned char uint8_t;
#endif

#ifndef uint16_t
typedef unsigned int uint16_t;
#endif

#ifndef uint32_t
typedef unsigned long uint32_t;
#endif

/* 晶振频率 */
#define FOSC 11059200L
/* 单片机周期数,默认为12T */
#define FOSC_DIV 12
/* 接收缓冲区大小 */
#define RECV_BUF_SIZE 64

/* 波特率列表 */
#define	BAUD_2400 2400L
#define BAUD_4800 4800L
#define	BAUD_9600 9600L
#define	BAUD_14400 14400L
#define	BAUD_19200 19200L // 使用此波特率需要加倍
#define	BAUD_38400 38400L // 使用此波特率及以上,1T单片机才支持,或者修改晶振频率
#define	BAUD_43000 43000L
#define	BAUD_57600 57600L
#define	BAUD_115200 115200L
#define	BAUD_230400 230400L
#define	BAUD_460800 460800L

/* 校验类型 */
typedef enum
{
	NONE_PARITY = 0, /* 无校验 */
	ODD_PARITY, /* 奇校验 */
	EVEN_PARITY, /* 偶校验 */
	MARK_PARITY, /* Mark parity */
	SPACE_PARITY, /* Space parity  */
} EtypeParity;

/* 串口模式 */
typedef enum
{
	Mode0 = 0, /* 同步移位寄存器 */
	Mode1, /* 8位串口,波特率可变 */
	Mode2, /* 9位串口,波特率固定 */
	Mode3, /* 9位串口,波特率可变 */
} EtypeSerialMode;

/* 串口数据结构 */
typedef struct
{
	uint32_t m_baudrate; /* 波特率 */
	EtypeParity m_parity; /* 校验方式 */
	uint8_t busy_flag; /* 缓冲区忙标志位, 1:表示忙, 0:空闲 */
	uint8_t m_bInterrupt; /* 使能中断, 1=enable, 0=disable */
	uint8_t (*InitSerial)(uint32_t baud); /* 初始化函数指针 */
	uint8_t (*SendByte)(const uint8_t byte_data); /* 发送函数指针 */
	uint8_t (*SendString)(uint8_t *p_buf); /* 发送函数指针 */
	void (*receive_callback)(void); /* 回调函数指针 */
	uint8_t *recv_buf; /* 接收缓冲区指针 */
	EtypeSerialMode m_mode; /* 串口模式,暂时为保留参数,缺省Mode1 */
} SerialPort_t;

/* 串口实例 */
extern SerialPort_t Serial;

#endif /* __SERIAL_H__ */

源文件

#include "serial.h"

xdata uint8_t recv_buf[RECV_BUF_SIZE] = {0};

static uint8_t InitSerial(uint32_t baud);
static uint8_t SendByte(uint8_t byte_data); /* 发送函数指针 */
static uint8_t SendString(const uint8_t *p_buf); /* 发送函数指针 */
static void receive_callback(void); /* 回调函数指针 */

// 允许输出
static unsigned char flag_Parity_out = 1;

/* 串口对象 */
SerialPort_t Serial = 
{
	BAUD_9600,
	NONE_PARITY,
	0,
	1,
	InitSerial,
	SendByte,
	SendString,
	receive_callback,
	recv_buf,
	Mode1,
};

static uint8_t InitSerial(uint32_t baud)
{
	uint8_t double_baud = 1;
	uint8_t div = 32;
	Serial.m_baudrate = baud;

	switch(Serial.m_parity)
	{
		/* 8-bit variable UART */
		case NONE_PARITY:
			SCON = 0x50;
			Serial.m_mode = Mode1;
			break;
		
		/* 9-bit variable UART,parity bit initial to 1  */
		case ODD_PARITY:
		case EVEN_PARITY:
		case MARK_PARITY:
			SCON = 0xda;
			Serial.m_mode = Mode3;
			break;
		
		/* 9-bit variable UART,parity bit initial to 0  */
		case SPACE_PARITY:
			SCON = 0xd2;
			Serial.m_mode = Mode3;
			break;
	}

	TMOD = 0x20; /* Set Timer1 as 8-bit auto reload mode */
	PCON &= 0x7F;
	if(Serial.m_baudrate > 14400 && FOSC_DIV == 12) // 12T单片机需要倍增波特率
	{
		PCON |= 0x80;
		double_baud = 2;
	}
	
	div /= double_baud;
	
	TH1 = TL1 = 256 - (FOSC / FOSC_DIV / div / Serial.m_baudrate); /* Set auto-reload value */
	TR1 = 1;
	ES = Serial.m_bInterrupt;
	EA = 1;
	
	return 0;
}

static uint8_t SendByte(uint8_t byte_data) 
{
	while(Serial.busy_flag);
	
	ACC = byte_data; // 计算校验和
	switch(Serial.m_parity)
	{
		case SPACE_PARITY:
			TB8 = 0;
			break;
		
		case MARK_PARITY:
			TB8 = 1;
			break;
		
		case EVEN_PARITY:
			TB8 = P;
			break;
		
		case ODD_PARITY:
			TB8 = ~P;
			break;
		
		default:
			break;
	}
	Serial.busy_flag = 1;
	SBUF = byte_data;
	
	return 0;
}

static uint8_t SendString(const uint8_t *p_buf)
{
	int ncount = 0;
	while(*p_buf != '\0')
	{
		SendByte(*p_buf++);
		ncount++;
	}
	return ncount;
}

static void receive_callback(void)
{
	/* Add your code here */
	uint8_t dat = SBUF;
	SendByte(dat);
}

void UartInterrupt(void) interrupt 4 using 1
{
	unsigned char flag_Parity = 0;
	if(RI)
	{
		RI = 0; /* clear receive interrupt flag */
		if(Serial.m_parity != NONE_PARITY)
			P = RB8;
		receive_callback(); /* 调用串口接收回调函数 */
	}
	if(TI)
	{
		TI = 0;
		Serial.busy_flag = 0;
	}
}
posted @ 2021-04-10 12:36  veis  阅读(202)  评论(0编辑  收藏  举报