Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
ART-Pi
GPS
UART
【ART-PI】RT-Thread 开启UART6 对接GPS模块
发布于 2022-02-24 09:22:08 浏览:1942
订阅该版
[tocm] [RT-Thread 入门学习笔记 - 目录](https://club.rt-thread.org/ask/article/3420.html) [【ART-PI】STM32H750XBH6 - 入手篇](https://club.rt-thread.org/ask/article/2462.html) [【ART-PI】STM32H750XBH6 - RT-Thread 最小系统移植](https://club.rt-thread.org/ask/article/2469.html) [【ART-PI】RT-Thread Freemodbus RS485 RTU 从机](https://club.rt-thread.org/ask/article/2477.html) [【ART-PI】RT-Thread 开启RTC 与 Alarm组件](https://club.rt-thread.org/ask/article/2501.html) [【ART-PI】STM32H750XBH6 RT-Thread 点亮LCD](https://club.rt-thread.org/ask/article/2676.html) [【ART-PI】RT-Thread 开启UART6 对接GPS模块](https://club.rt-thread.org/ask/article/3406.html) ## 引言 - 部分GPS模组使用的是串口,对接GPS模块,调通串口就可以了 - 如果使用的是GPS芯片,接口可能是I2C、SPI、UART等,就需要对接 - 我这里单独注册一个gps设备,用于对接各类接口的GPS芯片,GPS设备对于上层应用来讲,就算是一个字符设备而已 ## GPS模块验证 - 硬件使用:【ART-Pi】,当然其他的STM32相关的MCU,依旧可以。为何使用ART-Pi,因为这是我的验证环境 - 我使用的是UBLOX GPS模组:这个模组是串口的,对外4根线:VCC(+3V~+5V,我使用+3.3V),GND,RX、TX - 首先让GPS模组先能定到位,电脑使用USB转串口,能获取到GPS模组吐出的数据 - 验证下来,串口的收发要正确,尤其是USB转串口能配置电平的,配置为+3.3V的。这个GPS模组,耗电较大,大概有70mA左右的电流,再就是室内定位很难,使用GPS长的天线,放在窗户旁边,注意GPS天线的朝向,朝外效果会更好。 ![2022-02-23_105611.png](https://oss-club.rt-thread.org/uploads/20220224/6426ac80a832db33249118cf9edc3548.png.webp) - 可以使用GPS的工具,查看GPS的相关的数据 ![2022-02-23_110301.png](https://oss-club.rt-thread.org/uploads/20220224/704c810d6cbd315d3c7dce69f6672bc9.png.webp) ## 开发环境 - GPS模组验证OK,就要使用【ART-Pi】串口接收解析数据了 - 查看ART-Pi的原理图,找个合适的串口,最终选择了UART6(USART6) ![2022-02-24_090035.png](https://oss-club.rt-thread.org/uploads/20220224/0eb0ab8af558d84fac8166d277aaf174.png.webp) - 配置Kconfig,开启UART6 ```c config BSP_USING_UART6 bool "Enable UART6" select RT_USING_SERIAL default n ``` - 配置UART6的引脚,可以使用:STM32CubeMX图形配置好,生成,然后更新到工程的`stm32h7xx_hal_msp.c`文件 `void HAL_UART_MspInit(UART_HandleTypeDef* huart)` 函数增加: ```c else if(huart->Instance==USART6) { /* USER CODE BEGIN USART6_MspInit 0 */ /* USER CODE END USART6_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_USART6_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); /**USART6 GPIO Configuration PC7 ------> USART6_RX PC6 ------> USART6_TX */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART6; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* USER CODE BEGIN USART6_MspInit 1 */ /* USER CODE END USART6_MspInit 1 */ } ``` - `void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) `增加 ```c else if(huart->Instance==USART6) { /* USER CODE BEGIN USART6_MspDeInit 0 */ /* USER CODE END USART6_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART6_CLK_DISABLE(); /**USART6 GPIO Configuration PC7 ------> USART6_RX PC6 ------> USART6_TX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_7|GPIO_PIN_6); /* USER CODE BEGIN USART6_MspDeInit 1 */ /* USER CODE END USART6_MspDeInit 1 */ } ``` - 配置 UART6的时钟,这里修改:board.c 中的:`system_clock_config`,增加UART6相关的: ```c PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC|RCC_PERIPHCLK_USART3 |RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_SPI4 |RCC_PERIPHCLK_UART5|RCC_PERIPHCLK_USART6 |RCC_PERIPHCLK_SPI1|RCC_PERIPHCLK_SDMMC |RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_USB |RCC_PERIPHCLK_FMC; ``` ```c PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2; ``` ## 软件调试 - menuconfig 配置并使能UART6,`scons --target=mdk5`生成Keil MDK5工程,然后编译下载 - 没用,还需要开启串口做GPS的接收操作 - 测试一下uart6是否正常的工作: ```c #include
#ifndef GPS_UART_DEVICE_NAME #define GPS_UART_DEVICE_NAME "uart6" #endif #define DBG_TAG "gps.uart" #define DBG_LVL DBG_INFO #include
static rt_device_t gps_uart_dev = RT_NULL; static rt_thread_t gps_uart_thread = RT_NULL; static rt_err_t gps_uart_rx_ind(rt_device_t dev, rt_size_t size) { LOG_E("%s", __func__); return RT_EOK; } rt_err_t gps_uart_open(void) { gps_uart_dev = rt_device_find(GPS_UART_DEVICE_NAME); if (gps_uart_dev != RT_NULL) { rt_device_open(gps_uart_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX); rt_device_set_rx_indicate(gps_uart_dev, gps_uart_rx_ind); return RT_EOK; } else { LOG_E("%s : gps uart error!", __func__); return -RT_ERROR; } } void gps_uart_thread_entry(void *param) { rt_thread_mdelay(5000); gps_uart_open(); while (1) { rt_thread_mdelay(5000); rt_device_write(gps_uart_dev, 0, "gps uart ok", rt_strlen("gps uart ok")); } } int gps_uart_test(void) { if (gps_uart_thread != RT_NULL) { LOG_I("%s gps uart thread already!", __func__); return -RT_ERROR; } gps_uart_thread = rt_thread_create("gps_uart", gps_uart_thread_entry, RT_NULL, 1024, 20, 30); if (gps_uart_thread != RT_NULL) { rt_thread_startup(gps_uart_thread); LOG_D("%s gps uart thread ok!", __func__); } else { LOG_E("%s gps uart thread failed!", __func__); } return 0; } MSH_CMD_EXPORT(gps_uart_test, gps_uart_test); ``` - 【总结】 > 串口需要使能【接收中断】,需要在open 时,增加标志位 : RT_DEVICE_FLAG_INT_RX > rt_device_open(gps_uart_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX); > 这样,串口驱动才会配置串口接收中断,接收数据后,会调用: > `rt_device_set_rx_indicate(gps_uart_dev, gps_uart_rx_ind);` > 设置的回调函数:`gps_uart_rx_ind`,我开始没在意,发现串口能发送,不能接收,我以为引脚配 > 置错了,后来软件一步步调试,发现忘了这个标志位:`RT_DEVICE_FLAG_INT_RX` - drv_gps.c :实现 gps的串口收发 ```c #include "drv_gps.h" #include "board.h" #ifndef BSP_GPS_DEVICE_NAME #define BSP_GPS_DEVICE_NAME "gps" #endif #ifndef GPS_UART_DEVICE_NAME #define GPS_UART_DEVICE_NAME "uart6" #endif #define GPS_UART_BAUDRATE BAUD_RATE_9600 static struct rt_device _gps_dev; static rt_device_t gps_uart_dev = RT_NULL; static rt_bool_t gps_uart_open_flag = RT_FALSE; static rt_err_t _gps_dev_init(rt_device_t dev) { return RT_EOK; } static rt_err_t gps_uart_rx_ind(rt_device_t dev, rt_size_t size) { RT_ASSERT(dev != RT_NULL); if (_gps_dev.rx_indicate != RT_NULL) { _gps_dev.rx_indicate(&_gps_dev, size); } return RT_EOK; } static rt_err_t _gps_dev_open(rt_device_t dev, rt_uint16_t oflag) { struct serial_configure gps_uart_config = RT_SERIAL_CONFIG_DEFAULT; if (dev == RT_NULL) return -RT_ERROR; gps_uart_dev = rt_device_find(GPS_UART_DEVICE_NAME); if (gps_uart_dev != RT_NULL) { if (gps_uart_open_flag == RT_FALSE) { gps_uart_config.baud_rate = GPS_UART_BAUDRATE; rt_device_control(gps_uart_dev, RT_DEVICE_CTRL_CONFIG, &gps_uart_config); rt_device_open(gps_uart_dev, oflag); rt_device_set_rx_indicate(gps_uart_dev, gps_uart_rx_ind); gps_uart_open_flag = RT_TRUE; } } return RT_EOK; } static rt_err_t _gps_dev_close(rt_device_t dev) { rt_err_t ret = RT_EOK; if (gps_uart_open_flag == RT_TRUE) { ret = rt_device_close(gps_uart_dev); gps_uart_open_flag = RT_FALSE; } return ret; } rt_size_t _gps_dev_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { return rt_device_read(gps_uart_dev, pos, buffer, size); } rt_size_t _gps_dev_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { return rt_device_write(gps_uart_dev, pos, buffer, size); } static rt_err_t _gps_dev_control(rt_device_t dev, int cmd, void *args) { if (dev == RT_NULL) return -RT_ERROR; switch (cmd) { default: break; } return RT_EOK; } #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops gps_dev_ops = { _gps_dev_init, _gps_dev_open, _gps_dev_close, _gps_dev_read, _gps_dev_write, _gps_dev_control }; #endif static int gps_device_register(const char *name, void *user_data) { _gps_dev.type = RT_Device_Class_Char; _gps_dev.rx_indicate = RT_NULL; _gps_dev.tx_complete = RT_NULL; #ifdef RT_USING_DEVICE_OPS _gps_dev.ops = &gps_dev_ops; #else _gps_dev.init = _gps_dev_init; _gps_dev.open = _gps_dev_open; _gps_dev.close = _gps_dev_close; _gps_dev.read = _gps_dev_read; _gps_dev.write = _gps_dev_write; _gps_dev.control = _gps_dev_control; #endif _gps_dev.user_data = user_data; /* register device */ rt_device_register(&_gps_dev, name, RT_DEVICE_FLAG_RDWR); return 0; } int gps_device_init(void) { return gps_device_register(BSP_GPS_DEVICE_NAME, RT_NULL); } INIT_BOARD_EXPORT(gps_device_init); ``` - 这里使用【套娃】方式,注册一个gps 设备,实际调用:uart6 串口设备 - 【小结2】GPS串口波特率的调整方法,默认初始化为:115200,这里GPS模块默认是:9600,更改的方法如下 ```c struct serial_configure gps_uart_config = RT_SERIAL_CONFIG_DEFAULT; gps_uart_config.baud_rate = GPS_UART_BAUDRATE; rt_device_control(gps_uart_dev, RT_DEVICE_CTRL_CONFIG, &gps_uart_config); ``` - `RT_DEVICE_CTRL_CONFIG` control命令,最终会调用drv_usart.c 中的 configure函数,重新配置串口 ## 调试 - 底层的UART6 已经搭建好,上层只需要做好接收,并解析GPS接收的数据即可。 - 上层的接收,可以参考:虚拟GPS设备的实现那篇文章 ## 小结 - 熟悉了一下uart串口的接收配置、波特率设置方法 - 熟悉了GPS的调试
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
809
被采纳
175
关注TA
发私信
相关文章
1
rt thread 2.0.2 usart 接收缓存问题
2
关于STM32串口通信的问题
3
STM32F1+RTT串口接收终端数据丢失问题
4
UART TX丢数据?
5
RTT打开串口的时候如何自定义波特率呢?
6
STM32F4的USART数据接收问题
7
串口1234使用问题
8
串口接收回调函数
9
LPC18xx UART问题讨论
10
x1000串口配置的失败问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部