单片机 串口编程之串口通信仿真实验

单片机 串口编程之串口通信仿真实验单片机串口编程之串口通信仿真实验一、简述记–简单的使能串口,串口收发数据的例子。(使用Proteus仿真+虚拟串口调试)代码,仿真文件打包:链接:https://pan.baidu.com/s/1nyb46fTJrYcAy_VarFdO3A提取码:j44s蓝奏:https://www.lanzous.com/i2fx3oh……

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

单片机 串口编程之串口通信仿真实验

一、简述

       记–简单的使能串口,串口收发数据的例子。(使用Proteus仿真+虚拟串口调试)

       代码,仿真文件打包:链接: https://pan.baidu.com/s/1nyb46fTJrYcAy_VarFdO3A 提取码: j44s 

         蓝奏:https://www.lanzous.com/i2fx3oh

      虚拟串口调试软件打包:链接: https://pan.baidu.com/s/1qaOgM8P7ZRmXb903NkiMOQ 提取码: r18u 

         蓝奏:外链:https://wwm.lanzouv.com/b0catp8te 密码:6yug

       串口助手源码:链接: https://pan.baidu.com/s/1T9ZA8jnsjXDhNLuL1ezGdg 提取码: 6usr 

二、效果

        PC机通过串口调试助手发送数据给单片机,单片机收到之后回复:I received.。如果单片机收到的是’1’则点亮LED灯,否则熄灭LED灯。

           单片机 串口编程之串口通信仿真实验

   使用c#编写的串口助手

单片机 串口编程之串口通信仿真实验      

  (真实硬件实验:使用Keil C51将代码编译为HEX文件,用串口线/USB转串口线连接PC机,可以使用STC-ISP软件烧写到51单片机,在PC机可以使用串口调试助手(STC-ISP也有这个功能,也可以是其他软件,当然也可以自己编写串口程序)与单片机进行串口通信。实际中,电脑串口采用232电平,而单片机串口则采用TTL电平,如果不进行电平转换,单片机与电脑就无法正常通信,甚至单片机芯片可能会被烧坏。MAX232 芯片可以进行电平转换,是将单片机输出的TTL电平转换成PC机能接收的232电平或将PC机输出的232电平转换成单片机能接收的TTL电平。​​​​电平是个电压范围,如可能规定输出电压>2.4V则为高电平,输出电压低于<0.4V则为低电平,不同的电子器件、不同的标准有着不同的电压范围​​​)

       注:一个COM一般不能同时被两个程序占用。

三、工程结构及各属性设置

        keil工程

         单片机 串口编程之串口通信仿真实验

         单片机 串口编程之串口通信仿真实验

         单片机 串口编程之串口通信仿真实验

          

        proteus仿真

        单片机 串口编程之串口通信仿真实验

单片机 串口编程之串口通信仿真实验

添加虚拟串口

                                单片机 串口编程之串口通信仿真实验

单片机 串口编程之串口通信仿真实验

四、源文件

       main.c文件 

#include <reg51.h>
sbit p1_0 = P1^0;

//初始化串口 (设置串口,开启串口中断)
void init_uart(void)
{
	SCON = 0x50;		        // SCON: 方式 1, 8-bit, 允许接收数据 
	TMOD |= 0x20;               // TMOD: 设置定时器1工作在方式2, 8-bit 自动重装
	TH1 = 0xFD;               // TH1:  初始值为0xFD  波特率:9600 晶振频率:11.0592MHz  
	TL1 = 0x0;
	TR1 = 1;                  // TR1:  开启定时器1                         
	EA  = 1;                  //打开总中断
	ES  = 1;                  //打开串口中断
}       

           
// 发送一个字节数据
void uart_send_byte(unsigned char dat)
{
	SBUF = dat; // 将数据送到发送缓冲寄存器SBUF,一位一位的发送
	while(!TI); // 等待发送完毕 (发送完毕TI硬件置1)
	TI = 0;// 将TI清零,表示可以发送下一字节数据。
}

// 发送字符串
void uart_send_str(unsigned char *s)
{
	while(*s != '
#include <reg51.h>
sbit p1_0 = P1^0;
//初始化串口 (设置串口,开启串口中断)
void init_uart(void)
{
SCON = 0x50;		        // SCON: 方式 1, 8-bit, 允许接收数据 
TMOD |= 0x20;               // TMOD: 设置定时器1工作在方式2, 8-bit 自动重装
TH1 = 0xFD;               // TH1:  初始值为0xFD  波特率:9600 晶振频率:11.0592MHz  
TL1 = 0x0;
TR1 = 1;                  // TR1:  开启定时器1                         
EA  = 1;                  //打开总中断
ES  = 1;                  //打开串口中断
}       
// 发送一个字节数据
void uart_send_byte(unsigned char dat)
{
SBUF = dat; // 将数据送到发送缓冲寄存器SBUF,一位一位的发送
while(!TI); // 等待发送完毕 (发送完毕TI硬件置1)
TI = 0;// 将TI清零,表示可以发送下一字节数据。
}
// 发送字符串
void uart_send_str(unsigned char *s)
{
while(*s != '\0')// '\0':字符串结束标志
{
uart_send_byte(*s);// 发送1个字节数据,1个字符占8位,1字节
s++;// 指向下一个字符
}
}
// 串口中断处理函数 (串口接收到数据,发送数据完毕都可以引起串口中断)
void uart_interrupt(void) interrupt 4 		//也叫串行中断服务程序
{
unsigned char recv_data;// 用来存放接收到的数据
unsigned char send_data[] = "I received.\n";// 要发送的信息
if(RI) //接收数据(1字节)完毕,RI会被硬件置1
{
RI = 0;            		// 将 接收中断标志位 清零(让串口可以继续接收数据)
recv_data = SBUF;           	//读取接收到的数据,并存放到data
if(recv_data == '1')//如果收到的字符是'0',就让灯灭
{
p1_0 = 0;//  p1.0引脚低电平,LED灯亮
}
else
{
p1_0 = 1;// p1.0引脚高电平,LED灯灭
} 
uart_send_str(send_data); //收到数据之后,发送字符串"I received."给对方
}
if(TI)// 发送数据(1字节)完毕
{
TI = 0;// 将 发送中断标志位 清零(让串口可以继续发送数据)
}
} 
void main(void)
{
init_uart();// 初始化串口
while(1)// 主循环不做任何动作。(死循环)
{}
}
')// '
#include <reg51.h>
sbit p1_0 = P1^0;
//初始化串口 (设置串口,开启串口中断)
void init_uart(void)
{
SCON = 0x50;		        // SCON: 方式 1, 8-bit, 允许接收数据 
TMOD |= 0x20;               // TMOD: 设置定时器1工作在方式2, 8-bit 自动重装
TH1 = 0xFD;               // TH1:  初始值为0xFD  波特率:9600 晶振频率:11.0592MHz  
TL1 = 0x0;
TR1 = 1;                  // TR1:  开启定时器1                         
EA  = 1;                  //打开总中断
ES  = 1;                  //打开串口中断
}       
// 发送一个字节数据
void uart_send_byte(unsigned char dat)
{
SBUF = dat; // 将数据送到发送缓冲寄存器SBUF,一位一位的发送
while(!TI); // 等待发送完毕 (发送完毕TI硬件置1)
TI = 0;// 将TI清零,表示可以发送下一字节数据。
}
// 发送字符串
void uart_send_str(unsigned char *s)
{
while(*s != '\0')// '\0':字符串结束标志
{
uart_send_byte(*s);// 发送1个字节数据,1个字符占8位,1字节
s++;// 指向下一个字符
}
}
// 串口中断处理函数 (串口接收到数据,发送数据完毕都可以引起串口中断)
void uart_interrupt(void) interrupt 4 		//也叫串行中断服务程序
{
unsigned char recv_data;// 用来存放接收到的数据
unsigned char send_data[] = "I received.\n";// 要发送的信息
if(RI) //接收数据(1字节)完毕,RI会被硬件置1
{
RI = 0;            		// 将 接收中断标志位 清零(让串口可以继续接收数据)
recv_data = SBUF;           	//读取接收到的数据,并存放到data
if(recv_data == '1')//如果收到的字符是'0',就让灯灭
{
p1_0 = 0;//  p1.0引脚低电平,LED灯亮
}
else
{
p1_0 = 1;// p1.0引脚高电平,LED灯灭
} 
uart_send_str(send_data); //收到数据之后,发送字符串"I received."给对方
}
if(TI)// 发送数据(1字节)完毕
{
TI = 0;// 将 发送中断标志位 清零(让串口可以继续发送数据)
}
} 
void main(void)
{
init_uart();// 初始化串口
while(1)// 主循环不做任何动作。(死循环)
{}
}
':字符串结束标志 { uart_send_byte(*s);// 发送1个字节数据,1个字符占8位,1字节 s++;// 指向下一个字符 } } // 串口中断处理函数 (串口接收到数据,发送数据完毕都可以引起串口中断) void uart_interrupt(void) interrupt 4 //也叫串行中断服务程序 { unsigned char recv_data;// 用来存放接收到的数据 unsigned char send_data[] = "I received.\n";// 要发送的信息 if(RI) //接收数据(1字节)完毕,RI会被硬件置1 { RI = 0; // 将 接收中断标志位 清零(让串口可以继续接收数据) recv_data = SBUF; //读取接收到的数据,并存放到data if(recv_data == '1')//如果收到的字符是'0',就让灯灭 { p1_0 = 0;// p1.0引脚低电平,LED灯亮 } else { p1_0 = 1;// p1.0引脚高电平,LED灯灭 } uart_send_str(send_data); //收到数据之后,发送字符串"I received."给对方 } if(TI)// 发送数据(1字节)完毕 { TI = 0;// 将 发送中断标志位 清零(让串口可以继续发送数据) } } void main(void) { init_uart();// 初始化串口 while(1)// 主循环不做任何动作。(死循环) {} }

Jetbrains全家桶1年46,售后保障稳定

五、总结

       51单片机系列

      1、单片机的串口相关的寄存器

            1) 串口控制寄存器SCON:(Serial CONtrol)

            2) 串行数据寄存器SBUF:(Serial data BUFfer)

            3)电源管理寄存器PCON:(Power CONtrol)

      2、串口控制寄存器SCON

            用来对串口进行控制,其寄存器地址为0x98,支持位寻址。

            一般来说单片机的寄存器的个数在制作好就已经确定了,MCS-51单片机有一些寄存器是8位的(可以存放8位数据),有一些是16位的,这些寄存器有点像全局变量(寄存器名-变量名),它们分配了固定的地址空间,我们可以对这个寄存器变量进行赋值或读取值。比如我们禁止串口中断,那么我们可以设置相应的值,当系统处理串口相关的任务时,读取到这个我们设置的值时,直到我们要禁止串口中断,那么系统就不会相应串口中断。串口控制寄存器SCON的地址为0x98,我们可以直接对SCON这个”变量”进行赋值,支持位寻址意思是:SCON一共有8位,每1位代表的意思都有不同,可以直接单独对某一位进行设置,有一些寄存器是不可以位寻址的。

           

SCON控制寄存器
位编号

D7

D6

D5

D4

D3

D2

D1

D0

位名称

SM0

SM1

SM2

REN

TB8

RB8

TI

RI

位地址

9FH

9EH

9DH

9CH

9BH

9AH

99H

98H

SM0,SM1串行口工作方式控制位

SM0

SM1

工作方式

功能

波特率

0

0

方式0

8位同步移位寄存器

晶振频率/12

0

1

方式1

10位UART

可变

1

0

方式2

11位UART

晶振频率/64或晶振频率/32

1

1

方式3

11位UART

可变

SM2 多机通信控制位 当该位置1为多机通信,多机通信仅在方式2、方式3有效。
REN 接收允许位  为1允许接收,为0禁止接收
TB8 待发送的第9位数据  同来存放工作方式2,工作方式3模式下等待发送的第9位数据
RB8 收到的第9位数据 同来存放工作方式2,工作方式3模式下接收到的第9位数据,在方式1下为接收到的停止位,工作当时0不使用该位。
TI 发送中断标志位  发送完成标志位,当SBUF中的数据发送完成后由硬件置1,并且当单片机硬件中断被使能之后触发中断事件,该位必须由软件清零,并且该位被清零之后才能进行下一个字节数据的发送。
RI 接收中断标志位 接受完成标志位,当SBUF收到一个字节的数据后由硬件系统置1,并且当单片机硬件中断被使能之后触发串行中断事件,该位必须由软件清零,并且只有该位被清零之后才能够进行下一字节数据的接收。

      3、串行数据寄存器SBUF

            用于存放串行通信中发送和接收的相关数据。其寄存器地址是0x99。

            SBUF由发送缓冲寄存器和接收缓冲寄存器组成,这两个寄存器占用同一个寄存器地址。其中发送缓冲寄存器只写,接收寄存器只读。

           发送数据:当将一个数据写入SBUF后,单片机立即根据选择的工作方式和波特率将写入的字节数据进行相应的处理然后从TXD(P3.1)引脚串行发送出去,发送完成之后置位相应寄存器的标志位,只有相应的标志位被清除之后才能进行下一次的数据发送。

           接收数据:当RXD(P3.0)引脚根据工作方式和波特率接收到一个完整的数据字节后单片机将该数据字节放入接收缓冲寄存器中,并置位相应的标志位。接收缓冲寄存器是双字节的,这样就可以在单片机读取接收缓冲寄存器的数据时同时进行下一个字节的数据接收。不会发生前后两个字节的数据冲突(数据覆盖)。

      4. 电源管理寄存器PCON

            可以控制串口波特率加倍。

                                                                                         PCON电源管理寄存器

位编号

D7

D6

D5

D4

D3

D2

D1

D0

位符号

SMOD

SMOD0

LVDF

POF

GF1

GF0

PD

IDL

      SMOD:该位与串口通信有关。

      SMOD=0; 串口方式1,2,3时,波特率正常。

      SMOD=1; 串口方式1,2,3时,波特率加倍。

      5、串口的工作方式

            MCS-51单片机的串口一共4种工作方式。其中工作方式0为同步通信方式,其余3种为异步通信。

            工作方式0:外部引脚TXD(P3.0)为数据的输出输入端,外部引脚TXD(P3.1)提供数据的同步脉冲。

                                因此工作在方式0进行串口通信不需要考虑波特率。

           工作方式1:使用定时器作为波特率发生器。

                               波特率的计算  

                                              单片机 串口编程之串口通信仿真实验

                                                                          常见的波特率对应的初始值
波特率/工作频率 11.0592MHz 12MHz

14.74456MHz

16MHz 20MHz SMOD值
150(b/s) 0x40 0x30 0x00 0
300(b/s) 0xA0 0x98 0x80 0x75 0x52 0
600(b/s) 0xD0 0xCC 0xC0 0xBB 0xA9 0
1200(b/s) 0xF8 0xE6 0xE0 0xDE 0xD5 0
2400(b/s) 0xF4 0xF3 0xF0 0xEF 0xEA 0
4800(b/s) 0xF3 0xEF 0xEF 1
4800(b/s) 0xFA 0xF8 0xF5 0
9600(b/s) 0xFD 0xFC 0
9600(b/s) 0xF5 1
19200(b/s) 0xFD 0xFC 1

      工作方式2:

                                                                     单片机 串口编程之串口通信仿真实验

      工作方式3:波特率计算方式与工作方式1相同。 

     

      6.波特率

           波特率是指数据信号对载波的调制速率,它用单位时间内载波调制状态改变的次数来表示。

           在信息传输通道中,携带数据信息的信号单元叫码元,每秒钟通过信道传输的码元数称为码元传输速率,简称波特率。

           通信双方约定一致的波特率以便正确的接收数据。(数据发送前可能进行了调制,波特率不同,调制参数不同)

          如果收发双方的波特率不一样,那么调制与解调的参数不一样,就很有可能读取不到正确的数据,从而解读为乱码。

          通常串口工作方式1使用定时器作为波特率发生器。

      7、串口中断

            使能串口中断:打开总中断-中断控制寄存器IE的EA位置1,打开串口中断中断控制寄存器IE的ES位置1

                                                                                               中断控制寄存器IE(Interrupt Enable

位序号

D0

D1

D2

D3

D4

D5

D6

D7

说明

外部中断0

定时/计数0

外部中断1

定时/计数1

串行口中断

保留位

保留位

全局中断位

位符号

EX0

ET0

EX1

ET1

ES

EA

位地址

A8H

A9H

AAH

ABH

ACH

AFH

EX0 外部中断0允许位 EX0=1,允许外部中断0中断;EX0=0,禁止外部中断0中断。
ET0 T0溢出中断允许位 ET0=1,允许T0中断;ET0=0,禁止T0中断。
EX1 外部中断1允许位 EX1=1,允许外部中断1中断;EX1=0,禁止外部中断1中断。
ET1 T1溢出中断允许位 ET1=1,允许T1中断;ET1=0,禁止T1中断。
ES

串行中断允许位

(Enable Serial)

ES=1,允许串行口中断;ES=0,禁止串行口中断。
EA

中断总允许位

(Enable All)

EA=1,CPU开放中断;EA=0,CPU禁止所有的中断请求。总允许EA好比一个总开关。

     使能串口中断之后,接收到数据(RI置1)/完成发送(TI置1),RI/TI被置1就会触发串口中断事件,然后执行中断处理函数。

     中断处理函数编写格式:               

void 函数名(void) interrupt 4 using 工作寄存器组编号
{
    //要执行的动作
}

      4的含义: 一共5个中断编号为0~4,串口中断的编号为4

      using 寄存器组编号:一共4组工作寄存器组,编号为0~3,如果不写默认为工作寄存器组0。

8、初始化串口为模式1过程。

      1) SCON设置

位名称

SM0

SM1

SM2

REN

TB8

RB8

TI

RI

设置值

0

1

0

1

0

0

0

0

含义 工作在方式1 波特率不加倍 允许接收数据 工作方式1不设置该位 初始为未发送完数据

初始为为接收到数据

      SCON = 0x01010000 = 0x50    

       2) PCON设置

       

位编号

D7

D6

D5

D4

D3

D2

D1

D0

位符号

SMOD

SMOD0

LVDF

POF

GF1

GF0

PD

IDL

默认波特率不加倍 0 0 0 0 0 0 0 0
波特率加倍 1 0 0 0 0 0 0 0

      PCON = 0x00 (SMOD=0,波特率不加倍)

      PCON = 0x80 (SMOD=1,波特率加倍)

      3) 定时器设置

              工作方式设置:

单片机 串口编程之串口通信仿真实验
                                                                  MI,M0定时器模式选择

M1

M0

工作方式

功能说明

0

0

方式0

13位定时器/计数器

0

1

方式1

16位定时器/计数器

1

0

方式2

自动重载8位定时器/计数器

1

1

方式3

T0分为2个8位独立计数器,T1无方式3

            开启定时器1:将控制寄存器TCON的TR1置1

            设置定时器1的初值:TH1数据寄存器装载初值的高8位,TL1数据寄存器装载初值的低8位。

            定时器用作波特率发生器时,使用上面的波特率计算公式得到初始值,或直接查看常见的波特率对应的初始值。

            TH1 = 0xFD;// 11.0592MHz的工作频率,9600的波特率 对应的初始值。 

        4) 打开总中断 EA = 1; 打开串口中断 ES = 1;

              

================以下回复 qq_45096251 这位兄弟==============

两个单片机之间的串口通信仿真实验:

测试的仿真文件和代码:链接: https://pan.baidu.com/s/1PMu6dT-1DMEJllgv9gxqMA 提取码: hrcy

使用虚拟串口软件,虚拟出两对串口,例子中是com1<==>com2,  com3<==>com4,其中com2,com4分别对应单片机A和单片机B。com1和com3分别是PC端与单片机A、B通信的端口。在PC端使用串口工具实现两个仿真单片机的串口通信。

测试效果:

单片机 串口编程之串口通信仿真实验

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/200844.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号