STC12C5A系列单片机串口编程
串口头文件uart.h如下:
=================================================================== /*
* File : uart.h
* Description : This file is UART driver header of STC12C5A serial signal chip.
* Author : Chao
* Copyright : Chao
*
* History
* ----------------------
* Rev : 0.0
* Date : 20/08/2011
*
* create.
* ----------------------
*/
#ifndef UART_H_
#define UART_H_
//---------------Config-------------------------//
#define UART1_EN //使能串口1
#define UART1_RECEIVE_EN //允许串口1中断接收函数
#define UART2_EN //使能串口2
#define UART2_RECEIVE_EN //允许串口2中断接收函数
//#define ECHO //使能回显
//---------------Defines-------------------------//
#define SystemFosc 22118400 //系统时钟:22.1184MHz
#define UartBaud 9600 //串口波特率
#define UART_BUFFER_SIZE 16 //串口数据缓冲区大小
#define UartEndChar '>' //串口数据结束字符
//---------------Type define-------------------------//
typedef struct {
unsigned int receive_flag; //数据接收标志
unsigned char data_length; //数据缓冲区中有效数据个数
unsigned char receive_buffer[UART_BUFFER_SIZE]; //数据接收缓冲区
void (* init)(void); //串口初始化函数
void (* send_byte)(unsigned char ddata); //发送单个字符
void (* send_string)(unsigned char *ddata, unsigned char length); //发送字符串
}UART_T;
//---------------Extern-------------------------//
#ifdef UART1_EN
extern UART_T uart1;
#endif
#ifdef UART2_EN
extern UART_T uart2;
#endif
#endif /*UART_H_*/
======================================================================== 串口编程C程序文件uart.c如下:
======================================================================== /*
* File : uart.c
* Description : This file is UART driver of STC12C5A serial signal chip.
* Author : Chao
* Copyright : Chao
*
* History
* ----------------------
* Rev : 0.0
* Date : 20/08/2011
*
* create.
* ----------------------
*/
//---------------Include files-------------------------//
#include
#include"uart.h"
//---------------Function Prototype-------------------------//
#ifdef UART1_EN
static void uart1_init(void); //串口1初始化函数
static void uart1_send_byte(unsigned char ddata); //串口1发送单个字符
static void uart1_send_string(unsigned char *ddata, unsigned char length); //串口1发送字符串#endif
#ifdef UART2_EN
static void uart2_init(void); //串口2初始化函数
static void uart2_send_byte(unsigned char ddata); //串口2发送单个字符
static void uart2_send_string(unsigned char *ddata, unsigned char length); //串口2发送字符串#endif
//---------------Variable-------------------------//
unsigned long Fosc; //波特率设定时中间变量
#ifdef UART1_EN
UART_T uart1 = {
0, // receive_flag
0, // data_length
"Hello\n", // receive_buffer
uart1_init, // init
uart1_send_byte, // send_byte
uart1_send_string // send_string
};
unsigned char uart1_receive_temp;
unsigned char *uart1_receive_point=uart1.receive_buffer;
#endif
#ifdef UART2_EN
unsigned char uart1_receive_temp;
UART_T uart2 = {
0, // receive_flag
0, // data_length
"Hello\n", // receive_buffer
uart2_init, // init
uart2_send_byte, // send_byte
uart2_send_string, // send_string
};
unsigned char uart2_receive_temp;
unsigned char *uart2_receive_point=uart2.receive_buffer;
#endif
#ifdef UART1_EN
/*
* ---- FUNCTION ----------------------------------------------------------------------- * Name : uart1_init
* Description : 串口1初始化程序
* -------------------------------------------------------------------------------------------- */
static void uart1_init(void)
{
unsigned long baud;
//选择波特率产生方式:采用独立波特率发生器
AUXR |= S1BRS;
//设定波特率发生器重新计数初值
Fosc = SystemFosc/32;
baud = UartBaud;
if(baud > 9600)
AUXR |= BRTx12; //时钟频率不分频
else
Fosc /= 12;
BRT = 256-Fosc/baud;
//启动波特率发生器
AUXR |= BRTR;
SCON = 0x50; //设定串口1工作方式:方式1(8n1),允许接收
ES = 1; //开串口1中断
}
/*
* === FUNCTION ---------------------------------------------------------------------
* Name : uart1_send_byte
* Description : 串口1发送单个字节数据
* --------------------------------------------------------------------------------------------
*/
static void uart1_send_byte(unsigned char ddata)
{
SBUF = ddata; //写入要发送的字符
while(!TI); //等待发送完毕
TI = 0; //清发送标志
}
/*
* === FUNCTION ---------------------------------------------------------------------
* Name : uart1_send_string
* Description : 串口1发送以'\0'结尾的字符串
* --------------------------------------------------------------------------------------------
*/
static void uart1_send_string(unsigned char *ddata, unsigned char length)
{
while(length--)
uart1_send_byte(*ddata++);
}
#ifdef UART1_RECEIVE_EN
/*
* === FUNCTION ---------------------------------------------------------------------
* Name : ISR_uart1
* Description : 串口1中断数据接收程序
* --------------------------------------------------------------------------------------------
*/
void ISR_uart1(void) interrupt 4
{
if(RI) //确认接收到字符
{
uart1_receive_temp = SBUF;
#ifdef ECHO
uart1.send_byte(uart1_receive_temp);
#endif
if(uart1_receive_temp != UartEndChar) //如果没有接收到(假设接收缓冲区足够大){
*uart1_receive_point++ = uart1_receive_temp;
uart1.data_length++;
}
else
{
uart1_receive_point = uart1.receive_buffer; //重新将接收字符指针指向接收缓冲区头uart1.receive_flag = 1; //置位接收命令完成标志
}
RI = 0; //清接收标志
}
}
#endif
#endif
#ifdef UART2_EN
/*
* === FUNCTION ---------------------------------------------------------------------
* Name : uart2_init
* Description : 串口1初始化程序
* --------------------------------------------------------------------------------------------
*/
static void uart2_init(void)
{
#ifndef UART1_EN
unsigned long baud;
//选择波特率产生方式:采用独立波特率发生器
AUXR |= S1BRS;
//设定波特率发生器重新计数初值
Fosc = SystemFosc/32;
baud = UartBaud;
if(baud > 9600)
AUXR |= BRTx12; //时钟频率不分频
else
Fosc /= 12;
BRT = 256-Fosc/UartBaud;
//启动波特率发生器
AUXR |= BRTR;
#endif
S2CON=0x50; //设定串口工作方式:方式1(8n1),允许接收
IE2=0x01; //允许串口2中断
}
/*
* --- FUNCTION ---------------------------------------------------------------------
* Name : uart2_send_byte
* Description : 串口2发送单个字节数据
* --------------------------------------------------------------------------------------------
*/
static void uart2_send_byte(unsigned char ddata)
{
S2CON &= 0xFD; //清发送标志
S2BUF = ddata; //发送数据
while(!(S2CON&0x02)); //等待发送完成
}
/*
* === FUNCTION ---------------------------------------------------------------------
* Name : uart2_send_string
* Description : 串口2发送以'\0'结尾的字符串
* --------------------------------------------------------------------------------------------
*/
static void uart2_send_string(unsigned char *ddata, unsigned char length)
{
while(length--)
uart2_send_byte(*ddata++);
}
#ifdef UART2_RECEIVE_EN
/*
* ----- FUNCTION ---------------------------------------------------------------------
* Name : ISR_uart2
* Description : 串口2中断数据接收程序
* --------------------------------------------------------------------------------------------
*/
void ISR_uart2(void) interrupt 8 //单片机接收从机发来的数据
{
if(S2CON&0x01) //如果接收到数据
{
uart2_receive_temp = S2BUF; //读取数据
#ifdef ECHO
uart2.send_byte(uart2_receive_temp);
#endif
if(uart2_receive_temp != UartEndChar) //如果没有接收到(假设接收缓冲区足够大){
*uart2_receive_point++ = uart2_receive_temp;
uart2.data_length++;
}
else
{
uart2_receive_point = uart2.receive_buffer; //重新将接收字符指针指向接收缓冲区头uart2.receive_flag = 1; //置位接收命令完成标志
}
S2CON &= 0xFE; //清接收标志
}
}
#endif
#endif
======================================================================= 通过上面两个文件,就能很方便的实现STC12C5A系列单片机中串口操作,
并且能够通过配置uart.h文件来实现串口1、串口2的条件编译,测试主函数main.c如下:
======================================================================= #include
#include"uart.h"
void Sys_init(void); //系统初始化
void main()
{
Sys_init();
while(1)
{
if(uart1.receive_flag)
{
uart1.send_string(uart1.receive_buffer, uart1.data_length);
uart1.receive_flag = 0;
uart1.data_length = 0;
}
if(uart2.receive_flag)
{
uart2.send_string(uart2.receive_buffer, uart2.data_length);
uart2.receive_flag = 0;
uart2.data_length = 0;
}
}
}
void Sys_init(void) //系统初始化
{
uart1.init();
uart1.send_string("uart1\r\n",7);
uart2.init();
uart2.send_string("uart2\r\n",7);
EA = 1;
}
该测试主函数实现的功能是:上电后,从串口1、串口2分别输出字符串"uart1\r\n"、“uart2\r\n”,然后两路串口分别等待接收数据,接收的字符串以字符“>”作为结束标志(可以在uart.h文件中进行修改),串口每接收完一个以“>”作为结尾的字符串,会通过相应串口将接收的字符串发送出去。
总结:该项目采用C++中封装思想进行编程,利用自定义数据结构UART_T对串口相关数据和操作函数进行了封装,这让整体程序看起来非常清晰。另外,通过使用条件编译,能够让程序实现“按需编译”。