/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-05-06 lijian the first version */ #include #define AT_UART_NAME "uart3" LTE_t LTE; static rt_device_t AT_serial; /* 串口设备句柄 */ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */ /* 串口接收消息结构*/ struct rx_msg { rt_device_t dev; rt_size_t size; }; /* 消息队列控制块 */ static struct rt_messagequeue rx_mq; rt_uint8_t rx_length; rt_uint8_t check_flag; rt_err_t result; static char line_buffer[60]; void set_check_flag(rt_uint8_t flag){ check_flag = flag; } //AT指令发送 void AT_send(const char * cmd) { rt_device_write(AT_serial, 0, cmd, rt_strlen(cmd)); } /* 接收数据回调函数 */ static rt_err_t uart_callback(rt_device_t dev, rt_size_t size) { struct rx_msg msg; rt_err_t result; msg.dev = dev; msg.size = size; //rt_kprintf("in uart_callback\n"); result = rt_mq_send(&rx_mq, &msg, sizeof(msg)); if (result == -RT_EFULL) { /* 消息队列满 */ rt_kprintf("message queue full!\n"); } return result; } //接收数据线程 static void rx_serial_thread_entry(void *parameter) { struct rx_msg msg; static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1]; rt_uint8_t line_pos = 0; while (1) { rt_memset(&msg, 0, sizeof(msg)); /* 从消息队列中读取消息*/ result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER); if (result > 0) { // rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size); // rx_buffer[rx_length] = '\0'; // /* 打印数据 */ // rt_kprintf("%s\n", rx_buffer); rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size); for (int i = 0; i < rx_length; i++) { // 如果收到了换行符或回车符,就认为是一行的结束 if (rx_buffer[i] == '\n' || rx_buffer[i] == '\r') { line_buffer[line_pos] = '\0'; // 添加字符串结束符 if (line_pos > 0) // 如果这一行至少有一个字符 { if (check_flag == 1) //1检测MQTT { //+MQTTSTATU :0 离线 1 已经登陆认证过 2 还没认证,需要发送 MCONNECT char * ch_pos = rt_strstr(line_buffer, "+MQTTSTATU :"); // rt_kprintf("ch_pos c: %s\n", ch_pos); if (ch_pos != RT_NULL) { ch_pos = ch_pos + 12; set_MQTT_STATUS((rt_uint8_t) *ch_pos - '0'); //break; } } else if (check_flag == 2) //2检测LTE { //判断两个.为有IP,即联网成功 char *ch_pos2 = strchr(line_buffer, '.'); if (ch_pos2 != NULL) { // 计算点字符的位置 rt_uint8_t position = ch_pos2 - line_buffer; // 指针减法得到索引 if (line_buffer[position+2] == '.' || line_buffer[position+3] == '.' || line_buffer[position+4] == '.') { set_LTE_Status(1); } } else { //+CME ERROR:联网失败 ch_pos2 = rt_strstr(line_buffer, "+CME ERROR:"); if (ch_pos2 != RT_NULL) { set_LTE_Status(0); } } } if (LTE.log) { rt_kprintf("Received line: %s\n", line_buffer); } // rt_kprintf("Received line: %s , %d\n", line_buffer, line_pos); } line_pos = 0; // 重置行缓冲区位置 } else if (line_pos < sizeof(line_buffer) - 1) { // 否则,将字符添加到行缓冲区 line_buffer[line_pos++] = rx_buffer[i]; } } } } } //AT串口初始化 rt_uint8_t AT_device_init() { // rt_pin_mode(WAK, PIN_MODE_OUTPUT); // // 默认为高电平 // rt_pin_write(WAK, PIN_HIGH); // rt_pin_mode(GPS, PIN_MODE_OUTPUT); // // 默认为高电平 // rt_pin_write(GPS, PIN_LOW); rt_pin_mode(RST, PIN_MODE_OUTPUT); // 默认为高电平 rt_pin_write(RST, PIN_HIGH); rt_thread_mdelay(200); rt_pin_write(RST, PIN_LOW); rt_err_t ret = RT_EOK; static char msg_pool[256]; // char str[] = "AT\r\n"; AT_serial = rt_device_find(AT_UART_NAME); if (!AT_serial) { rt_kprintf("find %s failed!\n", AT_UART_NAME); return RT_ERROR; } config.baud_rate = BAUD_RATE_115200; //修改波特率为 115200 config.data_bits = DATA_BITS_8; //数据位 8 config.stop_bits = STOP_BITS_1; //停止位 1 config.bufsz = 128; //修改缓冲区 buff size 为 128 config.parity = PARITY_NONE; //无奇偶校验位 /* 初始化消息队列 */ rt_mq_init(&rx_mq, "rx_mq", msg_pool, /* 存放消息的缓冲区 */ sizeof(struct rx_msg), /* 一条消息的最大长度 */ sizeof(msg_pool), /* 存放消息的缓冲区大小 */ RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */ /* 串口设备控制参数 */ rt_device_control(AT_serial, RT_DEVICE_CTRL_CONFIG, &config); /* 打开串口设备。 DMA 接收及轮询发送模式打开串口设备 RT_DEVICE_FLAG_DMA_RX */ ret = rt_device_open(AT_serial, RT_DEVICE_FLAG_DMA_RX); if (ret != RT_EOK) { rt_kprintf("open AT_serial fail!\n"); return RT_ERROR; } // AT_send("ATE0\r\n"); /* 设置接收回调函数 */ rt_device_set_rx_indicate(AT_serial, uart_callback); /* 发送字符串 */ /* 创建 serial 线程 */ rt_thread_t rx_thread = rt_thread_create("rx_serial", rx_serial_thread_entry, RT_NULL, 1024, 25, 10); /* 创建成功则启动线程 */ if (rx_thread != RT_NULL) { rt_thread_startup(rx_thread); } else { ret = RT_ERROR; } rt_kprintf("open AT_serial ok!\n"); return ret; } //LTE初始化 rt_uint8_t LTE_init() { AT_send("AT\r\n"); AT_send("ATE0\r\n"); rt_thread_mdelay(1000); // AT_send("AT+CGMI\r\n"); //模块厂商信息 // rt_thread_mdelay(500); // // AT_send("AT+CPIN?\r\n"); //查询卡是否插好 // rt_thread_mdelay(500); // // AT_send("AT+CSQ\r\n"); //信号质量 // rt_thread_mdelay(500); // // AT_send("AT+CREG?\r\n"); //网络注册状态 // rt_thread_mdelay(500); // // AT_send("AT+CGATT?\r\n"); //附着GPRS // rt_thread_mdelay(500); AT_send("AT+CSTT=\"\",\"\",\"\"\r\n"); //自动APN rt_thread_mdelay(500); // AT_send("AT+CSTT?\r\n"); // rt_thread_mdelay(500); AT_send("AT+CIICR\r\n"); //激活移动场景 rt_thread_mdelay(500); AT_send("AT+CIFSR\r\n"); //查询IP rt_thread_mdelay(500); // AT_send("ATI\r\n"); // rt_thread_mdelay(500); //AT_send("ATD15612696324;\r\n"); return RT_EOK; } //获取LTE状态 rt_uint8_t get_LTE_status_flag() { set_check_flag(2); rt_uint8_t i = 0; AT_send("AT+CIFSR\r\n"); while (!get_LTE_Status()) { rt_thread_mdelay(200); if (i > 3) { break; } i++; } if (LTE.log) { rt_kprintf("LTE status:%d\n" , get_LTE_Status()); } return get_LTE_Status(); } void set_LTE_log(rt_uint8_t log){ LTE.log = log; } //LTE重新初始化 void LTE_Re_Init() { rt_pin_write(RST, PIN_HIGH); rt_thread_mdelay(500); rt_pin_write(RST, PIN_LOW); AT_send("AT+CSTT=\"\",\"\",\"\"\r\n"); //自动APN rt_thread_mdelay(500); // AT_send("AT+CSTT?\r\n"); // rt_thread_mdelay(500); AT_send("AT+CIICR\r\n"); //激活移动场景 rt_thread_mdelay(500); AT_send("AT+CIFSR\r\n"); //查询IP } //检测MQTT与LTE联网状态 void check_LTE_MQTT(){ if (LTE.toggle) { if (get_LTE_status_flag() != 1) { LTE.LTE_re++; } else { LTE.LTE_re = 0; } if (LTE.LTE_re == 3) { LTE_Re_Init(); } LTE.toggle = 0; } else { if (get_MQTT_Status_flag() != 1) { LTE.MQTT_re++; } else { LTE.MQTT_re = 0; } if (LTE.LTE_re == 0 && LTE.MQTT_re == 3) { MQTT_RE_init(); } LTE.toggle = 1; } } /** * @brief 设置/获取LTE使用键值 * @param rt_uint8_t key 要设置的Key值 * @return rt_uint8_t 返回当前的Key值 */ void set_LTE_Key(rt_uint8_t key) { LTE.Key = key; } rt_uint8_t get_LTE_Key() { return LTE.Key; } /** * @brief 设置/获取LTE状态键值 * @param rt_uint8_t key 要设置的Key值 * @return rt_uint8_t 返回当前的Key值 */ void set_LTE_Status(rt_uint8_t Status_t) { LTE.Status = Status_t; } rt_uint8_t get_LTE_Status() { return LTE.Status; } rt_uint8_t get_LTE_re() { return LTE.LTE_re; } rt_uint8_t get_L_MQTT_re() { return LTE.MQTT_re; }