STM32CubeIDE新建项目过程记录备忘(九) A/D转换并用串口定时上报
本项目,是将一个模拟量A/D转换后用USART输出,用开发板上的芯片转换成RS232电平后定时上传给上位机。同时对最近的学习做一个总结,归纳记录一下从模板项目建立新项目的方法,以及底层代码应用代码分离的框架的建立。
设置的流程
设置的流程简述:
复制粘贴新项目 更改.ioc文件名称
设置GPIO管脚和外设功能
设置时钟
设置生成成对的.h和.c文件以及生成hex文件
设置中断
设置调试配置
生成代码
软件的框架
设置完成后就进入软件编程阶段。
- 软件框架的大致套路:
新建xxx_app.h和xxx_app.c文件 xxx_app.h内声明功能的初始化函数原型和功能函数原型
xxx_app.c的任务:系统内置的虚函数重新定义、中断回调函数重新定义或桥接、各种功能函数的定义等
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_Hvoid 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 */
调试阶段
黄色齿轮、甲壳虫。但是发现并没有运行新的程序。
依次点击:
发现这里的.elf文件并不是本项目的。点击“Search Project...”
在弹出窗口选择本项目的.elf文件。点击“确定”。
再次运行调试,在上位机的仿真串口软件中接收到了上传的数据: