本文为博主 日月同辉,与我共生,csdn原创首发。希望看完后能对你有所帮助,不足之处请指正!一起交流学习,共同进步!
> 发布人:@日月同辉,与我共生_单片机-CSDN博客
> 欢迎你为独创博主日月同辉,与我共生点赞❤❤❤+关注👍+收藏🌹+评论☺。
系列专栏: CSDN-单片机串口通信学习系列🎁
> 我的格言是:“尽最大努力,做最好的自己!💪
要转载,请提前告知!!!
版权声明:本文为CSDN博主「日月同辉,与我共生」的原创文章,CSDN独一份。
目录
一、功能设计
功能:单片机com1先发送please xie a date.,当虚拟串口com3发送8个数据,由单片机接收到后,单片机将这8个数据发送回虚拟串口com3。
二、硬件设计
硬件设计可以参考前面的文章:博主csdn文章-串口通信(2)
虚拟终端RXD接单片机com1的接收端RXD。
三、软件设计
3.1初始化
初始化时,要设置寄存器SCON(工作方式、是否多机通信、数据位数),REN一般要接收(置1),初值就是定时初始值TH1/定时重载值TL1,工作方式为方式1(8位异步重载),波特率设置为9600bit/s,晶振频率为11.0592Mhz,因为串口通信是8位数据传输,所以定时器为定时器T1工作方式为方式2,还要打开总中断EA=1,串口中断开关ES=1。
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设置定时初始值
TH1 = 0xFD; //设置定时重载值
ET1 = 0; //禁止定时器中断
ES=1;
EA=1;
TR1 = 1; //定时器1开始计时
}
3.2接收一串数据
数组:k常数,定义数组int a[k],a[k]存储了k个元素,数据元素类型为int,a[0]=a0,a[k-1]=a k-1,最末尾有结束符‘\0’。当代码发送到字符等于‘\0’时,说明发送字符串已经完成。
*是解引用符,&是地址符。p存储有a的地址,所以*p会根据a的地址找到a的值,即*p=a;
而数组本质上是一个指针常量,使用下标代表每个元素的值,可以用指针代替下标,由指针代表每个元素值。a[]为一个数组,int *p=a;语句*p=a,此时指针默认指向下标0,即*p的值为a[0],语句*p++;可以让指针由原来指向下标0变为指向下标1,即此时*p=a[1]。
当RI=1会触发接收中断,在中断服务函数中,接收数据,并将RI清0,当接收完8个数据后,将标志位recv_flag置1(说明接收完成)。
void ES_timer() interrupt 4
{
static unsigned char datecnt=0;
if(RI) //接收中断
{
RI=0;
recv_date[datecnt++]=SBUF;//将接收到的数据赋给变量---SBUF--接收串行数据寄存器
if(recv_date==8)//固定8个字符
{
recv_flag=1;//中间变量置1
datecnt=0;
}
}
}
3.3发送数据
当标志位recv_flag=1时,说明单片机接收完成,则单片机将数据重新发送给虚拟串口com3。
#include <reg51.h>
#include "delay.h"
#include "uart.h"
void main()
{
UartInit();
printf("please xie a date.\r\n");
while(1)
{
if(recv_flag)
{
recv_flag=0;
sendString(recv_date);//发送一串数据
}
}
}
四、结果显示
好多人不懂十六进制和文本模式的,今天博主教你们。
当com3在发送缓冲区以HXT模式(十六进制模式)发送十六进制数0-9,接收缓冲区相当于单片机com1,模式为HXT模式时,接收到的数据也是十六进制。虚拟终端若选择HXT模式,接收到的数据也是十六进制。
当com3在发送缓冲区以文本模式发送数字0-9,接收缓冲区相当于单片机com1,模式为文本模式时,接收到的数据也是数字0-9。虚拟终端若不选择HXT模式,接收到的数据也是数字0-9。值得注意的是,文本模式是com3可以发送字符/字符串的,接收到的结果是正确的。
发送字符:
发生字符串:
五、知识回顾
回顾串口通信文章:
串口通信(3)printf串口输出重定向的实现及一帧一串数据的发送
将上述文章代码整合一下:
uart.c
#include "uart.h"
#define MAXdate 20 //字符最大长度
unsigned char recv_date[MAXdate];
unsigned char recv_flag=0;
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设置定时初始值
TH1 = 0xFD; //设置定时重载值
ET1 = 0; //禁止定时器中断
ES=1;
EA=1;
TR1 = 1; //定时器1开始计时
}
void sendByte(unsigned char dat) //发送一帧数据功能函数
{
SBUF=dat;//发送数据
while(!TI);//等待发送成功
TI=0;//发送标志位置0
}
void sendString(unsigned char *dat) //发送字符串函数 unsigned char *dat=123
{
while(*dat != '\0')
{
sendByte(*dat++);
}
}
char putchar(char c)
{
sendByte(c);
return c;
}
void ES_timer() interrupt 4
{
static unsigned char datecnt=0;
if(RI) //接收中断
{
RI=0;
recv_date[datecnt++]=SBUF;//将接收到的数据赋给变量---SBUF--接收串行数据寄存器
if(recv_date==8)//固定8个字符
{
recv_flag=1;//中间变量置1
datecnt=0;
}
}
}
uart.h
MAXdate是数据长度最大值,本文设计用的数据长度为8,也可改成其他长度,但不能超过20。修改数据长度,只需在接收中断模块的if语句修改条件即可。
#ifndef __UART_H__
#define __UART_H__
#include <reg51.h>
#include <stdio.h>
#define MAXdate 20
extern unsigned char recv_date[];
extern unsigned char recv_flag;
void UartInit();
void sendByte(unsigned char dat);
void sendString(unsigned char *dat);
char putchar(char c);
#endif
下一文将着重如何用定时器中断完成非固定长度的数据接收,亲爱的读者请多多支持博主大大,下一文更精彩!!!
一日不读书,胸臆无佳想。我叫不白吃,喜欢我的,可以支持我,博主名叫@日月同辉,与我共生