51单片机通过串口发送1 串口通信

点击获取更多
没有更多了
加入学习后,就可以记笔记了
同学的问题
点击获取更多
没有更多了
加入学习后,就可以提问题了
Loading...51 单片机UART 串口通信 方式1 实现
10:20:14来源: eefocus
1& 51串行口结构
的串行通信是基于其串行口的硬件结构,只要用正确的程序代码通过初始化串行口对应寄存器的形式将其串行硬件结构初始化,再编写符合此串行口通信的程序代码便能够实现串行通信,其硬件结构决定了编程机制( 当然还要靠51芯片内CPU等机制 )。此结构具有UART( 通用异步收发器 )的全部功能,能同时进行数据的发送和接收,也可作为同步使用。此结构集成于内部。
Figure1:51串行口结构
2& 51串行口通信编程机制
决定编程机制的先决条件是51单片机的硬件结构及51芯片内部CPU的执行机制。根据串行通信口硬件结构,实现UART通信可以分为两步:
(1)初始化串行通信口( UART )
&配置SCON:设定串口方式( SM0及SM1位配置4种方式&);串口是否要接收数据(REN位&)
设定PCON寄存器的SMOD位(若非串口方式0 )
若串口为方式1和方式3,则需要配置TMOD:选择定时器1并配置其初值装载方式(MI M0位),并设置TH1,TL0的初值以确定通信的波特率(由波特率的计算公式&),然后配置TCON:开启定时器1( TR1 )。
允许使用中断( ES ),开启UART中断( EA )
&可以这些寄存器的配置含义可以查看相应的知识点:中断配置IE寄存器、定时/计数方式配置寄存器TMOD、定时/计数控制寄存器及通信寄存器SCON寄存器笔记。
(2)程序实现:编写发送/接收数据代码及中断服务程序
注:TI及RI的置位可查看SCON寄存器TI& RI被置位的条件
[1]发送的数据需要通过程序指令&SBUF =数据;&来将数据送往串行发送缓冲寄存器中,在此条语句后,要用循环判断SCON寄存器中的TI位是否被硬件置位1(表示发送完毕),等待发送完毕,TI置位被置为1时会进入串行中断服务程序[由此不能在串行中断服务程序里面将TI置0,因为从循环里面进入中断后会返回到循环语句中来,所以要在串行中断服务程序之外将TI置0,置0的目的是提供下一次数据发送成功的依据或进入中断服务器程序&],需要用程序代码将TI重新置为0;然后再由CPU控制的时序将数据从TXD( P3.1 )脚发出,经过连接的串口线到从设备(接收数据的设备&)。
[2]获取接收到数据时需要通过程序指令&存数据变量=SBUF;&将串行接收缓冲寄存器接收到的数据读取到程序中来,当接收到数据完毕后,RI会被硬件置位1,此时也会进入串行中断服务程序,需要用程序指令将RI重新置位0。当然接收数据是由RXD( P3.0 )引脚完成。
[3]串行中断服务程序的中断号为4,所以编写串行中断服务程序时需要有以下格式:
void&函数名()& 4
&&&&&&&&&中断服务程序内容
串行中断服务函数当TI或RI被硬件置位1时才被系统调用。TI被硬件置1的情况是,当串行发送缓冲寄存器内的数据被通过TXD( P3.1 )发送完毕时(&不同的串口方式置1条件不同&)不是指将数据存入串行发送缓冲器中时TI会被置1,同理RI被置1的情况是当RXD( P3.0 )接收到数据将此数据按位存入串行接收缓冲寄存器内完毕时(&不同串口方式置1的条件不同&)不是指从串行接收缓冲寄存器读完数据时RI会被置1。这个数据的长度和TI( RI )被置位1根据串行通信方式不同而不同。
对于用程序来实现51单片机中的串行通信还需要明确两点(与其它部分的联系):
(1)在51单片机串行通信的方式1和方式3中,波特率由定时器1的溢出率决定。
(2)SBUF为特殊功能寄存器,它在程序中的两种不同的指令形式表示不同的含义,当在程序中用写指令&SBUF=a;&时,表示将a存入串行数据发送缓冲寄存器中;当在程序中使用读指令&a=SBUF;&时,表示向串行数据接收缓冲寄存器读数据并将得到数据赋值于a。接收器具有双缓冲结构,即在从接收寄存器中前一个已经收到的字节之前,便能接收第二个字节,如果第二个字节已经接收完毕,第一个字节还没有被读出,则第一个字节就损失( 被覆盖 )。而发送器中的数据是由CPU控制的,所以不必程序用户担忧。
3& 程序实现串行通信
程序的大体框架为main主函数、串行中断服务程序、子函数(初始化串口、延时函数,字符串处理函数等)
(1)首先是用程序实现串行通信的初始化
//串口初始化
void UART_Init(void)
&&&&&&&& SCON& = 0x40;&&&&&&&&&&&&&&& && //串口方式1
&&&&&&&& PCON& = 0;&&&&&&&&&&&&&&&&&& & //SMOD=0
&&&&&&&& REN& = 1;&&&&&&&&&&&&&&&&&&&& &&&&&&&&& //允许接收
&&&&&&&& TMOD = 0x20;&&&&&&&&&&&&&& &&&&&&&&&&&& //定时器1定时方式2
&&&&&&&& TR1& = 1;&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& //启动定时器
&&&&&&&& ES& = 1;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //UART中断
&&&&&&&& EA& = 1;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //中断使能
(2)用程序实现发数据
将要发送的数据赋值给SBUF即可。
while(TI == 0);//等待,直到发送成功
这是发送一次数据(如一个字符,在串口发送方式1下占10个位)的代码,可单独写成函数。此种写法不可以将&TI = 0;&写在中断函数中,不然会造成死循环。
(3)在中断函数中接受数据
不管发送数据成功还是接受到数据都会进入到中断程序中,故而在中断程序中判断是否RI被置位为1,如是则表示收到了数据。
void UART_Receive_Int() interrupt 4
&&&&&&&& if(& RI == 1)
&&&&&&&& {
&&&&&&&&&&&&&&&&&& RI&&&& = 0;&&&&&&&&&&&
&&&&&&&&&&&&&&&&&& if(& index < 1 )
&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&&&&&Receive[index] = SBUF;
&&&&&&&&&&&&&&&&&&&&&&&&&&& index++;
&&&&&&&&&&&&&&&&&& }else{
&&&&&&&&&&&&&&&&&&&&&&&&&&& index& = 0;
&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&
&&&&&&&& }&&&&&&&
然后只需要在主程序main函数中调用串行口初始化函数及用一定的逻辑调用数据发送函数即可。
(4)通过助手来观察程序执行效果
发数据显示
设置串口调试助手:
Figure2:向调试助手发数据显示
在串口调试助手中按照下划线部分设置后,结果显示区域就会显示由程序发将上来的数据。
串口调试助手往单片机发送数据并再显示到串口调试界面之上
Figure3:调试助手向单片机发送数据显示界面
对串口调试助手的设置除了发送数据之上的设置之外还需要在表格中填入字符串,然后点击表格下画圈使之为&停止循环发送&,然后就可以将收到的数据同将要发送的数据一起发送到串口调试界面之上来。
此次笔记记录完毕。
关键字:&&&&
编辑:什么鱼
引用地址:
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
微信扫一扫加关注 论坛活动 E手掌握
微信扫一扫加关注
芯片资讯 锐利解读
大学堂最新课程
汇总了TI汽车信息娱乐系统方案、优质音频解决方案、汽车娱乐系统和仪表盘参考设计相关的文档、视频等资源
热门资源推荐
频道白皮书
何立民专栏
北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)9596人阅读
单片机(87)
转自:http://www.cnblogs.com/weifeng727/category/845655.html
#include&reg52.h&
//------------------串口通信协议-----------------//
客户端数据包格式解释(长度恒为15):
例如:A01_fmq_01Off___#
A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
01-----设备代号
fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
#---------数据包的结束标记
服务器端数据包格式解释(长度恒为15):
例如:A02_SenT010250#
A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
02-----设备代号
SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
#---------数据包的结束标记
char buf_string[16];
//定义数据包长度为15个字符
#define deviceID_1Bit &#39;0&#39;
//用于串口通信时,定义本地设备ID的第1位
#define deviceID_2Bit &#39;2&#39;
//用于串口通信时,定义本地设备ID的第2位
#define datapackage_headflag &#39;A&#39;
//用于串口通信时,定义数据包头部的验证标记
char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,&#39;_&#39;,&#39;S&#39;,&#39;e&#39;,&#39;n&#39;,&#39;T&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;#&#39;};
char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,&#39;_&#39;,&#39;B&#39;,&#39;e&#39;,&#39;a&#39;,&#39;t&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;X&#39;,&#39;#&#39;};
//----------------------------------------------//
/*******************************
MCU:89C52RC
11.0592MHz
//11.0592MHz 0xd0 1200bps
//12MHz 0xcc 1200bps
//11.0592MHz 0xfa 9600bps
//0xf4 11.0592MHz
0xf3 12MHz 4800bps
//均在SMOD=1的情况下(波特率倍增模式)
*******************************/
//串口发送函数
void PutString(unsigned char *TXStr)
while(*TXStr!=0)
while(TI==0);
//串口接收函数
bit ReceiveString()
char * RecStr=buf_
char num=0;
unsigned char count=0;
*RecStr=SBUF;
if(num&14)
//数据包长度为15个字符,尝试连续接收15个字符
while(!RI)
if(count&130)return 0;
//接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现&数据包被分割&,默认count=130
//定时器1用作波特率发生器
void Init_USART()
SCON=0x50;
//串口方式1,使能接收
TMOD|=0x20;
//定时器1工作方式2(8位自动重装初值)
TMOD&=~0x10;
PCON|=0x80;
//提高串口中断优先级
//开启串口中断使能
//比较指令头部
bit CompareCMD_head(char CMD_head[])
unsigned char CharN
for(CharNum=0;CharNum&4;CharNum++)
//指令长度为10个字符
if(!(buf_string[CharNum+4]==CMD_head[CharNum]))
//指令头部匹配失败
//指令头部匹配成功
//比较指令尾部(start:从哪里开始比较,quality:比较多少个字符,CMD_tail[]:要比较的字符串)
bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[])
unsigned char CharN
for(CharNum=0;CharNum&CharNum++)
if(!(buf_string[start+CharNum]==CMD_tail[CharNum]))
bit Deal_UART_RecData()
//处理串口接收数据包函数(成功处理数据包则返回1,否则返回0)
//PutString(buf_string);
if(buf_string[0]==datapackage_headflag&&buf_string[14]==&#39;#&#39;)
//进行数据包头尾标记验证
switch(buf_string[1])
//识别发送者设备ID的第1位数字
case &#39;0&#39;:
switch(buf_string[2])
//识别发送者设备ID的第2位数字
case &#39;3&#39;:
if(CompareCMD_head(&Ligt&))
//判断指令头部是否为&Ligt&
//下面是指令尾部分析
switch(buf_string[8])
case &#39;0&#39;:
switch(buf_string[9])
case &#39;0&#39;:
case &#39;1&#39;:
if(CompareCMD_tail(10,3,&Off&))
//A03_Ligt01Off_#
//要执行的代码
if(CompareCMD_tail(10,3,&On_&))
case &#39;1&#39;:
if(CompareCMD_head(&SenT&))
if(CompareCMD_head(&jdq_&))
if(CompareCMD_head(&Try!&))
/************************
************************/
//串口中断服务函数-----------
void USART() interrupt 4
//标志位TI和RI需要手动复位,TI和RI置位共用一个中断入口
if(ReceiveString())
//数据包长度正确则执行以下代码
Deal_UART_RecData();
//数据包长度错误则执行以下代码
//LED1=~LED1;
//接收并处理一次数据后把接收中断标志清除一下,拒绝响应在中断接收忙的时候发来的请求
/***************************
***************************/
void main()
Init_USART();
//PutString(buf_string);//空格20H,回车0DH
访问:280265次
积分:5050
排名:第6590名
原创:168篇
转载:325篇
评论:17条
文章:21篇
阅读:13339
(2)(39)(57)(7)(4)(11)(1)(12)(16)(9)(7)(28)(19)(16)(37)(17)(21)(11)(6)(40)(18)(40)(31)(28)(2)(9)(7)80C51单片机的串行口通信原理及编程_谢贵波_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
80C51单片机的串行口通信原理及编程_谢贵波
&&单片机串口通信
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
你可能喜欢}

我要回帖

更多关于 串口通信的接收与发送 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信