顯示具有 serial 標籤的文章。 顯示所有文章
顯示具有 serial 標籤的文章。 顯示所有文章

2025年6月9日 星期一

IOT_PCB CODE 4G LTE 數據機狀態機分析

4G LTE 數據機狀態機分析器

4G LTE 數據機狀態機分析器

本頁提供 `modem_main()` 函式的核心流程控制邏輯解析、相關輔助函式的功能查詢,以及關鍵資料結構的詳細說明。

modem_main() 流程控制邏輯

modem_main() 函式主要透過一個大的 switch 語句來根據 info->session (當前數據機會話狀態) 執行不同的邏輯。每個 case 代表一個特定的數據機操作階段。

case _AT_SESSION_RESET: (數據機重置階段)

目的: 等待數據機完成硬體重置後的初始化延遲。

邏輯:

  • 檢查自 at_cmd_reset_tick 以來的時間是否超過 AT_RESET_INITIAL_TIMEOUT_MS (5 秒)。
  • 如果超過,表示重置延遲已滿足,則將會話切換到 _AT_SESSION_INIT (初始化階段)。
  • 同時初始化 at_cmd_polling_tickat_cmd_poll_gps_tick,為後續的命令輪詢和 GPS 數據讀取計時。
case _AT_SESSION_INIT: (數據機初始化階段)

目的: 執行一系列初始化的 AT 命令,包括基本設定、讀取 UUID、檢查訊號品質、設定 RTC 時間、以及 MQTT 相關參數載入和訂閱主題等。

邏輯:

  • 呼叫 cmd_processing(info):這是處理單個 AT 命令的核心函式,負責發送命令、等待響應、解析響應並更新命令狀態。
  • if(info->status == STATUS_CMD_OK)
    • 重置 info->statusSTATUS_CMD_NONE
    • 檢查訊號品質 (chk_cmd_response()==CMD_STATUS_BAD_SQ): 如果當前命令響應指示訊號品質不佳 (例如 AT+CSQ 命令返回的值低於預設閾值),則:
      • 增加 _modem.chk_sq_cnt
      • 根據當前會話是否為 _AT_SESSION_CHK_SQ,決定是直接切換到 _AT_SESSION_WAIT_TO_CHK_SQ 還是保留原會話並切換到 _AT_SESSION_WAIT_TO_CHK_SQ (使用 switchATSessionK 保留原會話)。
      • 更新 at_cmd_reset_tick
    • 檢查是否為命令集的末尾 (commands[info->index+1].mode == _CMD_MODE_END): 如果當前命令是會話中的最後一個命令:
      • 增加 info->index
      • 根據不同的會話類型執行相應的收尾工作:
        • _AT_SESSION_CHK_SQ: 恢復到之前的會話 (restoreToOrgSession())。
        • _AT_SESSION_TX: 將 _modem.lte_4G_TX_flag 清零,表示數據已發送,然後切換到 _AT_SESSION_FREE_RUN
        • _AT_SESSION_POLLING: 更新 at_cmd_polling_tick,然後切換到 _AT_SESSION_FREE_RUN
        • _AT_SESSION_GET_GPS: 更新 at_cmd_poll_gps_tick,然後切換到 _AT_SESSION_FREE_RUN
        • _AT_SESSION_INIT / _AT_SESSION_LOG_OUT_IN: 設定 _send_ping_data 為 1 (表示需要發送 PING 數據)、設定 _connected 為 1 (表示已連接 MQTT)、清除 _relog_request 旗標。
        • default: 切換到 info->cmdSet[info->index].sleeps 所指定的下一個會話。
  • else if (info->status == STATUS_CMD_ERROR)
    • 重置 info->statusSTATUS_CMD_NONE
    • 如果 _modem.error_count 超過 20 次,則執行 modem_reset() (硬體重置數據機)。
  • else if (info->status == STATUS_CMD_TIMEOUT)
    • STATUS_CMD_ERROR 處理方式類似,如果超時次數過多,也執行 modem_reset()
case _AT_SESSION_WAIT_TO_CHK_SQ: (等待檢查訊號品質階段)

目的: 在訊號品質不佳時,暫停其他操作,等待一段時間後重新檢查訊號。

邏輯:

  • 如果 _modem.chk_sq_cnt 小於 5 次 (表示還在初始的快速重試階段),且自 at_cmd_reset_tick 以來超過 5 秒,則切換到 _AT_SESSION_CHK_SQ
  • 如果 _modem.chk_sq_cnt 大於等於 5 次 (表示已經進行多次重試,需要更長的等待時間),且自 at_cmd_reset_tick 以來超過 30 秒,則切換到 _AT_SESSION_CHK_SQ
case _AT_SESSION_FREE_RUN: (自由運行階段)

目的: 釋放數據機物件的控制權 (semaphore),並切換到下一個自由運行階段。

邏輯:

  • 呼叫 releaseSemaObj(_OWNER_MODEM) 釋放數據機的互斥鎖。
  • 切換到 _AT_SESSION_FREE_RUN_1
  • 更新 at_cmd_reset_tick
case _AT_SESSION_FREE_RUN_1: (自由運行子階段)

目的: 提供一個短暫的窗口,允許其他模組 (例如 CAN) 處理數據,然後再進入數據機的輪詢階段。

邏輯:

  • 如果自 at_cmd_reset_tick 以來超過 1 秒,則切換到 _AT_SESSION_WAIT_TO_GET_GPS
case _AT_SESSION_WAIT_TO_GET_GPS: (等待獲取 GPS 或輪詢數據階段)

目的: 這是數據機在穩定連接後的主要運行階段,負責根據不同的條件觸發數據傳輸、重新登錄或 GPS/訊息輪詢。

邏輯:

  • 優先處理數據發送 (_modem.lte_4G_TX_flag==1): 如果有待發送的數據:
    • 嘗試獲取數據機的互斥鎖 (acquireSemaObj(_OWNER_MODEM))。
    • 如果成功,則切換到 _AT_SESSION_TX
  • 處理重新登錄請求 (chk_relog_request()): 如果有 MQTT 重新登錄請求:
    • 嘗試獲取數據機的互斥鎖。
    • 如果成功,則切換到 _AT_SESSION_LOG_OUT_IN,並將 _connected 設為 0。
  • 平衡 GPS 數據讀取和訊息輪詢: 這部分邏輯比較複雜,旨在交替執行 GPS 請求和輪詢接收到的數據,以避免阻塞:
    • 高頻率同時觸發 (chk_timeup_ms(timer1ms,at_cmd_poll_gps_tick, _modem.at_gps_read_time) && chk_timeup_ms(timer1ms, at_cmd_polling_tick, 5*1000)): 如果 GPS 讀取時間和輪詢時間都到期:
      • 嘗試獲取互斥鎖。
      • 根據 _prev_action_gps 的值,決定是切換到 _AT_SESSION_POLLING (輪詢) 還是 _AT_SESSION_GET_GPS (獲取 GPS),並更新 _prev_action_gps
    • 僅輪詢時間到期 (chk_timeup_ms(timer1ms, at_cmd_polling_tick, 5*1000)): 如果只有輪詢時間到期:
      • 嘗試獲取互斥鎖。
      • 切換到 _AT_SESSION_POLLING,並將 _prev_action_gps 設為 0。
    • 僅 GPS 時間到期 (chk_timeup_ms(timer1ms,at_cmd_poll_gps_tick, _modem.at_gps_read_time)): 如果只有 GPS 時間到期:
      • 嘗試獲取互斥鎖。
      • 切換到 _AT_SESSION_GET_GPS,並將 _prev_action_gps 設為 1。
cmd_processing(COMMAND_STATE_INFO *info) (輔助函式但與主邏輯緊密相關)

功能: 這是執行單個 AT 命令的核心。

邏輯: 根據 info->state (當前命令狀態) 進行處理:

  • _AT_CMD_TO_SEND: 準備並發送 AT 命令到 UART 0。如果命令類型是 _CMD_MODE_PUB, _CMD_MODE_DOWN, _CMD_MODE_UP,則需要處理 UUID 或將 IoT 數據轉換為十六進制格式發送。
  • _AT_CMD_WAIT_TO_RECEIVE: 等待 UART 0 接收到足夠的數據 (通過判斷 \r\n 的數量)。如果超時,則將 info->status 設為 STATUS_CMD_TIMEOUT
  • _AT_CMD_TO_RECEIVE: 檢查接收到的數據是否包含 "OK" 或 "ERROR"。
    • 如果包含 "OK",表示命令成功,清除錯誤計數,複製數據到 platformrxbuffer,並將狀態切換到 _AT_CMD_WAIT_TO_SEND
    • 如果包含 "ERROR",增加錯誤計數,如果錯誤是 MQTT 登錄相關且不影響後續流程,則切換到 _AT_CMD_WAIT_TO_SEND;否則切換到 _AT_CMD_ERROR_RESEND
    • 如果超時,則將 info->status 設為 STATUS_CMD_TIMEOUT
  • _AT_CMD_WAIT_TO_SEND: 等待一段時間後,將狀態切換到 _AT_CMD_TO_SEND 並增加命令索引,準備發送下一個命令。
  • _AT_CMD_ERROR_RESEND: 等待一段時間後,將狀態切換到 _AT_CMD_TO_SEND (重發當前命令)。
chk_cmd_response() (輔助函式但與主邏輯緊密相關)

功能: 解析 platformrxbuffer 中接收到的 AT 命令響應,並根據響應內容更新 _modem 結構中的相關資訊 (如 UUID, 訊號品質, RTC 時間, GPS 數據)。

邏輯: 根據解析結果返回 CMD_STATUS_OK, CMD_STATUS_BAD_SQCMD_STATUS_BAD_GPS

switchATSessionK(), switchATSession()restoreToOrgSession() (會話切換輔助函式)
  • switchATSessionK(AT_SESSION_STATES session):切換到新的 AT 會話,並保留當前會話的狀態資訊,以便後續恢復。
  • switchATSession(AT_SESSION_STATES session):切換到新的 AT 會話,不保留當前會話的狀態資訊。
  • restoreToOrgSession():恢復到之前保存的 AT 會話狀態。
modem_reset() (數據機硬體重置輔助函式)

功能: 執行數據機的硬體重置,包括 GPIO 控制電源和重置引腳,並初始化 _modem 結構中的所有相關變數。

acquireSemaObj()releaseSemaObj() (互斥鎖輔助函式)

功能: 用於實現對數據機操作的互斥鎖,確保在同一時間只有一個模組可以控制數據機,避免競爭條件。

輔助函式與資料結構查詢

請從左側列表選擇一個項目,或在上方搜尋。

核心資料結構定義

以下是 4G LTE 數據機狀態機中使用的核心資料結構定義,您可以展開查看詳細內容。

typedef enum COMMAND_STATUS

功能: 定義 AT 命令的執行狀態。

typedef enum
{
    STATUS_CMD_NONE=0,
    STATUS_CMD_OK,
    STATUS_CMD_ERROR,
    STATUS_CMD_TIMEOUT,
    STATUS_CMD_IN_PROCESS,
} COMMAND_STATUS;
  • STATUS_CMD_NONE: 無狀態,或初始狀態。
  • STATUS_CMD_OK: 命令執行成功。
  • STATUS_CMD_ERROR: 命令執行失敗或返回錯誤。
  • STATUS_CMD_TIMEOUT: 命令執行超時。
  • STATUS_CMD_IN_PROCESS: 命令正在處理中。
typedef enum AT_SESSION_STATES

功能: 定義數據機狀態機的各個會話階段。

typedef enum
{
    _AT_SESSION_INIT =0,
    _AT_SESSION_RESET,              //1
    _AT_SESSION_CHK_SQ,             //2 check signal quality when error or timeout happens.
    _AT_SESSION_WAIT_TO_CHK_SQ,     //3
    _AT_SESSION_FREE_RUN,           //4
    _AT_SESSION_TX,                 //5 MQTT up send json message
    _AT_SESSION_WAIT_TO_GET_GPS,    //6
    _AT_SESSION_GET_GPS,            //7
    _AT_SESSION_LOG_OUT_IN,         //8
    _AT_SESSION_POLLING,            //9
    _AT_SESSION_FREE_RUN_1,         //10
}AT_SESSION_STATES;
  • _AT_SESSION_INIT: 初始化會話。
  • _AT_SESSION_RESET: 數據機重置後等待階段。
  • _AT_SESSION_CHK_SQ: 檢查訊號品質會話。
  • _AT_SESSION_WAIT_TO_CHK_SQ: 等待檢查訊號品質的延遲階段。
  • _AT_SESSION_FREE_RUN: 自由運行階段 (釋放鎖)。
  • _AT_SESSION_TX: 數據上傳 (MQTT) 會話。
  • _AT_SESSION_WAIT_TO_GET_GPS: 等待獲取 GPS 或輪詢數據的決策階段。
  • _AT_SESSION_GET_GPS: 獲取 GPS 數據會話。
  • _AT_SESSION_LOG_OUT_IN: MQTT 登出再登入會話。
  • _AT_SESSION_POLLING: 輪詢接收數據會話。
  • _AT_SESSION_FREE_RUN_1: 自由運行子階段 (短暫延遲)。
typedef enum AT_CMD_STATES

功能: 定義單個 AT 命令的執行狀態,用於 cmd_processing() 函式。

typedef enum
{
    _AT_CMD_NONE = 0,
    _AT_CMD_TO_SEND,
    _AT_CMD_TO_RECEIVE,
    _AT_CMD_TO_RECEIVE1,
    _AT_CMD_WAIT_TO_SEND,
    _AT_CMD_ERROR_RESEND,
    _AT_CMD_WAIT_TO_RECEIVE,
}AT_CMD_STATES;
  • _AT_CMD_NONE: 無命令狀態。
  • _AT_CMD_TO_SEND: 準備發送命令。
  • _AT_CMD_TO_RECEIVE: 準備接收響應。
  • _AT_CMD_TO_RECEIVE1: 另一種接收響應狀態。
  • _AT_CMD_WAIT_TO_SEND: 等待下次發送命令。
  • _AT_CMD_ERROR_RESEND: 錯誤後等待重發。
  • _AT_CMD_WAIT_TO_RECEIVE: 等待接收響應數據。
typedef enum _CMD_MODES

功能: 定義 AT 命令的處理模式,影響命令的發送和響應解析方式。

typedef enum {
    _CMD_MODE_0 = 0,    //normal command, just send it to modem
    _CMD_MODE_PUB,
    _CMD_MODE_DOWN,
    _CMD_MODE_UP,
    _CMD_MODE_P0,
    _CMD_MODE_CSQ,
    _CMD_MODE_TM,
    _CMD_MODE_E,        //ignore the error
    _CMD_MODE_TEST,
    _CMD_MODE_GPS,
    _CMD_MODE_TX,
    _CMD_MODE_POLL,         //poll reading the data of Link Commands from uBlox catched buffer.
    _CMD_MODE_MQTTLOGIN,        //=== 20241111 handel check mqtt login === "+UUMQTTC: 1 ,1"
    _CMD_MODE_END,
}_CMD_MODES;
  • _CMD_MODE_0: 普通命令,直接發送。
  • _CMD_MODE_PUB: MQTT 發布相關命令。
  • _CMD_MODE_DOWN: MQTT 訂閱下載相關命令。
  • _CMD_MODE_UP: MQTT 上傳相關命令。
  • _CMD_MODE_P0: 可能用於特定參數設定或檔案操作。
  • _CMD_MODE_CSQ: 查詢訊號品質命令。
  • _CMD_MODE_TM: 查詢時間命令。
  • _CMD_MODE_E: 忽略錯誤的命令模式。
  • _CMD_MODE_TEST: 測試模式命令。
  • _CMD_MODE_GPS: GPS 相關命令。
  • _CMD_MODE_TX: 數據傳輸命令。
  • _CMD_MODE_POLL: 輪詢 Link Command 數據命令。
  • _CMD_MODE_MQTTLOGIN: MQTT 登錄檢查命令。
  • _CMD_MODE_END: 命令集的結束標誌。
typedef struct AT_COMMANDS

功能: 定義單個 AT 命令的結構,包括其模式、延遲時間和命令字串。

typedef struct{
    _CMD_MODES mode;
    uint8_t sleeps;
    char *command;
} AT_COMMANDS;
  • mode: 命令的處理模式 (參考 _CMD_MODES)。
  • sleeps: 命令發送後的延遲時間或切換到的下一個會話狀態。
  • command: AT 命令字串。
typedef struct COMMAND_STATE_INFO

功能: 儲存數據機狀態機的當前運行資訊。

typedef struct{
    AT_SESSION_STATES   session;
    AT_SESSION_STATES   prev_session;
    AT_CMD_STATES       state;
    uint8_t             index;
    uint8_t             prev_index;
    COMMAND_STATUS      status;
    AT_COMMANDS* cmdSet;
    uint8_t             signal_bad; //the quality of 4G signal, 0: good, 1:bad
}COMMAND_STATE_INFO;
  • session: 當前會話狀態。
  • prev_session: 上一個會話狀態 (用於恢復)。
  • state: 當前命令執行狀態。
  • index: 當前命令在命令集中的索引。
  • prev_index: 上一個命令的索引。
  • status: 當前命令的執行結果狀態。
  • cmdSet: 指向當前使用的 AT 命令集陣列。
  • signal_bad: 4G 訊號品質標誌 (0: 好, 1: 差)。
typedef struct GPS_LOCATION

功能: 儲存 GPS 定位資訊。

typedef struct {
    char utcTime[16];
    char utcDate[16];
    char latitude[32];
    char longitude[32];
} GPS_LOCATION;
  • utcTime: UTC 時間字串。
  • utcDate: UTC 日期字串。
  • latitude: 緯度字串。
  • longitude: 經度字串。
typedef struct MODEM_DATA

功能: 數據機的整體數據和狀態儲存結構,包含了數據機運行所需的所有關鍵資訊。

typedef struct MODEM_DATA
{
    uint8_t modem_uuid_md5[33];
    uint8_t lte_4G_TX_flag;
    uint8_t lte_4G_TX_data[UART_TX_RX_SIZE*2+100];

    uint8_t lte_4G_RX_index1;
    uint8_t lte_4G_RX_index2;
    uint8_t lte_4G_RX_data[LTE_4G_RX_DATA_COUNT][UART_TX_RX_SIZE];
    uint8_t error_count;
    uint8_t relog_request;

    uint8_t chk_sq_cnt;

    COMMAND_STATE_INFO at_cmd_info;

    uint8_t  lte_4G_gps_first_flag;
    uint8_t  lte_4G_gps_read_flag;
    uint32_t lte_4G_gps_tick;

    GPS_LOCATION gpsLoc;

    uint32_t at_gps_read_time;

    UTC_TIME rtc_time;
    uint8_t chk_mqtt_login;
    uint8_t lte_4G_csqval;
} MODEM_DATA;
  • modem_uuid_md5: 數據機的 UUID (MD5 格式)。
  • lte_4G_TX_flag: 4G 數據發送標誌。
  • lte_4G_TX_data: 用於發送 IoT 數據的緩衝區。
  • lte_4G_RX_index1, lte_4G_RX_index2: 接收數據緩衝區的索引。
  • lte_4G_RX_data: 接收到的訊息列表。
  • error_count: 錯誤計數。
  • relog_request: 重新登錄請求標誌。
  • chk_sq_cnt: 檢查訊號品質的計數。
  • at_cmd_info: 數據機狀態機的當前資訊。
  • lte_4G_gps_first_flag, lte_4G_gps_read_flag, lte_4G_gps_tick: GPS 讀取相關的標誌和計時。
  • gpsLoc: GPS 定位資訊。
  • at_gps_read_time: GPS 讀取時間間隔。
  • rtc_time: RTC 時間資訊。
  • chk_mqtt_login: MQTT 登錄狀態 (1: 登錄, 0: 登出)。
  • lte_4G_csqval: 4G 訊號品質 (CSQ 值)。
typedef enum CMD_STATUS (不同於 COMMAND_STATUS 的狀態)

功能: 定義命令響應的狀態,特別用於 chk_cmd_response() 函式的返回結果。

typedef enum {
    CMD_STATUS_OK = 0,
    CMD_STATUS_BAD_SQ,
    CMD_STATUS_BAD_GPS,
}CMD_STATUS;
  • CMD_STATUS_OK: 命令響應正常。
  • CMD_STATUS_BAD_SQ: 訊號品質不佳。
  • CMD_STATUS_BAD_GPS: GPS 數據不佳。
靜態 AT 命令集陣列

以下是數據機初始化、檢查訊號、獲取 GPS、發送數據、登出登入和輪詢等不同會話所使用的 AT 命令集定義。

這些陣列包含了 _CMD_MODESsleeps (延遲或下一會話) 和實際的 command 字串。

例如:

static AT_COMMANDS atCmdInit[]={
    // ...
    {_CMD_MODE_CSQ    ,2  ,"AT+CSQ\r\n"},
    {_CMD_MODE_TM     ,2  ,"AT+CCLK?\r\n"},
    // ...
    {_CMD_MODE_END    ,_AT_SESSION_FREE_RUN ,""}
};

static AT_COMMANDS atCmdChkSQ[] = {
    {_CMD_MODE_CSQ    ,1  ,"AT+CSQ\r\n"},
    {_CMD_MODE_END    ,99 ,""} //back to previous session
};

static AT_COMMANDS atCmdGetGPS[] = {
    {_CMD_MODE_TM     ,1  ,"AT+CCLK?\r\n"},
    {_CMD_MODE_GPS    ,1  ,"AT+UGRMC?\r\n"},
    {_CMD_MODE_END    ,_AT_SESSION_FREE_RUN  ,""}
};

static AT_COMMANDS atTxData[] = {
    {_CMD_MODE_TM     ,1  ,"AT+CCLK?\r\n"},
    {_CMD_MODE_UP     ,1  ,"AT+UMQTTC=2,0,0,1,\"EMOTO/DEV/"},
    {_CMD_MODE_END    ,_AT_SESSION_FREE_RUN  ,""}
};

static AT_COMMANDS atCmdLogOutIn[] = {
    {_CMD_MODE_0      ,2  ,"AT+UMQTTC=0\r\n"},
    {_CMD_MODE_0      ,2  ,"AT+UMQTTC=1\r\n"},
    {_CMD_MODE_DOWN   ,2  ,"AT+UMQTTC=4,0,\"EMOTO/DEV/"},
    {_CMD_MODE_PUB    ,2  ,"AT+UMQTTC=4,0,\"EMOTO/DEV/"},
    {_CMD_MODE_END    ,_AT_SESSION_FREE_RUN  ,""}
};

static AT_COMMANDS atCmdPolling[] = {
    {_CMD_MODE_TM     ,1  ,"AT+CCLK?\r\n"},
    {_CMD_MODE_POLL   ,1  ,"AT+UMQTTC=6\r\n"},
    {_CMD_MODE_END    ,_AT_SESSION_FREE_RUN ,""}
};

static void* atCommands[] = {
    atCmdInit,          //_AT_SESSION_INIT
    0,                  //_AT_SESSION_RESET
    atCmdChkSQ,         //_AT_SESSION_CHK_SQ
    0,                  //_AT_SESSION_WAIT_TO_CHK_SQ
    0,                  //_AT_SESSION_FREE_RUN
    atTxData,           //_AT_SESSION_TX
    0,                  //_AT_SESSION_WAIT_TO_GET_GPS
    atCmdGetGPS,        //_AT_SESSION_GET_GPS
    atCmdLogOutIn,      //_AT_SESSION_LOG_OUT_IN
    atCmdPolling,       //_AT_SESSION_POLLING
    0                   //_AT_SESSION_FREE_RUN1
};

2017年6月28日 星期三

GSM模塊SMS相關AT命令使用說明

[轉載] GSM模塊SMS相關AT命令使用說明

GSM模塊SMS相關AT命令使用說明
(本文可以自由轉載,但必須註明出處)  
[日期:2006-1-28]來源:www.21icbbs.com 通信技術版 作者:飛雪季節

適合人群:首次接觸G網模塊人員
凡是利用GSM模塊二次開發的,不管是用來做公話,還是GPRS通信,其中短消息基本都要使用的。本文大致介紹一下短消息相關的AT命令使用方法。
詳細的AT指令說明,可以參考 07.05,或者西門子MC35I的AT手冊,西門子手冊感覺還是很不錯的。

    由於本文表達的錯誤給您帶來的物資損失和精神損傷,本人概不負責。
1、    短消息的格式
我所見到的模塊短消息基本都提供2種格式,TEXT和PDU。文本模式相對來說比較簡單,
特別適合傳輸那些字符什麼的,對於老外來說,基本就發26個字幕,簡直太方便了。
PDU模式需要進行編碼,目前的漢字傳輸好多都採用PDU模式。由於本人對PDU和怎麼發漢字基本一竅不通,這段就暫時忽略了。

一般模塊默認的都是PDU模式,你可以使用如下命令切換到TEXT模式:
AT+CMGF=1

如果想再切換到PDU模式,使用:
AT+CMGF=0
即可,以下短消息發送&讀取都採用TEXT模式,因為PDU我不是很懂。

2、    怎樣給我發送一條短消息?
現在你手裡有了G網模塊,但首先你要確保如下操作已經完成:
1)    模塊上電並且AT命令同你的PC串口通信順暢。
2)    SIM卡沒有欠費,並且已經登陸GSM網絡(可以使用AT+CREG?查詢,如果返回1或者5表示正常)。
3)     AT+CMGF=1設置完畢。

有了以上的過程,那麼你就可以給我發信息了,你要使用的AT命令是:AT+CMGS。
假如我的手機號是:13636371111(後四位是假的)。
1)    從串口輸入:AT+CMGS=」13636371111」 然後按回車鍵。
2)    這個時候你可以看到有個大於號 『>』彈出,提示你可以輸入消息的內容了。
假如你想發送「hello world」,直接在』>』後面輸入即可,輸入完了後按』CTRL^Z」,
稍微等一下,你的信息也就發出去了,如果編程好像是0x1B(記不清了,你可以查下ASCII表)。

全部過程如下:
AT+CMGS="13636371111"
> hello world
+CMGS: 199
OK

你需要一直等到OK返回,才能確定是成功發出,中間的那個東西可以先不管。
如果你輸入 「 hello world」後,但又不想發了,按ESC可以取消發送,就不再介紹。

3、    怎樣打開傳送回報?
手機上我們都可以找到一個菜單,可以選擇傳送回報的功能,也就是說別人收到你的信息後,
短消息中心會給你一個確認信息,假如是發給心上人,這個功能尤其重要。

對於模塊我們沒有菜單可選,但我們有 AT+CSMP 這樣一條AT命令,在TEXT模式下,
對於手機上的那個選項可以通過這條命令實現,這個命令的具體含義我搞得不是很清楚,
也懶得去研究,曾經有個人告訴我按照下面設置後,傳送回報就可以回來:
AT+CSMP=33
   但即使你這樣設置後,別人收到後,傳送回報你可能還是看不到,
   你還需要設置另外一條AT命令:「AT+CNMI=2,1,,1」,下面就會介紹到這個命令的用法。
   對於PDU模式,控制傳送回報有很大差別。

4、    AT+CNMI的用法。
到目前為止,你至少還有如下的疑惑:

1)    來了新短信,我怎麼知道?
2)    我擔心時間長了SIM卡會寫壞,FLASH也可能寫壞,或者我單片機很強短信不需要存儲,就要模塊直接給我,我該怎麼辦?
3)    我要看傳送回報!

  上面一切疑慮都可以從AT+CNMI中得到答案。
我手頭上有個西門子MC35的手冊,CNMI的幾個參數如下:
AT+CNMI =[<mode>][,<mt>][,<bm>][,<ds>][,<bfr>]
方括號表示參數是可選的,簡要說明下:

<mode>  用來選擇來了新短信,提示信息是否需要從串口直接打出,一般取2。
<mt>    用來選擇新短信的提示方式,取1的話,就比較簡單,比如「+CMTI: "SM",3」,告訴你新短信存在SIM卡裡,序號是3,稍後告訴你怎樣讀取。取2的話,來了新短信就會不作存儲,直接從串口顯示出來。
<ds>   用來選擇傳送回報,如果想看回報的話,一般取1(同AT+CSMP結合使用)。

其他參數不作說明。
這裡提供3組參數可以供你使用:
1)    AT+CNMI=2,1,,1 這組參數可以提供新信息提示,以及傳送回報的功能
2)    AT+CNMI=2,2,,1 這組參數來了新信息直接顯示到串口,不作存儲,仍然打開傳送回報。
3)    AT+CNMI=2,1 這組參數,一般的模塊都會有新信息提示,不會打開回報功能(打開可能會干擾單片機處理)     以上僅供參考,不同廠家模塊實現形式以及支持參數可能會有不同,需要實際測試。

5、    怎樣讀取SIM卡或者手機內部的信息?
比如我們收到這樣的信息:「+CMTI: "SM",3」,知道來了新信息,並且存儲在SIM卡,第3個位置區。我們怎麼去讀取呢?
比較EASY,用AT+CMGR來讀取,如下:
AT+CMGR=3,回車後,即可看到短信內容,比較簡單,這裡就不舉例了。
還有一個用來讀取短信的命令,AT+CMGL,可以列出手機內部的全部AT命令,
比如:
AT+CMGL=」ALL」,回車後可以返回當前存儲區的所有短信,結果自己實踐即可。
+CMGL還有另外3個參數,可以參考手冊,並且PDU還有些不同,參數使用的是數字。
6、    怎樣選擇存儲區?
現在的模塊一般都提供2-3個存儲區,SIM卡,手機(FLASH), SIM卡+FLASH。
我們可以使用 AT+CPMS?進行選擇,關於CPMS的3個參數,這裡簡要介紹一下,比較容易搞混,並不是表示SIM卡或者手機分別有3個存儲區。
設置命令如下:AT+CPMS=<mem1>[,<mem2>][,<mem3>]]
<mem1> Memory to be used when listing, reading and deleting messages:
<mem2> Memory to be used when writing and sending messages:
<mem3> Received messages will be placed to this storage if routing to TE is not
set.
上面是我為了省事直接從西門子手冊COPY的,需要仔細理解。組合著多試幾次就知道了。
7、    怎樣刪除一條短信?
使用AT+CMGD,比如:
AT+CMGD=1 將刪除<mem1>內部的第一條信息(注意模塊返回OK都是刪除成功,有些模塊會返回ERROR,其實表示當前這個位置沒有短信息)。
AT+CMGD還有個全刪的功能,比如:
AT+CMGD=1,4 將刪除<mem1>存儲區內部的全部短信息。(注意第二個參數還有3個,可以看手冊,並且並不是所有廠家模塊都支持全刪)
到這為此吧,已經弄了2個小時了,我要去睡覺了,明天還要起早上班。  
關於短消息的編程,2年前做過一次,是首次接觸AT命令,啥都不會,網上搜索只能零零碎碎的找到點,
結果是沒怎麼做好。體會初學者的苦衷,現在已經不作了,把我所知道的拿出來分享下,獻給初學者。
為了處理好代碼,還是要仔細研究07.05協議和廠家提供的手冊,然後對照實際驗證,盡量不要瞎猜,
即使在一個地方蒙對了,到另外城市你的東西可能就不能用了。
如果有想要代碼的話,再等一等,現在在測試PPP的代碼。

python serial com port demo code

link form =>http://pizgchen.blogspot.tw/2014/08/pyserial.html


安裝 pySerial

您可以使用 pySerial 透過 COM port 與 Arduino 聯繫。

官網 http://pyserial.sourceforge.net/#


下載

切換至下載頁面 https://pypi.python.org/pypi/pyserial,點擊 pyserial-2.7-win32.exe (md5)。


安裝

雙擊  pyserial-2.7-win32.exe,然後依照視窗提示安裝即可。它會被安裝到 C:\Python27\Lib\site-packages\serial\ 這個位置。


開啟 COM4 並送出訊息

COM port 的編號是從 0 開始,所以  serial.Serial(3) 表開啟 COM4。

import serial
ser = serial.Serial(3)  # open COM4 port
print ser.name          # check which port was really used
ser.write("hello")      # write a string
ser.close()             # close port


以名稱方式開啟 COM port 並讀取訊息

超時設為 1 秒,讀取資料時如果時間超過 1 秒沒接收到資料就中斷接收。

import serial
ser = serial.Serial('COM4', 19200, timeout=1)
x = ser.read()          # read one byte
s = ser.read(10)        # read up to ten bytes (timeout)
line = ser.readline()   # read a '\n' terminated line
ser.close()


稍後才設定 COM 的參數

您不必一開始就指定某個特定的 COM port 必須使用多少鮑率等參數,而是可以隨著程式的進行隨時改變參數,方法如下所示:

>>> import serial
>>> ser = serial.Serial()
>>> ser.baudrate = 19200
>>> ser.port = 0
>>> ser
Serial<id=0xa81c10, open=False>(port='COM1', baudrate=19200, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=0, rtscts=0)
>>> ser.open()
>>> ser.isOpen()
True
>>> ser.close()
>>> ser.isOpen()
False


獲取可用的 COM port

import serial.tools.list_ports

coms=serial.tools.list_ports.comports()
for a in coms:
     print a



讓 Arduino 板子 pin 13 的 LED 閃爍

Python code:

import serial

def main():
    sp = serial.Serial()
    sp.port = 'COM4'
    sp.baudrate = 9600
    sp.timeout = 5

    sp.open()
    sp.readline() #to give the hardware handshake time to happen
    sp.write(chr(1))
    value = sp.readline()
    print value
    sp.write(chr(0))
    sp.close()

if __name__ == "__main__":

    main()


Arduino code:

const int ledPin = 13;

void setup(){
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
}

void loop(){
    while(Serial.available()){
        switch(Serial.read()) {
          case 0:
            digitalWrite(ledPin, LOW);
            break;
          case 1:
            digitalWrite(ledPin, HIGH);
            break;
        }  
        delay(20);
    }

}


您可能也喜歡

Arduino and Python
http://playground.arduino.cc/interfacing/python

pyFirmata
https://github.com/tino/pyFirmata

Python Arduino Prototyping API
https://github.com/vascop/Python-Arduino-Proto-API-v2


<Python Serial Port Extension>


1. wxTerminal.py
http://sourceforge.net/p/pyserial/code/HEAD/tree/trunk/pyserial/examples/wxTerminal.py


2. wxSerialConfigDialog.py
http://sourceforge.net/p/pyserial/code/HEAD/tree/trunk/pyserial/examples/wxSerialConfigDialog.py