单片机的串口通讯编程
一、串口
1.1串口基本认知
串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了本,特别适用于远距离通信,但传送速度较慢
小结:
1).是设备间接线通讯的一种方式
2).数据是一位一位的传输
3).双向全双工通讯
4).传输速度相对较慢
1.2串口标准与协议
串行接口常用接口有RS-232、RS-422、RS-485接口
**RS-232**
由于RS-232其发送电平与接收电平的差仅为2V至3V左右,所以其共模抑制能力差,再加上双绞线上的分布电容,其传送距离最大为约15米,最高速率为20kb/s。RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其驱动器负载为3~7kΩ。所以RS-232适合本地设备之间的通信。
**RS-422**
典型的RS-422是四线接口。实际上还有一根信号地线,共5根线。其DB9连接器引脚定义。由于接收器采用高输入阻抗和发送驱动器比RS232更强的驱动能力,故允许在相同传输线上连接多个接收节点,最多可接10个节点。即一个主设备(Master),其余为从设备(Salve),从设备之间不能通信,所以RS-422支持点对多的双向通信。
RS-422的最大传输距离为1219米,最大传输速率为10Mb/s。其平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能达到最大传输距离。只有在很短的距离下才能获得最高速率传输。一般100米长的双绞线上所能获得的最大传输速率仅为1Mb/s。
RS-422需要一终接电阻,要求其阻值约等于传输电缆的特性阻抗。在短距离传输时可不需终接电阻,即一般在300米以下不需终接电阻。终接电阻接在传输电缆的最远端。
**RS-485**
由于RS-485是从RS-422基础上发展而来的,所以RS-485许多电气规定与RS-422相仿。如都采用平衡传输方式、都需要在传输线上接终接电阻等。RS-485可以采用二线与四线方式,二线制可实现真正的多点双向通信,而采用四线连接时,与RS-422一样只能实现点对多的通信,即只能有一个主(Master)设备,其余为从设备,但它比RS-422有改进, 无论四线还是二线连接方式总线上可多接到32个设备。
RS-485与RS-422的不同还在于其共模输出电压是不同的,RS-485是-7V至+12V之间,而RS-422在-7V至+7V之间,RS-485接收器最小输入阻抗为12k剑 鳵S-422是4k健; 旧峡梢运礴S-485满足所有RS-422的规范,所以RS-485的驱动器可以用在RS-422网络中应用。
RS-485与RS-422一样,其最大传输距离约为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能使用规定最长的电缆长度。只有在很短的距离下才能获得最高速率传输。一般100米长双绞线最大传输速率仅为1Mb/s
RS-485需要2个终接电阻,其阻值要求等于传输电缆的特性阻抗。在短距离传输时可不需终接电阻,即一般在300米以下不需终接电阻。终接电阻接在传输总线的两端。
1.3接口电平
RS-232电平
逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,注意电平的定义反相了一次
TTL电平
+5V等价于逻辑“1”,0V等价于逻辑“0”(采用二进制来表示数据时)。
输出高电平>=2.4V,输出低电平<=0.4V;
输入高电平>=2.0V,输入低电平<=0.8V
1.4串口通讯接线
**两个芯片之间的通讯**
芯片与计算机串口连接
二、串口配置与基础印象
2.1基础印象
对于输入输出的数据需要先传送到SBUF寄存器中
想要接收数据
char datas= = SBUF;
想要发送数据
SBUF = datas
2.2串口配置与工作模式
2.2.1:串行口相关寄存器
2.2.2:串行口控制器SCON与PCON
串行口控制器SCON:可寻址位
SFR name | address | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
SCON | 98H | SM0/FE | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
SM0与SM1组合之后的工作方式
REN:允许/禁止串行接口接收控制位,由软件控制,即当REN=1时,则为允许接收,可启动RxD,开始接收消息,反之则禁止接收
TI:发送请求中断标志位。当发送的8位数据结束之后,硬件内部自动置位,TI=1,向主机发送中断请求,相应中断之后必须用软件进行复位,即TI=0。
RI:接收请求中断标志位。当接收的8位数据结束之后,硬件内部自动置位,RI=1,向主机发送中断请求,相应中断之后必须用软件进行复位,即RI=0。
串行口控制器PCON:不可寻址位
SFR name | address | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
PCON | 87H | SMOD | SMOD0 | - | POF | GF1 | GF0 | PD | IDL |
SMOD:波特率选择。当软件进行置位后,即SMOD = 1,则串行通讯方式1,2,3比特率加倍;当SMOD=0,则各个工作方式的波特率加倍。
2.2.3:串行口中断控制器
中断允许寄存器IE(可寻址位)
SFR name | address | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
IE | A8H | EA | - | ET2 | ES | ET1 | EX1 | ET0 | EX0 |
EA:CPU总中断控制,EA=1,CPU开放中断,EA=0,CPU停止中断;在各个中断中,首先有EA控制,然后在由自己中断进行控制
ES:串口中断允许标志,ES =1,允许中断;ES=0,禁止中断
三.串口配置方式
配置串口要求:晶振频率11.0592Mhz,波特率为9600,选择串口UART1,工作方式配置为1,允许串行接收控制,允许接收与发送中断标志位
SCON位 :0 1 0 1 0 0 1 1
PCON位: 0 1 0 1 0 0 0 0
由波特率计算出定时器初始值:设定时器的初始值为“X”
解出X = 3,定时器溢出率=10#253=16#FD
代码实现
void UartInit(void) //9600bps@11.0592MHz
{PCON &= 0x7F; //波特率不倍速SCON = 0x50; //8位数据,可变波特率AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12TAUXR &= 0xFE; //串口1选择定时器1为波特率发生器TMOD &= 0x0F; //清除定时器1模式位TMOD |= 0x20; //设定定时器1为8位自动重装方式TL1 = 0xFD; //设定定时初值TH1 = 0xFD; //设定定时器重装值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1
}
四.程序练习
1.通过串口向电脑每次间隔一秒发送一个字符“A”
#include <reg52.h>
#include "intrins.h"
sfr AUXR = 0x8E;
/*配置C51串口的通信方式*/
void UartInit(void) //9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x40; //配置串口工作方式1,REN不使能接收TMOD &= 0xF0;TMOD |= 0x20;//定时器1工作方式位8位自动重装TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//启动定时器
}void Delay1000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void main()
{char data_msg = 'a'; //data_msg为内部数据参数,并给定数据字符“a“UartInit();while(1){Delay1000ms();//往发送缓冲区写入数据,就完成数据的发送SBUF = data_msg;}
}
2.通过串口向电脑每次间隔一秒发送字符
#include <REGX52.H>
#include "intrins.h"
/*配置C51串口的通信方式*/
void UartInit() //9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x40; //配置串口工作方式1,REN不使能接收TMOD &= 0xF0;TMOD |= 0x20;//定时器1工作方式位8位自动重装TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//启动定时器
}
void Delay1000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}
/*由于SBUF是8位为一组,因此需要建立一个字节发送函数,以发送相应的字节
形式参数:datas,用于承接发送的实际内容*/
void sendbyte(char datas)
{SBUF = datas;while(TI == 0); //当发送数据的时候,TI=0,这时while循环满足,不执行下面的程序,当TI=1时,while循环不满足,执行下面的程序:复位TITI = 0;
}
/*发送字符串函数
形式参数:char型字符*/
void sendstring(char* str)
{sendbyte(*str);while(*str !='\0'){sendbyte(*str);str++;} //当字符串没有结尾的时候,则要调用sendbyte函数,进行函数的发送
}
void main()
{UartInit();while(1){Delay1000ms();sendstring("youare handsome\r\n") //向sendstring形式参数中传输实际参数}
}
3.通过串口接收到的数据控制指示灯亮灭
#include <REGX52.H>
#include <intrins.h>
sbit LED = P2^0;
void UartInit()
{PCON &= 0x7F; SCON = 0x50; TMOD &= 0x0F; TMOD |= 0x20; TL1 = 0xFD; TH1 = 0xFD; ET1 = 0; TR1 = 1;
}
void Delay1000ms()
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}
/*void sendbyte(char datas)
{SBUF = datas;while(TI == 0);TI=0;
}
void sendstring(char *str)
{while(*str !='\0'){sendbyte(*str)str++;}
}
*/
void main()
{char cmd;LED = 0; //LED指示灯初始化为熄灭状态UartInit();while(1){Delay1000ms();RI = 0; //当接收到数据完成之后,RI=0cmd = SBUF; //当RI=0之后,将SBUF中的数据读取到cmd中/*当读取到的字符为“O”时,点亮LED;当读取到字符为“C”时,熄灭LED*/if(cmd = 'O'){LED = 0;}if(cmd = 'C'){LED = 1;}}}
经过测试,这段代码没有功能上的问题,但是会存在一定的延迟
4.通过串口中断的方法控制LED指示灯
中断优先级
#include "reg52.h"
#include "intrins.h"
sbit D5 = P3^7;
char cmd;void UartInit(void)
{SCON = 0x50; TMOD &= 0xF0;TMOD |= 0x20;TH1 = 0xFD;TL1 = 0xFD;TR1 = 1;EA = 1;ES = 1;
}void Delay1000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}
/*
void sendByte(char data_msg)
{SBUF = data_msg;while(!TI);TI = 0;
}void sendString(char* str)
{while( *str != '\0'){sendByte(*str);str++;}
}
*/
void main()
{D5 = 1;//配置C51串口的通信方式UartInit();while(1){Delay1000ms();//往发送缓冲区写入数据,就完成数据的发送/*sendString("chenlichen shuai\r\n");*/}
}void Uart_Handler() interrupt 4
{if(RI)//中断处理函数中,对于接收中断的响应{RI = 0;//清除接收中断标志位cmd = SBUF;if(cmd == 1){D5 = 0;//点亮D5}if(cmd == 0){D5 = 1;//熄灭D5}}if(TI);
}
5.通过发送字符方式控制指示灯
#include "reg52.h"
#include "intrins.h"
#include <string.h>#define SIZE 12
sbit D5 = P3^7;
char cmd[SIZE];void UartInit(void)
{SCON = 0x50; TMOD &= 0xF0;TMOD |= 0x20;TH1 = 0xFD;TL1 = 0xFD;TR1 = 1;EA = 1;ES = 1;
}void Delay1000ms()
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}
/*
void sendByte(char data_msg)
{SBUF = data_msg;while(!TI);TI = 0;
}void sendString(char* str)
{while( *str != '\0'){sendByte(*str);str++;}
}
*/
void main()
{D5 = 1;//配置C51串口的通信方式UartInit();while(1){Delay1000ms();//往发送缓冲区写入数据,就完成数据的发送sendString("chenlichen shuai\r\n");}
}void Uart_Handler() interrupt 4
{static int i = 0;//定义字符串的指针,静态变量,被初始化一次if(RI)//中断处理函数中,对于接收中断的响应{RI = 0;//清除接收中断标志位cmd[i] = SBUF; //将SBUF中的数据读取到cmd中i++; //将指针进行右移if(i == SIZE){i = 0;} //当移动到最后一位时,将指针移动到首位if(strstr(cmd,"en")){D5 = 0;//点亮D5i = 0;memset(cmd,'\0',SIZE);} //当接收到字符中有‘en’(open),启动LED,同时将cmd中数据清空if(strstr(cmd,"cl")){D5 = 1;//熄灭D5i = 0;memset(cmd,'\0',SIZE);} //当接收到字符中有‘cl’(close),关闭LED,同时将cmd中数据清空}if(TI);
}
单片机的串口通讯编程相关推荐
- ABOV单片机UART串口通讯实现讲解及示例代码-[MC96F6332D]
一.准备工作 1.KEIL C51编译环境 2.CodeGen8 代码生成器 3.MC96F6332D 开发板 4.USB-OCD II仿真器 二.生成串口通讯代码 1.在CodeGen8 代码生成器 ...
- c语言stm32串口控制单片机,基于STM32F103C8T6单片机电脑串口通讯控灯设计(原理图+程序+论文)...
题目:基于STM32F103C8T6单片机电脑串口通讯控灯设计 内容要求: 一. 任务 通信是指不同的独立系统利用线路互相交换数据,它的主要目的是将数据从一端传送到另一端,实现数据的交换.在现代工业控 ...
- 串口通讯编程一日通1(整合资料) .
本文以VC++为平台进行串口通信编程 串口通讯在VC++下实现方式有很多,控件自然是最简单话的方式了,但由于控件只支持对话框程序,有些场合又不需要对话框,所以用Windows API实现是比较好的方式 ...
- plc.单片机的串口通讯的调试方法——通过虚拟串口工具和串口助手来调试串口
加一个,串口助手和虚拟串口工具统合使用的链接,可以一起看哦~https://blog.csdn.net/qq_32278309/article/details/101384003 博主是新入坑的新人, ...
- 51单片机之串口通讯应用实例(逻辑分析仪调试)
硬件:STC89C52RC 开发工具:Keil uVision4 前言:8051是一款很经典的.历史悠久的单片机,作为一款入门级的单片机8051受到很多初学者的欢迎.89c52是8051系列的成员之一 ...
- DELPHI串口通讯编程
spcomm更加简单 转贴 Delphi中串口通信的实现 河南省计算中心 张海航 ------------------------------- ...
- 串口通讯编程一日通3(COMMTIMEOUTS DCB整理)
上一篇看了Overlapped IO模型后,接下来看剩下两个重要结构: 2.COMMTIMEOUTS结构 超时设置 COMMTIMEOUTS:COMMTIMEOUTS主要用于串口超时参数设置.COM ...
- 21 树莓派和电脑之间串口通讯编程
linux特性:一切皆文件(设备虽然是硬件,但在Linux当中它还是以文件形式存在) 在cd/dev目录下ls 初次使用树莓派串口编程,需要配置. 参考:树莓派wiringPi库详解 - lulipr ...
- 51单片机——UART串口通讯-波特率可选,增添定时器2产生波特率1.0
1.51单片机自带硬件串口接口,使用时只需要进行寄存器配置即可. 2.定时器1波特率有4种可选择,默认9600bps.另外还有1个字节的发送函数,字符串发送函数. 3.增添:定时器2波特率有5种可选择 ...
最新文章
- C语言的HashTable简单实现
- vue仿今日头条_vue2.0仿今日头条开源项目
- 尝试优化骨骼动画计算的意外收获——使用嵌入式汇编对float转int进行优化
- 神策 FM | 数据驱动时代,你的岗位如何转变?
- JAVA Socket 底层是怎样基于TCP/IP 实现的???
- suse10 linux安装,SuSE10.2 安装手记
- Log4j(1)--hellloworld
- BUPT复试专题—C翻转(2010)
- nginx 配置文件详解 深入理解nginx配置文件
- jsp数据库连接大全和数据库操作封装到Javabean
- 找回foxmail下的邮箱密码
- 推荐系统 AB 测试
- 数据集中趋势度量:众数、平均数、中位数、几何平均数
- linux下搜狗输入法wps无法使用,搜狗输入法能在WPS下使用,但其他地方不能输入...
- html桌面共享文件夹,win7共享文件夹在哪? win7和win10怎么共享文件夹
- 转载 2015A国赛优秀论文
- Axure9的使用经验分享:如何高效的实现弹窗交互模型
- 计算机usb无法识别网络连接,usb无法识别是什么原因 usb无法识别解决方法【详解】...
- 【软件工程实践】Hive研究-Blog7
- 高速信号的完整性分析
热门文章
- drupal 用的什么php框架,7个使用Drupal的理由
- OBJ2GLTF使用,将obj格式模型转换为gltf
- latch和DFF的区别和联系
- 神器 Markmap
- 毕夏钟伟强沧桑战全场泪奔
- Android头像上传实战模拟
- Docker Swarm Could not attach to network not manually attachable.
- 360手机助手 无法android 4.2手机软件移动sd卡,360手机助手怎么设置安装到sd卡 360手机助手设置安装位置...
- MAC电脑 安全与隐私 中没有任何来源选项怎么办
- SyntaxHighlighter示例源码[代码高亮]