使用 RT-Thread Studio 和 STM32CubeMx 开发驱动

本文详细介绍了如何使用RT-ThreadStudio和STM32CubeMx来开发STM32的驱动程序,包括新建RT-Thread工程,配置外设和系统时钟,复制和修改HAL库文件,以及初始化和使用ADC外设。文章强调了驱动开发的一些注意事项,如不直接使用CubeMx生成的工程,而是在RT-Thread工程中集成必要的代码。
摘要由CSDN通过智能技术生成

1 前言

本文参照官方参考文章,只不过官方的教程有些过时,在此基础上重新实现一遍。
注意:这里的驱动是指未对接到rtthread设备驱动框架的的驱动,对接需要自行实现。

2 简介

使用 RT-Thread Studio 和 STM32CubeMx 开发驱动可分为以下几个步骤

  • 使用 RT-Thread Studio 新建 RT-Thread 工程

  • 使用 STM32CubeMx 配置外设和系统时钟

  • 复制 stm32xxxx_hal_msp.c 函数

  • 修改 stm32xxxx_hal_config.h 文件,打开相应外设支持。

  • 替换 board.c 文件中时钟配置函数

  • 使用外设

3 实现

3.1 使用 RT-Thread Studio 新建 RT-Thread 工程

在这里插入图片描述
根据芯片型号配置工程
在这里插入图片描述
这是生成工程的完整目录结构,双击打开CubeMX Settings
在这里插入图片描述

3.2 使用 STM32CubeMx 配置外设和系统时钟

因为rtthread默认使用芯片内部时钟,目的是为了更加通用。所以我们打开后根据自己的开发板选择时钟,我这里以STM32F407霸天虎开发板为例配置时钟
在这里插入图片描述
在这里插入图片描述
然后我们简单的驱动一个ADC外设,配置如下
在这里插入图片描述
工程目录以及Toolchain/IDE随便选就好,因为我们只需要源码,不需要工程
在这里插入图片描述
这里最好不要为每个驱动单独生成一个文件,方便我们待会复制
在这里插入图片描述
选择好之后点击右上角的GENERATE CODE即可生成一个工程

3.3 复制 stm32xxxx_hal_msp.c 函数

生成的代码在rtthread studio的工程目录cubemx下,需要刷新一下工程目录才能看到
在这里插入图片描述
我们需要的是stm32f4xx_hal_msp.c这个文件
在这里插入图片描述

将 CubeMx 生成的代码 stm32l4xx_hal_msp.c 函数复制到 RT-Thread Studio 生成的工程中,并参与工程编译。复制完成后的结果如下图所示

adc-hal

由于我们并没有使用 CubeMx 生成的工程,所以这里需要将stm32l4xx_hal_msp.c 文件中 #include "main.h"替换为 #include "board.h"

3.4 修改 stm32xxxx_hal_config.h 文件,打开相应外设支持。

由于我们使能了ADC外设,所以我们需要在stm32f4xx_hal_conf.h中将ADC模块使能,即取消注释
在这里插入图片描述

3.5 替换 board.c 文件中时钟配置函数

首先找到在cubemx中生成的配置时钟的代码,复制下来
在这里插入图片描述
找到drv_clk.c中的system_clock_config函数替换该函数即可

如果使用外部时钟,则需要更新工程中的stm32xxxx_hal_conf.h 中的对应的外部时钟频率的值,以 HSE 为例,需要修改下面的时钟频率为实际使用的值:

#define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz 我这里是25MHz的外部晶振*/

3.6 使用外设

将cubemx生成的main.c中的MX_ADC_Init函数复制到工程中的main.c中进行ADC的初始化,即可正常使用ADC外设。

void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}
rt_uint32_t get_adc_value(void)
{
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);

    return (rt_uint32_t)HAL_ADC_GetValue(&hadc1);
}

int main(void)
{
    int count = 1;
    rt_uint32_t read_value = 0;

    MX_ADC1_Init();
    while (count++)
    {
        read_value = get_adc_value();
        rt_thread_mdelay(1000);
        rt_kprintf("adc value = %d\r\n", read_value);
    }

    return RT_EOK;
}
  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指针到处飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值