51单片机串口通信(UART)

项目描述:
1.串口工作方式为1(8位UART,波特率可变),无校验位;
2.通信数据格式为:1位起始位 + 8位数据位 + 1位停止位;
3.上电后MCU给上位机发送问候语,之后等待上位机的信息;MCU和上位机的通信为收发交替进行。MCU接收到的信息会实时的显示在LCD上。上位机接收到的信息会在串口助手上显示。
C语言程序如下:

/*-----------------------
FileName: UART.h
Function: 头文件
Author: Zhang Kaizhou
Date: 2019-6-10 11:33:35
------------------------*/
#include "reg52.h"
#include 
#define uchar unsigned char
#define uint unsigned int
#define FOSC 11059200L // 系统晶振频率为11.0592MHz
#define BAUD 9600 // 波特率位9600bps
#define MAXSIZE 8

/*LCD1602显示模块端口定义*/
sbit lcdrs = P1^0;
sbit lcdrw = P1^1;
sbit lcden = P2^5;

/*主模块函数声明*/
void timer1Init();
void sendChar(uchar dat);
void sendString(char * str);

/*LCD1602模块函数声明*/
void writeCommand(uchar command);
void writeData(uchar dat);
void delay(uchar xms);
void LCDInit();
void display(uchar * str);

/*--------------------------------------------
FileName: main.c
Function: 实现单片机与上位机的串口异步通信
Description: 上电后MCU给上位机发送问候语,
之后等待上位机的信息;MCU和上位机的通信为收发
交替进行。MCU接收到的信息会实时的显示在LCD上。
上位机接收到的信息会在串口助手上显示。
----------------------------------------------
Author: Zhang Kaizhou
Date: 2019-6-10 11:16:29
--------------------------------------------*/
#include "UART.h"

uchar code table3[] = {"Hello, I am ZKZ!\r\n"};
uchar code table4[] = {"I get it!\r\n"};
uchar info[MAXSIZE] = { 0 }; // 通信信息
uchar count = 0; // 接收到的字符个数
uchar temp = 0;
bit busy = 0; // 串口忙标志

/*主函数*/
void main(){
	LCDInit();
	timer1Init();
	sendString(table3);
	while(1){
		if(count == MAXSIZE){
			count = 0;
			sendString(table4);
			display(info);
		}
	}
}

/*定时器1用作波特率发生器*/
void timer1Init(){
	SM0 = 0; SM1 = 1; // 设置串口为8位UART
	REN = 1; // 允许串口接收数据
	TMOD = 0x20; // 设置timer1为8位自动重装初值的定时器
	PCON = 0x00; // SMOD = 0
	TH1 = 0xfd; // 装初值,可通过查表求得
	TL1 = 0xfd;
    TR1 = 1; // 启动定时器1
	ES = 1; // 开串口中断
    EA = 1; // 开全局中断
}

/*串口中断服务程序*/
void uartService() interrupt 4{
    if (RI){ // 串口接收结束
    	info[count++] = SBUF; // 将接收到的数据从串口缓存中取出放到info中
		RI = 0; // 串口接收标志软件复位
    }
    if (TI){ // 串口发送结束
		TI = 0; // 软件复位串口发送中断标志
      	busy = 0;
    }
}

/*向串口发送一个字符的函数*/
void sendChar(uchar dat){
    while (busy); // 等待串口空闲
	temp = dat;
    busy = 1;
    SBUF = temp;
}

/*向串口发送一个字符串的函数*/
void sendString(char * str){
    while (* str){
        sendChar(*str++);
    }
}
/*-----------------------------
FileName:display.c
Function: LCD1602显示函数
Author: Zhang Kaizhou
Date: 2019-6-7 13:52:11
------------------------------*/
#include "UART.h"

uchar code table0[] = {"Welcome here!"};
uchar code table1[] = {"This is UART!"};
uchar code table2[] = {"Too long!"};
uchar num = 0;

/*初始化LCD1602的设置*/
void LCDInit(){
	uchar i;
	lcden = 0; // 拉低使能端,准备产生使能高脉冲信号
	writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口)
	writeCommand(0x0c); // 开显示,不显示光标
	writeCommand(0x06); // 写一个字符后地址指针自动加1
	writeCommand(0x01); // 显示清零,数据指针清零
	
	/*LCD上电界面*/
	writeCommand(0x80); // 将数据指针定位到第一行首
	for(i = 0; i < strlen(table0); i++){
		writeData(table0[i]);
		delay(5);
	}
	
	writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
	for(i = 0; i < strlen(table1); i++){
		writeData(table1[i]);
		delay(5);
	}
}

/*LCD显示函数*/
void display(uchar * str){
	uchar i;
	writeCommand(0x01); // 清屏
	writeCommand(0x80);
	for(i = 0; i < MAXSIZE; i++){
		writeData(str[i]);
		delay(5);
	}
}

/*写指令函数*/
void writeCommand(uchar command){
	lcdrs = 0; // 命令选择
	lcdrw = 0;
	P0 = command;
	delay(5);
	
	lcden = 1; // 产生一个正脉冲使能信号
	delay(5);
	lcden = 0;
}

/*写数据函数*/
void writeData(uchar dat){
	lcdrs = 1; // 数据选择
	lcdrw = 0;
	P0 = dat;
	delay(5);
	
	lcden = 1;
	delay(5);
	lcden = 0;
}

/*延时函数*/
void delay(uchar xms){
	uint i, j;
	for(i = xms; i > 0; i--)
		for(j = 110; j > 0; j--);
}

实现效果:
单片机每接收到一个来自上位机的字符串(规定长度为8个字符),就会向上位机发送一个应答语"I get it!"。
上位机会通过串口助手向单片机循环发送"12345678",“abcdefgh”,"ijklmnop"三个字符串,单片机接收到后会显示在LCD上。
51单片机串口通信(UART)_第1张图片

你可能感兴趣的:(C51)