基于proteus和CubeMx的联合温度检测控制仿真系统——微控个人项目

温度检测控制仿真系统

软件环境

  • proteus8.17 win64
  • VSPD
  • sscom或Xcom
  • keil
  • stm32CubeMx

功能要求::

1.MCU通过串行接口组件与上位机PC进行双向通信,PC机用串口调试助 手软件向MCU发送“运行”命令,MCU收到后向PC机发送“OK”。 PC机上 的串口调试助手软件接收窗口显示收到的字符串“OK”。

2. MCU控制驱动直流电 机,当环境温度低于预定的温度(摄氏25°+(学号末3位数的和/3))时,直流 电机停止转动;当环境温度等于或高于预定的温度(摄氏25°+(学号末3位数 的和/3))时,启动直流电机转动

3.同时,实时环境温度在 LCD 上显示,LCD 第一行显示TEMPRATURE:第二行显示摄氏温度值。

4.MCU 向PC 机发送实时环境温度。PC机上的串口调试助手软件接收窗口显示收到的 实时环境温度。

如:学生学号末3位数为“078”,手动增加温度等于或超过设 定的温度值30°(25+(0+7+8)/3=30)时,驱动直流电机开始顺时针方向转动。 预定的温度值如果有小数部分,按照“四舍五入”取整。

系统框图如下:

 

备注:在最近的更新中,我将相关的工程文件资源上传并绑定该文。但是由于没有注意,资源仅VIP可见,且我这边似乎没有修改权限,各位同学如果没有会员不必理会,相关代码在文章中已给出。

一、proteus的安装与原理图绘制

(1)proteus的安装

proteus 8.17安装包
链接: https://pan.baidu.com/s/1234ejVVuMXblklUHeuX5Eg 提取码: XDer 

解压后获得以下几个文件

 选择setup,右键以管理员身份运行

 

修改安装路径,之后next下一步

 

一直next,等待安装完成后,点finish退出 ;

在桌面选中proteus 8,右键打开文件所在位置

退到上一级,也就是Proteus 8 Professional目录下

​ 

将解压文件夹里的Translations文件夹复制到上图Proteus 8 Professional目录下

​ 

替换目标中的文件 

打开proteus,如图所示,破解完成;

​ 

(2)系统原理图绘制

1. proteus工程文件可在此获取:temp_dect.rar

temp_dect
链接: https://pan.baidu.com/s/1-5Tr6jQj3Kh0p19cN6jI-g 提取码: XDer 

提示:最近有同学反应使用上面的工程后最后仿真没有反应,一般都是原理图问题。proteus在绘制原理图时尽量不要复制粘贴,有条件可以自己尝试跟着画一下。

新版经测试,理论上可以正常使用:temp_csdndemo.zip
https://pan.baidu.com/s/1NiaD9GfxGUjv5QApQX836w 

提取码:XDER

完整原理图如下:

 2. 创建工程文件和原理图绘制过程

2.1 打开proteus,点击“新建工程”,修改工程名称和路径(自测一般中文名称和路径不会有影响)

 2.2 next

 

2.3 选择创建固件项目,选择芯片,一直next后点finish创建完成

​ 

 刚创建好的工程原理图如下:

完整系统的原理图绘制见下一篇文章

二、虚拟串口软件与串口调试助手

虚拟串口软件:VSPD,

串口调试助手:XCOM或sscom (本文以sscom为例)

安装包以下获取:
链接: https://pan.baidu.com/s/1CRrg1uou8ebfhKms-I05rg 提取码: XDer 
 

(1)虚拟串口软件VSPD的安装,破解,使用

1. 下载安装包后,解压;运行vspd进行安装

2.点击OK

3.点击next后,同意协议再点击next 

​ 

​ 

4.更改为自己的路径后,一直next,直至安装(install)

​ 

5.安装完成后,先不运行,将 解压文件中的vspdctl.dll 文件复制到安装的工程目录中,覆盖原有文件,即完成破解 

​ 

6.破解后,打开vspd

​ 

7.点击add pair,创建虚拟串口对(我这里已经创建过,即COM1和COM2,可在左侧栏看出) 

​ 

8. 可以在设备管理器中查看创建的虚拟串口:按下win+X,点击设备管理器,即可在端口项中看到虚拟串口COM1和2。

​ 

(2)串口调试助手的使用

1.解压后直接打开即可(其实不解压也能使用)(该软件打开后稍卡,但是博主懒得换😂)

2.可以在左下角直接选择端口和设置波特率,也可以在左上方串口设置处选择端口并设置波特率等;

​ 

3. 发送数据时,先设置好串口,打开串口后输入数据并发送即可

4.如果有中文,可以在上方点击显示,字体,设置字体和字符集,如:中文GB2312

​ 

5.为了保证proteus仿真时串口之间的正确的数据传输,proteus原理图中的虚拟串口也需要设置端口和波特率等,端口选择与sscom中成对的虚拟串口,波特率等设置一致。

proteus中,选中COMPIM,右键,选择编辑属性;设置端口和波特率等。

​ 

​ 

三、Keil的安装

相关安装包:

Keil.rar
链接: https://pan.baidu.com/s/1NaqXRzFadHUkIu_ancpsNw 提取码: XDer 

1. 下载解压后得到以下文件,详细安装过程参考PDF:Keil集成开发环境的安装

​ 

2.注意:由于已经提供相关软件包,PDF安装教程中的从官网获取可以跳过,直接从以下开始

​ 

四、stm32cubeMX 安装

相关安装包:cubemx
链接: https://pan.baidu.com/s/1CdUxKKWcG-dWRm8b8XjU5g 提取码: XDer 

下载并解压后,可以得到以下文件:

(1)安装Java环境

选择安装环境文件夹,根据自己情况选择64位或32位


以64位为例,打开两个任意一个安装包,勾选更改目标文件夹,点击安装;

选择合适的安装目录,点击 下一步;

等待自动安装;安装完毕后,点击 关闭;

在开始菜单中搜Java,看到下图即代表安装成功。

安装成功后,配置环境变量:右键此电脑,点击“属性”,点击高级系统设置

新建系统变量,点击新建,变量名为JAVA_HOME,路径改为自己的路径

 步骤同上,新建一个CLASSPATH,变量值为:

.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar

 然后找到path环境变量,双击进去

%JAVA_HOME\bin
%JAVA_HOME\jre\bin

 注意下面的改为自己的路径

C:\Program Files\Java\jdk-1.8\bin

接下来检验:按下win+R,输入cmd,打开命令行

 分别输入java -version,java,javac,回车

输出以上信息,没有“不是内部或外部命令”的输出就是配置成功 

(2) CubeMX 安装

在以下路径中,找到cubemx安装包


解压任意一个后,打开 SetupSTM32CubeMX-6.x.x.exe 文件,如果未安装 Java 环境或没有配置环境变量,将会出现以下报错:

安装 Java 并配置环境变量后,重新打开 SetupSTM32CubeMX-6.x.x.exe 文件,点击 Next;

勾选 I accpt,点击 Next;

勾选第一个,点击 Next;


选择合适的安装路径,点击 Next;(若路径未创建,会提示路径将被创建)


根据需求勾选,点击 Next;

程序自动安装,安装完成后,一直点击 Next,点击 Done结束;

打开 STM32CubeMX 软件,软件界面如下。

五、CubeMx新建工程并进行芯片配置

 (1)修改默认配置

        新建工程之前,建议先修改PACK安装地址。pack是需要额外下载的对芯片的支持包,默认的安装位置是C盘,会非常占用C盘空间,在此将其改到其他内存盘。
点击最上方一栏的HELP按钮,并打开update setting选项,如图:

修改Repository Folder里面的文件夹路径即可将PACK安装路径修改到其他磁盘。

(2)新建工程 

1. 选中菜单栏File,点击New Project新建工程

2.在左上方搜索框中搜索要使用的MCU(或在左侧选择栏逐步筛选找到),本项目使用STM32F411RE芯片;找到后双击芯片即可直接建立工程(或选中芯片后,点击右上角START PROJECT)


4.STM32CUBEMX工程配置修改
        点击上侧菜单栏的Project Manager,打开后如下,然后设置工程名称;修改工程路径,注意不要有中文路径。在TOOLCHAIN出修改编译工具,我们使用的Keil,因此选择 MDK ARM。

点击最左边的Code Generate,进入代码生成的配置界面,推荐勾选下面的选项(这个选项默认是不勾选的),勾选之后代码会更加清晰明了。

5.生成代码
基本配置完成后,可以开始生成代码,(到这里我们没有进行有关芯片的配置,等下再进行,先了解生成代码的步骤),点击GENERATE CODE 按钮

如果点击后提示以下界面,即缺少依赖包,是否自动下载,点击yes即可

 

生成成功后,点击“Open porject”直接打开项目。如果提示生成失败请检查是否存在中文路径。


工程自动调用keil5打开,如图所示

注:可以关闭browse information以提示编译速度,步骤如下:

先点击这个按钮;然后在最上面一行选择output;把browse information选项取消勾选,然后点击确定,完成修改。此时按下F7进行编译,可以极大提升编译速度。

六、CubeMx配置芯片

根据原理图:以下引脚均需配置

 1. LCD相关引脚:

RS,RW,E,D0~D7与LCD连接,进行以下配置:点击pinout进行引脚配置,点击右图芯片对应引脚,配置为GPIO_Output,选择左侧system Core下的GPIO,在中间栏对每个引脚进行详细配置,GPIO_output level 改为high。“User Label”可以设置为原理图中的label

2.LM温度传感器相关:

ADC连接PA7。在右侧点击芯片对应的PA7,配置为ADC_IN7。ADC相关属性可以在左侧Analog栏下选择ADC1,点击中间栏的“parameter Settings”查看。

3.电机有关管脚:

IN1,IN2,ENA;对应PA11,12,13。与1同方法,点击右图芯片对应引脚,配置为GPIO_Output,选择左侧system Core下的GPIO,在中间栏对对应引脚进行详细配置,如图所示“User Label”可以设置为原理图中的label。

4.串口配置

串口有关引脚:TXD,RXD,对应PA2,PA3。首先选择connectivity下的USART2,将Mode改为“Asynchronous”,在“parameter Settings”下将波特率改为9600;再点击NVIC settings,勾选enable

至此,我们用到的所有管脚均配置完成,点击右上角的“GENERATE CODE”,再次生成代码。

接下来,就需要根据我们的功能要求,写出对应的代码了。

七、在Keil中写入相关代码

1.LCD相关:(.c和.h文件)

LCD1602.c

#include "LCD1602.h"


//D0-D7设定方向:I-输入;O-输出
void DataDir(char dir)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	HAL_GPIO_WritePin(GPIOC, D0_Pin|D1_Pin|D2_Pin|D3_Pin|D4_Pin|D5_Pin|D6_Pin|D7_Pin, GPIO_PIN_SET);
	GPIO_InitStruct.Pin = D0_Pin|D1_Pin|D2_Pin|D3_Pin|D4_Pin|D5_Pin|D6_Pin|D7_Pin;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	if(dir == 'I')
	{
		GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	}
	else if(dir == 'O')
	{
		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	}
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

//D0-D7读数据
uint8_t ReadData()
{
	uint8_t dat=0;
	//DataDir('I');
	if(HAL_GPIO_ReadPin(GPIOC, D0_Pin)==GPIO_PIN_SET) dat|=0x01;
	if(HAL_GPIO_ReadPin(GPIOC, D1_Pin)==GPIO_PIN_SET) dat|=0x02;
	if(HAL_GPIO_ReadPin(GPIOC, D2_Pin)==GPIO_PIN_SET) dat|=0x04;
	if(HAL_GPIO_ReadPin(GPIOC, D3_Pin)==GPIO_PIN_SET) dat|=0x08;
	if(HAL_GPIO_ReadPin(GPIOC, D4_Pin)==GPIO_PIN_SET) dat|=0x10;
	if(HAL_GPIO_ReadPin(GPIOC, D5_Pin)==GPIO_PIN_SET) dat|=0x20;
	if(HAL_GPIO_ReadPin(GPIOC, D6_Pin)==GPIO_PIN_SET) dat|=0x40;
	if(HAL_GPIO_ReadPin(GPIOC, D7_Pin)==GPIO_PIN_SET) dat|=0x80;
	return dat;
}

//D0-D7写数据
void WriteData(uint8_t dat)
{
	uint16_t Set_Pins = 0, Rst_Pins = 0;
	//DataDir('O');
	if(dat & 0x01) Set_Pins |= D0_Pin;
	else Rst_Pins |= D0_Pin;
	if(dat & 0x02) Set_Pins |= D1_Pin;
	else Rst_Pins |= D1_Pin;
	if(dat & 0x04) Set_Pins |= D2_Pin;
	else Rst_Pins |= D2_Pin;
	if(dat & 0x08) Set_Pins |= D3_Pin;
	else Rst_Pins |= D3_Pin;
	if(dat & 0x10) Set_Pins |= D4_Pin;
	else Rst_Pins |= D4_Pin;
	if(dat & 0x20) Set_Pins |= D5_Pin;
	else Rst_Pins |= D5_Pin;
	if(dat & 0x40) Set_Pins |= D6_Pin;
	else Rst_Pins |= D6_Pin;
	if(dat & 0x80) Set_Pins |= D7_Pin;
	else Rst_Pins |= D7_Pin;
	
	HAL_GPIO_WritePin(GPIOC, Set_Pins, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC, Rst_Pins, GPIO_PIN_RESET);
}

//LCD忙等待
void LCD_Busy_Wait()
{
	uint8_t status;
	DataDir('I');
	RS_InstructionR();
	RW_Read();
	do
	{
		E_Set();
		__NOP();
		status = ReadData();
		E_Rst();
	}
	while(status & 0x80);
}

//写LCD指令
void LCD_Write_Cmd(uint8_t cmd)
{
	DataDir('O');
	WriteData(cmd);
	RS_InstructionR();
	RW_Write();
	E_Rst();
	RS_InstructionR();
	RW_Write();
	E_Set();
	__NOP();
	E_Rst();
	LCD_Busy_Wait();
}

//写LCD数据寄存器
void LCD_Write_Data(uint8_t dat)
{
	DataDir('O');
	WriteData(dat);
	RS_DataR();
	RW_Write();
	E_Set();
	__NOP();
	E_Rst();
	LCD_Busy_Wait();
}

//LCD初始化
void LCD_Init()
{
	LCD_Write_Cmd(0x38);
	HAL_Delay(2);
	LCD_Write_Cmd(0x01);
	HAL_Delay(2);
	LCD_Write_Cmd(0x06);
	HAL_Delay(2);
	LCD_Write_Cmd(0x0c);
	HAL_Delay(2);
}

//在x行(0-1),y列(0-15)显示字符串
void LCD_ShowString(uint8_t x, uint8_t y, char *str)
{
	uint8_t i=0;
	//设置显示起始位置
	if(x == 0)
		LCD_Write_Cmd(0x80|y);
	else if(x == 1)
		LCD_Write_Cmd(0xc0|y);
	//输出字符串
	for(i=0; i<16 && str[i]!='\0'; i++)
	{
		LCD_Write_Data(str[i]);
		HAL_Delay(2);
	}
}


LCD1602.h

#ifndef INC_LCD1602_H_
#define INC_LCD1602_H_
#include "main.h"

//选择数据寄存器
#define RS_DataR() HAL_GPIO_WritePin(GPIOA, RS_Pin, GPIO_PIN_SET)
#define RS_InstructionR() HAL_GPIO_WritePin(GPIOA, RS_Pin, GPIO_PIN_RESET)

//选择指令寄存器
//读操作
#define RW_Read() HAL_GPIO_WritePin(GPIOA, RW_Pin, GPIO_PIN_SET)
//写操作
#define RW_Write() HAL_GPIO_WritePin(GPIOA, RW_Pin, GPIO_PIN_RESET)

//Enable操作:高电平-读取信息;下降沿-执行指令
#define E_Set() HAL_GPIO_WritePin(GPIOA, E_Pin, GPIO_PIN_SET)
#define E_Rst() HAL_GPIO_WritePin(GPIOA, E_Pin, GPIO_PIN_RESET)


void LCD_Init(void);

void LCD_ShowString(uint8_t x, uint8_t y, char *str);




#endif //INC_LCD1602_H_


 步骤:在此处右键,选择新建文件

分别选择.c文件和.h文件,命名后add,将以上代码分别粘贴到对应文件中 

2.motor的c和h文件

motor.c

#include "motor.h"
#include "main.h"

void SZhun()
{
	HAL_GPIO_WritePin(IN1_GPIO_Port,IN1_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(IN2_GPIO_Port,IN2_Pin,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(ENA_GPIO_Port,ENA_Pin,GPIO_PIN_SET);
}

void NZhun()
{
	HAL_GPIO_WritePin(IN1_GPIO_Port,IN1_Pin,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(IN2_GPIO_Port,IN2_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(ENA_GPIO_Port,ENA_Pin,GPIO_PIN_SET);
}

void Stop()
{
	HAL_GPIO_WritePin(IN1_GPIO_Port,IN1_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(IN2_GPIO_Port,IN2_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(ENA_GPIO_Port,ENA_Pin,GPIO_PIN_SET);
}

motor.h

#ifndef __motor_H_
#define __motor_H_

void SZhun(void);//顺时针转动
void NZhun(void);//逆时针转动
void Stop(void);//停止转动

#endif

与1同理,在Keil中新建对应的motor.c和motor.h

3.main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2025 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 "LCD1602.h"
#include <stdio.h>
#include "motor.h"
#include <stdlib.h>
#include <string.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 */
uint32_t AD_value;
	int temp;
	int last_temp=0;
	char str[20];
	uint8_t Rx_data = 0;
	int Flag=0;
	
	char str1[]="TEMPRATURE:";
	uint8_t str2[] = "OK!\r\n";
	char str3[] = "";

/* 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 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2)
    {
        static uint8_t buffer[4];  
        static uint8_t index = 0;  

        buffer[index++] = Rx_data;  

        if (index >= 4)
        {
            
            if (buffer[0] == 0xD4 && buffer[1] == 0xCB && buffer[2] == 0xD0 && buffer[3] == 0xD0)
            {
                uint8_t response[] = "OK\r\n";  
                HAL_UART_Transmit(&huart2, response, sizeof(response) - 1, 1000);  
                Flag = 1;  
            }
            index = 0;  
        }

        HAL_UART_Receive_IT(&huart2, &Rx_data, 1);  
    }
}


void LCD_ShowTemperature(int temp)
{
    char tempStr[16];
    sprintf(tempStr, "%d", temp);  
    LCD_ShowString(1, 0, tempStr);  
}
/* 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_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	LCD_Init();  
	LCD_ShowString(0,0,str1);  
	HAL_UART_Receive_IT(&huart2,&Rx_data,1);
	//HAL_ADCEx_Calibration_Start(&hadc1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1,50);
	  if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC))
	  {
		  AD_value=HAL_ADC_GetValue(&hadc1);
		  temp=(int)AD_value*500/4095.0;		 
	  }
	  
	  if(Flag == 1)
	  {
		  // 温度低于25℃时,停止电机(请在此处根据个人学号修改)
        if (temp < 25)
        {
            Stop();  // 停止电机
        }
        // 温度高于或等于25℃时,启动电机
        else if (temp >= 25)
        {
            SZhun();  // 启动电机
        }

        if (temp != last_temp)
        {
            
            LCD_ShowTemperature(temp); 
		    sprintf(str3, "%d℃\r\n", temp);  
            HAL_UART_Transmit(&huart2, (uint8_t *)str3, strlen(str3), HAL_MAX_DELAY);  
            last_temp = temp;  
        }
			 
	  }

  }
  /* 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_SCALE1);
  /** 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 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

可以将以上代码直接复制到你的main.c中,代码解释有时间另外写一篇进行讲解。

4.可能存在的问题:

解决方法:

  1. 点击魔法棒

  2. 在弹出的窗口中,选择 C/C++ 选项卡。

  3. 在 Include Paths 部分,点击右侧的 ... 按钮。

  4. 添加 LCD1602.h 文件所在的目录路径(将鼠标放在左侧对应文件处就能看到路径啦!)。

 

另外,经反馈与排查,也有同学单纯是因为相关头文件命名与本文章不一致,但main.c文件的头文件名称没有改为一致😁。

(2)此处感谢某位同学的补充

对于最后仿真没有现象的问题,请检查此处"Use MicroLIB"是否勾选

5. 编译生成.hex文件

点击魔法棒,选择output,勾选创建hex文件,点击编译

八、在proteus中仿真

1. 打开proteus,选中芯片,右键选择编辑属性

2.  找到自己的HEX文件(就在cubemx的工程目录下)并导入,确定

3. 点击左下角绿色三角开始仿真(对于仿真后没反应的现象,优先考虑原理图问题;其次考虑cubemx配置问题)

4.打开串口调试工具sscom,打开串口,发送“运行”,可以看到收到“OK” 

5.手动调节温度,可以看到LCD显示和串口接收,以及电机转动。

注意每个人的学号不同,设定温度不同,记得修改哦!(修改位置已经在main.c中标出)

学习过程中出现的问题可以私信我或在评论区留言,有时间便会回复,也感谢大家为文章的完善贡献力量。

到此,个人项目仿真部分已经完成。有关个人项目硬件演示部分,由于较为简单,不出详细教程,可以参考我的对应文章(但是由于考虑各种情况,对应代码比个人会麻烦一些)。

 

 

 

 

 

 

 

 

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值