初学者
10 分钟

使用LENA-R8和STM32G071RB实现全球连接和精确位置跟踪

适用于针对跟踪和远程信息处理领域的开发者

4G LTE&GNSS Click with Nucleo 64 with STM32G071RB MCU

已发布 10月 08, 2024

点击板

4G LTE&GNSS Click

开发板

Nucleo 64 with STM32G071RB MCU

编译器

NECTO Studio

微控制器单元

STM32G071RB

通过 LENA-R8 对 14 个 LTE 频段、四个 GSM/GPRS 频段以及集成的 u-blox GNSS 技术的支持,实现全球范围内的连接和精准的全球追踪能力。

A

A

硬件概览

它是如何工作的?

4G LTE&GNSS Click 基于 LENA-R8 (LENA-R8001M10-00C),这是来自 Trasna 的多模式 LTE Cat 1bis 模块,具有广泛的网络支持。该蜂窝模块拥有 14 个 LTE 频段和 4 个 GSM/GPRS 频段,提供全球网络连接和全面覆盖。其集成的 Trasna GNSS 功能使其成为全球跟踪和车队管理应用的首选,确保高精度和可靠性。LENA-R8 的连接和定位服务能力简化了设备在基于云的生态系统中的部署,提供了连接即服务 (CaaS) 和定位即服务 (LaaS) 的流线型解决方案。这使其成为开发人员在不牺牲 GNSS 性能或全球可访问性的情况下,创建更小更高效解决方案的宝贵组件。除了全球 LTE Cat 1bis 连接,LENA-R8 在支持广泛的物联网 (IoT) 应用方面表现出色,特别是在跟踪和车队管理领域。其对广泛的 LTE 和 2G 频段的兼容性确保了不同地理区域的最佳漫游覆盖,使物联网设备可以通过单一产品 SKU 实现真正的全球覆盖。该模块的高度集成包括对 Thingstream 平台上的 MQTT Anywhere 服务的支持,增强了其在全球无缝漫游中的实用性。它还具有最多支持四个 GNSS 系统(GPS、GLONASS、Galileo 和北斗)的并发接收能力,默认配置为 GPS 和 Galileo。该多功能性,结合蜂窝调制解调器和 GNSS 子系统的专用接口,允许独立操作和灵活使用,优化性能和功率效率。LENA-R8 支持 CellLocate,这是一种基于网络的位置服务,进一步突显了其在各种高性能、位置依赖应用中的多用途性和适用性。LENA-R8 通过 UART 接口

与主 MCU 通信,使用常用的 UART RX 和 TX 引脚以及硬件流控制引脚 UART CTS、RTS、RI(Clear to Send、Ready to Send 和 Ring Indicator),默认配置为 115200 bps 以传输和交换数据。除了 UART 引脚外,此 Click board™ 还使用 RST 引脚作为 LENA-R8 的硬件复位,此复位将在不存储当前参数设置的情况下进行,并进行干净的网络分离。LENA-R8 还包括一个符合 USB High-Speed 2.0 标准的接口,最大数据速率为 480 Mbit/s。模块本身作为 USB 设备,可以连接到任何兼容的 USB 主机。该接口可用于与外部主机应用处理器(AT 命令、数据、通过 FOAT 进行的固件更新)、通过专用工具进行的固件更新和诊断。此外,电路板背面有一个 USB BOOT 跳线,允许您选择启动模式。将其置于位置 1 时,启用通过 USB 接口的专用工具进行的固件更新,置于位置 0 时为正常操作模式启动。除了用于手动激活的集成电源 (PWR) 按钮外,LENA-R8 模块还可以通过外部 PWR 引脚供电。此外,模块有两个不同的 LED 指示灯,以视觉方式传达关键的操作状态信息。标有 NI 的黄色 LED 作为网络状态指示灯,提供关于模块网络连接状态的即时反馈,这对于故障排除和确认网络集成成功至关重要。同样,标有 TP 的红色 LED 作为时间脉冲指示灯,发出精确信号以表示时间同步事件,这对于需要高时间精度的应用(如时间敏感的数据收集或基于 GPS 的定位)特别有益。电路板配有 u.Fl 连接器,用于 LTE 和 GNSS 天线,配合 IPEX-SMA 电

缆以实现灵活高效的连接选项。此设置确保了本地和卫星通信的最佳信号强度和质量。值得注意的是,GNSS 天线连接包括电源选择功能,允许用户根据具体需求调整天线的电源供应,增强卫星导航的精度和可靠性。此外,电路板配备一个 nano SIM 卡座,支持 1.8V 和 3.0V SIM 卡,确保与各种蜂窝网络的兼容性,并允许用户根据特定用例选择最合适的服务提供商。此 Click board™ 还使用德州仪器的 TPS7A7002 低压差稳压器 (LDO) 生成模块优化操作所需的 3.8V 电源。该电源来自 5V mikroBUS™ 电源轨或可用的 USB 连接,确保电源来源的多样性。电路板有多个测试点,用于进一步的诊断和操作调整。TP1 专用于诊断模块的内部条件,当模块的蜂窝组件激活时,提供典型输出为 1.8V。这允许实时监控模块的电源状态。TP2 具有与 PWR 引脚相同的功能,TP3 为复位,TP4 为 USB Boot。TP5 和 TP6 连接 GNSS UART,启用内部 Trasna M10 GNSS 芯片组与外部主机之间的串行通信。此功能允许 GNSS 模块与主设备之间的直接数据交换和配置,增强了模块在 GNSS 应用中的功能和灵活性。此 Click board™ 可以通过 VCC SEL 跳线选择使用 3.3V 或 5V 逻辑电压电平。这样,3.3V 和 5V 兼容的 MCU 都可以正确使用通信线路。此外,此 Click board™ 配备了一个包含易于使用的功能和示例代码的库,可用作进一步开发的参考。

4G LTE&GNSS Click hardware overview image

功能概述

开发板

Nucleo-64 搭载 STM32G071RB MCU 提供了一种经济高效且灵活的平台,供开发者探索新想法并原型设计他们的项目。该板利用 STM32 微控制器的多功能性,使用户能够为他们的项目选择最佳的性能与功耗平衡。它配备了 LQFP64 封装的 STM32 微控制器,并包含了如用户 LED(同时作为 ARDUINO® 信号)、用户和复位按钮,以及 32.768kHz 晶体振荡器用于精确的计时操作等基本组件。Nucleo-64 板设计考虑到扩展性和灵活性,它特有的 ARDUINO® Uno

V3 扩展连接器和 ST morpho 扩展引脚头,提供了对 STM32 I/O 的完全访问,以实现全面的项目整合。电源供应选项灵活,支持 ST-LINK USB VBUS 或外部电源,确保在各种开发环境中的适应性。该板还配备了一个具有 USB 重枚举功能的板载 ST-LINK 调试器/编程器,简化了编程和调试过程。此外,该板设计旨在简化高级开发,它的外部 SMPS 为 Vcore 逻辑供电提供高效支持,支持 USB 设备全速或 USB SNK/UFP 全速,并内置加密功能,提升了项目的功效

和安全性。通过外部 SMPS 实验的专用连接器、 用于 ST-LINK 的 USB 连接器以及 MIPI® 调试连接器,提供了更多的硬件接口和实验可能性。开发者将通过 STM32Cube MCU Package 提供的全面免费软件库和示例得到广泛支持。这些,加上与多种集成开发环境(IDE)的兼容性,包括 IAR Embedded Workbench®、MDK-ARM 和 STM32CubeIDE,确保了流畅且高效的开发体验,使用户能够充分利用 Nucleo-64 板在他们的项目中的能力。

Nucleo 64 with STM32G071RB MCU double side image

微控制器概述 

MCU卡片 / MCU

default

建筑

ARM Cortex-M0

MCU 内存 (KB)

128

硅供应商

STMicroelectronics

引脚数

64

RAM (字节)

36864

你完善了我!

配件

Click Shield for Nucleo-64 配备了两个专有的 mikroBUS™ 插座,使得所有的 Click board™ 设备都可以轻松地与 STM32 Nucleo-64 开发板连接。这样,Mikroe 允许其用户从不断增长的 Click boards™ 范围中添加任何功能,如 WiFi、GSM、GPS、蓝牙、ZigBee、环境传感器、LED、语音识别、电机控制、运动传感器等。您可以使用超过 1537 个 Click boards™,这些 Click boards™ 可以堆叠和集成。STM32 Nucleo-64 开发板基于 64 引脚封装的微控制器,采用 32 位 MCU,配备 ARM Cortex M4 处理器,运行速度为 84MHz,具有 512Kb Flash 和 96KB SRAM,分为两个区域,顶部区域代表 ST-Link/V2 调试器和编程器,而底部区域是一个实际的开发板。通过 USB 连接方便地控制和供电这些板子,以便直接对 Nucleo-64 开发板进行编程和高效调试,其中还需要额外的 USB 线连接到板子上的 USB 迷你接口。大多数 STM32 微控制器引脚都连接到了板子左右边缘的 IO 引脚上,然后连接到两个现有的 mikroBUS™ 插座上。该 Click Shield 还有几个开关,用于选择 mikroBUS™ 插座上模拟信号的逻辑电平和 mikroBUS™ 插座本身的逻辑电压电平。此外,用户还可以通过现有的双向电平转换器,使用任何 Click board™,无论 Click board™ 是否在 3.3V 或 5V 逻辑电压电平下运行。一旦将 STM32 Nucleo-64 开发板与我们的 Click Shield for Nucleo-64 连接,您就可以访问数百个工作于 3.3V 或 5V 逻辑电压电平的 Click boards™。

Click Shield for Nucleo-64 accessories 1 image

LTE Flat Rotation Antenna 是增强 3G/4G LTE 设备性能的多功能选择。凭借 700-2700MHz 的宽频率范围,它确保在全球主要蜂窝频段上的最佳连接。该平板天线采用 SMA 公头连接器,便于直接连接到设备或 SMA 模块连接器。其亮点之一是可调角度,可按 45⁰ 增量(0⁰/45⁰/90⁰)设置,允许您微调天线的方向以获得最佳信号接收。具有 50Ω 阻抗和 <2.0:1 的电压驻波比 (VSWR),此天线确保可靠高效的连接。其 5dB 增益、垂直极化和全向辐射图形增强了信号强度,适用于各种应用。天线长度为 196mm,宽度为 38mm,提供紧凑但有效的解决方案来改善您的连接。最大输入功率为 50W,能够满足各种设备的需求。

4G LTE&GNSS Click accessories 1 image

GNSS Active External Antenna 是来自 u-blox 的独特多频段天线,非常适合需要高精度定位功能(如 RTK)的高精度 GNSS 应用。ANN-MB-00 是一款多频段(L1、L2/E5b/B2I)有源 GNSS 天线,配有 5 米电缆和 SMA 连接器。该天线支持 GPS、GLONASS、Galileo 和北斗系统,包含高性能多频段 RHCP 双馈补丁天线元件、内置高增益 LNA 和 SAW 预过滤器、5 米天线电缆和 SMA 连接器,并且防水。

4G LTE&GNSS Click accessories 2 image

IPEX-SMA 电缆是一种射频 (RF) 电缆组件。"IPEX" 指的是 IPEX 连接器,这是一种常用于小型电子设备的微型同轴连接器。"SMA" 代表 SubMiniature Version A,是另一种常用于射频应用的同轴连接器。IPEX-SMA 电缆组件的一端是 IPEX 连接器,另一端是 SMA 连接器,使其能够连接使用这些特定连接器的设备或组件。这些电缆常用于 WiFi 或蜂窝天线、GPS 模块以及其他需要可靠且低损耗连接的射频通信系统。

4G LTE&GNSS Click accessories 3 image

使用的MCU引脚

mikroBUS™映射器

Module Power-ON
PC0
AN
Reset / ID SEL
PC12
RST
UART RTS / ID COMM
PB12
CS
NC
NC
SCK
NC
NC
MISO
NC
NC
MOSI
Power Supply
3.3V
3.3V
Ground
GND
GND
Ring Indicator
PC8
PWM
UART CTS
PC14
INT
UART TX
PA2
TX
UART RX
PA3
RX
NC
NC
SCL
NC
NC
SDA
Power Supply
5V
5V
Ground
GND
GND
1

“仔细看看!”

Click board™ 原理图

4G LTE&GNSS Click Schematic schematic

一步一步来

项目组装

Click Shield for Nucleo-64 accessories 1 image hardware assembly

从选择您的开发板和Click板™开始。以Nucleo 64 with STM32G071RB MCU作为您的开发板开始。

Click Shield for Nucleo-64 accessories 1 image hardware assembly
Nucleo 64 with STM32F401RE MCU front image hardware assembly
LTE IoT 5 Click front image hardware assembly
Prog-cut hardware assembly
LTE IoT 5 Click complete accessories setup image hardware assembly
Board mapper by product8 hardware assembly
Necto image step 2 hardware assembly
Necto image step 3 hardware assembly
Necto image step 4 hardware assembly
Necto image step 5 hardware assembly
Necto image step 6 hardware assembly
Clicker 4 for STM32F4 HA MCU Step hardware assembly
Necto No Display image step 8 hardware assembly
Necto image step 9 hardware assembly
Necto image step 10 hardware assembly
Debug Image Necto Step hardware assembly

软件支持

库描述

该库包含 4G LTE&GNSS Click 驱动程序的 API。

关键功能:

  • c4gltegnss_set_sim_apn - 此函数设置 SIM 卡的 APN。

  • c4gltegnss_send_sms_text - 此函数向电话号码发送短信。

  • c4gltegnss_parse_gga - 此函数解析从读取响应缓冲区中的 GGA 数据。

开源

代码示例

完整的应用程序代码和一个现成的项目可以通过NECTO Studio包管理器直接安装到NECTO Studio 应用程序代码也可以在MIKROE的GitHub账户中找到。

/*!
 * @file main.c
 * @brief 4G LTE GNSS Click Example.
 *
 * # Description
 * Application example shows device capability of connecting to the network and
 * sending SMS or TCP/UDP messages, or retrieving data from GNSS using standard "AT" commands.
 *
 * The demo application is composed of two sections :
 *
 * ## Application Init
 * Initializes the driver, restarts the device, and after that tests the communication by sending "AT" command.
 *
 * ## Application Task
 * Application task is split in few stages:
 *  - C4GLTEGNSS_CONFIGURE_FOR_NETWORK:
 * Sets configuration to device to be able to connect to the network (used only for SMS or TCP/UDP demo examples).
 *
 *  - C4GLTEGNSS_WAIT_FOR_CONNECTION:
 * Waits for the network registration indicated via CREG URC event and then checks
 * the connection status (used only for SMS or TCP/UDP demo examples).
 *
 *  - C4GLTEGNSS_CONFIGURE_FOR_EXAMPLE:
 * Sets the device configuration for sending SMS or TCP/UDP messages or for retrieving data from GNSS 
 * depending on the selected demo example.
 *
 *  - C4GLTEGNSS_EXAMPLE:
 * Depending on the selected demo example, it sends an SMS message (in PDU or TXT mode) or TCP/UDP message or 
 * waits for the GPS fix to retrieve location info from GNSS.
 *
 * By default, the TCP/UDP example is selected.
 *
 * ## Additional Function
 * - static void c4gltegnss_clear_app_buf ( void )
 * - static void c4gltegnss_log_app_buf ( void )
 * - static err_t c4gltegnss_process ( void )
 * - static void c4gltegnss_error_check ( err_t error_flag )
 * - static err_t c4gltegnss_rsp_check ( uint8_t *rsp )
 * - static err_t c4gltegnss_config_for_network ( void )
 * - static err_t c4gltegnss_check_connection ( void )
 * - static err_t c4gltegnss_config_for_example ( void )
 * - static err_t c4gltegnss_example ( void )
 *
 * @note
 * In order for the examples to work (except GNSS example), user needs to set the APN and SMSC (SMS PDU mode only)
 * of entered SIM card as well as the phone number (SMS mode only) to which he wants to send an SMS.
 * Enter valid values for the following macros: SIM_APN, SIM_SMSC and PHONE_NUMBER_TO_MESSAGE.
 * Example:
    SIM_APN "internet"
    SIM_SMSC "+381610401"
    PHONE_NUMBER_TO_MESSAGE "+381659999999"
 *
 * @author Stefan Filipovic
 *
 */

#include "board.h"
#include "log.h"
#include "c4gltegnss.h"
#include "conversions.h"

// Example selection macros
#define EXAMPLE_TCP_UDP                     0               // Example of sending messages to a TCP/UDP echo server
#define EXAMPLE_SMS                         1               // Example of sending SMS to a phone number
#define EXAMPLE_GNSS                        2               // Example of retrieving location info from GNSS
#define DEMO_EXAMPLE                        EXAMPLE_TCP_UDP // Example selection macro

// SIM APN config
#define SIM_APN                             "internet"      // Set valid SIM APN

// SMS example parameters
#define SIM_SMSC                            ""              // Set valid SMS Service Center Address - only in SMS PDU mode
#define PHONE_NUMBER_TO_MESSAGE             ""              // Set Phone number to message
#define SMS_MODE                            "1"             // SMS mode: "0" - PDU, "1" - TXT

// TCP/UDP example parameters
#define REMOTE_IP                           "77.46.162.162" // TCP/UDP echo server IP address
#define REMOTE_PORT                         "51111"         // TCP/UDP echo server port

// Message content
#define MESSAGE_CONTENT                     "4G LTE GNSS Click board - demo example."

// Application buffer size
#define APP_BUFFER_SIZE                     256
#define PROCESS_BUFFER_SIZE                 256

/**
 * @brief Example states.
 * @details Predefined enum values for application example state.
 */
typedef enum
{
    C4GLTEGNSS_CONFIGURE_FOR_NETWORK = 1,
    C4GLTEGNSS_WAIT_FOR_CONNECTION,
    C4GLTEGNSS_CONFIGURE_FOR_EXAMPLE,
    C4GLTEGNSS_EXAMPLE

} c4gltegnss_example_state_t;

static c4gltegnss_t c4gltegnss;
static log_t logger;

/**
 * @brief Application example variables.
 * @details Variables used in application example.
 */
static uint8_t app_buf[ APP_BUFFER_SIZE ] = { 0 };
static int32_t app_buf_len = 0;
static err_t error_flag = C4GLTEGNSS_OK;
static c4gltegnss_example_state_t example_state;

/**
 * @brief 4G LTE GNSS clearing application buffer.
 * @details This function clears memory of application buffer and reset its length.
 * @note None.
 */
static void c4gltegnss_clear_app_buf ( void );

/**
 * @brief 4G LTE GNSS log application buffer.
 * @details This function logs data from application buffer to USB UART.
 * @note None.
 */
static void c4gltegnss_log_app_buf ( void );

/**
 * @brief 4G LTE GNSS data reading function.
 * @details This function reads data from device and concatenates data to application buffer. 
 * @return @li @c  0 - Read some data.
 *         @li @c -1 - Nothing is read.
 * See #err_t definition for detailed explanation.
 * @note None.
 */
static err_t c4gltegnss_process ( void );

/**
 * @brief Check for errors.
 * @details This function checks for different types of
 * errors and logs them on UART or logs the response if no errors occured.
 * @param[in] error_flag  Error flag to check.
 */
static void c4gltegnss_error_check ( err_t error_flag );

/**
 * @brief Response check.
 * @details This function checks for response and
 * returns the status of response.
 * @param[in] rsp  Expected response.
 * @return @li @c  0 - OK response.
 *         @li @c -2 - Timeout error.
 *         @li @c -3 - Command error.
 *         @li @c -4 - Unknown error.
 * See #err_t definition for detailed explanation.
 */
static err_t c4gltegnss_rsp_check ( uint8_t *rsp );

/**
 * @brief Configure device for connection to the network.
 * @details Sends commands to configure and enable
 * connection to the specified network.
 * @return @li @c  0 - OK response.
 *         @li @c -2 - Timeout error.
 *         @li @c -3 - Command error.
 *         @li @c -4 - Unknown error.
 * See #err_t definition for detailed explanation.
 */
static err_t c4gltegnss_config_for_network ( void );

/**
 * @brief Wait for connection signal.
 * @details Wait for connection signal from CREG URC.
 * @return @li @c  0 - OK response.
 *         @li @c -2 - Timeout error.
 *         @li @c -3 - Command error.
 *         @li @c -4 - Unknown error.
 * See #err_t definition for detailed explanation.
 */
static err_t c4gltegnss_check_connection ( void );

/**
 * @brief Configure device for example.
 * @details Configure device for the specified example.
 * @return @li @c  0 - OK response.
 *         @li @c -2 - Timeout error.
 *         @li @c -3 - Command error.
 *         @li @c -4 - Unknown error.
 * See #err_t definition for detailed explanation.
 */
static err_t c4gltegnss_config_for_example ( void );

/**
 * @brief Execute example.
 * @details This function executes SMS, TCP/UDP or GNSS example depending on the DEMO_EXAMPLE macro.
 * @return @li @c  0 - OK response.
 *         @li @c -2 - Timeout error.
 *         @li @c -3 - Command error.
 *         @li @c -4 - Unknown error.
 * See #err_t definition for detailed explanation.
 */
static err_t c4gltegnss_example ( void );

void application_init ( void ) 
{
    log_cfg_t log_cfg;  /**< Logger config object. */
    c4gltegnss_cfg_t c4gltegnss_cfg;  /**< Click config object. */

    /** 
     * Logger initialization.
     * Default baud rate: 115200
     * Default log level: LOG_LEVEL_DEBUG
     * @note If USB_UART_RX and USB_UART_TX 
     * are defined as HAL_PIN_NC, you will 
     * need to define them manually for log to work. 
     * See @b LOG_MAP_USB_UART macro definition for detailed explanation.
     */
    LOG_MAP_USB_UART( log_cfg );
    log_init( &logger, &log_cfg );
    log_info( &logger, " Application Init " );

    // Click initialization.
    c4gltegnss_cfg_setup( &c4gltegnss_cfg );
    C4GLTEGNSS_MAP_MIKROBUS( c4gltegnss_cfg, MIKROBUS_1 );
    if ( UART_ERROR == c4gltegnss_init( &c4gltegnss, &c4gltegnss_cfg ) ) 
    {
        log_error( &logger, " Communication init." );
        for ( ; ; );
    }
    // Power cycle device
    c4gltegnss_set_power_state ( &c4gltegnss, C4GLTEGNSS_POWER_STATE_OFF );
    c4gltegnss_set_power_state ( &c4gltegnss, C4GLTEGNSS_POWER_STATE_ON );
    
    // Dummy write to activate AT commands interface
    c4gltegnss_send_cmd( &c4gltegnss, C4GLTEGNSS_CMD_AT );
    c4gltegnss_process( );
    c4gltegnss_clear_app_buf( );
    
    // Check communication
    c4gltegnss_send_cmd( &c4gltegnss, C4GLTEGNSS_CMD_AT );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    c4gltegnss_error_check( error_flag );
    
    log_info( &logger, " Application Task " );
    example_state = C4GLTEGNSS_CONFIGURE_FOR_NETWORK;
}

void application_task ( void ) 
{
    switch ( example_state )
    {
        case C4GLTEGNSS_CONFIGURE_FOR_NETWORK:
        {
            if ( C4GLTEGNSS_OK == c4gltegnss_config_for_network( ) )
            {
                example_state = C4GLTEGNSS_WAIT_FOR_CONNECTION;
            }
            break;
        }
        case C4GLTEGNSS_WAIT_FOR_CONNECTION:
        {
            if ( C4GLTEGNSS_OK == c4gltegnss_check_connection( ) )
            {
                example_state = C4GLTEGNSS_CONFIGURE_FOR_EXAMPLE;
            }
            break;
        }
        case C4GLTEGNSS_CONFIGURE_FOR_EXAMPLE:
        {
            if ( C4GLTEGNSS_OK == c4gltegnss_config_for_example( ) )
            {
                example_state = C4GLTEGNSS_EXAMPLE;
            }
            break;
        }
        case C4GLTEGNSS_EXAMPLE:
        {
            c4gltegnss_example( );
            break;
        }
        default:
        {
            log_error( &logger, " Example state." );
            break;
        }
    }
}

int main ( void ) 
{
    /* Do not remove this line or clock might not be set correctly. */
    #ifdef PREINIT_SUPPORTED
    preinit();
    #endif
    
    application_init( );
    
    for ( ; ; ) 
    {
        application_task( );
    }

    return 0;
}

static void c4gltegnss_clear_app_buf ( void ) 
{
    memset( app_buf, 0, app_buf_len );
    app_buf_len = 0;
}

static void c4gltegnss_log_app_buf ( void )
{
    for ( int32_t buf_cnt = 0; buf_cnt < app_buf_len; buf_cnt++ )
    {
        log_printf( &logger, "%c", app_buf[ buf_cnt ] );
    }
}

static err_t c4gltegnss_process ( void ) 
{
    uint8_t rx_buf[ PROCESS_BUFFER_SIZE ] = { 0 };
    int32_t overflow_bytes = 0;
    int32_t rx_cnt = 0;
    int32_t rx_size = c4gltegnss_generic_read( &c4gltegnss, rx_buf, PROCESS_BUFFER_SIZE );
    if ( ( rx_size > 0 ) && ( rx_size <= APP_BUFFER_SIZE ) ) 
    {
        if ( ( app_buf_len + rx_size ) > APP_BUFFER_SIZE ) 
        {
            overflow_bytes = ( app_buf_len + rx_size ) - APP_BUFFER_SIZE;
            app_buf_len = APP_BUFFER_SIZE - rx_size;
            memmove ( app_buf, &app_buf[ overflow_bytes ], app_buf_len );
            memset ( &app_buf[ app_buf_len ], 0, overflow_bytes );
        }
        for ( rx_cnt = 0; rx_cnt < rx_size; rx_cnt++ ) 
        {
            if ( rx_buf[ rx_cnt ] ) 
            {
                app_buf[ app_buf_len++ ] = rx_buf[ rx_cnt ];
            }
        }
        return C4GLTEGNSS_OK;
    }
    return C4GLTEGNSS_ERROR;
}

static err_t c4gltegnss_rsp_check ( uint8_t *rsp )
{
    uint32_t timeout_cnt = 0;
    uint32_t timeout = 120000;
    c4gltegnss_clear_app_buf( );
    c4gltegnss_process( );
    while ( ( 0 == strstr( app_buf, rsp ) ) &&
            ( 0 == strstr( app_buf, C4GLTEGNSS_RSP_ERROR ) ) )
    {
        c4gltegnss_process( );
        if ( timeout_cnt++ > timeout )
        {
            c4gltegnss_clear_app_buf( );
            return C4GLTEGNSS_ERROR_TIMEOUT;
        }
        Delay_ms ( 1 );
    }
    Delay_ms ( 100 );
    c4gltegnss_process( );
    if ( strstr( app_buf, rsp ) )
    {
        return C4GLTEGNSS_OK;
    }
    else if ( strstr( app_buf, C4GLTEGNSS_RSP_ERROR ) )
    {
        return C4GLTEGNSS_ERROR_CMD;
    }
    else
    {
        return C4GLTEGNSS_ERROR_UNKNOWN;
    }
}

static void c4gltegnss_error_check ( err_t error_flag )
{
    switch ( error_flag )
    {
        case C4GLTEGNSS_OK:
        {
            c4gltegnss_log_app_buf( );
            break;
        }
        case C4GLTEGNSS_ERROR:
        {
            log_error( &logger, " Overflow!" );
            break;
        }
        case C4GLTEGNSS_ERROR_TIMEOUT:
        {
            log_error( &logger, " Timeout!" );
            break;
        }
        case C4GLTEGNSS_ERROR_CMD:
        {
            log_error( &logger, " CMD!" );
            break;
        }
        case C4GLTEGNSS_ERROR_UNKNOWN:
        default:
        {
            log_error( &logger, " Unknown!" );
            break;
        }
    }
    Delay_ms ( 500 );
}

static err_t c4gltegnss_config_for_network ( void )
{
    err_t func_error = C4GLTEGNSS_OK;
#if ( ( DEMO_EXAMPLE == EXAMPLE_TCP_UDP ) || ( DEMO_EXAMPLE == EXAMPLE_SMS ) )
    // Set SIM APN
    c4gltegnss_set_sim_apn( &c4gltegnss, SIM_APN );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );

    // Enable full functionality
    #define FULL_FUNCTIONALITY "1"
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_CFUN, FULL_FUNCTIONALITY );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );

    // Enable network registartion
    #define ENABLE_REG "2"
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_CREG, ENABLE_REG );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );
    
    // Automatic registration
    #define AUTOMATIC_REGISTRATION "0"
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_COPS, AUTOMATIC_REGISTRATION );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
#endif
    return func_error;
}

static err_t c4gltegnss_check_connection ( void )
{
#if ( ( DEMO_EXAMPLE == EXAMPLE_TCP_UDP ) || ( DEMO_EXAMPLE == EXAMPLE_SMS ) )
    #define CONNECTED "+CREG: 1"
    c4gltegnss_process( );
    if ( strstr( app_buf, CONNECTED ) )
    {
        Delay_ms ( 100 );
        c4gltegnss_process( );
        c4gltegnss_log_app_buf( );
        log_printf( &logger, "\r\n" );
        c4gltegnss_clear_app_buf( );
        // Check signal quality
        c4gltegnss_send_cmd( &c4gltegnss, C4GLTEGNSS_CMD_CSQ );
        error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
        c4gltegnss_error_check( error_flag );
        return error_flag;
    }
    return C4GLTEGNSS_ERROR;
#endif
    return C4GLTEGNSS_OK;
}

static err_t c4gltegnss_config_for_example( void )
{
    err_t func_error = C4GLTEGNSS_OK;
#if ( DEMO_EXAMPLE == EXAMPLE_TCP_UDP )
    #define ACTIVATE_PDP_CONTEXT "1,1"
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_CGACT, ACTIVATE_PDP_CONTEXT );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );
#elif ( DEMO_EXAMPLE == EXAMPLE_SMS )
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_CMGF, SMS_MODE );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );
#elif ( DEMO_EXAMPLE == EXAMPLE_GNSS )
    c4gltegnss_send_cmd_check( &c4gltegnss, C4GLTEGNSS_CMD_UGPS );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    #define GPS_POWERED_OFF "+UGPS: 0"
    if ( strstr( app_buf, GPS_POWERED_OFF ) )
    {
        c4gltegnss_error_check( error_flag );
        #define ENABLE_GPS "1,0,1"
        c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_UGPS, ENABLE_GPS );
        error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
        func_error |= error_flag;
        c4gltegnss_error_check( error_flag );
        Delay_ms ( 1000 );
    }
    #define ENABLE_NMEA_GGA "1"
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_UGGGA, ENABLE_NMEA_GGA );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );
#else
    #error "No demo example selected"
#endif
    return func_error;
}

static err_t c4gltegnss_example( void )
{
    err_t func_error = C4GLTEGNSS_OK;
#if ( DEMO_EXAMPLE == EXAMPLE_TCP_UDP )
    uint8_t cmd_buf[ 100 ] = { 0 };
    uint8_t urc_buf[ 20 ] = { 0 };
    uint16_t timeout_cnt = 0;
    uint16_t timeout = 30000;
    uint8_t * __generic_ptr socket_num_buf = 0;
    uint8_t tcp_socket_num[ 2 ] = { 0 };
    uint8_t udp_socket_num[ 2 ] = { 0 };

    // Create TCP socket
    #define RSP_USOCR "+USOCR:"
    #define TCP_PROTOCOL "6"
    c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USOCR, TCP_PROTOCOL );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    socket_num_buf = strstr( app_buf, RSP_USOCR ) + strlen ( RSP_USOCR );
    tcp_socket_num[ 0 ] = *socket_num_buf;
    c4gltegnss_error_check( error_flag );

    // Create UDP socket
    #define UDP_PROTOCOL "17"
    c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USOCR, UDP_PROTOCOL );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    socket_num_buf = strstr( app_buf, RSP_USOCR ) + strlen ( RSP_USOCR );
    udp_socket_num[ 0 ] = *socket_num_buf;
    c4gltegnss_error_check( error_flag );

    // Connect TCP socket to remote IP and port
    strcpy( cmd_buf, tcp_socket_num );
    strcat( cmd_buf, ",\"" );
    strcat( cmd_buf, REMOTE_IP );
    strcat( cmd_buf, "\"," );
    strcat( cmd_buf, REMOTE_PORT );
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_USOCO, cmd_buf );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );

    // Connect UDP socket to remote IP and port
    #define ASYNC_CONNECT "1"
    strcpy( cmd_buf, udp_socket_num );
    strcat( cmd_buf, ",\"" );
    strcat( cmd_buf, REMOTE_IP );
    strcat( cmd_buf, "\"," );
    strcat( cmd_buf, REMOTE_PORT );
    strcat( cmd_buf, "," );
    strcat( cmd_buf, ASYNC_CONNECT );
    c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USOCO, cmd_buf );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );

    // Get message length
    uint8_t message_len_buf[ 5 ] = { 0 };
    uint16_t message_len = strlen( MESSAGE_CONTENT );
    uint16_to_str( message_len, message_len_buf );
    l_trim( message_len_buf );
    r_trim( message_len_buf );

    // Write message to TCP socket
    strcpy( cmd_buf, tcp_socket_num );
    strcat( cmd_buf, "," );
    strcat( cmd_buf, message_len_buf );
    strcat( cmd_buf, ",\"" );
    strcat( cmd_buf, MESSAGE_CONTENT );
    strcat( cmd_buf, "\"" );
    c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USOWR, cmd_buf );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );

    // Read response message from TCP socket
    #define URC_READ_SOCKET_DATA_TCP "+UUSORD:"
    strcpy( urc_buf, URC_READ_SOCKET_DATA_TCP );
    strcat( urc_buf, tcp_socket_num );
    for ( ; ; )
    {
        c4gltegnss_process( );
        uint8_t * __generic_ptr start_response_buf = strstr( app_buf, urc_buf );
        if ( start_response_buf )
        {
            Delay_ms ( 100 );
            c4gltegnss_process( );
            uint8_t response_len_buf[ 5 ] = { 0 };
            uint8_t * __generic_ptr start_response_len = strstr( start_response_buf, "," ) + 1;
            memcpy ( response_len_buf, start_response_len, app_buf_len - ( start_response_len - app_buf ) );
            strcpy( cmd_buf, tcp_socket_num );
            strcat( cmd_buf, "," );
            strcat( cmd_buf, response_len_buf );
            c4gltegnss_log_app_buf( );
            c4gltegnss_clear_app_buf( );
            c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USORD, cmd_buf );
            error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
            func_error |= error_flag;
            c4gltegnss_error_check( error_flag );
            break;
        }
        if ( timeout_cnt++ > timeout )
        {
            break;
        }
        Delay_ms ( 1 );
    }
    timeout_cnt = 0;

    // Write message to UDP socket
    strcpy( cmd_buf, udp_socket_num );
    strcat( cmd_buf, "," );
    strcat( cmd_buf, message_len_buf );
    strcat( cmd_buf, ",\"" );
    strcat( cmd_buf, MESSAGE_CONTENT );
    strcat( cmd_buf, "\"" );
    c4gltegnss_send_cmd_with_par( &c4gltegnss, C4GLTEGNSS_CMD_USOWR, cmd_buf );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );

    // Read response message from UDP socket
    #define URC_READ_SOCKET_DATA_UDP "+UUSORF:"
    strcpy( urc_buf, URC_READ_SOCKET_DATA_UDP );
    strcat( urc_buf, udp_socket_num );
    for ( ; ; )
    {
        c4gltegnss_process( );
        uint8_t * __generic_ptr start_response_buf = strstr( app_buf, urc_buf );
        if ( start_response_buf )
        {
            Delay_ms ( 100 );
            c4gltegnss_process( );
            uint8_t response_len_buf[ 5 ] = { 0 };
            uint8_t * __generic_ptr start_response_len = strstr( start_response_buf, "," ) + 1;
            memcpy ( response_len_buf, start_response_len, app_buf_len - ( start_response_len - app_buf ) );
            strcpy( cmd_buf, udp_socket_num );
            strcat( cmd_buf, "," );
            strcat( cmd_buf, response_len_buf );
            c4gltegnss_log_app_buf( );
            c4gltegnss_clear_app_buf( );
            c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USORF, cmd_buf );
            error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
            func_error |= error_flag;
            c4gltegnss_error_check( error_flag );
            break;
        }
        if ( timeout_cnt++ > timeout )
        {
            break;
        }
        Delay_ms ( 1 );
    }
    
    // Close TCP socket
    c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USOCL, tcp_socket_num );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );
    
    // Close UDP socket
    c4gltegnss_send_cmd_with_par ( &c4gltegnss, C4GLTEGNSS_CMD_USOCL, udp_socket_num );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
#elif ( DEMO_EXAMPLE == EXAMPLE_SMS )
    // Check SMS mode
    #define CMGF_PDU "+CMGF: 0"
    #define CMGF_TXT "+CMGF: 1"
    c4gltegnss_send_cmd_check( &c4gltegnss, C4GLTEGNSS_CMD_CMGF );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    c4gltegnss_error_check( error_flag );
    if ( strstr( app_buf, CMGF_PDU ) )
    {
        // Send SMS in PDU mode
        c4gltegnss_send_sms_pdu( &c4gltegnss, SIM_SMSC, PHONE_NUMBER_TO_MESSAGE, MESSAGE_CONTENT );
        error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
        func_error |= error_flag;
        c4gltegnss_error_check( error_flag );
    }
    else if ( strstr( app_buf, CMGF_TXT ) )
    {
        // Send SMS in TXT mode
        c4gltegnss_send_sms_text ( &c4gltegnss, PHONE_NUMBER_TO_MESSAGE, MESSAGE_CONTENT );
        error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
        func_error |= error_flag;
        c4gltegnss_error_check( error_flag );
    }
    // 30 seconds delay
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
    Delay_ms ( 1000 );
#elif ( DEMO_EXAMPLE == EXAMPLE_GNSS )
    c4gltegnss_send_cmd_check( &c4gltegnss, C4GLTEGNSS_CMD_UGGGA );
    error_flag = c4gltegnss_rsp_check( C4GLTEGNSS_RSP_OK );
    func_error |= error_flag;
    if ( app_buf_len > ( sizeof ( C4GLTEGNSS_RSP_GGA ) + C4GLTEGNSS_GGA_ELEMENT_SIZE ) ) 
    {
        uint8_t element_buf[ 100 ] = { 0 };
        if ( C4GLTEGNSS_OK == c4gltegnss_parse_gga( app_buf, C4GLTEGNSS_GGA_LATITUDE, element_buf ) )
        {
            static uint8_t wait_for_fix_cnt = 0;
            if ( strlen( element_buf ) > 0 )
            {
                log_printf( &logger, "\r\n Latitude: %.2s degrees, %s minutes \r\n", element_buf, &element_buf[ 2 ] );
                c4gltegnss_parse_gga( app_buf, C4GLTEGNSS_GGA_LONGITUDE, element_buf );
                log_printf( &logger, " Longitude: %.3s degrees, %s minutes \r\n", element_buf, &element_buf[ 3 ] );
                memset( element_buf, 0, sizeof( element_buf ) );
                c4gltegnss_parse_gga( app_buf, C4GLTEGNSS_GGA_ALTITUDE, element_buf );
                log_printf( &logger, " Altitude: %s m \r\n", element_buf );
                wait_for_fix_cnt = 0;
            }
            else
            {
                if ( wait_for_fix_cnt % 5 == 0 )
                {
                    log_printf( &logger, " Waiting for the position fix...\r\n\n" );
                    wait_for_fix_cnt = 0;
                }
                wait_for_fix_cnt++;
            }
            c4gltegnss_clear_app_buf(  );
        }
    }
    Delay_ms ( 1000 );
#else
    #error "No demo example selected"
#endif
    return func_error;
}

// ------------------------------------------------------------------------ END

额外支持

资源

喜欢这个项目吗?

'购买此套件' 按钮会直接带您进入购物车,您可以在购物车中轻松添加或移除产品。