51单片机UART通信[发送接收数字字母中文,控制LED亮灭] 

【烧录的时候,一定选择外部晶振】

内部6M的IRC时钟,会有各种问题!






1、发送什么就接收什么

/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:12M
功能:串口的应用
波特率:4800 8 无 1 无

*/

#include <REG51.h> //  可以使用通用的头文件

//串口中断初始化程序
void UART_init(void){
 	EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
	ES=1;//允许串口的中断

	TMOD=0x20;  // 定时器1 T/C1工作方式,用来产生串口工作频率
	SCON=0x50;  // 串口工作方式1
	TH1=0xF3;   // 定时器初始值高8位的设置,查表得频率
	TL1=0xF3;    // 定时器初始值低8位的设置,查表得频率
	PCON=0x80;  // 波特率倍频2400为4800了
	TR1=1;      // 定时器启动
}

void UART_R(void) interrupt 4 using 1{
  unsigned char UART_data;
	RI=0;						//RI接收标志位1就会进入该程序,手动置0,等待新的接收
	UART_data=SBUF; //把接收到的1bit数据放到UART_data
	
	SBUF=UART_data; //把UART_data数据发送出去
	while(TI==0);   //等待发送结束
	TI=0;           //TI发送标志位置0,等待新的发送
}

void main (void) {
	UART_init();
  while (1) {
   }
}






2、把UART_data数据加2发送出去

/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:12M
功能:串口的应用
波特率:4800 8 无 1 无

*/

#include <REG51.h> //  可以使用通用的头文件

//串口中断初始化程序
void UART_init(void){
 	EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
	ES=1;//允许串口的中断

	TMOD=0x20;  // 定时器1 T/C1工作方式,用来产生串口工作频率
	SCON=0x50;  // 串口工作方式1
	TH1=0xF3;   // 定时器初始值高8位的设置,查表得频率
	TL1=0xF3;    // 定时器初始值低8位的设置,查表得频率
	PCON=0x80;  // 波特率倍频2400为4800了
	TR1=1;      // 定时器启动
}

void UART_R(void) interrupt 4 using 1{
  unsigned char UART_data;
	RI=0;						//RI接收标志位1就会进入该程序,手动置0,等待新的接收
	UART_data=SBUF; //把接收到的1bit数据放到UART_data
	
	SBUF=UART_data+0x02; //把UART_data数据加2发送出去
	while(TI==0);   //等待发送结束
	TI=0;           //TI发送标志位置0,等待新的发送
}

void main (void) {
	UART_init();
  while (1) {
   }
}





3、串口的应用:输出指定的数值

/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:12M
功能:串口的应用:输出指定的数值
波特率:4800 8 无 1 无

*/

//#include <REG51.h> //  可以使用通用的头文件
#include <STC12C5A60S2.H>


//串口中断初始化程序
void UART_init(void){
 	EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
  ES=1;//允许串口的中断

	TMOD=0x20;  // 定时器1 T/C1工作方式,用来产生串口工作频率
	SCON=0x50;  // 串口工作方式1
	TH1=0xF3;   // 定时器初始值高8位的设置,查表得频率
	TL1=0xF3;    // 定时器初始值低8位的设置,查表得频率
	PCON=0x80;  // 波特率倍频2400为4800了 
	TR1=1;      // 定时器启动
}

void main (void) {
	UART_init();
  while (1) {
		SBUF=0xfa;
		while(TI==0);
		TI=0;
   }
}





4、串口的应用:输出字符“Ok9”

/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:12M
功能:串口的应用:输出字符“Ok9”
波特率:4800 8 无 1 无
*/

#include <STC12C5A60S2.H>
#include <STRING.H>


void UART_init(void){
 	EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
  ES=1;//允许串口的中断

	TMOD=0x20;  // 定时器1 T/C1工作方式,用来产生串口工作频率
	SCON=0x50;  // 串口工作方式1
	TH1=0xF3;   // 定时器初始值高8位的设置,查表得频率
	TL1=0xF3;    // 定时器初始值低8位的设置,查表得频率
	PCON=0x80;  // 波特率倍频2400为4800了 
	TR1=1;      // 定时器启动
}

void UART_T (unsigned char UART_data){ //定义串口发送数据变量
	SBUF = UART_data;	//将接收的数据发送回去
	while(TI == 0);		//检查发送中断标志位
	TI = 0;			//令发送中断标志位为0(软件清零)
}

void UART_TC (unsigned char *str){
	while(*str != '\0'){
		UART_T(*str);
		*str++;
	}
	*str = 0;
}

void main (void) {
	UART_init();
  while (1) {
    UART_TC ("Ok");
		UART_T(0x30+9);// 数字偏移量
   }
}





5、串口的应用:输出字符“Ok0”到“Ok9”

/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:12M
功能:串口的应用:输出字符“Ok9”
波特率:4800 8 无 1 无
*/

#include <STC12C5A60S2.H>
#include <STRING.H>


void UART_init(void){
 	EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
  ES=1;//允许串口的中断

	TMOD=0x20;  // 定时器1 T/C1工作方式,用来产生串口工作频率
	SCON=0x50;  // 串口工作方式1
	TH1=0xF3;   // 定时器初始值高8位的设置,查表得频率
	TL1=0xF3;    // 定时器初始值低8位的设置,查表得频率
	PCON=0x80;  // 波特率倍频2400为4800了 
	TR1=1;      // 定时器启动
}

void UART_T (unsigned char UART_data){ //定义串口发送数据变量
	SBUF = UART_data;	//将接收的数据发送回去
	while(TI == 0);		//检查发送中断标志位
	TI = 0;			//令发送中断标志位为0(软件清零)
}

void UART_TC (unsigned char *str){
	while(*str != '\0'){
		UART_T(*str);
		*str++;
	}
	*str = 0;
}

void main (void) {
	unsigned char a=0 ;
	UART_init();
  while (1) {
    UART_TC ("Ok");
		UART_T(0x30+a); // 数字偏移量
		a++;
		if(a>9){
			a=0;
     }
   }
}

// 输出结果
// k0Ok1Ok2Ok3Ok4Ok5Ok6Ok7Ok8Ok9




6、输出中文

/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:12M
功能:串口的应用:输出字符“Ok9”
波特率:4800 8 无 1 无
*/

#include <STC12C5A60S2.H>
#include <STRING.H>


void UART_init(void){
 	EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
  ES=1;//允许串口的中断

	TMOD=0x20;  // 定时器1 T/C1工作方式,用来产生串口工作频率
	SCON=0x50;  // 串口工作方式1
	TH1=0xF3;   // 定时器初始值高8位的设置,查表得频率
	TL1=0xF3;    // 定时器初始值低8位的设置,查表得频率
	PCON=0x80;  // 波特率倍频2400为4800了 
	TR1=1;      // 定时器启动
}

void UART_T (unsigned char UART_data){ //定义串口发送数据变量
	SBUF = UART_data;	//将接收的数据发送回去
	while(TI == 0);		//检查发送中断标志位
	TI = 0;			//令发送中断标志位为0(软件清零)
}

void UART_TC (unsigned char *str){
	while(*str != '\0'){
		UART_T(*str);
		*str++;
	}
	*str = 0;
}

void main (void) {
	unsigned char a;
	UART_init();
  while (1) {
    UART_TC ("寄存器值是");
		UART_T(0x30+a); // 数字偏移量
		a++;
		if(a>9){
			a=0;
     }
   }
}

// 超级终端输出结果
//寄存器的值是0寄存器的值是1寄存器的值是2寄存器的值是3寄存器的值是4
//寄存器的值是5寄存器的值是6寄存器的值是7寄存器的值是8寄存器的值是9




7、串口的应用,按0键控制超级终端控制LED灯亮灭

/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:12M
功能:串口的应用,超级终端控制LED灯亮灭,
波特率:4800 8 无 1 无

*/

#include <STC12C5A60S2.H>  
#include <STRING.H>
sbit LED=P0^0;


//串口中断初始化程序
void UART_init(void){
 	EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
	ES=1;//允许串口的中断

	TMOD=0x20;  // 定时器1 T/C1工作方式,用来产生串口工作频率
	SCON=0x50;  // 串口工作方式1
	TH1=0xF3;   // 定时器初始值高8位的设置,查表得频率
	TL1=0xF3;    // 定时器初始值低8位的设置,查表得频率
	PCON=0x80;  // 波特率倍频2400为4800了
	TR1=1;      // 定时器启动
}


void UART_T (unsigned char UART_data){ //定义串口发送数据变量
	SBUF = UART_data;	//将接收的数据发送回去
	while(TI == 0);		//检查发送中断标志位
	TI = 0;			//令发送中断标志位为0(软件清零)
}

void UART_TC (unsigned char *str){
	while(*str != '\0'){
		UART_T(*str);
		*str++;
	}
	*str = 0;
}

void UART_R(void) interrupt 4 using 1{
  unsigned char UART_data;
	RI=0;						//RI接收标志位1就会进入该程序,手动置0,等待新的接收
	UART_data=SBUF; //把接收到的1bit数据放到UART_data
	if(UART_data==0x30) {
		LED=~LED;
		UART_TC ("成功!");
		}
	SBUF=UART_data; //把UART_data数据发送出去
	while(TI==0);   //等待发送结束
	TI=0;           //TI发送标志位置0,等待新的发送
}

void main (void) {
	UART_init();
	UART_TC ("0键开关LED灯");
	
    while (1) {
   }
}

按0键控制LED亮灭效果图:

wKioL1YOl2KCbRHGAAkh5jMVwBc002.jpg






// STC-ISP终端乱码的处理办法

// 1,试试下载XP超级终端,Win7超级终端,Hyper_Terminal

// 2,可以按照下图,恢复KEIL原来的字符编码集,把上面的程序粘贴进去,把49行和58行的这两条提示从新修改为中文。

wKioL1YOgXiBkEKnAArftoP5Ijc251.gif









【波特率参考】串口通信常用波特率,中断函数



1、12M晶振产生2400 4800波特率

/****************************************************************
函数名:UART串口初始化函数
调  用:UART_init();
参  数:无
返回值:无
结  果:启动UART串口接收中断,允许串口接收,启动T/C1产生波特率(占用)
备  注:振荡晶体为12MHz,PC串口端设置 [ 4800,8,无,1,无 ]
/**************************************************************/
void UART_init (void){
	EA = 1; //允许总中断(如不使用中断,可用//屏蔽)
	ES = 1; //允许UART串口的中断

	TMOD = 0x20;	//定时器T/C1工作方式2
	SCON = 0x50;	//串口工作方式1,允许串口接收(SCON = 0x40 时禁止串口接收)
	TH1 = 0xF3;	//定时器初值高8位设置
	TL1 = 0xF3;	//定时器初值低8位设置
	PCON = 0x80;	//波特率倍频(屏蔽本句波特率为2400)
	TR1 = 1;	//定时器启动    
}




2、11.0592MHz晶振产生9600 19200 波特率

/**************************************************************
函数名:UART串口初始化函数
调  用:UART_init();
参  数:无
返回值:无
结  果:启动UART串口接收中断,允许串口接收,启动T/C1产生波特率(占用)
备  注:振荡晶体为11.0592MHz,PC串口端设置 [ 19200,8,无,1,无 ]
/***********************************************************/
void UART_init (void){
	EA = 1; //允许总中断(如不使用中断,可用//屏蔽)
	ES = 1; //允许UART串口的中断

	TMOD = 0x20;	//定时器T/C1工作方式2
	SCON = 0x50;	//串口工作方式1,允许串口接收(SCON = 0x40 时禁止串口接收)
	TH1 = 0xFD;	//定时器初值高8位设置
	TL1 = 0xFD;	//定时器初值低8位设置
	PCON = 0x80;	//波特率倍频(屏蔽本句波特率为9600)
	TR1 = 1;	//定时器启动    
}



3、UART串口接收到数据时产生中断,用户对数据进行处理(并发送回去)

/**************************************************************
函数名:UART串口接收中断处理函数
调  用:[SBUF收到数据后中断处理]
参  数:无
返回值:无
结  果:UART串口接收到数据时产生中断,用户对数据进行处理(并发送回去)
备  注:过长的处理程序会影响后面数据的接收
/***********************************************************/
void UART_R (void) interrupt 4  using 1{ //切换寄存器组到1
	unsigned char UART_data; //定义串口接收数据变量
	RI = 0;			//令接收中断标志位为0(软件清零)
	UART_data = SBUF;	//将接收到的数据送入变量 UART_data
	
	//用户函数内容(用户可使用UART_data做数据处理)
	
	//SBUF = UART_data;	//将接收的数据发送回去(删除//即生效)
	//while(TI == 0);	//检查发送中断标志位
	//TI = 0;		//令发送中断标志位为0(软件清零)
}




4、循环查寻接收标志位RI,如有收到数据则进入if (RI == 1){}

/******************************************************************
函数名:UART串口接收CPU查寻语句(非函数体)
调  用:将下面内容放入主程序
参  数:无
返回值:无 
结  果:循环查寻接收标志位RI,如有收到数据则进入if (RI == 1){}
备  注:
/****************************************************************/

unsigned char UART_data; //定义串口接收数据变量
if (RI == 1){		//接收中断标志位为1时
	UART_data = SBUF;	//接收数据 SBUF 为单片机的接收发送缓冲寄存器
	RI = 0;			//令接收中断标志位为0(软件清零)

	//用户函数内容(用户可使用UART_data做数据处理)

	//SBUF = UART_data;	//将接收的数据发送回去(删除//即生效)
	//while(TI == 0);	//检查发送中断标志位
	//TI = 0;		//令发送中断标志位为0(软件清零)
}




5、将参数中的数据(0-9)发送给UART串口,确认发送完成后退出

/********************************************************************
函数名:UART串口发送函数
调  用:UART_T (?);
参  数:需要UART串口发送的数据(8位/1字节)
返回值:无 
结  果:将参数中的数据发送给UART串口,确认发送完成后退出
备  注:
/*******************************************************************/
void UART_T (unsigned char UART_data){ //定义串口发送数据变量
	SBUF = UART_data;	//将接收的数据发送回去
	while(TI == 0);		//检查发送中断标志位
	TI = 0;			//令发送中断标志位为0(软件清零)
}



6、向串口发送一个字符串,长度不限。

/******************************************************************
函数名:UART串口发送字符串函数
调  用:UART_TC (?);
参  数:需要UART串口发送的数据(8位/1字节)
返回值:无 
结  果:向串口发送一个字符串,长度不限。
备  注:例:UART_TC("d9887321$"); 此函数需要#include <string.h>头文件支持。
/**************************************************************/
void UART_TC (unsigned char *str){
	while(*str != '\0'){
		UART_T(*str);
		*str++;
	}
	*str = 0;
}



7、STC12C5A60S2 115200波特率  无 1 无

串口发送什么,就返回什么



/*
工程创建MCU选取,Atmel 89C55
单片机:STC12C5A60S2
晶振:11.0592M
功能:串口发送什么,就返回什么
波特率:STC12C5A60S2 115200波特率  无 1 无
 
*/


#include "STC12C5A60S2.H"
void init_uart()
{ 
	  EA=1; //打开总中断【定时器,ADC,串口,比较,计数,外部】等中断类型
    ES=1;//允许串口的中断

	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x04;		//独立波特率发生器时钟为Fosc,即1T
	BRT = 0xFD;		//设定独立波特率发生器重装值
	AUXR |= 0x01;		//串口1选择独立波特率发生器为波特率发生器
	AUXR |= 0x10;		//启动独立波特率发生器

}

void UART_R(void) interrupt 4 using 1{
  unsigned char UART_data;
    RI=0;                       //RI接收标志位1就会进入该程序,手动置0,等待新的接收
    UART_data=SBUF; //把接收到的1bit数据放到UART_data
     
    SBUF=UART_data; //把UART_data数据发送出去
    while(TI==0);   //等待发送结束
    TI=0;           //TI发送标志位置0,等待新的发送
}
 

void main (void) {
init_uart();
  while (1) {
   }
}

wKioL1YROh6gSbPcAAFmvwOd0Zk203.jpg





89C52 9600波特率测试

//****************************************************************//
//单片机 :AT89S52 或 STC89C52RC 
//功能  :串口测试 波特率 9600 
//晶振  :12M (用户系统时钟如不是12M 请更改相关宏定义及注释的延时时间)
//波特率:9600
//编译环境:  Keil 4
//****************************************************************//
 
#include "reg52.h"
#include <intrins.h>

#define FOSC  12000000
#define BAUD  9600  
 

void delay1ms(unsigned int t)
{
  unsigned int i;
  unsigned int j;
  for(j=t;j>0;j--)
   for(i=124;i>0;i--);  
}
 
void InitUART(void)
{
    unsigned int iTmpBaud;
    unsigned long lTmpBaud;
    iTmpBaud = 0;
    //首先选定定时器2作为波特率发生器,16位定时器,自动装载
    SCON = 0x50;  //SM0 SM1 SM2 REN TB8 RB8 TI RI      //0   1   0   1   0   0   0  0 
    PCON = 0x00;  //PCON的地址是87H,这里SMOD =0
     
    T2CON = 0x30; //TF2 EXF2 RCLK TCLK EXEN2 TR2 C(/T2) CP(/RL2) //0 0 1 1 0 0 0 0 
    T2MOD = 0x00; // /   /   /   /       /   /   T2OE    DCEN   //0 0 0 0 0 0 0 0
 
    //fosc = 22.1184M,6T: 144,设置波特率
    //(RCAP2H,RCAP2L) = 65536- fosc/(n*Baud)。n:32(12T-mode),16:(6T-mode)
    lTmpBaud = FOSC/BAUD;
    lTmpBaud /= 32;                       //12T-mode
    iTmpBaud = lTmpBaud & 0xFFFF;      
    iTmpBaud = 65536 - iTmpBaud;
    RCAP2H = (iTmpBaud>>8) & 0x0FF;
    RCAP2L = iTmpBaud & 0x0FF;
 
    RI = 0;           //清除接收中断标志
    REN = 1;      //允许串行接收
    ES = 1;           //允许串行中断
    TR2 = 1;      //启动定时器1
 
    EA=1;//开总中断
}  
 
//串口发送
void UARTSend(char UCHAR)
{
   SBUF=UCHAR;
  while(TI==0);
  TI=0;
}
 

void UART_PutString(unsigned char *buf )
{
    while(*buf)
		{
      UARTSend(*buf++);	
		}

} 
 
  
 
void main(void)
{

	
  InitUART();
	while(1)
  {
		 UART_PutString("Hello C51");
		 UARTSend(0x0A);
     delay1ms(500);   //延时 2S    (两次读取间隔至少2S)
  }
}












UART串口到此告一段落!