nmea_sample.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-07-08 Shine the first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <string.h>
  13. #include "stdio.h"
  14. #include "string.h"
  15. #define DBG_TAG "nmea"
  16. #define DBG_LVL DBG_LOG
  17. #include <rtdbg.h>
  18. #include "nmea/nmea.h"
  19. /* 串口接收消息结构*/
  20. struct rx_msg
  21. {
  22. rt_device_t dev;
  23. rt_size_t size;
  24. };
  25. static rt_device_t serial;
  26. static struct rt_messagequeue rx_mq;
  27. /* 接收数据回调函数 */
  28. static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
  29. {
  30. struct rx_msg msg;
  31. rt_err_t result;
  32. msg.dev = dev;
  33. msg.size = size;
  34. result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
  35. if (result == -RT_EFULL)
  36. {
  37. /* 消息队列满 */
  38. rt_kprintf("message queue full!\n");
  39. }
  40. return result;
  41. }
  42. //#define __GPS_DEBUG
  43. /**
  44. * @brief trace 在解码时输出捕获的GPS语句
  45. * @param str: 要输出的字符串,str_size:数据长度
  46. * @retval 无
  47. */
  48. #ifdef NMEALIB_DEBUG
  49. static void trace(const char *str, int str_size)
  50. {
  51. rt_kprintf("\nnmea trace:");
  52. for (int i = 0; i < str_size; i++)
  53. rt_kprintf("%c", str[i]);
  54. rt_kprintf("\n");
  55. }
  56. #endif
  57. /**
  58. * @brief error 在解码出错时输出提示消息
  59. * @param str: 要输出的字符串,str_size:数据长度
  60. * @retval 无
  61. */
  62. #ifdef NMEALIB_DEBUG
  63. static void error(const char *str, int str_size)
  64. {
  65. rt_kprintf("\nnmea error:");
  66. for (int i = 0; i < str_size; i++)
  67. rt_kprintf("%c", str[i]);
  68. rt_kprintf("\n");
  69. }
  70. #endif
  71. static void nmea_thread_entry(void *parameter)
  72. {
  73. struct rx_msg msg;
  74. rt_err_t result;
  75. rt_uint32_t rx_length;
  76. static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];
  77. char ss[128]; //打印字符串buffer
  78. double deg_lat; //转换成[degree].[degree]格式的纬度
  79. double deg_lon; //转换成[degree].[degree]格式的经度
  80. nmeaINFO info; //GPS解码后得到的信息
  81. nmeaPARSER parser; //解码时使用的数据结构
  82. #ifdef NMEALIB_DEBUG
  83. nmea_property()->trace_func = &trace;
  84. nmea_property()->error_func = &error;
  85. #endif
  86. nmea_zero_INFO(&info);
  87. nmea_parser_init(&parser);
  88. while (1)
  89. {
  90. rt_memset(&msg, 0, sizeof(msg));
  91. /* 从消息队列中读取消息*/
  92. result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
  93. if (result == RT_EOK)
  94. {
  95. /* 从串口读取数据*/
  96. rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
  97. rx_buffer[rx_length] = '\0';
  98. nmea_parse(&parser, (const char *) &rx_buffer[0], rx_length, &info);
  99. //info.lat lon中的格式为[degree][min].[sec/60],使用以下函数转换成[degree].[degree]格式
  100. deg_lat = nmea_ndeg2degree(info.lat);
  101. deg_lon = nmea_ndeg2degree(info.lon);
  102. LOG_D("utc_time:%d-%02d-%02d,%d:%d:%d ", info.utc.year + 1900, info.utc.mon + 1, info.utc.day,
  103. info.utc.hour, info.utc.min, info.utc.sec);
  104. //因为LOG_D不支持浮点数,所以此处使用snprintf进行打印,再用LOG_D输出
  105. snprintf(ss, 128, "wd:%f,jd:%f", deg_lat, deg_lon);
  106. LOG_D(ss);
  107. snprintf(ss, 128, "high:%f m", info.elv);
  108. LOG_D(ss);
  109. snprintf(ss, 128, "v:%f km/h", info.speed);
  110. LOG_D(ss);
  111. snprintf(ss, 128, "hangxiang:%f du", info.direction);
  112. LOG_D(ss);
  113. snprintf(ss, 128, "used GPS:%d,show GPS:%d", info.satinfo.inuse, info.satinfo.inview);
  114. LOG_D(ss);
  115. snprintf(ss, 128, "PDOP:%f,HDOP:%f,VDOP:%f", info.PDOP, info.HDOP, info.VDOP);
  116. LOG_D(ss);
  117. }
  118. }
  119. }
  120. static int nmea_thread_init(int argc, char *argv[])
  121. {
  122. rt_err_t ret = RT_EOK;
  123. static char msg_pool[256];
  124. static char up_msg_pool[256];
  125. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  126. /* 查找串口设备 */
  127. serial = rt_device_find(NMEALIB_UART_PORT);
  128. /* 初始化消息队列 */
  129. rt_mq_init(&rx_mq, "rx_mq", msg_pool, sizeof(struct rx_msg), sizeof(msg_pool), RT_IPC_FLAG_FIFO);
  130. //修改波特率为9600
  131. config.baud_rate = NMEALIB_UART_BAUDRATE;
  132. rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
  133. rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX); /* 以 DMA 接收及轮询发送方式打开串口设备 */
  134. rt_device_set_rx_indicate(serial, uart_input); /* 设置接收回调函数 */
  135. rt_thread_t thread = rt_thread_create("nmea", nmea_thread_entry, RT_NULL, 4096, 25, 10); /* 创建 serial 线程 */
  136. /* 创建成功则启动线程 */
  137. if (thread != RT_NULL)
  138. {
  139. rt_thread_startup(thread);
  140. }
  141. else
  142. {
  143. ret = RT_ERROR;
  144. }
  145. return ret;
  146. }
  147. /* 导出到 msh 命令列表中 */
  148. MSH_CMD_EXPORT(nmea_thread_init, nmea thread init);
  149. INIT_APP_EXPORT(nmea_thread_init);