STC15F2K60S2串口通信

.
.

一、先斩后奏,上代码!!!!

先强调:通常我们做单片机与单片机通信、单片机与PC通信、PC与PC串口通信,基本选择方式1的串口通信方式,下面的讲解中我会详细的介绍串口方式1

下面这段代码实现在PC端发送一个数据,15接受后发送给PC端 “I get xx”

#include <stc15f2k60s2.h>
#define uchar unsigned char
#define uint unsigned int
uchar Flag,a,i;
uchar code table[]="I get ";//下面这个初始化有问题,不能正常初始化,先待定,过几天我查查问题,看看哪里出错了。
/*
void init()
{TMOD=0x20;//T1定时器的方式2工作:8位自动重装定时器TH1=0xfd;TL1=0xfd;//溢出后,TH1中的值将被自动重装到TL1中TR1=1;//定时器1开始运行REN=1;//允许串口接受数据SM0=0;SM1=1;//串口方式1,10位异步收发(8位数据),波特率可变(由定时器1的溢出率控制)EA=1;//开启全局中断允许ES=1;//开启串口中断允许
}
*///下面这段初始化是由stc-isp上自带的波特率计算器实现的。到时候直接在上面选择设置,然后就自动生成出想要的代码了,下面会有详细的介绍
void UartInit(void)     //9600bps@11.0592MHz
{PCON &= 0x7F;//01111111波特率不倍速,PCON电源管理寄存器SCON = 0x50;//8位数据,可变波特率,SCON,串口控制寄存器AUXR |= 0x40;//定时器1时钟为Fosc,即1TAUXR &= 0xFE;//串口1选择定时器1为波特率发生器TMOD &= 0x0F;//清除定时器1模式位TMOD |= 0x20;//设定定时器1为8位自动重装方式TL1 = 0xDC;//设定初值TH1 = 0xDC;//设定定时器重装初值ET1 = 0;//禁止定时器1中断TR1 = 1;//启动定时器1//下面这两句是stc-isp没有生成的,需要我们自己加上EA=1;//开启全局中断允许ES=1;//开启串口中断允许
}void main()
{UartInit();while(1){if(Flag==1)//Flag是我们定义的进入中断程序的标志(这里判断我们是否进入了中断程序){ES=0;//发送数据前,先将禁止串口中断for(i=0;i<6;i++)//(发送10个数据出去){SBUF=table[i];//将table[]中的数据一个一个给SBUF寄存器,并一个一个发送出去while(!TI);//等待数据发送完毕TI=0;//将发送数据标志位清零(因为我们成功发送数据,系统自动会把TI置1,标志数据发送成功,从而向CPU申请中断,我们需要手动吧TI清零)}SBUF=a;//将Data中的数据给SBUF,并发送while(!TI);//等待数据发送成功TI=0;//手动将发送数据标志位清零ES=1;//允许串口中断(当所有数据发送完成之后,再打开接受数据的串口中断,因为当我们没有发送完数据,而定时器T1溢出时候,这个时候我们如果打开串口中断,那么我们就会在发送数据的过程中进入到接收数据的中断程序里面,SBUF寄存器里面的数据就会混乱,导致产生错误的结果,所以我们需要发送数据时候关闭串口中断,接收数据的时候打开串口中断)Flag=0;//进入中断程序标志位清零}}
}void ser() interrupt 4
{RI=0;//接受数据标志位清零a=SBUF;//将接受到的数据存入Data中Flag=1;//进入中断标志位置1
}

大家把这段程序看完之后,是不是还是一脸懵,没关系,我们会一步一步来分析,进行详细的讲解。

PS:这个程序有BUG,从PC端发送过去的数据单片机能接收到,但是就用文本方式打印不到PC端的串口助手里面。不是没有接受到数据,实际上是接收到数据了,可以将打印的方式设置成为HEX,这样就能看到被打印的数据,不过都是16进制的数据。目前这个BUG我也不知道该怎么去修复,还请路过的大佬帮忙看下

HEX接收方式

文本接收方式

二、详细的讲解

1、串口通信前,先需要了解的知识
(1)、波特率

定义:在信息传输通道中,携带数据信息的信号单元叫码元,每秒钟通过信道传输的码元数称为码元传输速率,简称波特率。波特率是传输通道频宽的指标。 
详细的讲解,请看我的另一篇文章:波特率的辨析

(2)、波特率的计算

在串行通信中,收发双方对发送或接收数据的速率要有约定。通过编程,可对单片机串行口设定为4种工作方式,方式0、方式2的波特率是固定的;方式1、方式3的是可变的,有定时器T1的溢出率(即1/T1每秒溢出的次数)
在这里我们只介绍方式1的波特率计算,因为对于初学者来说,方式1是我们最常用的也是需要掌握的
方式1的波特率:=((2^(SMOD))/32) * (T1的溢出率)
SMOD是PCON寄存器的最高位
T1的溢出率:计算出T1每溢出1次所需要的时间T,则1/T为T1的溢出率。
.
.

2、初始化中涉及到的一些寄存器的使用
(1)、PCON(不可位寻址)


SMOD(SERIAL MODE):与串口通信有关的位。SMOD=0,串口方式1、2、3时波特率正常;SMOD=1,串口方式1、2、3时,波特率加倍。

PD(POWER DOWN)——掉电模式设定位;PD=0,单片机正常工作;PD=1,单片机进入掉电模式,可由外部中断低电平触发、下降沿触发、硬件复位模式唤醒。进入掉电后:1.外部晶振停振; 2.CPU、定时器、串口全部停止工作。3.外部中断继续工作
IDL(IDLE)——空闲模式设定位。IDL=0,单片机正常工作;IDL=1,单片机进入空闲模式:除CPU不工作,其他都正常工作。可由任意一个中断或者硬件复位唤醒。

其他几个不过多介绍,以后学到再介绍。
.
.

(2)、SCON(可位寻址)


SM0/SM1

SM0 SM1 方式 功能说明
0 0 0 同步移位寄存器方式(通常用于扩展I/O口)
0 1 1 10位异步收发(8位数据),波特率可变(由定时器1的溢出率控制)
1 0 2 11位异步收发(9位数据),波特率固定
1 1 3 11位异步收发(9位数据),波特率可变(由定时器1的溢出率控制)

REN:允许串行接受位。REN=1,允许串口接受数据;REN=0,禁止串口接受数据。
.
.

(3)、AUXR(不可位寻址)


.
.

(4)、TMOD(不可位寻址)


.
.

(5)、IE&IP(可位寻址)


ET1、ES、EA等上述代码所需要调动的寄存器的位都在这里
.
.
.

3、数据的存储和发送

一个转运站——SBUF


程序代码中
SBUF=table[i];
一旦SBUF中被写入了数据,在被写入之后,数据就会自动通过串口发送出去
Data=SBUF;
在PC端接受的数据也被存储到SBUF中,需要我们读出来,上述就是一个读取的操作
.
.
.

4、怎么能够简单的得到串口的波特率设置

就像我程序中第第一个void init()函数一样,我是照着相关书籍和数据手册的指导一步一步去配置寄存器,而且还自己计算了一下波特率位9600时候,我需要将T1的溢出率调节到多少,给TH1和TL1装入的值是多少。太麻烦了!!!,而且最重要的是,不知道漏了哪一步,没有调对,程序不能运行,对于一个为了调寄存器到凌晨1点的人来所,内心真的很F**K。
后来突然想起,STC-ISP上有个波特率计算器,本想着只是计算下波特率,T1中要装入的初值是多少,不过没想到ISP把大部分的工作都做好了,简直太人性化的一个软件了 ~感动的都哭了~

好了废话不多说,上软件!

这个软件大家应该都不陌生,不过里面的有些功能大家还没有接触过。下面就带大家了解下如何快速的计算波特率并且生成初始化的寄存器配置代码:

(1)、

打开我们的界面后看到这些

(2)、

注意红色框框里面的,需要我们去调节的参数

(3)、

这是调节好后的参数,根据我们这次讲的,我们用这种方式调节,当然,我们要根据自己的需求,去调节不同的方式都可。

然后就生成代码ctrl c +ctrl v 到我们的程序中就可了

PS:由于某些版本的KEIL汉字的字符是由两个位组成的,而我们上述生成的代码中的备注只是一个位的汉字,所以当我们复制上述代码到我们程序中的时候,备注部分的汉字会变成乱码。这个时候,不要惊讶,不要慌张,轻轻的说一声艹,然后重新在KEIL上一个一个的敲上去就OK了。别说我没有提醒你哦。
.
.
.

5、串口通信的实例化程序——通过PC端控制开发板上的LED灯

这是19年吉林大学无线电爱好者协会林师哥设计的开发板,上面有8个可控的LED灯,我们通过下面的那一段程序,实现PC端对开发板上的LED灯的控制

下面这个是LED灯的引脚定义,有少许错误,大家直接顺着编号定义下来就OK

附上最终的代码:
大家可以自己试试效果,然后在代码中找下,为什么会这样。

#include <stc15f2k60s2.h>
#define uchar unsigned char
#define uint unsigned int
#define led1 P00
#define led2 P01
#define led3 P02
#define led4 P03
#define led5 P04
#define led6 P05
#define led7 P06
#define led8 P07
uchar Flag,a,i;
uchar code table[]="I get ";
void led();//下面这个初始化有问题,不能正常初始化,先待定,过几天我查查问题,看看哪里出错了。
/*
void init()
{TMOD=0x20;//T1定时器的方式2工作:8位自动重装定时器TH1=0xfd;TL1=0xfd;//溢出后,TH1中的值将被自动重装到TL1中TR1=1;//定时器1开始运行REN=1;//允许串口接受数据SM0=0;SM1=1;//串口方式1,10位异步收发(8位数据),波特率可变(由定时器1的溢出率控制)EA=1;//开启全局中断允许ES=1;//开启串口中断允许
}
*///下面这段初始化是由stc-isp上自带的波特率计算器实现的。到时候直接在上面选择设置,然后就自动生成出想要的代码了,下面会有详细的介绍
void UartInit(void)     //9600bps@11.0592MHz
{PCON &= 0x7F;//01111111波特率不倍速,PCON电源管理寄存器SCON = 0x50;//8位数据,可变波特率,SCON,串口控制寄存器AUXR |= 0x40;//定时器1时钟为Fosc,即1TAUXR &= 0xFE;//串口1选择定时器1为波特率发生器TMOD &= 0x0F;//清除定时器1模式位TMOD |= 0x20;    //设定定时器1为8位自动重装方式TL1 = 0xDC;//设定初值TH1 = 0xDC;//设定定时器重装初值ET1 = 0;//禁止定时器1中断TR1 = 1;//启动定时器1//下面这两句是stc-isp没有生成的,需要我们自己加上EA=1;//开启全局中断允许ES=1;//开启串口中断允许
}void main()
{UartInit();while(1){if(Flag==1)//Flag是我们定义的进入中断程序的标志(这里判断我们是否进入了中断程序){ES=0;//发送数据前,先将禁止串口中断for(i=0;i<6;i++)//(发送10个数据出去){SBUF=table[i];//将table[]中的数据一个一个给SBUF寄存器,并一个一个发送出去while(!TI);//等待数据发送完毕TI=0;//将发送数据标志位清零(因为我们成功发送数据,系统自动会把TI置1,标志数据发送成功,从而向CPU申请中断,我们需要手动吧TI清零)}SBUF=a;//将Data中的数据给SBUF,并发送while(!TI);//等待数据发送成功TI=0;//手动将发送数据标志位清零ES=1;//允许串口中断(当所有数据发送完成之后,再打开接受数据的串口中断,因为当我们没有发送完数据,而定时器T1溢出时候,这个时候我们如果打开串口中断,那么我们就会在发送数据的过程中进入到接收数据的中断程序里面,SBUF寄存器里面的数据就会混乱,导致产生错误的结果,所以我们需要发送数据时候关闭串口中断,接收数据的时候打开串口中断)Flag=0;//进入中断程序标志位清零led();}}
}void ser() interrupt 4
{RI=0;//接受数据标志位清零a=SBUF;//将接受到的数据存入Data中Flag=1;//进入中断标志位置1
}void led()
{switch(a){case 1:led1=!led1;break;case 2:led2=!led2;break;case 3:led3=!led3;break;case 4:led4=!led4;break;case 5:led5=!led5;break;case 6:led6=!led6;break;case 7:led7=!led7;break;case 8:led8=!led8;break;}
}

.
.
.
这个串口通信教程到这里就结束了,还有很多不足,请大家在评论区指教。同时,如果有哪些地方不太懂,也可以在评论区留言,我会及时的解答。

STC15F2K60S2串口通信/波特率设置/通信初始化/发送(接收)一个数据教程相关推荐

  1. c 语言 如何设置串口波特率,串口自动波特率设置程序

    来源:网上转载    作者: 在另外一套程序中并没有ISP功能,要实现程序的更新功能,要了解芯片的IAP调用,这一点在芯片的资料上也有介绍,然后就是接收上位机的程序,一般是通过串口,下面介绍一下P89 ...

  2. STC89C51 串口通信波特率设置

    STC89C51 串口通信波特率设置 //9600T2L = 0xE0; //设定定时初值T2H = 0xFE; //设定定时初值//115200T2L = 0xE8; //设定定时初值T2H = 0 ...

  3. java发送接收UDP数据包:字符串,byte[]字节数组,文件等

    全栈工程师开发手册 (作者:栾鹏) java教程全解 java发送接收UDP数据包,数据内容为byte[],包括一切可以转换为byte[]的内容. 测试代码 public static void ma ...

  4. 计算机串口3f8波特率设置,串口波特率转换的实现-硬件方式

    串口通信,就是RS-232/RS-485通信,要求通信的双方波特率等通信格式一样才可以通信成功.可是在许多情况下,两种不同格式比如不同波特率的串口也要相互通信,这就必须进行串口波特率等格式的转换.本文 ...

  5. 串口发送接收浮点型数据

    转自:https://blog.csdn.net/liangwei88624/article/details/6885803 转自:https://blog.csdn.net/newstoy/arti ...

  6. 【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)

    前言: 本系列教程将 对应外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具: 1.芯片: STM32F407ZET6/ STM32F103ZET6 ...

  7. linux串口操作及设置

    串口操作需要的头文件 #include /*标准输入输出定义*/ #include /*标准函数库定义*/ #include /*Unix 标准函数定义*/ #include #include #in ...

  8. linux 串口 延迟,linux串口操作及设置详解

    串口操作需要的头文件 #include #include #include #include #include #include #include #include 1.打开串口 在前面已经提到lin ...

  9. linux两个进程同时打开串口,linux串口操作及设置详解

    串口操作需要的头文件 #include /*标准输入输出定义*/ #include /*标准函数库定义*/ #include /*Unix标准函数定义*/ #include #include #inc ...

最新文章

  1. python 线程锁 共享全局变量 线程通信
  2. 浅谈双人游戏的设计与魅力——由《双人成行》引发的思考
  3. php session存到redis,php Session存储到Redis的方法
  4. mysql 忘记密码处理方式
  5. 数据:昨日BTC和ETH期货持仓均减少约三成,波动率创3月以来新高
  6. Python 揭秘斐波那契定律,如何帮助码农分析股票?| 技术头条
  7. 图书管理系统实验报告
  8. 批量生成ip地址shell脚本
  9. 漫步微积分三十七——力和功
  10. 【微信小程序怎么开店铺】微信小程序店铺怎么制作?
  11. 离线语音控制系统 唤醒词.命令字
  12. js动态添加多个元素
  13. 【python中级】 ico图标生成器
  14. CF 1728 D. Letter Picking 区间dp 1800
  15. 人人商城(分销版)1.11.7微擎原版,装修店铺后,网站链接失效,页面不显示数据
  16. AI强度相关的研究:MCTS 蒙特卡洛树搜索 Monte Carlo Tree Search
  17. Chapter8.金融时间序列
  18. [机器学习][基础编程][pandas]pandas基本操作
  19. 高德地图添加安全密钥
  20. 指标 | 指标波动归因

热门文章

  1. webpack中对js进行转译
  2. Mybatis大致框架
  3. 美学生用ChatGPT写论文被识破,导师:好到不符合我对学生的预期
  4. 思考、创新、坚持——阿里做了七年前端,我的成长经验分享
  5. 什么是消融实验(Ablation experiment)?
  6. 人人网登录(通过cookiejar)
  7. mac-快速打开终端的方法
  8. 二进制除法转乘法原理
  9. Python爬虫入门教程 37-100 云沃客项目外包网数据爬虫 scrapy
  10. 如何提高linux ssh连接速度