zoukankan      html  css  js  c++  java
  • 分享一个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 != '')
    	{
    		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 By veis
  • 相关阅读:
    mongodb简介
    tomcat简介
    date的详细说明
    30岁前成功的12条黄金法则
    2012春晚经典语录
    统计文件中某个单词出现的次数
    nginx简介
    ATM取款机系统模拟仿真
    十三种时间管理方法
    笔试常见的智力题 附答案
  • 原文地址:https://www.cnblogs.com/veis/p/14556554.html
Copyright © 2011-2022 走看看