51单片机串口通信学习总结.docx
- 文档编号:8254344
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:19
- 大小:508.48KB
51单片机串口通信学习总结.docx
《51单片机串口通信学习总结.docx》由会员分享,可在线阅读,更多相关《51单片机串口通信学习总结.docx(19页珍藏版)》请在冰豆网上搜索。
51单片机串口通信学习总结
51单片机串口通信学习总结
1.近距离的单片机点对点通信:
如果两个51单片机系统之间的距离很短,可以通过将它们的自带串口直接相连的方法实现双机通信,连接时注意要将一方的TXD和另一方的RXD引脚相连。
2.如果通信距离较远,可以利用RS-232C接口延长通信距离,但必须将单片机的TTL电平和RS-232C标准电平进行转换,如常用的MAX232,。
内部结构基本可分三个部分:
第一部分是电荷泵电路。
由1、2、3、4、5、6脚和4只电容构成。
功能是产生+12v和-12v两个电源,提供给RS-232串口电平的需要。
第二部分是数据转换通道。
由7、8、9、10、11、12、13、14脚构成两个数据通道。
其中13脚(R1IN)、12脚(R1OUT)、11脚(T1IN)、14脚(T1OUT)为第一数据通道。
8脚(R2IN)、9脚(R2OUT)、10脚(T2IN)、7脚(T2OUT)为第二数据通道。
TTL/CMOS数据从T1IN、T2IN输入转换成RS-232数据从T1OUT、T2OUT送到电脑DB9插头;DB9插头的RS-232数据从R1IN、R2IN输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。
第三部分是供电。
15脚GND、16脚VCC(+5v)。
硬件电路设计:
注意:
怎样连线……单片机与MAX232同名相对,R—R,T—T
MAX232与DB9异名相对,R—T,T—R
串口通信主要包括:
串口数据发送和接收。
发送实例:
/******************************************************
作者:
淋哥电子
说明:
本程序实现串口数据发送,从0到10每隔500ms发送一次
******************************************************/
#include
#defineuintunsignedint//宏定义
#defineucharunsignedchar
voiddelay_ms(ucharms);//声明一个ms级延时函数
voidUART_Init(void);//声明串口初始化函数
voidUART_Send_Byte(ucharbyte);//声明串口发送单字节函数
voidmain(void)//主函数
{
uchari=0;//定义一个变量
UART_Init();//串口初始化
while
(1)//死循环
{
UART_Send_Byte(i);//串口发送单字节数据
delay_ms(500);//延时500ms
if(++i>10)//i自加到10清0
i=0;
}
}
//定义delay_ms函数
voiddelay_ms(ucharms)
{
uchari;
while(ms--)
{
for(i=0;i<120;i++);
}
}
//定义UART_Init函数
voidUART_Init(void)
{
SCON=0x40;//设定串行口工作方式,8位数据位
T2CON=0x34;//设置定时器2,作为波特率发生器
RCAP2L=0XD9;//9600波特率的低8位
RCAP2H=0XFF;//9600波特率的高8位
}
//定义UART_Send_Byte函数
voidUART_Send_Byte(ucharbyte)
{
SBUF=byte;//缓冲区装载要发送的字节数据
while(TI==0);//等待发送完毕,TI标志位会置1
TI=0;//清零发送完成标志位
}
在串口调试助手中看到程序运行的结果:
在串口初始化中涉及到的寄存器有:
接收实例:
1)
/******************************************************
作者:
淋哥电子
说明:
本程序实现串口数据接收(查询法)
单片机晶振11.0592M
******************************************************/
#include
#defineuintunsignedint//宏定义
#defineucharunsignedchar
voidUART_Init(void);//声明串口初始化函数
voidUART_Send_Byte(ucharbyte);//声明串口发送单字节函数
voidmain(void)//主函数
{
uchari=0;//定义一个变量
UART_Init();//串口初始化
while
(1)//死循环
{
if(RI)//检测接收完成标志位置1
{
RI=0;//清零接收完成标志位
i=SBUF;//读取接收到的数据
UART_Send_Byte(i);//串口发送单字节数据
}
}
}
//定义UART_Init函数
voidUART_Init(void)
{
SCON=0x50;//设定串行口工作方式,8位数据位,允许接收
T2CON=0x34;//设置定时器2,作为波特率发生器
RCAP2L=0XD9;//9600波特率的低8位
RCAP2H=0XFF;//9600波特率的高8位
}
//定义UART_Send_Byte函数
voidUART_Send_Byte(ucharbyte)
{
SBUF=byte;//缓冲区装载要发送的字节数据
while(TI==0);//等待发送完毕,TI标志位会置1
TI=0;//清零发送完成标志位
}
2)
/******************************************************
作者:
淋哥电子
说明:
本程序实现串口数据接收(中断法)
单片机晶振11.0592M
******************************************************/
#include
#defineuintunsignedint//宏定义
#defineucharunsignedchar
voidUART_Init(void);//声明串口初始化函数
voidUART_Send_Byte(ucharbyte);//声明串口发送单字节函数
voidmain(void)//主函数
{
UART_Init();//串口初始化
while
(1)//死循环
{
}
}
//定义UART_Init函数
voidUART_Init(void)
{
SCON=0x50;//设定串行口工作方式,8位数据位,允许接收
T2CON=0x34;//设置定时器2,作为波特率发生器
RCAP2L=0XD9;//9600波特率的低8位
RCAP2H=0XFF;//9600波特率的高8位
ES=1;//允许串口中断
EA=1;//允许总中断
}
//定义UART_Send_Byte函数
voidUART_Send_Byte(ucharbyte)
{
SBUF=byte;//缓冲区装载要发送的字节数据
while(TI==0);//等待发送完毕,TI标志位会置1
TI=0;//清零发送完成标志位
}
uchari=0;//定义一个变量
//串口中断服务程序
voidUART(void)interrupt4
{
if(RI)//检测接收完成标志位置1
{
RI=0;//清零接收完成标志位
i=SBUF;//读取接收到的数据
UART_Send_Byte(i);//串口发送单字节数据
}
}
重点说明:
51单片机可以通过SBUF寄存器对串行接收或发送寄存器进行访问,两个寄存器共用一个地址99H,但在物理上是两个独立的寄存器,有指令操作决定访问哪一个。
eg:
接收时,我们写“a=SBUF;”
发送时,我们写“SBUF=a;”
实例一:
/******************************************************
作者:
淋哥电子
说明:
本程序实现在上位机上用串口调试助手发送一个字符X,
单片机收到字符后返回给上位机“IgetX”
单片机晶振11.0592M
******************************************************/
#include
#defineuintunsignedint//宏定义
#defineucharunsignedchar
ucharuart_flag,a,i;
ucharcodetable[]={"Iget"};
voidUART_Init(void);//声明串口初始化函数
voidUART_Send_Byte(ucharbyte);//声明串口发送单字节函数
voidmain(void)//主函数
{
UART_Init();//串口初始化
while
(1)//死循环
{
if(uart_flag==1)//接收到
{
ES=0;//关串口中断
for(i=0;i<6;i++)//在串口发送时,每次只能发一位数据,所以必须用循环将所有位全部发送,也可以用puts(“”);
{
UART_Send_Byte(table[i]);
}
UART_Send_Byte(a);//发送接收到的字符
ES=1;//允许串口中断
uart_flag=0;//中断标志位置0
}
}
}
//定义UART_Init函数
voidUART_Init(void)
{
SCON=0x50;//设定串行口工作方式,8位数据位,允许接收
T2CON=0x34;//设置定时器2,作为波特率发生器
RCAP2L=0XDC;//9600波特率的低8位
RCAP2H=0XFF;//9600波特率的高8位
ES=1;//允许串口中断
EA=1;//允许总中断
}
//定义UART_Send_Byte函数
voidUART_Send_Byte(ucharbyte)
{
SBUF=byte;//缓冲区装载要发送的字节数据
while(TI==0);//等待发送完毕,TI标志位会置1
TI=0;//清零发送完成标志位
}
//串口接收中断服务程序
voidUART(void)interrupt4
{
if(RI)//检测接收完成标志位置1
{
RI=0;//清零接收完成标志位
a=SBUF;//读取接收到的数据
uart_flag=1;//中断标志位置1
}
}
实例二:
/***********************************************************************************************************
作者:
淋哥电子
说明:
本程序实现:
单片机上电后等待从上位机串口发送来的命令,
当收到上位机以十六进制发送来的01后,向上位机发送字符串“Turnonad!
”同时在数码管以每秒刷新显示AD值
当收到上位机以十六进制发送来的02后,向上位机发送字符串“TurnoffAD!
”
当收到上位机发送来的其他任何数据,向上位机发送字符串“Error!
!
”
单片机晶振11.0592
***********************************************************************************************************/
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitsmg1=P2^6;//数码管位选
sbitsmg2=P2^5;//数码管位选
sbitsmg3=P2^4;//数码管位选
ucharflag_uart;//串口中断标志
ucharflag_time;//1s钟标志
ucharflag_on;//AD运行标志
uchara;
uchari;
uchart0_num;//T050ms定时标志
ucharad_val;//AD采集得到的值(二进制表示)
floatad_vo;//实际电压标准值
unsignedcharcodetable[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管段选显示0--9
sbitcs=P3^3;////ad的cs控制管脚定义
sbitwr=P3^5;//ad的wr控制管脚定义
sbitrd=P3^4;//ad的rd控制管脚定义
voiddelay(uintcount)//delay
{
uinti;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
voidinit(void)
{
TMOD=0x21;//定计0工作方式1,定计1工作方式2
TH0=(65536-50000)/256;//定计0赋初值
TL0=(65536-50000)%256;
TH1=0XFD;//定计1赋初值
TL1=0XFD;
TR1=1;//开定计1
ET0=1;//开定计0中断
SCON=0X50;//串口控制寄存器:
SM0=0,SM1=1,REN=1
EA=1;//开总中断
ES=1;//开串口中断
}
/*************读AD0804子程序*******************************/
unsignedcharadc0804(void)//读AD0804子程序
{
unsignedcharaddata,i;
rd=1;wr=1;//int1=1;//读ADC0804前准备
P1=0xff;//P1全部置一准备
cs=0;wr=0;wr=1;//启动ADC0804开始测电压
rd=0;//开始读转换后数据
i=i;i=i;//无意义语句,用于延时等待ADC0804读数完毕
addata=P1;//读出的数据赋与addate
rd=1;cs=1;//读数完毕
return(addata);//返回最后读出的数据
}
/*************数码管显示程序*******************************/
voiddisplay(inttemp)
{
/****************************************************/
smg3=1;
smg2=1;
delay
(1);
P0=table[temp/100];//显示百位
smg1=0;
delay
(1);
smg1=1;
/****************************************************/
smg3=1;
P0=table[temp%100/10];//显示十位
smg2=0;
delay
(1);
smg2=1;
/****************************************************/
smg1=1;
P0=table[temp%10];//显示个位
smg3=0;
delay
(1);
smg3=1;
/****************************************************/
}
/*************主程序*******************************/
voidmain(void)
{
init();//初始化
while
(1)
{
if(flag_uart==1)//接收到数据
{
flag_uart=0;//串口中断标志置0
ES=0;//关串口中断,若不关闭,每发送一个字节,程序就会申请进入串口中断,从而导致程序出错
TI=1;//发送标志置1
switch(flag_on)
{
case0:
puts("TurnonAD!
");
TR0=1;
break;
case1:
puts("TurnoffAD!
");
TR0=0;
break;
case2:
puts("Error!
");
break;
default:
break;
}
while(!
TI);//等待发送完毕
TI=0;//发送完毕,手动清
ES=1;
}
if(flag_time==1)
{
flag_time=0;
ad_val=adc0804();//将AD采集回来的8位二进制数赋给ad_val
ad_vo=(float)ad_val*5.0/256.0;//以浮点数表示AD实际采集到的电压标准值
ES=0;
TI=1;
printf("Thevoltageis%fV\n",ad_vo);
while(!
TI);
TI=0;
ES=1;
}
display(ad_val);
}
}
/*************定计0中断服务子程序*******************************/
voidtimer0(void)interrupt1
{
TH0=(65536-50000)/256;//定计0重装初值
TL0=(65536-50000)%256;
t0_num++;
if(t0_num==20)
{
t0_num=0;
flag_time=1;
}
}
/*************串口中断服务子程序*******************************/
voidser(void)interrupt4
{
RI=0;//清零接收完成标志位
a=SBUF;//读取接收到的数据
flag_uart=1;//串口中断标志位置1
if(a==1)
flag_on=0;
elseif(a==2)
flag_on=1;
else
flag_on=2;
}
说明:
printf()和puts()的区别:
1)puts()自带换行符;
2)printf()可以在后面追加要输出的变量,而puts()只能输出字符串
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 51 单片机 串口 通信 学习 总结