51单片机串口的应用(单片机和电脑互发数据)

这篇具有很好参考价值的文章主要介绍了51单片机串口的应用(单片机和电脑互发数据)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

现在来详细看一下寄存器,我们直接查看单片机手册。

SCON寄存器

先来说说SCON寄存器。

51单片机串口的应用(单片机和电脑互发数据)

前一节我们提过,我们一般使用串口用的是模式1,即8位UART,这样我们就用不到校验位。从手册中可以看到,寄存器SCON中的SM0和SM1配置成01即可。
51单片机串口的应用(单片机和电脑互发数据)

SM2寄存器明显用不到,因为我们没有用模式2和3.

REN寄存器控制接收串行,发送数据时候置0,接收数据时置1。

TB8和RB8同SM2,一样用不到。

TI就比较关键了。我们肯定会用到。从串口结构图中可以看到,TI是一个标志位,来判断发送是否结束。举个例子,发送数据就是全自动步枪,TI寄存器就是我们的枪栓。我们发送结束后,TI的值会自动置1,我们需要手动写程序在软件层面给TI置0,让它能够再次使用。

这里插一句,软件层面指的就是我们的代码工程,硬件层面就是我们的板子和电路
51单片机串口的应用(单片机和电脑互发数据)

51单片机串口的应用(单片机和电脑互发数据)

那么RI和TI的原理是类似的,就不详细说了。我们在初始化配置的时候,一般两位都置0,让它能够直接使用。

51单片机串口的应用(单片机和电脑互发数据)

发送数据时,代码如下:

void UART_Init()
{
	SCON = 0x40;//0100 0000
}

接收数据时,代码如下:

void UART_Init()
{
	SCON = 0x50;//010 0000
}

PCON寄存器

再来说说PCON寄存器。

51单片机串口的应用(单片机和电脑互发数据)

SMOD选择波特率是否加倍。我们对晶振频率进行过分频,所以波特率是需要加倍的。

定时器寄存器

除了串口寄存器,我们还需要用到定时器,打开我们上一章定时器的.c文件(不用打开工程,用记事本方式以文本文件方式打开即可)
51单片机串口的应用(单片机和电脑互发数据)

复制出定时器的初始化代码。

void Timer0Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
    ET0 = 1;
	EA = 1;
	PT0 = 0;
}

然而串口所用到的定时器是Timer1,和我们之前用的Timer0是不同的寄存器,所以我们需要修改定时器寄存器的代码。串口用的定时器模式也不是我们之前的16位定时器模式,而是8位自动重装载模式。(相比16位定时器模式,这个模式在计数满后,高八位的初值数据会自动转入低八位)

这里还是详细说一下吧,想简单说两句发现说不清楚16位定时器高八位和低八位都用来计时,所以计数范围会比较大,每次计数高八位和低八位都置初始值,然后开始计数,计数满了我们再手动赋初值。八位重装载模式只用低八位寄存器来计时,高八位里面存放的是我们的定时器初值,在低八位加满之后高八位存的数据会流入低八位,这样就不需要我们手动给计时器置初值了

51单片机串口的应用(单片机和电脑互发数据)
51单片机串口的应用(单片机和电脑互发数据)

首先在TMOD中我们需要打开定时器1,我们使用逻辑语言 &= 给TMOD赋值。这样就不会影响我们上一次对TMOD的操作了。

51单片机串口的应用(单片机和电脑互发数据)

代码如下:

void Timer0Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL0 = ;		//设置定时初值
	TH0 = ;		//设置定时初值
}

软件生成初始化代码

初始值的计算太复杂了,我们还是用STC-ISP软件生成代码,不用再用手算了。 别的寄存器也通过软件来生成吧。
51单片机串口的应用(单片机和电脑互发数据)

这里提一嘴,波特率倍速得勾选,上面讲PCON的时候说了原因了。不过实在懒得重新截图了。具体分析看下面小标题里的内容!!!

那么初始化函数里面的内容如下

void UartInit(void)		//4800bps@12.000MHz
{
	PCON &= 0x80;		//波特率不倍速
	SCON = 0x40;		//8位数据,可变波特率
//	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
//	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

波特率计算

现在来说一下如何计算TL和TH。

0xF3就是十进制的243,而定时器每隔256溢出一次。我们定时器重装值设为243,那么计数13次后定时器就溢出了(定时器那里讲过,忘记了可以翻看以前的博客)。

12M的晶振,在12T模式下,每隔1us计数一次(因为12分频了嘛,很好理解的对不对)。

51单片机串口的应用(单片机和电脑互发数据)

那么定时器Timer1的溢出率就是1/(13us),即0.07692MHz,假如我们倍速波特率,那么SMOD的开关会走上面的路,上面的频率需要再除以16,进入接收控制器,即0.07692MHz/16=4807.69Hz,这就是我们所设置的波特率4800。、
51单片机串口的应用(单片机和电脑互发数据)

同理,假如我们不勾选倍速波特率,SMOD开关会走下面除以2的路,相当于频率除以32。软件帮我们计算出来的TH和TL值是F9,即十进制249,即7us溢出一次,溢出率1/(7us)=0.14285MHz,再除以32,进入接收控制器,即0.14285MHz/32=4464.28Hz,此时误差就比较大了。

51单片机串口的应用(单片机和电脑互发数据)

发送数据

我们需要将数据写进SBUF寄存器里,这样在配置好寄存器后,数据会直接被发送出。

51单片机串口的应用(单片机和电脑互发数据)

void UART_SendByte(unsigned char Byte)
{
	SBUF = Byte;//将数据写进SUBF中
	while(TI==0);//发送完成标志位一旦变为1,说明数据发送成功了。接下来软件复位。
	TI = 0;
}

主文件里面的内容如下(其实Delay和Timer0没必要导入,因为没用到):

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"
void UartInit(void)		//4800bps@12.000MHz
{
	PCON |= 0x80;		//使能波特率倍速位SMOD
	SCON = 0x40;		//8位数据,可变波特率
//	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
//	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}
void UART_SendByte(unsigned char Byte)
{
	SBUF = Byte;//将数据写进SUBF中
	while(TI==0);//发送完成标志位一旦变为1,说明数据发送成功了。接下来软件复位。
	TI = 0;
}
void main()
{
	UartInit();
	UART_SendByte(0x11);
	while(1)
	{
		
	}
}

烧录程序后,连续按下复位键,可以看到,串口不断接收到字符11。

51单片机串口的应用(单片机和电脑互发数据)

当然,我们也可以把UART_SendByte函数写在while(1)里面,这样就能通过串口持续收到11。但是此时我们需要再发送数据之后加上一定的延时,不然因为晶振频率和波特率的误差,会导致接受数据发生错误。

串口模块化

现在我们通过实验验证了串口发送接收数据的可行性,那么按照前面学习的内容,就可以对串口进行模块化了。具体操作不细说,直接上内容(别忘了加上注释):

//UART.c
#include <REGX52.H>
/**
  * @brief	串口初始化4800bps,@12.000MHz
  * @param	无
  * @retval 无
*/
void UartInit(void)		
{
	PCON |= 0x80;		//使能波特率倍速位SMOD
	SCON = 0x40;		//8位数据,可变波特率
//	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
//	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}
/**
  * @brief	串口发送一个字节数据
  * @param	Byte 要发送的一个字节数据
  * @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
	SBUF = Byte;//将数据写进SUBF中
	while(TI==0);//发送完成标志位一旦变为1,说明数据发送成功了。接下来软件复位。
	TI = 0;
}
#ifndef __UART_H__
#define __UART_H__

void UartInit(void);
void UART_SendByte(unsigned char Byte);

#endif

此时在主文件内直接引用函数就可以正常使用了。

串口接收数据

刚才所讲的内容是关于串口向电脑发送数据。现在再来说一说串口如何接收电脑数据。电脑发送数据被串口收到时,我们不能直接处理,必须进入中断函数进行处理。否则会影响单片机正常工作。

51单片机串口的应用(单片机和电脑互发数据)

先打开中断使能EA,然后ES置1,相当于打开中断。

51单片机串口的应用(单片机和电脑互发数据)

只需要在最下面加两行代码。同时修改一下SCON,因为要接收数据,REN需要置1,上面讲SCON的时候提到过。

void UartInit(void)		//4800bps@12.000MHz
{
	PCON &= 0x80;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
//	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
//	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
    EA = 1;
    ES = 1;
}

查询串口的中断次序号
51单片机串口的应用(单片机和电脑互发数据)

我们可以这样写,当串口收到电脑发送的数据时,LED灯亮。那么中断服务子函数写法如下:

void UART_Routine() interrupt 4
{
    P2 = 0x00}

写好之后,烧录程序,在STC-ISP上发送任意一个数据,可以看到,单片机上的所有LED都亮了。

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"
#include "UART.h"

void main()
{
	UartInit();
	while(1)
	{
		
	}
}
void UART_Routine() interrupt 4
{
    P2 = 0x00;
}

51单片机串口的应用(单片机和电脑互发数据)

说明串口接收数据可行,现在我们可以发挥想象力,大展拳脚了。

电脑发送数据控制LED灯

这样写:

void UART_Routine() interrupt 4
{
    if(RI == 1)
	{
		P2 = SBUF;
		RI =  0;
	}
}

51单片机串口的应用(单片机和电脑互发数据)

因为TI和RI都有可能使程序进入中断,所以我们要用判断语句来确认是串口收到了数据。

SUBF中保存的是接收和发送的数据,我们可以直接提取出来进行处理。

同时类似于TI,我们在接收时也需要进行软件复位,在确认每次收到数据(即RI=1)后,让RI归零(RI=0)。

那么上面程序的效果,就是前四个LED灭,后四个LED亮。

注意,在中断函数里面的调用的函数,不能在主函数里面使用。因为假如主函数正在调用函数,进入中断后你再调用一次,主函数中的调用就会被打断,那么程序就会出错。

我们可以让单片机再通过串口,把接收到的数据返回给电脑,只需要用之前写好的语句,很简单。

void UART_Routine() interrupt 4
{
    if(RI == 1)
	{
		P2 = SBUF;
		UART_SendByte(SBUF);
		RI =  0;
	}
}

将接收中断模块化

#include <REGX52.H>
/**
  * @brief	串口初始化4800bps,@12.000MHz
  * @param	无
  * @retval 无
*/
void UartInit(void)		
{
	PCON |= 0x80;		//使能波特率倍速位SMOD
	SCON = 0x50;		//8位数据,可变波特率
//	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
//	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	EA = 1;
    ES = 1;
}
/**
  * @brief	串口发送一个字节数据
  * @param	Byte 要发送的一个字节数据
  * @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
	SBUF = Byte;//将数据写进SUBF中
	while(TI==0);//发送完成标志位一旦变为1,说明数据发送成功了。接下来软件复位。
	TI = 0;
}
/*串口中断函数模板
void UART_Routine() interrupt 4
{
    if(RI == 1)
	{
	
		RI =  0;
	}
}
*/

以模板的形式加入到我们的模块里,需要使用的时候,直接挪到主函数下面就可以了。它和主函数耦合性还是比较高的,可以直接使用。

数据显示模式

HEX模式/十六进制模式/二进制模式

以原始数据的形式显示

文本模式/字符模式

以原始数据编码后的形式显示

说人话

HEX模式就是进行ASCI编码后的数据,而文本模式,就是ASCI译码之后的结果,C语言大家应该了解过,可以对照图来验证一下。
51单片机串口的应用(单片机和电脑互发数据)

同样也需要留意,SendByte函数里面的参数,如果是0x开头的十六进制,用文本模式和HEX模式发送和接收,结果是不一样的。挺简单的,各位自行验证。

随便扯两句

其实写完上一篇笔记,就已经马不停蹄地开始写这一篇笔记。中间鸽了近两个月,当时以为处理完手头的事情,就可以继续用空闲时间学点东西,结果学了一半的内容就被课内的任务缠身,忙的不可开交,而且串口这一块知识点环环相扣,时隔两个月,很多东西都忘记了。处理完课内大作业,删无用文件时太激动了小手一抖把之前的keil工程文件都给删了,还好有之前的笔记,让我不至于从头开始去写以前的模块内容。这两天还发着低烧,不过还是硬挺着完成中断了这么久的内容。不能再拖了,越拖越难重新拾起来。文章来源地址https://www.toymoban.com/news/detail-471158.html

到了这里,关于51单片机串口的应用(单片机和电脑互发数据)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C51单片机串口发送数据的使用

             假如说电路板上没有CH340芯片,我们就要使用TTL转USB模块来进行电平的转换,然后将模块的RX接单片机的TX,模块的TX接单片机的RX,来进行接线连接。          在连接好连线后,我们打开计算机管理,来查看端口是否存在,如果没有,我们需要下载CH340驱动,

    2024年02月03日
    浏览(76)
  • c51单片机串口通信(中断方式接收数据)(单片机--单片机通信)示例代码 附proteus图

         单片机一般采用中断方式接受数据,这样便于及时处理 其中发送数据段采用的是查询方式,接收端采用了中断方式, 要注意的地方有: 在中断处理函数int_0()内,处理数据前要先关闭中断,否则中断可能会不断传过来, EA=0; 然后退出中断处理函数前恢复中断处理能力:

    2024年02月13日
    浏览(65)
  • 51单片机串口通信的原理及使用方法(附串口收发数据例程代码)

    温馨提示:本篇文章详细介绍了串口的原理及使用方法,涉及的内容较多,但也较为全面,学者若想充分掌握串口通信的原理和具体使用方法(部分限于51单片机),请静下心来将其读完,相信一定会受益匪浅!而且对32单片机的串口学习也有非常好的辅助! 一.串行通信的原

    2024年02月09日
    浏览(41)
  • 【单片机】51单片机串口的收发实验,串口程序

    这段代码是使用C语言编写的用于8051单片机的串口通信程序。它实现了以下功能: 引入必要的头文件,包括reg52.h、intrins.h、string.h、stdio.h和stdlib.h。 定义了常量FSOC和BAUD,分别表示系统时钟频率和波特率。 定义了一个发送数据的函数send,该函数将数据发送到串口,等待数据

    2024年02月14日
    浏览(45)
  • 基于串口通信技术——让数码管显示的数据发送给电脑,电脑控制单片机外设——15单片机

    目录 1.使用的单片机为IAPI15F2K61S2 2.使用的外设 3.各个外设的作用 1.数码管功能  2.LED灯 3.蜂鸣器与继电器 4.按键 5.串口通信 4.利用发送单个字符函数 发送字符型的数字值,为一个变量+\\\'0\\\',发送为字符型数字。 4.初始化 5.程序 1.main 2.iic.h 3.onewire.c 1.LED灯,继电器与蜂鸣器。 2.数

    2024年02月10日
    浏览(47)
  • 单片机通过串口向电脑端发送数据&&电脑端发送数据控制led

    上节课我们学习了串口的理论部分,这节课我们要来学习实操部分。 要想实现单片机通过串口向电脑端发送数据,我们首先要来配置寄存器。 1.配置SCON SCON寄存器中的SM0配置为0,SM1配置为1决定了串口工作在模式一,也就是 8位UART, 波特率可变的工作模式。REN置1表示能接收

    2023年04月21日
    浏览(42)
  • 51单片机串口使用

    今天将为大家讲解51单片机的串口原理及代码编写。 51单片机串口是一种通信接口,它可以将51单片机与外部设备连接起来,实现数据的双向传输。51单片机串口的原理是,51单片机的串口接口由两个管脚组成,一个是RXD,另一个是TXD,RXD用于接收数据,TXD用于发送数据。当5

    2024年02月05日
    浏览(49)
  • 51单片机串口

    1.1串口接线方式 RXD:数据输入引脚,数据接受;STC89系列对应P3.0口,上官一号有单独引出 TXD:数据发送引脚,数据发送;STC89系列对应P3.1口,上官一号有单独引出 接线方式 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FMY5yTZI-1690308835514)(C:Use

    2024年02月15日
    浏览(40)
  • 51单片机串口通信

    串口通信(serial communication)是指外设和计算机间通过数据信号线、地线等按位进行传输数据的一种通信方式,属于串行通信方式。 接口标准:常用RS-232和RS-485 RS-232C有一种9针的非标准连接器口,简称DB9。串口通信使用的大多都是DB9接口。在串口通信中,通常我们只使用2、

    2024年02月05日
    浏览(48)
  • 51单片机-串口通信

    目录 1.什么是通信 1.1.通信的概念 1.2.传送方式 1.3.同步方式 1.4.传送方向 1.5.校验方式 2.单片机串口介绍 2.1.硬件电路 2.2.电平标准 2.3.常见接口 2.4.内部结构 2.5.相关寄存器 2.6.工作模式(模式1) 2.7.如何配置串口中断 3.实际应用 3.1.单片机向电脑发送数据 3.2.电脑向单片机发送

    2024年02月01日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包