本文介绍按照MCU+支持TCP的模组集成过程,将使用C Link SDK的设备移植到STM32F103,并结合广域网SIM800C连接到阿里云物联网平台。本示例中SIM800C模组支持TCP能力,STM32F103上集成了SDK并直接基于MQTT TOPIC的方式与阿里云物联网平台实现数据收发。
背景信息
MCU+支持TCP的模组集成过程,请参见MCU+支持TCP的模组。
用户也可参考本移植方案,将ST其他类型的芯片实现快速连接阿里云物联网平台。
芯片 | 开发板 | 参数 |
STM32F103RBT6 | 32bits, M3 72Mhz, 128KB-Flash 20KB-SRAM | |
SIM800C | SIM800C开发板 | 无 |
环境搭建
本节仅供参考使用,若用户在环境搭建中碰到问题,请联系开发板供货商解决问题之后再进行SDK的移植。
STM32F103
搭建目标:
MCU的两个串口(作为调试串口和与模组通信的AT串口)可以正常收发。
开发工具:
硬件连接:
MCU的AT串口通过Arduino™ Uno或ST morpho接口外接模组,示意图如下(通过TX/RX/GND连接外挂模组)。
ST开发板:ST-LINK驱动。
图示:
软件环境
使用ST-cubemx新建Project,然后在Board Seletor选择NUCLEO-F103RB开发板并双击,最后添加合适的串口作为MCU与模组通信的AT口,如下图USART1所示。
在Configuration中选择USARTx,并将USART1(作为AT口)的interrupt置为enable,单击Apply/Ok,然后单击Cubemx的Project选项中的Generate Code,设置对应的选项。
其中Toolchain/IDE可以选择
ARM® Keil®
或IAR™
,Heap/Stack 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模组工作正常。
配置SDK
配置命令
Windows运行
config.bat
Linux运行
make menuconfig
配置步骤
如下图所示:
在本示例中使能了下面的选项:
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
。
抽取步骤
执行抽取命令后生成的代码路径在
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相关的源码文件,修改头文件路径配置。
Keil配置
按下图依次创建新的Group并修改为linkkit,手动添加源文件(*.c
)并设置正确的头文件路径如下。
# 设置头文件路径,请以实际路径为准
;../Src/linkkit/atm;../Src/linkkit/dev_sign;../Src/linkkit/infra;../Src/linkkit/mqtt;../Src/linkkit/wrappers
编译、烧录流程如下:
在Keil工程下添加Group:
在Keil工程下添加.c文件:
设置头文件路径:
IAR配置
类似步骤,依次选择Project > Add Group,输入linkkit,创建新的Group之后将Src\linkkit
里所有子目录下的.c
文件添加进去,最后选择Project > options,添加以下依赖的头文件路径。
# 设置头文件路径,请以实际路径为准
$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
编译、烧录流程如下:
在IAR工程下添加
.c
文件:在IAR工程下设置头文件路径:
完成编译:
结果
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='a1A******rT.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/a1A******rT/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/a1A******rT/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 '/a1A******rT/test_device/get' (msgId=3)
Packet Ident : 00000003
Topic : /a1A******rT/test_device/get
QoS : 0
Packet Length : 35
[10:44:23.861]收←◆mqtt subscribe packet sent,topic = /a1A******rT/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 : /a1A******rT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A******rT/test_device/get
Payload: hello,world
[10:44:46.408]收←◆PUBLISH
Packet Ident : 00000000
Topic Length : 28
Topic Name : /a1A******rT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A******rT/test_device/get
Payload: hello,world
[10:45:07.348]收←◆PUBLISH
Packet Ident : 00000000
Topic Length : 28
Topic Name : /a1A******rT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A******rT/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 : /a1A******rT/test_device/get
Payload Len/Room : 11 / 992
Receive Buflen : 1024
delivering msg ...
topic be matched
Message Arrived:
Topic : /a1A******rT/test_device/get
Payload: hello,world