【STC8H】IO口模拟串口UART

本文介绍了单片机通过UART通信向电脑发送数据的过程,包括起始位、数据位、波特率设定以及字符发送方法,同时提到了串口协议和使用空指令进行延时。
摘要由CSDN通过智能技术生成
(1)单片机->电脑(一个字节)

要模拟串口,首先肯定是需要了解串口的协议,根据协议来编写程序。

在这里插入图片描述

UART的通信方式是由1个起始位,8个数据位,包含一个奇偶校验位,和结束位构成 。在本次的设计中默认为波特率为9600,停止位为1位,8位数据位,无奇偶校验位。

先介绍起始位,从高电平跳变为低电平,表示通信开始。再来简单介绍下波特率,单位时间内传送码元符号的个数。波特率9600,也就是1s内传送9600个bit,一个bit所需要的时间为 1000000us / 9600 = 104.166 us,也就是104us。

这是用示波器调出来的,就不一一展示示波器的使用教程了。

空指令使用时会占用执行一个指令的CPU时间片。常用于程序延时或精确计时,不过在较快的CPU上不明显。如果使用这个空指令nop()就一定要引入

当单片机 想给电脑 发送数据时,比如发送一个 0xE4 这个数据,用二进制形式表 示就是 0b11100100,在 UART 通信过程中,是低位先发,高位后发的原则,那么就让 TXD 首先拉低电平,持续一个波特率的时间,发送一位 0,然后继续拉低,再持续一段时间,又发送了一 位 0,然后拉高电平,持续一段时间,发了一位 1……一直到把 8 位二进制数字 0b11100100 全部发送完毕

\

你可能会问为什么上面代码为什么用的是P31?

答:单片机有两个引脚是专门用来做 UART 串行通信的,它们分别叫做 RXD 和 TXD,由它们组成的通信接口就叫做串行接口,简称串口,STC8H8K64U用的是P31为TXD发送,P30为RXD接收。

代码示例:单片机通过P31发送十六进制0X21给电脑:

/****************************数据类型******************************
unsigned char	uchar	8	0~255
signed	 char	char	8	-128~127
unsignec int	uint	16	0~65535
signed	 int	int		16	-32768~32767
******************************************************************/
#include"STC8H.h"		//单片机头文件(包含单片机的特殊功能寄存器的定义)	
#include "intrins.h" 
#include "Delay_ms.h"


/************************函数声明*************************************/
void STC8H_IOinit(void);			//STC15W单片机引脚初始化函数


/*===========================================================*/
/*函数:void STC8H_IOinit(void)
/*功能:STC18H单片机引脚初始化函数
/*说明:统一将单片机所有引脚初始化为准双向口工作模式
/*修改日期:2023.10.16
/*===========================================================*/
void STC8H_IOinit(void)
{
	P0M1 = 0;	P0M0 = 0;	//设置为准双向口   参考用户手册387页
	P1M1 = 0;	P1M0 = 0;	//设置为准双向口   参考用户手册387页
	P2M1 = 0;	P2M0 = 0;	//设置为准双向口   参考用户手册387页
	P3M1 = 0;	P3M0 = 0;	//设置为准双向口   参考用户手册387页
	P4M1 = 0;	P4M0 = 0;	//设置为准双向口   参考用户手册387页
	P5M1 = 0;	P5M0 = 0;	//设置为准双向口   参考用户手册387页
	P6M1 = 0;	P6M0 = 0;	//设置为准双向口   参考用户手册387页
	P7M1 = 0;	P7M0 = 0;	//设置为准双向口   参考用户手册387页  
	P0 = 0XFF;	P1 = 0XFF;	P2 = 0XFF; 
	P3 = 0XFF;	P4 = 0XFF;	P5 = 0XFF; 
	P6 = 0XFF;	P7 = 0XFF;						//设置P0~P7所有I/O口为高电平
}
/****************************************************************************************************
/*函数void Pote(unsigned char x)
/*功能:
/*说明:
/*修改日期:2023.10.23
/****************************************************************************************************/
void Pote()
{
	unsigned int i;
		for(i=0;i<466;i++)//通过改变i的参数获得准确的时间
		{
			_nop_();//空指令,用于消耗时间
		}
}

void Pote_Half()
{
	unsigned int i;
		for(i=0;i<189;i++)
		{
			_nop_();
		}
}

void Uart_TX(unsigned char temp)
{
	unsigned char x;	
	unsigned char i=8;
	//起始位
	P31=0;//置零
	Pote();//过1个波特率的时间
	

	//数据位
	for(x=1;x<=8;x++)
	{
		//从低位到高位
		P31=temp&0x01;
		temp=temp>>1;
		Pote();//过1个波特率的时间
	}
	
	//结束位
	P31=1;//置1
	Pote();//过1个波特率的时间

}


/****************************************************************************************************
/*函数:void main()
/*功能:
/*说明:主函数
/*修改日期:2023.10.16 
/****************************************************************************************************/
void main()
{
	STC8H_IOinit();			//STC15W单片机引脚初始化函数

	while(1)
	{
			Uart_TX(0x21);//单片机发送十六进制0x21给电脑
			Delay_ms(300);//延时300ms
	}

}

烧录+结果:(箭头从左到右,从上到下)

示波器展示:

(2)单片机->电脑(字符串)

首先,一个字符串是由一个个字符组成的,每个字符在计算机中都有相应的编码。在ASCII编码中,一个字符通常用一个字节(8位二进制)表示。

我们可以借助指针用while循环(条件为*S!=NULL)将字符串中的字符一个个传进之前写好的Uart_TX 函数,并且使用后缀递增运算符 ++ 将指针移动到下一个字符。

单片机每隔300ms发送“Hello,world!”给电脑

/****************************数据类型******************************
unsigned char	uchar	8	0~255
signed	 char	char	8	-128~127
unsignec int	uint	16	0~65535
signed	 int	int		16	-32768~32767
******************************************************************/
#include"STC8H.h"		//单片机头文件(包含单片机的特殊功能寄存器的定义)	
#include "intrins.h" 
#include "Delay_ms.h"


/************************函数声明*************************************/
void STC8H_IOinit(void);			//STC15W单片机引脚初始化函数


/*===========================================================*/
/*函数:void STC8H_IOinit(void)
/*功能:STC18H单片机引脚初始化函数
/*说明:统一将单片机所有引脚初始化为准双向口工作模式
/*修改日期:2023.10.16
/*===========================================================*/
void STC8H_IOinit(void)
{
	P0M1 = 0;	P0M0 = 0;	//设置为准双向口   参考用户手册387页
	P1M1 = 0;	P1M0 = 0;	//设置为准双向口   参考用户手册387页
	P2M1 = 0;	P2M0 = 0;	//设置为准双向口   参考用户手册387页
	P3M1 = 0;	P3M0 = 0;	//设置为准双向口   参考用户手册387页
	P4M1 = 0;	P4M0 = 0;	//设置为准双向口   参考用户手册387页
	P5M1 = 0;	P5M0 = 0;	//设置为准双向口   参考用户手册387页
	P6M1 = 0;	P6M0 = 0;	//设置为准双向口   参考用户手册387页
	P7M1 = 0;	P7M0 = 0;	//设置为准双向口   参考用户手册387页  
	P0 = 0XFF;	P1 = 0XFF;	P2 = 0XFF; 
	P3 = 0XFF;	P4 = 0XFF;	P5 = 0XFF; 
	P6 = 0XFF;	P7 = 0XFF;						//设置P0~P7所有I/O口为高电平
}

void Pote()
{
	unsigned int i;
		for(i=0;i<466;i++)//通过改变i的参数获得准确的时间
		{
			_nop_();//空指令,用于消耗时间
		}
}

void Pote_Half()
{
	unsigned int i;
		for(i=0;i<189;i++)
		{
			_nop_();
		}
}

void Uart_TX(unsigned char temp)
{
	unsigned char x;	
	unsigned char i=8;
	//起始位
	P31=0;//置零
	Pote();//过1个波特率的时间
	
	//数据位
	for(x=1;x<=8;x++)
	{
		//从低位到高位
		P31=temp&0x01;
		temp=temp>>1;
		Pote();
	}

	//结束位
	P31=1;
	Pote();
	
}

void UART_SendString(unsigned char *S)
{
	while(*S)
	{
		Uart_TX(*S++);
	}

}

void main()
{
	STC8H_IOinit();			//STC15W单片机引脚初始化函数

	while(1)
	{
			UART_SendString("Hello,World!");
			Delay_ms(300);//延时300ms
	}

}

实验结果如下:

(3)电脑->单片机->电脑

上面我们将了单片机发送数据给电脑,那单片机如何接收电脑所给的数据呢?

示例:

/****************************数据类型******************************
unsigned char	uchar	8	0~255
signed	 char	char	8	-128~127
unsignec int	uint	16	0~65535
signed	 int	int		16	-32768~32767
******************************************************************/
#include"STC8H.h"		//单片机头文件(包含单片机的特殊功能寄存器的定义)	
#include "intrins.h" 
#include "Delay_ms.h"


/************************函数声明*************************************/
void STC8H_IOinit(void);			//STC15W单片机引脚初始化函数
 
/*===========================================================*/
/*函数:void STC8H_IOinit(void)
/*功能:STC18H单片机引脚初始化函数
/*说明:统一将单片机所有引脚初始化为准双向口工作模式
/*修改日期:2023.10.16
/*===========================================================*/
void STC8H_IOinit(void)
{
	P0M1 = 0;	P0M0 = 0;	//设置为准双向口   参考用户手册387页
	P1M1 = 0;	P1M0 = 0;	//设置为准双向口   参考用户手册387页
	P2M1 = 0;	P2M0 = 0;	//设置为准双向口   参考用户手册387页
	P3M1 = 0;	P3M0 = 0;	//设置为准双向口   参考用户手册387页
	P4M1 = 0;	P4M0 = 0;	//设置为准双向口   参考用户手册387页
	P5M1 = 0;	P5M0 = 0;	//设置为准双向口   参考用户手册387页
	P6M1 = 0;	P6M0 = 0;	//设置为准双向口   参考用户手册387页
	P7M1 = 0;	P7M0 = 0;	//设置为准双向口   参考用户手册387页  
	P0 = 0XFF;	P1 = 0XFF;	P2 = 0XFF; 
	P3 = 0XFF;	P4 = 0XFF;	P5 = 0XFF; 
	P6 = 0XFF;	P7 = 0XFF;						//设置P0~P7所有I/O口为高电平
}

void Pote()
{
	unsigned int i;
		for(i=0;i<466;i++)
		{
			_nop_();
		}
}

void Pote_Half()
{
	unsigned int i;
		for(i=0;i<189;i++)
		{
			_nop_();
		}
}

void UART_TX(unsigned char temp)
{
	unsigned char x;	
	unsigned char i=8;
	
	//启始位
	P31=0;
	Pote();
	
	//数据位
	for(x=1;x<=8;x++)
	{
		P31=temp&0x01;
		temp=temp>>1;
		Pote();
	}
	
	//停止位
	P31=0;
	Pote();
	P31=1;
	Pote();
}

unsigned char UART_RX()
{
    unsigned char y=0;			//计数
	unsigned char x=0;			//计时
    unsigned char Data=0;		//保存一个八位的十六进制数据
		unsigned char RX_Data[8];	//保存8位
	
		Pote_Half(); 
	
		//接收
		for(y=0;y<8;y++)
		{
			Pote();			
			RX_Data[y]=P30&0x01; 	
		}
		//结束信号时间
		Pote();	
		Pote_Half();	
		//数据转换
		Data=(RX_Data[0]<<0)+(RX_Data[1]<<1)+(RX_Data[2]<<2)+(RX_Data[3]<<3)+(RX_Data[4]<<4)+(RX_Data[5]<<5)+(RX_Data[6]<<6)+(RX_Data[7]<<7);
		P2=Data;
		return Data;
}

void main()
{
		unsigned char i,j;
		unsigned char DAT_UART[20];	
    
    STC8H_IOinit();
	
    while(1)
    {
				//串口接收到数据
        if(P30==0)	
        {
					//接收数据
					for(i=0;i<20;i++)			
					{
						DAT_UART[i]=UART_RX();	
					}
					//发送数据
					for(j=0;j<20;j++)		
					{
						UART_TX(DAT_UART[j]);	
					}
        }
    }
}

实验现象:

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STC8H1K28是STC微控制器公司的一款单片机芯片,具有内置UART通信模块。UART例程是指在STC8H1K28芯片上使用UART模块进行通信的实例代码。 UART(通用异步收发传输)是一种常见的串行通信接,用于在芯片之间传输数据。STC8H1K28芯片的UART模块有多个寄存器,包括数据寄存器、状态寄存器、控制寄存器等,通过配置这些寄存器和使用相应的UART例程代码,可以实现与其他设备的串行通信。 UART例程主要包括以下几个方面的内容: 1. 初始化UART模块:在使用UART通信前,需要对UART模块进行初始化配置。通过设置相应的寄存器,比如波特率寄存器、控制寄存器等,可以设置数据位数、停止位数、波特率等参数。 2. 发送数据:将要发送的数据写入数据寄存器,然后启动发送操作,UART模块将会根据配置的参数将数据发送出去。可以通过循环发送,逐个发送数据字节,也可以一次性发送一串数据。 3. 接收数据:接收数据需要判断接收寄存器是否有数据,如果有数据,则读取数据寄存器中的数据,存储到指定的变量中。可以使用中断方式进行接收,也可以使用轮询方式。 4. 错误处理:UART通信中可能发生错误,比如数据丢失、帧错误等,需要在程序中添加错误处理的代码,以确保数据的准确传输。 以上是STC8H1K28芯片上使用UART模块进行通信的基本内容。当然,具体的UART例程代码会因应用需求的不同而有所差异,但是基本原理是相同的。需要根据具体的通信要求和UART模块的寄存器配置,来编写相应的例程代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值