“第十九课--串口调试/zh”的版本间的差异
(Created page with "== 目的 == USART(Universal Synchronous/Asynchronous Receiver/Transmitter)中文为“通用同步/异步串行接收/发送器”,也就是常说的串口(Serial)...") |
(→结果) |
||
(未显示2个用户的15个中间版本) | |||
第1行: | 第1行: | ||
== 目的 == | == 目的 == | ||
− | USART(Universal Synchronous/Asynchronous Receiver/Transmitter)中文为“通用同步/异步串行接收/ | + | USART(Universal Synchronous/Asynchronous Receiver/Transmitter)中文为“通用同步/异步串行接收/发送器”,也就是常说的串口(Serial),是最常用的通信协议之一。本课讲解Microduino CoreSTM32串口的使用,通过虚拟USB串口实现数据的收发。 |
+ | |||
== 设备 == | == 设备 == | ||
* [[Microduino-CoreSTM32/zh|Microduino CoreSTM32 ]] | * [[Microduino-CoreSTM32/zh|Microduino CoreSTM32 ]] | ||
第10行: | 第11行: | ||
USART 是一个全双工通用同步/异步串行收发器,高度灵活的串行通信接口。下面以同步串行通信方式加以介绍: | USART 是一个全双工通用同步/异步串行收发器,高度灵活的串行通信接口。下面以同步串行通信方式加以介绍: | ||
异步串行通信以帧作为传送单位,每一帧由起始位、数据位、校验位和停止位组成。 在异步通信中有两个比较重要的指标,字符帧格式和波特率。数据通常以字符或者字节为单位组成字符帧传送。字符帧由发送端逐帧发送,通过传输线被接收设备逐帧接收。发送端和接收端可以由各自的时钟来控制数据的发送和接收,这两个时钟源彼此独立,互不同步。接收端检测到传输线上发送过来的低电平逻辑"0"(即字符帧起始位)时,确定发送端已开始发送数据,每当接收端收到字符帧中的停止位时,就知道一帧字符已经发送完毕。 结果如下图所示。 | 异步串行通信以帧作为传送单位,每一帧由起始位、数据位、校验位和停止位组成。 在异步通信中有两个比较重要的指标,字符帧格式和波特率。数据通常以字符或者字节为单位组成字符帧传送。字符帧由发送端逐帧发送,通过传输线被接收设备逐帧接收。发送端和接收端可以由各自的时钟来控制数据的发送和接收,这两个时钟源彼此独立,互不同步。接收端检测到传输线上发送过来的低电平逻辑"0"(即字符帧起始位)时,确定发送端已开始发送数据,每当接收端收到字符帧中的停止位时,就知道一帧字符已经发送完毕。 结果如下图所示。 | ||
− | [[File:异步串行通信|600px|thumbnail|center|1]] | + | [[File:异步串行通信.png|600px|thumbnail|center|1]] |
* 起始位: 先发出一个逻辑” 0”的信号,表示传输字符的开始。 | * 起始位: 先发出一个逻辑” 0”的信号,表示传输字符的开始。 | ||
* 数据位: 紧接着起始位之后。 数据位的个数可以是 4、 5、 6、 7、 8 等,构成一个字符。通常采用 ASCII 码。从最低位开始传送,靠时钟定位。 | * 数据位: 紧接着起始位之后。 数据位的个数可以是 4、 5、 6、 7、 8 等,构成一个字符。通常采用 ASCII 码。从最低位开始传送,靠时钟定位。 | ||
第17行: | 第18行: | ||
*空闲位: 处于逻辑“ 1”状态,表示当前线路上没有资料传送。 | *空闲位: 处于逻辑“ 1”状态,表示当前线路上没有资料传送。 | ||
*波特率: 是衡量资料传送速率的指标。表示每秒钟传送的符号数( symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如资料传送速率为 120 字符/秒,传输使用256阶符号,每个符号代表 8bit,则波特率就是 120baud,比特率是 120*8=960bit/s。这两者的概念很容易搞错。 | *波特率: 是衡量资料传送速率的指标。表示每秒钟传送的符号数( symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如资料传送速率为 120 字符/秒,传输使用256阶符号,每个符号代表 8bit,则波特率就是 120baud,比特率是 120*8=960bit/s。这两者的概念很容易搞错。 | ||
+ | |||
=== Microduino-CoreSTM32 USART === | === Microduino-CoreSTM32 USART === | ||
Microduino-CoreSTM32 硬件串口1~3使用Serial1、Serial2、Serial3三个对象来控制。Maple所使用的STM32有一个专用的USB控制器,这个控制器被配置成一个虚拟串口设备,使用户在计算机上能通过标准的串口协议与Maple通信。对USB虚拟串口的调用是通过SerialUSB对象实现的。大多数情况下,你可以用SerialUSB直接替代Serial1、Serial2、Serial3。每次通过USB虚拟串口发送数据至少消耗约50 ms的时间,并且虚拟串口并不会检测USB接口是否真的已连接。USART设备间的通信主要依靠TX和RX两个信号,设备A的TX接到设备B的RX,设备B的RX接到设备A的TX,如下图所示。 | Microduino-CoreSTM32 硬件串口1~3使用Serial1、Serial2、Serial3三个对象来控制。Maple所使用的STM32有一个专用的USB控制器,这个控制器被配置成一个虚拟串口设备,使用户在计算机上能通过标准的串口协议与Maple通信。对USB虚拟串口的调用是通过SerialUSB对象实现的。大多数情况下,你可以用SerialUSB直接替代Serial1、Serial2、Serial3。每次通过USB虚拟串口发送数据至少消耗约50 ms的时间,并且虚拟串口并不会检测USB接口是否真的已连接。USART设备间的通信主要依靠TX和RX两个信号,设备A的TX接到设备B的RX,设备B的RX接到设备A的TX,如下图所示。 | ||
− | [[File:Stm32 USART|600px|thumbnail|center|2]] | + | [[File:Stm32 USART.jpg|600px|thumbnail|center|2]] |
'''注意,USART≠RS232,请勿将USART接口直接与RS232相连,RS232传输的信号使用±12 V的电压,会损坏Maple。''' | '''注意,USART≠RS232,请勿将USART接口直接与RS232相连,RS232传输的信号使用±12 V的电压,会损坏Maple。''' | ||
PC上的COM口由于历史原因都是RS232接口。现在大部分计算机都取消了RS232接口,如果需要,可以利用专用的USB串口适配器,通常这类适配器会提供TTL电平输出,该TTL电平输出可以直接连接到Microduino-CoreSTM32的USART接口。 | PC上的COM口由于历史原因都是RS232接口。现在大部分计算机都取消了RS232接口,如果需要,可以利用专用的USB串口适配器,通常这类适配器会提供TTL电平输出,该TTL电平输出可以直接连接到Microduino-CoreSTM32的USART接口。 | ||
− | Microduino USBTTL:[[Microduino-USBTTL/zh|Microduino USBTTL]] | + | *'''Microduino USBTTL:[[Microduino-USBTTL/zh|Microduino USBTTL]]''' |
+ | |||
== 程序 == | == 程序 == | ||
<source lang="cpp"> | <source lang="cpp"> | ||
− | int inByte; | + | int inByte; |
char a='W'; | char a='W'; | ||
char b[]="elcome to Microduino"; | char b[]="elcome to Microduino"; | ||
第31行: | 第34行: | ||
void setup() | void setup() | ||
{ | { | ||
− | // Serial1.begin(9600); | + | // Serial1.begin(9600); //初始化串口1,波特率设置为9600 |
} | } | ||
void loop() | void loop() | ||
{ | { | ||
− | SerialUSB.print(1); | + | SerialUSB.print(1); //发送整数 |
− | SerialUSB.print("----"); | + | SerialUSB.print("----"); //发送字符串 |
− | SerialUSB.write(a); | + | SerialUSB.write(a); //发送字符W |
− | SerialUSB.write(b,5); | + | SerialUSB.write(b,5); //发送字符串 char b[]="elcome to Microduino"; |
− | SerialUSB.println(" to Microduino"); | + | SerialUSB.println(" to Microduino"); //发送字符串并换行 |
SerialUSB.print("2----"); | SerialUSB.print("2----"); | ||
− | SerialUSB.print(5); | + | SerialUSB.print(5); |
− | SerialUSB.print(-2.5); | + | SerialUSB.print(-2.5); //发送浮点数 |
− | SerialUSB.print('='); | + | SerialUSB.print('='); //发送单个字符 |
− | SerialUSB.println(2.5); | + | SerialUSB.println(2.5); //发送浮点数 |
− | SerialUSB.println(255,DEC); | + | SerialUSB.println(255,DEC); //255以十进制显示 |
− | SerialUSB.println(255,BIN); | + | SerialUSB.println(255,BIN); //255以二进制显示 |
− | SerialUSB.println(255,HEX); | + | SerialUSB.println(255,HEX); //255以十六进制显示 |
− | SerialUSB.println(""); | + | SerialUSB.println(""); //换行 |
− | while (SerialUSB.available()>0) | + | while (SerialUSB.available()>0) //如果USB虚拟串口有数据接收 |
{ | { | ||
− | inByte = SerialUSB.read(); | + | inByte = SerialUSB.read(); //接收数据,这里只能接收1个字节 |
− | SerialUSB.print("Byte Received :"); | + | SerialUSB.print("Byte Received :"); |
− | SerialUSB.println(inByte, BYTE); | + | SerialUSB.println(inByte, BYTE); //把接收到的字节送显 |
SerialUSB.println(""); | SerialUSB.println(""); | ||
} | } | ||
− | delay(5000); | + | delay(5000); //加延时,防止因数据发送过 |
+ | //快,Serial monitor窗口或者Maple IDE卡死,同时便于观察调试 | ||
} | } | ||
</source> | </source> | ||
+ | 程序说明: | ||
+ | *1) begin() | ||
+ | :* begin()用于设定串口工作的波特率,在进行串口通信前必须先调用begin()设定波特率,对于Microduino CoreSTM32常用的波特率有9600 Hz与115200Hz。通过Microduino CoreSTM32与PC通信时,虚拟串口波特率默认为9600 Hz。 | ||
+ | :* SerialUSB.begin()通常不需要调用,只有当使用SerialUSB.end()关闭虚拟串口后,才可以利用该函数恢复虚拟串口通信。 | ||
+ | *2) write() | ||
+ | *:“void write(unsigned char ch)”函数是一个低层函数,通过USART发送单个字符,现在已被屏蔽。 | ||
+ | *: “void write(const char* str)”函数可以通过USART发送一个带有NULL终止符的字符串。 | ||
+ | *:“void write(void* buf, unsigned int size)”函数发送buf变量的前size字节数据,每个字节按照独立的字符发送。 | ||
+ | *3) print()与println() | ||
+ | :* print()与println()的区别是println()会自动在每次发送的数据后加入换行符。 | ||
+ | 此外:available()函数会返回等待接收的字节数。常用于接收一长串数据。 | ||
+ | :*flush()函数用于清空串口接收缓冲,保证之后所读取到的都是全新的数据。该函数只用于Serial1、Serial2、Serial3,对于SerialUSB不需要使用此函数。 | ||
+ | :*txPin()与rxPin()函数分别会返回发送和接收引脚的编号。 | ||
+ | :*end()函数用于结束串口通信,并释放其所占用的端口。“SerialUSB.end()”用于结束虚拟串口的通信。当使用“SerialUSB.end()”结束虚拟串口通信后,下载程序时不会自动复位进入bootloader模式等待下载,需要手动复位进入下载。 | ||
+ | |||
== 调试 == | == 调试 == | ||
+ | 复制程序代码到Maple IDE,如图编译程序代码,下载程序,然后打开串口监视窗口 | ||
+ | [[File:Lesson 19 .jpg|600px|thumb|center]] | ||
+ | 在串口监视界面可以看到Microduino CoreSTM32发送的数据,如下图所示 | ||
+ | [[File:Lesson 19 Microduino CoreSTM32 send.jpg|600px|thumb|center]] | ||
+ | 在串口监视界面填写发送数据框写入任意数据,点击发送(或按回车),在接收数据显示框就显示发送的数据文字。 | ||
+ | [[File:Lesson 19 Serial send.jpg|600px|thumb|center]] | ||
+ | [[File:Lesson 19 Serial receive.jpg|600px|thumb|center]] | ||
+ | |||
== 结果 == | == 结果 == | ||
+ | 通过虚拟USB串口在Maple IDE的串口监视界面显示“1---Welcome to Microduino”、“2---5-2.5=2.5”、“255(2进制、10进制和16进制)”显示以及Microduino CoreSTM32把通过串口接收到的字节“b”又通过串口送显。 | ||
+ | [[File:Lesson16.png|600px|thumbnail|center]] | ||
+ | 大家可以结合之前的课程做更有趣的东西,通过串口监视界面发送命令控制其它外模块。 | ||
+ | |||
== 视频 == | == 视频 == |
2015年1月18日 (日) 14:16的最新版本
目的
USART(Universal Synchronous/Asynchronous Receiver/Transmitter)中文为“通用同步/异步串行接收/发送器”,也就是常说的串口(Serial),是最常用的通信协议之一。本课讲解Microduino CoreSTM32串口的使用,通过虚拟USB串口实现数据的收发。
设备
Microduino-CoreSTM32是Microduino系列的核心模块之一,采用 STM32F103CBT6芯片的ARM开发板。Microduino-CoreSTM32是一个开放源码硬件与Maple Mini兼容,可利用 Microduino 扩展模块和其他电子元件、模块、传感器,做出很多丰富有趣的互动作品。
- USB数据连接线 一根
原理
串行通信
串行通信是指计算机主机与外设之间以及主机系统与主机系统之间数据的串行传送,串行通信的工作方式有异步和同步两种,本课讲解异步串行通信。 USART 是一个全双工通用同步/异步串行收发器,高度灵活的串行通信接口。下面以同步串行通信方式加以介绍: 异步串行通信以帧作为传送单位,每一帧由起始位、数据位、校验位和停止位组成。 在异步通信中有两个比较重要的指标,字符帧格式和波特率。数据通常以字符或者字节为单位组成字符帧传送。字符帧由发送端逐帧发送,通过传输线被接收设备逐帧接收。发送端和接收端可以由各自的时钟来控制数据的发送和接收,这两个时钟源彼此独立,互不同步。接收端检测到传输线上发送过来的低电平逻辑"0"(即字符帧起始位)时,确定发送端已开始发送数据,每当接收端收到字符帧中的停止位时,就知道一帧字符已经发送完毕。 结果如下图所示。
- 起始位: 先发出一个逻辑” 0”的信号,表示传输字符的开始。
- 数据位: 紧接着起始位之后。 数据位的个数可以是 4、 5、 6、 7、 8 等,构成一个字符。通常采用 ASCII 码。从最低位开始传送,靠时钟定位。
- 奇偶校验位: 数据位加上这一位后,使得“ 1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验资料传送的正确性。
- 停止位: 它是一个字符数据的结束标志。可以是 1 位、 1.5 位、 2 位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
- 空闲位: 处于逻辑“ 1”状态,表示当前线路上没有资料传送。
- 波特率: 是衡量资料传送速率的指标。表示每秒钟传送的符号数( symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如资料传送速率为 120 字符/秒,传输使用256阶符号,每个符号代表 8bit,则波特率就是 120baud,比特率是 120*8=960bit/s。这两者的概念很容易搞错。
Microduino-CoreSTM32 USART
Microduino-CoreSTM32 硬件串口1~3使用Serial1、Serial2、Serial3三个对象来控制。Maple所使用的STM32有一个专用的USB控制器,这个控制器被配置成一个虚拟串口设备,使用户在计算机上能通过标准的串口协议与Maple通信。对USB虚拟串口的调用是通过SerialUSB对象实现的。大多数情况下,你可以用SerialUSB直接替代Serial1、Serial2、Serial3。每次通过USB虚拟串口发送数据至少消耗约50 ms的时间,并且虚拟串口并不会检测USB接口是否真的已连接。USART设备间的通信主要依靠TX和RX两个信号,设备A的TX接到设备B的RX,设备B的RX接到设备A的TX,如下图所示。
注意,USART≠RS232,请勿将USART接口直接与RS232相连,RS232传输的信号使用±12 V的电压,会损坏Maple。 PC上的COM口由于历史原因都是RS232接口。现在大部分计算机都取消了RS232接口,如果需要,可以利用专用的USB串口适配器,通常这类适配器会提供TTL电平输出,该TTL电平输出可以直接连接到Microduino-CoreSTM32的USART接口。
- Microduino USBTTL:Microduino USBTTL
程序
int inByte;
char a='W';
char b[]="elcome to Microduino";
char c[]="2.5-5=-2.5";
void setup()
{
// Serial1.begin(9600); //初始化串口1,波特率设置为9600
}
void loop()
{
SerialUSB.print(1); //发送整数
SerialUSB.print("----"); //发送字符串
SerialUSB.write(a); //发送字符W
SerialUSB.write(b,5); //发送字符串 char b[]="elcome to Microduino";
SerialUSB.println(" to Microduino"); //发送字符串并换行
SerialUSB.print("2----");
SerialUSB.print(5);
SerialUSB.print(-2.5); //发送浮点数
SerialUSB.print('='); //发送单个字符
SerialUSB.println(2.5); //发送浮点数
SerialUSB.println(255,DEC); //255以十进制显示
SerialUSB.println(255,BIN); //255以二进制显示
SerialUSB.println(255,HEX); //255以十六进制显示
SerialUSB.println(""); //换行
while (SerialUSB.available()>0) //如果USB虚拟串口有数据接收
{
inByte = SerialUSB.read(); //接收数据,这里只能接收1个字节
SerialUSB.print("Byte Received :");
SerialUSB.println(inByte, BYTE); //把接收到的字节送显
SerialUSB.println("");
}
delay(5000); //加延时,防止因数据发送过
//快,Serial monitor窗口或者Maple IDE卡死,同时便于观察调试
}
程序说明:
- 1) begin()
- begin()用于设定串口工作的波特率,在进行串口通信前必须先调用begin()设定波特率,对于Microduino CoreSTM32常用的波特率有9600 Hz与115200Hz。通过Microduino CoreSTM32与PC通信时,虚拟串口波特率默认为9600 Hz。
- SerialUSB.begin()通常不需要调用,只有当使用SerialUSB.end()关闭虚拟串口后,才可以利用该函数恢复虚拟串口通信。
- 2) write()
- “void write(unsigned char ch)”函数是一个低层函数,通过USART发送单个字符,现在已被屏蔽。
- “void write(const char* str)”函数可以通过USART发送一个带有NULL终止符的字符串。
- “void write(void* buf, unsigned int size)”函数发送buf变量的前size字节数据,每个字节按照独立的字符发送。
- 3) print()与println()
- print()与println()的区别是println()会自动在每次发送的数据后加入换行符。
此外:available()函数会返回等待接收的字节数。常用于接收一长串数据。
- flush()函数用于清空串口接收缓冲,保证之后所读取到的都是全新的数据。该函数只用于Serial1、Serial2、Serial3,对于SerialUSB不需要使用此函数。
- txPin()与rxPin()函数分别会返回发送和接收引脚的编号。
- end()函数用于结束串口通信,并释放其所占用的端口。“SerialUSB.end()”用于结束虚拟串口的通信。当使用“SerialUSB.end()”结束虚拟串口通信后,下载程序时不会自动复位进入bootloader模式等待下载,需要手动复位进入下载。
调试
复制程序代码到Maple IDE,如图编译程序代码,下载程序,然后打开串口监视窗口
在串口监视界面可以看到Microduino CoreSTM32发送的数据,如下图所示
在串口监视界面填写发送数据框写入任意数据,点击发送(或按回车),在接收数据显示框就显示发送的数据文字。
结果
通过虚拟USB串口在Maple IDE的串口监视界面显示“1---Welcome to Microduino”、“2---5-2.5=2.5”、“255(2进制、10进制和16进制)”显示以及Microduino CoreSTM32把通过串口接收到的字节“b”又通过串口送显。
大家可以结合之前的课程做更有趣的东西,通过串口监视界面发送命令控制其它外模块。