单片机学习笔记---串口向电脑发送数据&电脑通过串口控制LED

目录

串口向电脑发送数据

每隔一秒串口就发送一个递增的数给电脑

电脑通过串口控制LED

波特率的具体计算

HEX模式和文本模式


前两节是本节的理论基础,这节开始代码演示!

串口向电脑发送数据

接下来先开始演示一下串口单向发送一个数字给电脑:

写好框架后把前几节写好的Delay程序添加进来,后面会用到

接下来就是怎么配置串口的问题。

我们要写一个串口初始化函数,可以借助STC软件上的一个小工具帮我们生成代码

复制过来

改造成

即完成了下图中的定时器(橘色标识)和串口相关寄存器(蓝色标识)的配置(目前是禁止中断状态,即还没有配置中断系统)

开始调用

然后我们尝试发送一个字节给电脑

首先要把值写进SBUF,只要上面写的那个串口函数的波特率配置好了,定时器配置好了之后就自动发出去了。

但是我们还需要检测是否完成发送,因为刚写完不会立即发完,如果连续发就会出错,所以我们需要检测。怎么检测呢?就是看TI标志位。

标志位置1之后,我们用软件清零

然后我们来调用一下这个函数,假设传一个字节0110 0110过去

编译无错误后下载到单片机里面,重启板子,然后找到串口助手,点击打开串口****(注意打开串口之后一定要把波特率改成4800,因为我们前面选择定时器1的初始值(波特率)是4800,采样之前要保证接收双方的速率是相同的,所以这里接收的话也要设置为4800)****然后一般都是选择无校验位,停止位为1位

然后按下开发板上的复位

就可以看到电脑的确接收了0x66的数据,以十六进制显示

PS:以后我们可以把这里给勾上,以后就不用每次都要点击打开串口了

以上单向发送就已经写好了。

每隔一秒串口就发送一个递增的数给电脑

下面我们开始演示本节要实现的第一个示例:每隔一秒串口就发送一个递增的数给电脑。

首先我们要在以上程序的基础之上添加一个全局变量

然后主程序改成每发送一次就延迟1秒

看看效果

第一个程序完成!

然后我们可以模块化我们的程序,方便下一次代码演示。

main.c

UART.c

UART.h

别忘了还有我们的延时Delay函数的模块化,前面很多节都模块化过了,这里就不说了。

模块化后的程序放在评论区了,需要的自取!

电脑通过串口控制LED

下面我们开始演示本节要实现的第二个示例:电脑通过串口控制LED

我们把新创建一个工程(可以复制前面的工程文件,修改工程文件名)打开

然后把前面写的UART代码改造一下。

我们要添加一个中断函数,因为我们不知道电脑什么时候发过来,我们也不能一直检测,我们就利用中断,当电脑发过来之后就触发中断,然后再中断函数里面进行数据处理,把这个数据拿出来。

这次我们要将REN置1,所以把SCON改成0x50

REN允许接收后,单片机接收完数据之后触发中断,这时我们要把串口的中断打开

启动中断后,程序就跳转到中断函数里面

我们要查询串口中断的中断号,由下图我们可以知道UART的中断号为4

然后我们就应用这个中断号写一个串口中断函数在主程序文件中

由于给SBUF写数据的时候(即串口给电脑发送数据的时候)也会触发中断,而且发送和接收的中断标志位是占用同一通道的

所以发送和接收要区分开,因此加一个if判断语句

编译无错误后下载到单片机,然后重启板子,在串口助手中的发送区写入数据(然后串口就能接收到数据),点击发送后就能看到开发板上的LED发生响应的变化。

比如我写一个11即0x11,也就是0001 0001,所以LED的状态如下:

如果想让LED按二进制响应,比如你输入数字1,就是D1亮,输入2就是D2亮,输入3就是D2和D1亮,要实现这样的效果的话可以对输入的数据进行取反:

以上是单片机接收数据,然后我们还要把单片机接收的数据发给电脑

怎么写呢?就是调用前面写的UART_SendByte ( )函数

完整的代码:

main.c

UART.c

UART.h

别忘了还有我们的延时Delay函数的模块化,前面很多节都模块化过了,这里就不说了。

模块化后的程序放在评论区了,需要的自取!

编译后下载到单片机里面,当我们在发送区写入数据后,LED按响应的二进制响应,同时接收区就收到我们的数据

到这里,电脑和串口之间互相通信的程序就写好了。

波特率的具体计算

接下来我们具体说一下串口初始化函数里面的这个波特率怎么计算的

首先我们的波特率产生时是这个环节

然后函数里面我们当时在STC上选择的波特率是4800,生成的代码是F3

F3的十进制是243

每隔256溢出一次

256-243=13,就说明计数值是13,也就是每计13个数就溢出一次。

我们的单片机晶振是12MHz,机器周期是1微秒,也就是每一微秒就计一次数,也就是每隔13微秒就溢出一次,那溢出的频率就是1/13微秒,这就是定时器的溢出率。

1/13等于:

也就是说T1定时器的溢出率是0.07692MHz

然后我们这里还设置了波特率的倍数SMOD=1

那它就走的是除以16这条路线,

那0.07692还要除以16

这个结果是兆赫兹,我们需要转换成赫兹,那就乘以1000000

四舍五入就等于我们当时选的4800,这就是波特率了,大概0.16%的误差

如果不选择SMOD=1的话,那就是1/13先除2再除以16,那最后波特率就是SMOD=1时的一半

手册上也有计算公式

最后再补充一下数据显示模式方面的知识

HEX模式和文本模式

我们看到串口助手这里有两种数据模式:HEX模式和文本模式

HEX模式/十六进制模式/二进制模式:以原始数据的形式显示

文本模式/字符模式:以原始数据编码后(对照ASCII表上的数据)的形式显示

为什么需要这个ASCII值呢?

是因为原始数据只能发0~255这些数字,如果我们需要发其他的,比如说发个ABCD和其他一些符号,怎么发呢?这个时候就需要它按照这个ASCII表对我们输入的数据进行编码。

比如我们想要给电脑发个A,那我就可以输入0x41

文本模式下,它就会把0x41编码成A

如果你忘记了A这个字符的ASCII值,可以写成 'A',它和0x41是一个意思

以上就是本节所有内容,本节的代码都放在文件在评论区了,自取!

如有问题,请评论区留言。

相关推荐
绵绵细雨中的乡音6 分钟前
C++第28课-布隆过滤器的介绍
c++·哈希算法
C++忠实粉丝33 分钟前
计算机网络socket编程(5)_TCP网络编程实现echo_server
网络·c++·网络协议·tcp/ip·计算机网络·算法
北京迅为36 分钟前
【北京迅为】iTOP-4412全能版使用手册- 第五章 Linux常用命令
linux·嵌入式硬件·4412开发板
胜天半子_王二_王半仙2 小时前
c++源码阅读__smart_ptr__正文阅读
开发语言·c++·开源
程序猿阿伟2 小时前
《C++智能合约与区块链底层交互全解析:构建坚实的去中心化应用桥梁》
c++·区块链·智能合约
沐泽Mu2 小时前
嵌入式学习-C嘎嘎-Day08
开发语言·c++·算法
LinuxST2 小时前
27、基于Firefly-rk3399中断休眠唤醒实验(按键中断)
linux·开发语言·stm32·嵌入式硬件
水饺编程3 小时前
【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-32
linux·嵌入式硬件·fpga开发·硬件架构
黑不溜秋的3 小时前
C++ 编程指南04 - 尽量编写静态类型安全的程序
开发语言·c++·安全
生活很暖很治愈3 小时前
C51数字时钟/日历---LCD1602液晶显示屏
数据库·单片机·mongodb