IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【ART-PI】RT-Thread 开启UART6 对接GPS模块 -> 正文阅读

[嵌入式]【ART-PI】RT-Thread 开启UART6 对接GPS模块

引言

  • 部分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

  • 可以使用GPS的工具,查看GPS的相关的数据

2022-02-23_110301.png

开发环境

  • GPS模组验证OK,就要使用【ART-Pi】串口接收解析数据了
  • 查看ART-Pi的原理图,找个合适的串口,最终选择了UART6(USART6)

2022-02-24_090035.png

  • 配置Kconfig,开启UART6
    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) 函数增加:
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)增加
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相关的:
  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;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;

软件调试

  • menuconfig 配置并使能UART6,scons --target=mdk5生成Keil MDK5工程,然后编译下载
  • 没用,还需要开启串口做GPS的接收操作
  • 测试一下uart6是否正常的工作:
#include <rtthread.h>

#ifndef GPS_UART_DEVICE_NAME
#define GPS_UART_DEVICE_NAME        "uart6"
#endif

#define DBG_TAG    "gps.uart"
#define DBG_LVL    DBG_INFO
#include <rtdbg.h>

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的串口收发
#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,更改的方法如下
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的调试
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:46:32  更:2022-02-26 11:46:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:34:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码