目录
对STM32利用Arduino进行串行通信时,如果直接使用默认Serial函数,可能无法在串口监视器中看到数据,下面给出了出现这种情况的原因与解决方法。
一、STM32系列单片机串口资源介绍
不同系列与型号的单片机,串口资源的数量不同,具体串口数目可以在Datasheet和官方选型工具中产找到。
如:STM32F1系列的串口数量在2~5个:
如:STM32F4系列的串口数量在2~10个:
对于不同的芯片,其默认的映射到通用Serial名的管脚是不同的!你可以在variant_generic.h文件中产找到默认引脚定义:
默认情况下,只有一个Serialx实例映射到通用Serial
名。对于STM32F407ZET6而言,映射的管脚为:PA1
和PA0
。可以在variant_generic.h文件中找到:C:\Users\Evan\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.3.0\variants\STM32F4xx\F407Z(E-G)T_F417Z(E-G)T\variant_generic.h(将Evan替换成你的用户名)。
// Default pin used for generic 'Serial' instance
// Mandatory for Firmata
#ifndef PIN_SERIAL_RX
#define PIN_SERIAL_RX PA1
#endif
#ifndef PIN_SERIAL_TX
#define PIN_SERIAL_TX PA0
#endif
查阅芯片手册可知,PA1和PA0的对应的是USART4(可以复用为USART2),在Arduino中使用默认Serial名,你还在串口1上监测数据,肯定不能监测到数据了!
很多朋友在用STM32 Blue Pill,其芯片选用STM32F103C8T6,默认串口映射的管脚是:PA3和PA2,对应的是USART2,同样也可以在variant_generic.h文件中产找到默认引脚定义:C:\Users\Evan\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.3.0\variants\STM32F1xx\F103C8T_F103CB(T-U)\variant_generic.h(将Evan替换成你的用户名)。
// Default pin used for generic 'Serial' instance
// Mandatory for Firmata
#ifndef PIN_SERIAL_RX
#define PIN_SERIAL_RX PA3
#endif
#ifndef PIN_SERIAL_TX
#define PIN_SERIAL_TX PA2
#endif
二、指定串口管脚用法示例
使用ST官方Arduino库,可在STM32全系列开发板上进行如下实验。
注意:实例化串口对象需要加数字编号(Serialx中的x是串口编号,取值是1,2……):
HardwareSerial Serialx(PA10, PA9); //将Serialx(x=1-4)串口x的管脚,一定要带编号,如:Serial1
强调一下:不能实例化默认的串口:HardwareSerial Serial(PA10, PA9);
/*===============================================
(1)持续向串口输出“This is a test message !”
(2)当接收到“stop!”时,停止输出
(3)输入“begin”时,继续输出
(4)测试环境为STM32开发板
================================================*/
HardwareSerial Serial1(PA10, PA9); //将串口1的管脚指定到PA10(RX),PA9(TX)引脚上
int flag = 1; //串口发送标志位,1表示正在发送,0表示停止发送
void setup() {
// put your setup code here, to run once:
Serial1.begin(115200); //打开串口,波特率为115200
}
void loop() {
// put your main code here, to run repeatedly:
if (flag == 1) {
Serial1.println("This is a test message !");
delay(1000); //间隔一秒打印提示信息
}
usart();
}
void usart() {
String Stop_flag = "stop\n"; //停止发送信号
String Begin_flag = "begin\n"; //重新发送信号
String rxdata = ""; //储存接接收到的数据
while (Serial1.available() > 0) //判断串口是否接收到数据
{
rxdata = Serial1.readString(); //读取字符到字符串rxdata中
//Serial.print(rxdata);
}
if (rxdata == Stop_flag)
flag = 0; //停止发送标志
if (rxdata == Begin_flag)
flag = 1; //恢复发送标志
}
仍以采用STM32F103C8T6的STM32 Blue Pill为例,说明串口复用引脚的指定。查阅STM32F103C8T6的Datasheet可知,PB7和PB6是串口1的复用引脚:
使用此复用引脚通信。只需将引脚实例化:
HardwareSerial Serial1(PB7, PB6); //将串口1的管脚指定到PB7(RX),PB6(TX)引脚上
当然,你也可以使用:
Serial1.setRx(PA10);
Serial1.setTx(PA9);
来指定串口,但是由于WSerial.h文件定义SERIAL_UART_INSTANCE时,将其被定义为2,即Serial被导到的串口2去了,需要去修改该源码,这种方式有点麻烦,因此,我一般采用HardwareSerial指定串口引脚。