51单片机串口通信学习总结Word文档下载推荐.docx
《51单片机串口通信学习总结Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《51单片机串口通信学习总结Word文档下载推荐.docx(19页珍藏版)》请在冰豆网上搜索。
//单片机52头文件,存放着单片机的寄存器
#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
while
(1)//死循环
if(RI)//检测接收完成标志位置1
{
RI=0;
//清零接收完成标志位
i=SBUF;
//读取接收到的数据
UART_Send_Byte(i);
}
SCON=0x50;
//设定串行口工作方式,8位数据位,允许接收
2)
本程序实现串口数据接收(中断法)
ES=1;
//允许串口中断
EA=1;
//允许总中断
//清零发送完成标志位
uchari=0;
//串口中断服务程序
voidUART(void)interrupt4
if(RI)//检测接收完成标志位置1
重点说明:
51单片机可以通过SBUF寄存器对串行接收或发送寄存器进行访问,两个寄存器共用一个地址99H,但在物理上是两个独立的寄存器,有指令操作决定访问哪一个。
eg:
接收时,我们写“a=SBUF;
”
发送时,我们写“SBUF=a;
实例一:
本程序实现在上位机上用串口调试助手发送一个字符X,
单片机收到字符后返回给上位机“IgetX”
ucharuart_flag,a,i;
ucharcodetable[]={"
Iget"
};
if(uart_flag==1)//接收到
ES=0;
//关串口中断
for(i=0;
6;
i++)//在串口发送时,每次只能发一位数据,所以必须用循环将所有位全部发送,也可以用puts(“”);
{
UART_Send_Byte(table[i]);
}
UART_Send_Byte(a);
//发送接收到的字符
ES=1;
//允许串口中断
uart_flag=0;
//中断标志位置0
}
RCAP2L=0XDC;
//串口接收中断服务程序
a=SBUF;
uart_flag=1;
//中断标志位置1
实例二:
/***********************************************************************************************************
本程序实现:
单片机上电后等待从上位机串口发送来的命令,
当收到上位机以十六进制发送来的01后,向上位机发送字符串“Turnonad!
”同时在数码管以每秒刷新显示AD值
当收到上位机以十六进制发送来的02后,向上位机发送字符串“TurnoffAD!
当收到上位机发送来的其他任何数据,向上位机发送字符串“Error!
!
单片机晶振11.0592
***********************************************************************************************************/
#include<
//单片机51头文件,存放着单片机的寄存器
intrins.h>
//为了使用空指令加载的头文件
stdio.h>
#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;
//启动ADC0804开始测电压
rd=0;
//开始读转换后数据
i=i;
//无意义语句,用于延时等待ADC0804读数完毕
addata=P1;
//读出的数据赋与addate
cs=1;
//读数完毕
return(addata);
//返回最后读出的数据
/*************数码管显示程序*******************************/
voiddisplay(inttemp)
/****************************************************/
smg3=1;
smg2=1;
delay
(1);
P0=table[temp/100];
//显示百位
smg1=0;
smg1=1;
/****************************************************/
P0=table[temp%100/10];
//显示十位
smg2=0;
P0=table[temp%10];
//显示个位
smg3=0;
/*************主程序*******************************/
voidmain(void)
init();
//初始化
while
(1)
if(flag_uart==1)//接收到数据
flag_uart=0;
//串口中断标志置0
//关串口中断,若不关闭,每发送一个字节,程序就会申请进入串口中断,从而导致程序出错
TI=1;
//发送标志置1
switch(flag_on)
case0:
puts("
TurnonAD!
"
);
TR0=1;
break;
case1:
TurnoffAD!
TR0=0;
case2:
Error!
default:
break;
while(!
TI);
//等待发送完毕
TI=0;
//发送完毕,手动清
if(flag_time==1)
flag_time=0;
ad_val=adc0804();
//将AD采集回来的8位二进制数赋给ad_val
ad_vo=(float)ad_val*5.0/256.0;
//以浮点数表示AD实际采集到的电压标准值
printf("
Thevoltageis%fV\n"
ad_vo);
display(ad_val);
/*************定计0中断服务子程序*******************************/
voidtimer0(void)interrupt1
//定计0重装初值
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()只能输出字符串