本示例按照MCU+TCP模组中描述的过程,将Link SDK移植到STM32F103,并结合广域网SIM800C连接到阿里云物联网平台。在示例中SIM800C模组支持TCP能力,STM32F103上集成了SDK并使用直接基于MQTT TOPIC的方式与阿里云物联网平台实现数据收发。
用户也可参考本移植方案,将ST其他类型的芯片实现快速连接阿里云物联网平台。

芯片 | 开发板 | 参数 |
---|---|---|
STM32F103RBT6 | NUCLEO-F103RB | 32bits, M3 72Mhz, 128KB-Flash 20KB-SRAM |
SIM800C | SIM800C开发板 |
准备
环境搭建
STM32F103
- 搭建目标:MCU的两个串口(作为调试串口和与模组通信的AT串口)可以正常收发
- 开发工具:ARM® Keil® 或 IAR™。
- 硬件连接:
- MCU的AT串口通过Arduino™ Uno或ST morpho接口外接模组,示意图如下(通过TX/RX/GND连接外挂模组)
- ST开发板ST-LINK驱动
- 图示
- 软件环境
- 在Configuration中选择USARTx,并将USART1(作为AT口)的interrupt置为enable,点击Apply/Ok后点击Cubemx的"Project"选项中的"Generate Code",设置对应的选项,其中Toolchain/IDE可以选择ARM® Keil® 或 IAR™,Heap/Satck size按需选进行配置, 点击OK后自动生成代码和工程。

配置ToolChain/IDE

注:针对不一样的应用场景,需根据实际情况合理修改heap和stack的大小(如上图中圈选位置),在我们的测试中设置**4k(0x1000)的Heap和2.5K(0xA00)**的Stack可以正常工作
- 验证
- 根据上述软件环境配置生成对应的Keil/IAR工程,增加简单的代码,自行验证串口输入输出是否OK。
SIM800
- 请根据厂商提供的应用手册自行验证SIM800通信模组是否工作正常。
注:本次调试使用的是开发板而非市面上常见的模组,请参考硬件连接中的示例图与MCU的串口(TX--RX, RX--TX, GND--GND)进行硬件连接,注意开发板上电后按压PWRKEY按键(大于1秒),待STATUS和NETLIGHT两个LED灯陆续点亮,其中NETLIGHT LED会以2HZ进行闪烁,此时SIM800C模组ready。
移植SDK
配置SDK
- 配置命令
- Windows运行
config.bat
- Linux运行
make menuconfig
- Windows运行
-
配置步骤
如下图所示:在本示例中使能了下面的选项:
- PLATFORM_HAS_STDINT
- PLATFORM_HAS_DYNMEM
- FEATURE_MQTT_COMM_ENABLED
- FEATURE_MQTT_DEFAULT_IMPL
- FEATURE_MQTT_DIRECT
- FEATURE_ATM_ENABLED
- FEATURE_AT_TCP_ENABLED
- FEATURE_AT_PARSER_ENABLED
- FEATURE_AT_TCP_HAL_SIM800
注:上面选择了FEATURE_AT_TCP_HAL_SIM800,因此SDK将会生成驱动模组SIM800C相关的AT指令代码。
抽取
- 抽取命令
- Window运行
extract.bat
- Linux运行
extract.sh
- Window运行
- 抽取步骤
执行抽取命令后生成的代码路径在output/eng,需要用户实现位于文件output/eng/wrappers/wrapper.c
中的HAL对接函数。
集成
按下述步骤集成。
步骤
- 将抽取生成的output/eng代码
atm dev_sign infra mqtt wrappers
目录拷贝到上述已生成的Keil/IAR开发环境中,拷贝/使用examples下的mqtt_example_at.c作为示例,并将mqtt_example_at.c中的main函数名更改为mqtt_example以解决编译冲突问题。 - 在Src/main.c中调用mqtt_example_at.c的mqtt_example函数进行示例验证,更多其他细节请参照MCU+TCP模组中的相关章节。
/* add mqtt example in this file Src/main.c */
int main(void)
{
......
......
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
.......
mqtt_example(); /* add mqtt_example here*/
}

-
针对不一样的应用场景,需根据实际情况合理修改heap和stack的大小,本次组合设置4k(0x1000)的heap和2.5K(0xA00)的stack,修改方法如下:
- Keil中MDK-ARM/startup_xx.s
- IAR中EWARM/xx_flash.icf
-
用户需要实现wrapper.c中的HAL函数
- 本例中因为选择MCU上不运行OS,因此与系统相关的HAL函数实现可以参考文件wrappers\os\nos\HAL_Nos.c中的函数实现
- 对于
HAL_GetProductKey
、HAL_GetDeviceName
、HAL_GetDeviceSecret
需要用户返回用户自己设备的相应身份信息 - 对于HAL_AT_Uart_Init、HAL_AT_Uart_Deinit、HAL_AT_Uart_Recv、HAL_AT_Uart_Send需要用户去进行相关串口初始化以及数据收发
- wrapper.c参考, STM32上无OS
- wrapper.c参考, STM32上运行FreeRTOS
IDE配置
Keil/IAR中添加SDK相关的源码文件,修改头文件路径配置:
IAR配置
类似步骤,依次选择Project -> Add Group,输入“linkkit”,创建新的Group之后将Src\linkkit里所有子目录下的.c文件添加进去,最后Project -> options, 添加以下依赖的头文件路径。编译、烧录请参考下图9。
# 设置头文件路径,请以实际路径为准
$PROJ_DIR$/../Src/linkkit/atm
$PROJ_DIR$/../Src/linkkit/dev_sign
$PROJ_DIR$/../Src/linkkit/infra
$PROJ_DIR$/../Src/linkkit/mqtt
$PROJ_DIR$/../Src/linkkit/wrappers



结果
- MCU侧Log
[10:44:17.491]收←◆sim800_uart_selfadaption 283 failed rsp OK
retry count 1
[10:44:17.526]收←◆signal quality is
+CSQ: 31,0
OK
network registration is
+CREG: 0,1
OK
gprs attach check
+CGATT: 1
OK
[10:44:18.809]收←◆mqtt example
MQTT init success!
establish tcp connection with server(host='a1A6QHnzzrT.iot-as-mqtt.cn-shanghai.aliyuncs.com', port=[1883])
[10:44:20.000]收←◆success to establish tcp, fd=0
[10:44:21.576]收←◆mqtt connect success!
devinfo report
devinfo report topic: /sys/a1A6QHnzzrT/test_device/thing/deviceinfo/update
devinfo report data: {"id":"0","version":"1.0","params":[{"attrKey":"SYS_LP_SDK_VERSION","attrValue":"3.0.0","domain":"SYSTEM"},{"attrKey":"SYS_SDK_LANGUAGE","attrValue":"C","domain":"SYSTEM"}],"method":"thing.deviceinfo.update"}
[10:44:22.738]收←◆cmd AT+CIPSEND=0,267 rsp retry 1 at HAL_AT_CONN_Send 858 fail
[10:44:22.820]收←◆devinfo report succeed
firmware version report start in MQTT
firmware report topic: /ota/device/inform/a1A6QHnzzrT/test_device
firmware report data: {"id":"1","params":{"version":"app-1.0.0-20190118.1000"}}
[10:44:23.547]收←◆firmware version report finished, iotx_publish() = 2
PERFORM subscribe to '/a1A6QHnzzrT/test_device/get' (msgId=3)
Packet Ident : 00000003
Topic : /a1A6QHnzzrT/test_device/get
QoS : 0
Packet Length : 35
[10:44:23.861]收←◆mqtt subscribe packet sent,topic = /a1A6QHnzzrT/test_device/get!
[10:44:24.442]收←◆PUBACK
msg->event_type : 9
PUBACK
msg->event_type : 9
PUBACK
msg->event_type : 9
SUBACK
Return Value : 1
Packet ID : 3
Count : 1
Granted QoS[00] : 1
packet_id = 3, event_type=3
msg->event_type : 3
[10:44:25.511]收←◆PUBLISH
Packet Ident : 00000000
Topic Length : 28
Topic Name : /a1A6QHnzzrT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A6QHnzzrT/test_device/get
Payload: hello,world
[10:44:46.408]收←◆PUBLISH
Packet Ident : 00000000
Topic Length : 28
Topic Name : /a1A6QHnzzrT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A6QHnzzrT/test_device/get
Payload: hello,world
[10:45:07.348]收←◆PUBLISH
Packet Ident : 00000000
Topic Length : 28
Topic Name : /a1A6QHnzzrT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A6QHnzzrT/test_device/get
Payload: hello,world
[10:45:22.414]收←◆len = MQTTSerialize_pingreq() = 2
[10:45:23.241]收←◆send MQTT ping...
[10:45:24.246]收←◆receive ping response!
[10:45:29.128]收←◆PUBLISH
Packet Ident : 00000000
Topic Length : 28
Topic Name : /a1A6QHnzzrT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A6QHnzzrT/test_device/get
Payload: hello,world