西电大二微控制项目个人作业软件部分总结。
临时通知需要用stm32f401仿真,于是使用cubemx写了HAL库版本,各种问题折磨了我将近两天 本篇总结记录一下遇到的问题。
一. 所需软件:
Proteus、Keil5、VSPD、串口调试助手(XCOM)、Stm32CubeMX
二.Proteus部分
详细步骤可以参考:
proteus创建工程、芯片选择、元件配置操作方法
1.接线图
所需元器件:
a)整体图
b)LCD部分
注.红色的是可变电阻,器件名为POT-HG
c)串口
d)温度传感器
注.与单片机连接时需将虚拟串口的RX与单片机的RX连接(TX同理)
e)电机
f)单片机部分
2.各项参数配置
a)电源均配置为+5V,注意接地
注. 单片机上的VSSA(VREF+)要接地并且VDDA要接+5V(给ADC提供参考电压,否则ADC读取数据会异常)
b)双击单片机配置
c)虚拟串口配置如下
三.CUBEMX部分
1. 引脚图
2.GPIO
3. UART
4.ADC
5.SYS
SYS如果不设置为Serial Wire串口会接收不到数据
6.时钟
7.NVIC
四.Keil部分
Keil部分需具备STM32的HAL库基础知识
1.LCD(HAL库版)
a)管脚连接
#define LCD_E GPIO_PIN_9
#define LCD_RS GPIO_PIN_8
#define LCD_D0 GPIO_PIN_0
#define LCD_D1 GPIO_PIN_1
#define LCD_D2 GPIO_PIN_2
#define LCD_D3 GPIO_PIN_3
#define LCD_D4 GPIO_PIN_4
#define LCD_D5 GPIO_PIN_5
#define LCD_D6 GPIO_PIN_6
#define LCD_D7 GPIO_PIN_7
b)代码.c
#include "lcd.h"
#define LCD_E GPIO_PIN_9
#define LCD_RS GPIO_PIN_8
#define LCD_D0 GPIO_PIN_0
#define LCD_D1 GPIO_PIN_1
#define LCD_D2 GPIO_PIN_2
#define LCD_D3 GPIO_PIN_3
#define LCD_D4 GPIO_PIN_4
#define LCD_D5 GPIO_PIN_5
#define LCD_D6 GPIO_PIN_6
#define LCD_D7 GPIO_PIN_7
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6
|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_SET);
/*Configure GPIO pins : PB0 PB1 PB2 PB10
PB3 PB4 PB5 PB6
PB7 PB8 PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6
|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void Lcd_ready(){
Lcd_write_cmd(0x38);
Lcd_write_cmd(0x0C);//开显不显示光标
Lcd_write_cmd(0x06);//写一个指针加一
Lcd_clear();//清屏
Lcd_write_cmd(0x80);//设置数据指针起点
}
void Lcd_write(uint8_t data){
HAL_GPIO_WritePin(GPIOB, LCD_D7 , (GPIO_PinState)((data & 0x80) >>7));//取出数据第8位并向右移7位
HAL_GPIO_WritePin(GPIOB, LCD_D6 , (GPIO_PinState)((data & 0x40) >>6));//其余同理
HAL_GPIO_WritePin(GPIOB, LCD_D5 , (GPIO_PinState)((data & 0x20) >>5));
HAL_GPIO_WritePin(GPIOB, LCD_D4 , (GPIO_PinState)((data & 0x10) >>4));
HAL_GPIO_WritePin(GPIOB, LCD_D3 , (GPIO_PinState)((data & 0x08) >>3));
HAL_GPIO_WritePin(GPIOB, LCD_D2 , (GPIO_PinState)((data & 0x04) >>2));
HAL_GPIO_WritePin(GPIOB, LCD_D1 , (GPIO_PinState)((data & 0x02) >>1));
HAL_GPIO_WritePin(GPIOB, LCD_D0 , (GPIO_PinState)((data & 0x01)));
}
void Lcd_clear(){
Lcd_write_cmd(0x01);
}
void Lcd_set_coord(uint8_t x, uint8_t y){
uint8_t x_show;
if(y==0){
x_show = x;//如果是第一行则x坐标为x
}else{
x_show = x + 0x40;//如果为第二行则x坐标需要加0x40
}
Lcd_write_cmd(x_show | 0x80);//取得最终坐标
}
void Lcd_write_cmd(uint8_t cmd){
HAL_GPIO_WritePin(GPIOB,LCD_RS,GPIO_PIN_RESET);//RS置低电平
Lcd_write(cmd);//写指令
Delay_us(5);
HAL_GPIO_WritePin(GPIOB,LCD_E,GPIO_PIN_SET);//使能
Delay_us(5);
HAL_GPIO_WritePin(GPIOB,LCD_E,GPIO_PIN_RESET);//失能
Delay_ms(5);
}
void Lcd_write_data(uint8_t data){
HAL_GPIO_WritePin(GPIOB,LCD_RS,GPIO_PIN_SET);//RS置高电平
Lcd_write(data);//写数据
Delay_us(5);
HAL_GPIO_WritePin(GPIOB, LCD_E,GPIO_PIN_SET);
Delay_us(5);
HAL_GPIO_WritePin(GPIOB, LCD_E,GPIO_PIN_RESET);
Delay_ms(5);
}
void Lcd_write_ch(uint8_t x, uint8_t y, uint8_t ch){
Lcd_set_coord(x, y);//写坐标
Lcd_write_data(ch);//在坐标上写入字符
}
void Lcd_write_str(uint8_t x, uint8_t y, uint8_t *str){
Lcd_set_coord(x, y);//写入坐标
while(*str != '\0'){
Lcd_write_ch(x , y, *str);//取出数组中的首地址,数组本质是指针
x += 1;//每写一个字符x坐标右移一位
str++;//字符指针右移一位
}
}
uint32_t Lcd_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X;
}
return Result;
}
void Lcd_write_num(uint8_t x, uint8_t y, uint32_t num, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
Lcd_write_ch(x + i, y, num/ Lcd_Pow(10, Length - i - 1) % 10 + '0');
}
}
c)代码.h
#ifndef __LCD_H
#define __LCD_H
#include "main.h"
#ifdef __cplusplus
extern "C" {
#endif
void LCD_init(void);
void Lcd_ready(void);
void Lcd_write(uint8_t data);
void Lcd_clear(void);
void Lcd_set_coord(uint8_t x, uint8_t y);
void Lcd_write_cmd(uint8_t cmd);
void Lcd_write_data(uint8_t data);
void Lcd_write_ch(uint8_t x, uint8_t y, uint8_t ch);
void Lcd_write_str(uint8_t x, uint8_t y, uint8_t *str);
void Lcd_write_num(uint8_t x, uint8_t y, uint32_t num, uint8_t Length);
void LCD_Init(void);
#ifdef __cplusplus
}
#endif
#endif
2.main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2024 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include "stdio.h"
#include "lcd.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */;
char *strx,*extstrx,*Readystrx;
char RxBuffer[200],Rxcouter; //存放接收的数据
extern char RxBuffer[200],Rxcouter;
char *strstr(const char *, const char *);//比较字符是否一样,判断是否接收到运行命令
uint8_t Res;//存放接收数据
float tem = 0;//存放温度数据
uint16_t ADC_Value = 0;//接收ADC原始数据
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#include "stm32f4xx.h" // Device header
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
/**
* 函数功能: 比较温度值若大于等于24则电机正转,小于24则停止
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Compare()
{
if((int)tem>=24)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
}
}
/**
* 函数功能: UART中断回调函数
* 输入参数: uart结构体
* 返 回 值: 无
* 说 明:无
*/
void HAL_UART_RxCpltCallback (UART_HandleTypeDef *huart){
UNUSED (huart);
if(huart->Instance ==USART1)
{
RxBuffer[Rxcouter++]= Res ;
HAL_UART_Receive_IT(&huart1,(uint8_t *)&Res, 1);
}
}
/**
* 函数功能: ADC中断回调函数
* 输入参数: adc结构体
* 返 回 值: 无
* 说 明:无
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
ADC_Value = HAL_ADC_GetValue(&hadc1);
tem = ADC_Value*500/4096.0;
}
HAL_ADC_Stop_IT(&hadc1);
}
/**
* 函数功能: 清除中断寄存器缓存
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Clear_Buffer(void) {
uint8_t i;
for(i=0;i<Rxcouter;i++)
RxBuffer[i]=0;
Rxcouter=0;
}
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1,&Res,1); //uart接收数据
LCD_Init(); //lcd屏幕时钟初始化
Lcd_ready(); //lcd屏幕显示参数初始化
Lcd_write_str(0,0,(uint8_t *)"TEMPERATURE:"); //lcd第一行显示TEMPERATURE:
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
strx=strstr((const char*)RxBuffer,(const char*)"运行"); //判断串口是否接收到运行命令
if(strx!=NULL) //如果接收到
{
Clear_Buffer(); //清除缓存,用于下一次接收
printf("OK\r\n"); //串口打印OK
while(1)
{
HAL_ADC_Start_IT(&hadc1); //开始ADC转换
Compare(); //比较温度,判断是否开启电机
printf("%d\r\n",(int)tem); //串口打印温度
Lcd_write_num(0,1,tem,2); //lcd显示温度
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
由于lcd用到了Delay函数,所以将Delay函数写在了main.c里。因此需要在main.h里声明函数
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2024 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
//声明Delay函数
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
3.main.c中所添加的代码
a)uart
/**
* 函数功能: UART中断回调函数
* 输入参数: uart结构体
* 返 回 值: 无
* 说 明:无
*/
void HAL_UART_RxCpltCallback (UART_HandleTypeDef *huart){
UNUSED (huart);
if(huart->Instance ==USART1)
{
RxBuffer[Rxcouter++]= Res ;
HAL_UART_Receive_IT(&huart1,(uint8_t *)&Res, 1);
}
}
/**
* 函数功能: 清除中断寄存器缓存
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Clear_Buffer(void) {
uint8_t i;
for(i=0;i<Rxcouter;i++)
RxBuffer[i]=0;
Rxcouter=0;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
b)ADC
/**
* 函数功能: ADC中断回调函数
* 输入参数: adc结构体
* 返 回 值: 无
* 说 明:无
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
ADC_Value = HAL_ADC_GetValue(&hadc1);
tem = ADC_Value*500/4096.0;
}
HAL_ADC_Stop_IT(&hadc1);
}
c)比较温度函数
/**
* 函数功能: 比较温度值若大于等于24则电机正转,小于24则停止
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Compare()
{
if((int)tem>=24)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
}
}
d)Delay函数
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
五.VSPD
第一次使用点击Add Pair即可(添加的串口对要和虚拟串口里设置的对应
六 .XCOM串口助手
波特率设置要与虚拟串口、STM32的设置保持一致
直接发送 运行 即可。
七 .Proteus导入HEX文件
Keil程序需要生成HEX文件
1.点击KEIL魔法棒
2.点击output
3.点击生成HEX文件
4.进入proteus双击单片机并选择程序路径,选择刚刚生成的HEX文件进行仿真即可
八.实验现象
九.问题总结
1.串口接收不到数据或接收到乱码
解决方法:a)调整波特率让单片机、虚拟串口、cubemx里的设置一致
b)cubeMX里SYS调整至Serial Wire
c)接收到乱码可能是由于Keil与串口调试助手编码格式不同导致的
将二者编码格式调为一至后解决问题
2.串口无法判断是否接收到运行命令
解决办法:main函数里加入以下代码
strx=strstr((const char*)RxBuffer,(const char*)"运行");
3.ADC无法收到数据
解决办法:a)注意ADC所涉及到的变量要定义为全局变量,不能在写函数时定义一次
主函数里再定义一次,这样会导致变量取值错误。
b)注意自己的代码要写在/* USER CODE BEGIN x */到
/* USER CODE END 2 */之间
不能写在
/* USER CODE BEGIN Init */
/* USER CODE END Init */间。
否则会导致初始化失败。
c) 转换公式数据类型不匹配.ADC_Voltage = ADC_Value / 4096 * 3.3,
把4096更换为4096.0后解决问题,因为输出电压ADC_Voltage
为浮点型数据。
d)也可能是未设置参考电压,解决办法为
单片机上的VSSA要接地并且VDDA要接+5V。
4.Printf有关
问题描述:使用 printf(”%f“,tem);打印温度到串口时,串口一直显示0.00000。
解决办法:a)printf只能打印整形数据,把%f改为%d后问题解决。
5. Keil使用cubeMX生成代码时的.c和.h文件存放问题
解决办法:.c文件存在Core的Inc下、.h文件存在Core的Src下。