STM32CubeIDE新建项目过程记录备忘(九) A/D转换并用串口定时上报

       本项目,是将一个模拟量A/D转换后用USART输出,用开发板上的芯片转换成RS232电平后定时上传给上位机。同时对最近的学习做一个总结,归纳记录一下从模板项目建立新项目的方法,以及底层代码应用代码分离的框架的建立。

  • 设置的流程

设置的流程简述:

        复制粘贴新项目 \rightarrow 更改.ioc文件名称 \rightarrow 设置GPIO管脚和外设功能 \rightarrow 设置时钟 \rightarrow 设置生成成对的.h和.c文件以及生成hex文件 \rightarrow 设置中断 \rightarrow 设置调试配置 \rightarrow 生成代码       


  • 软件的框架

        设置完成后就进入软件编程阶段。

  • 软件框架的大致套路:

        新建xxx_app.h和xxx_app.c文件 \rightarrow xxx_app.h内声明功能的初始化函数原型和功能函数原型 \rightarrow xxx_app.c的任务:系统内置的虚函数重新定义、中断回调函数重新定义或桥接、各种功能函数的定义等 \rightarrow main.c内运行各种功能的初始化函数以及调用自定义的功能函数


  • 创建一个新项目和配置阶段

1. 复制粘贴新项目
  • 打开已经存储在本地的模板项目:

  • 在项目管理器里鼠标右键复制之前创建好的模板项目,粘贴为新项目并重命名:

  • 项目管理器中模板文件上鼠标右键,删除模板项目,工作区只保留新项目:

 2. 更改.ioc文件的名称

3. 设置GPIO管脚 

这个项目用到的外设功能是ADC和USART,另外需要有定时器中断来控制定时上传数据。

双击.ioc文件,打开设置视窗:

        我的开发板,PA0、PA1、PA2和PA3都已有定义,并接有器件,所以不适合作为ADC的输入。这里选择IN4作为ADC输入,它对应的输入管脚是PA4:

4. 设置ADC参数

全部默认即可。

5. 打开ADC中断

6. 设置定时器

7. 设置USART

这里注意优先级的设定,USART最高,TIM其次,ADC最低。

7. 设置时钟

ADC的输入时钟不得超过14MHz,所以时钟设置这里要设为合适的分频比:

8、生成代码前的设置

选择“生成成对的.h和.c文件”。

设置生成hex文件:

资源管理器右键项目

9. 调试的设置

如果这里已有内容但不是本项目的名称,将其删除,并新建配置

调试器的设置:DAP.cfg是之前创建的模板项目中的文件,参见之前的文章。

10. 生成代码

        由于前面选择了“生成成对的.h和.c文件”,系统在生成代码时会对各个功能外设生成独立的文件,可以方便低管理和修改。


  • 软件编程阶段

1. 新建应用功能文件

        新建xxx_app.h和xxx_app.c文件,用以存放应用层的功能代码和函数:

        本项目,是将一个模拟量A/D转换后用USART输出,用开发板上的芯片转换成RS232电平后上传给上位机。用到的功能是A/D转换和USART通信以及定时器中断。所以新建了adc_app.h、adc_app.c和uart_app.h、uart_app.c以及tim_app.h、tim_app.c文件,用来存放相关功能的定义、函数等,方便项目管理和项目移植。

2. adc_app.h
#ifndef __ADC_APP_H
#define __ADC_APP_H

#include "stm32f1xx_hal.h"

void ADC_APP_Init(void);        // 声明adc应用初始化函数原型
uint16_t ADC_APP_GetValue(void); // 返回采样值的功能函数原型

#endif
3. adc_app.c
#include "adc_app.h"
#include "stm32f1xx_hal.h"   // 根据实际芯片型号调整

extern ADC_HandleTypeDef hadc1;   // Cube 生成的句柄

void ADC_APP_Init(void)
{
    HAL_ADC_Start(&hadc1);        // 软件触发,连续转换
}

uint16_t ADC_APP_GetValue(void)    // 获取采样值
{
    return HAL_ADC_GetValue(&hadc1);
}
4. uart_app.h
#ifndef __UART_APP_H
#define __UART_APP_H

#include "stm32f1xx_hal.h"   // 根据实际芯片型号调整

void UART_APP_Init(void);
void UART_APP_SendVoltage(uint16_t raw12);  // 发送格式 "RAW=1234\r\n"

#endif
5. uart_app.c
#include "uart_app.h"
#include <stdio.h>

extern UART_HandleTypeDef huart1;

static uint8_t txBuf[16];

void UART_APP_Init(void)
{
    /* Cube 已经初始化 huart1,这里什么都不用做 */
}

void UART_APP_SendVoltage(uint16_t raw12)
{
    int len = sprintf((char*)txBuf, "RAW=%04u\r\n", raw12);
    HAL_UART_Transmit(&huart1, txBuf, len, HAL_MAX_DELAY);
}
6. tim_app.h
#ifndef __TIM_APP_H
#define __TIM_APP_H

void TIM_APP_Init(void);   // main 里调用一次

#endif
7. tim_app.c
#include "tim_app.h"
#include "stm32f1xx_hal.h"
#include "adc_app.h"
#include "uart_app.h"

extern TIM_HandleTypeDef htim2;

void TIM_APP_Init(void)
{
    HAL_TIM_Base_Start_IT(&htim2);   // 启动中断
}

/* 在 stm32xxxx_it.c 里生成的 TIM2_IRQHandler 会自动调用 HAL_TIM_IRQHandler,
   HAL_TIM_IRQHandler 又会调用 HAL_TIM_PeriodElapsedCallback,我们只需重写它 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2)
    {
        uint16_t v = ADC_APP_GetValue();
        UART_APP_SendVoltage(v);
    }
}
8. main.c
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "adc_app.h"
#include "tim_app.h"
#include "uart_app.h"
/* USER CODE END Includes */
/* USER CODE BEGIN 2 */
  ADC_APP_Init();
  UART_APP_Init();
  TIM_APP_Init();
  /* USER CODE END 2 */

调试阶段

黄色齿轮、甲壳虫。但是发现并没有运行新的程序。

依次点击:

发现这里的.elf文件并不是本项目的。点击“Search Project...”

在弹出窗口选择本项目的.elf文件。点击“确定”。

再次运行调试,在上位机的仿真串口软件中接收到了上传的数据:

  • 程序的改进

        上面的程序,即使模拟量输入值发生变化,AD转换的数据值也是固定不变的。原因是ADC设置里面没有打开连续转换模式:

设置成连续转换模式后,就可以读取到变化的ADC数据了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

深蓝海拓

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

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

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

打赏作者

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

抵扣说明:

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

余额充值