当前位置: 首页 > article >正文

06:串口通信

串口通信

  • 1、基础知识
    • 1.1、通信
    • 2.1、数据帧格式
    • 2.3、波特率
  • 2、串口UART
    • 2.1、寄存器简介
    • 2.2、串口内部基本结构
    • 2.3、工作方式和波特率
  • 3、实验
    • 3.1、串口发送
      • 3.1.1、实验①
      • 3.1.2、实验②
      • 3.1.3、实验③
    • 3.2、串口接收
      • 3.2.1、实验①
      • 3.2.2、实验②

1、基础知识

1.1、通信

2.1、数据帧格式

2.3、波特率

2、串口UART

2.1、寄存器简介

在这里插入图片描述

2.2、串口内部基本结构

在这里插入图片描述

2.3、工作方式和波特率

在这里插入图片描述

综上:若想将串口在方式1的波特率配置为9600,则应该如何设置?

在这里插入图片描述

3、实验

3.1、串口发送

3.1.1、实验①

实验:使用轮询方式让单片机通过串口向外发送一个字节的数据
在这里插入图片描述

①UART.c文件的代码如下:

#include "UART.h"

/**
 * 串口初始化
 * 参数:波特率
 */
void UART_Init(unsigned int Baud)
{
	/* 串口寄存器的配置 */
	 PCON &= 0x3F;	//PCON = 00xx xxxx
	 SCON &= 0x0F;
	 SCON |= 0x50;	//SCON = 0101 xxxx
	
	/* 配置T1的寄存器 */
	TMOD &= 0x0F;
	TMOD |= 0x20;	//TOMD = 0010 xxxx
	TH1 = 256 - (28800/Baud);//配置波特率
	TL1 = 256 - (28800/Baud);//配置波特率
	ET1 = 0;		//关闭T1溢出中断
	TR1 = 1;		//使能T1
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H

#include <reg51.h>		//包含51头文件,里面全是寄存器地址

void UART_Init(unsigned int Baud);//串口初始化

#endif

③mian.c文件的代码如下:

#include "UART.h"
#include "Delay.h"

void main(void)
{
	UART_Init(9600);//9600波特率
	while(1)
	{
		SBUF = 0x88;//给SBUF写入一个字节数据0x88	
		while(!TI);	//等待数据发送完成(未完成TI = 0,完成TI = 1)
		TI = 0;		//手动清0
		Delayms(500);
	}
}

在这里插入图片描述

3.1.2、实验②

实验:
①使用轮询方式让单片机通过串口向外发送一个字节的数据
②使用轮询方式让单片机通过串口向外发送多个字节的数据
③使用轮询方式让单片机通过串口向外发送字符串

①UART.c文件的代码如下:

#include "UART.h"

/**
 * 串口初始化
 * 参数:波特率
 */
void UART_Init(unsigned int Baud)
{
	/* 串口寄存器的配置 */
	 PCON &= 0x3F;	//PCON = 00xx xxxx
	 SCON &= 0x0F;
	 SCON |= 0x50;	//SCON = 0101 xxxx
	
	/* 配置T1的寄存器 */
	TMOD &= 0x0F;
	TMOD |= 0x20;	//TOMD = 0010 xxxx
	TH1 = 256 - (28800/Baud);//配置波特率
	TL1 = 256 - (28800/Baud);//配置波特率
	ET1 = 0;		//关闭T1溢出中断
	TR1 = 1;		//使能T1
}

/**
 * 发送一个字节的数据
 */
void Send_Char(unsigned char ch)
{
	SBUF = ch;	//给SBUF写入一个字节数据
	while(!TI);	//等待数据发送完成(未完成TI = 0,完成TI = 1)
	TI = 0;		//手动清0
}

/**
 * 发送多个字节的数据
 */
void Send_Array(unsigned char* Array,unsigned char Len)
{
	unsigned char i;
	for(i = 0; i<Len; i++)
	{
		Send_Char(*(Array+i));
	}
}

/**
 * 发送字符串
 */
void Send_String(unsigned char* str)
{
	while(*str != '\0')
	{
		Send_Char(*str++);
	}
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H

#include <reg51.h>		//包含51头文件,里面全是寄存器地址

void UART_Init(unsigned int Baud);//串口初始化
void Send_Char(unsigned char ch);//发送一个字节的数据
void Send_Array(unsigned char* Array,unsigned char Len);//发送多个字节的数据
void Send_String(unsigned char* str);//发送字符串

#endif

③mian.c文件的代码如下:

#include "UART.h"
#include "Delay.h"

void main(void)
{
	UART_Init(9600);//9600波特率
	while(1)
	{
		Send_Char(0xAA);//发送一个字节数据AA
		Delayms(500);
		
		Send_Array(Arr,5);//发送多个字节数据
		Delayms(500);
		
	}
}

在这里插入图片描述

3.1.3、实验③

实验:
printf函数的重定向

#include <stdio.h>

void mian(void) 
{
  char a = 1;
  int b  = 12365;
  long c = 0x7FFFFFFF;

  unsigned char x = 'A';
  unsigned int y  = 54321;
  unsigned long z = 0x4A6F6E00;

  float f = 10.0;
  float g = 22.95;

  char buf [] = "Test String";
  char *p = buf;

  printf ("char %bd int %d long %ld\n",a,b,c);
  printf ("Uchar %bu Uint %u Ulong %lu\n",x,y,z);
  printf ("xchar %bx xint %x xlong %lx\n",x,y,z);
  printf ("String %s is at address %p\n",buf,p);
  printf ("%f != %g\n", f, g);
  printf ("%*f != %*g\n", (int)8, f, (int)8, g);
}

①UART.c文件的代码如下:

#include "UART.h"

/**
 * 串口初始化
 * 参数:波特率
 */
void UART_Init(unsigned int Baud)
{
	/* 串口寄存器的配置 */
	 PCON &= 0x3F;	//PCON = 00xx xxxx
	 SCON &= 0x0F;
	 SCON |= 0x50;	//SCON = 0101 xxxx
	
	/* 配置T1的寄存器 */
	TMOD &= 0x0F;
	TMOD |= 0x20;	//TOMD = 0010 xxxx
	TH1 = 256 - (28800/Baud);//配置波特率
	TL1 = 256 - (28800/Baud);//配置波特率
	ET1 = 0;		//关闭T1溢出中断
	TR1 = 1;		//使能T1
}

/**
 * 发送一个字节的数据
 */
void Send_Char(unsigned char ch)
{
	SBUF = ch;	//给SBUF写入一个字节数据
	while(!TI);	//等待数据发送完成(未完成TI = 0,完成TI = 1)
	TI = 0;		//手动清0
}

/**
 * 对printf函数进行重定向
 */
char putchar(char ch)
{
	Send_Char(ch);
    return ch;
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H

#include <reg51.h>		//包含51头文件,里面全是寄存器地址

void UART_Init(unsigned int Baud);//串口初始化
void Send_Char(unsigned char ch);//发送一个字节的数据
char putchar(char ch);//printf()重定向

#endif

③mian.c文件的代码如下:

#include "UART.h"
#include "Delay.h"

void main(void)
{
	UART_Init(9600);//9600波特率
	while(1)
	{
		printf("nihao\r\n");
		printf("%bd\r\n",88);
		printf("%d\r\n",12365);
		printf("%f\r\n",3.14);
		Delayms(500);
	}
}

在这里插入图片描述

3.2、串口接收

使用VSPD软件模拟串口,软件安装包:链接: link
在这里插入图片描述
电路连接和串口的配置如下图所示:
在这里插入图片描述

3.2.1、实验①

实验:
使用轮询方式接收一个字节的数据

①UART.c文件的代码如下:

#include "UART.h"

/**
 * 串口初始化
 * 参数:波特率
 */
void UART_Init(unsigned int Baud)
{
	/* 串口寄存器的配置 */
	 PCON &= 0x3F;	//PCON = 00xx xxxx
	 SCON &= 0x0F;
	 SCON |= 0x50;	//SCON = 0101 xxxx
	
	/* 配置T1的寄存器 */
	TMOD &= 0x0F;
	TMOD |= 0x20;	//TOMD = 0010 xxxx
	TH1 = 256 - (28800/Baud);//配置波特率
	TL1 = 256 - (28800/Baud);//配置波特率
	ET1 = 0;		//关闭T1溢出中断
	TR1 = 1;		//使能T1
}

/**
 * 发送一个字节的数据
 */
void Send_Char(unsigned char ch)
{
	SBUF = ch;	//给SBUF写入一个字节数据
	while(!TI);	//等待数据发送完成(未完成TI = 0,完成TI = 1)
	TI = 0;		//手动清0
}

/**
 * 对printf函数进行重定向
 */
char putchar(char ch)
{
	Send_Char(ch);
    return ch;
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H

#include <reg51.h>		//包含51头文件,里面全是寄存器地址

void UART_Init(unsigned int Baud);//串口初始化
void Send_Char(unsigned char ch);//发送一个字节的数据
char putchar(char ch);//printf()重定向

#endif

③mian.c文件的代码如下:

#include "UART.h"
#include "Delay.h"

void main(void)
{
	unsigned char Data = 0;		//一个字节的数据缓冲区
	UART_Init(9600);			//9600波特率

	while(1)
	{
		if(RI)					//RI = 1,SBUF里面接收到数据
		{
			Data = SBUF;		//对数据进行处理
			RI = 0;
			Send_Char(Data);	//将数据发送出去
		}
	}
}

在这里插入图片描述

3.2.2、实验②

实验:
使用中断方式接收一个字节数据

①UART.c文件的代码如下:

#include "UART.h"

/**
 * 串口初始化,且开启中断
 * 参数:波特率
 */
void UART_It_Init(unsigned int Baud)
{
	/* 串口寄存器的配置 */
	 PCON &= 0x3F;	//PCON = 00xx xxxx
	 SCON &= 0x0F;
	 SCON |= 0x50;	//SCON = 0101 xxxx
	
	/* 配置T1的寄存器 */
	TMOD &= 0x0F;
	TMOD |= 0x20;	//TOMD = 0010 xxxx
	TH1 = 256 - (28800/Baud);//配置波特率
	TL1 = 256 - (28800/Baud);//配置波特率
	ET1 = 0;		//关闭T1溢出中断
	TR1 = 1;		//使能T1
	
	/* 使能串口中断 */
	ES = 1;			//使能串口中断
	EA = 1;			//使能中断总开关
}

/***********中断服务函数*************/
/**
 * 中断服务函数
 */
unsigned char Data2 = 0;
unsigned char Flag2 = 0;
void UART_Routine(void) interrupt 4
{
	/* 若是发送完成中断:TI = 1*/
	if(TI)
	{
		//一般情况下不使用你中断进行发送数据
	}
	
	/* 若接收数据完成中断 RI = 1*/
	if(RI)
	{
		RI = 0;
		Data2 = SBUF;//对数据进行处理
		Flag2 = 1;	//标志位置1
	}
}

②UART.h文件的代码如下:

#ifndef __UART_H
#define __UART_H

#include <reg51.h>		//包含51头文件,里面全是寄存器地址
#include <stdio.h>

void UART_Init(unsigned int Baud);//串口初始化
void Send_Char(unsigned char ch);//发送一个字节的数据
void Send_Array(unsigned char* Array,unsigned char Len);//发送多个字节的数据
void Send_String(unsigned char* str);//发送字符串
char putchar(char ch);//printf()重定向

void UART_It_Init(unsigned int Baud);//串口初始化(使能中断)

extern unsigned char Data2;
extern unsigned char Flag2;

#endif

③mian.c文件的代码如下:

#include "UART.h"

void main(void)
{
	UART_It_Init(9600);		//9600波特率

	while(1)
	{
		if(Flag2)			//Flag = 1,数据处理完成
		{
			Flag2 = 0;
			Send_Char(Data2);//将数据发送出去
		}
	}
}

在这里插入图片描述


http://www.kler.cn/a/544593.html

相关文章:

  • python使用虚拟环境
  • Python 依赖管理的革新——Poetry 深度解析
  • C# Dictionary的实现原理
  • 走进 Tcl 语言:历史、特性与应用
  • 数据结构:图论入门
  • JavaSE基本知识补充 -IO流
  • DeepSeek 助力 Vue 开发:打造丝滑的通知栏(Notification Bar)
  • post、get、delete、put请求
  • cnn以及例子
  • AI时代前端工程师的职业发展新路径
  • IS-IS 泛洪机制 | LSP 处理流程
  • 【Unity3D杂谈】使用NDK命令行工具翻译Android Vitals上的内存堆栈
  • 如何部署DeepDeepSeek-V3 大模型部署全流程解析:从云平台到本地化实践Seek—V3
  • OpenAI推出全新AI助手“Operator”:让人工智能帮你做事的新时代!
  • ConcurrentHashMap扩容
  • Spring Boot 中的事务管理:默认配置、失效场景及集中配置
  • Android原生的HighCPU使用率查杀机制
  • 基于Python的医院运营数据可视化平台:设计、实现与应用(下)
  • 使用CherryStudio、Ollama、腾讯云搭建本地个人知识库、智能体
  • LabVIEW外腔二极管激光器稳频实验