首页 > 其他分享 >stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发

时间:2023-12-26 13:34:09浏览次数:31  
标签:MDK BEGIN CODE END Proteus8 USER 串口 USART1


stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发


文章目录

  • stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发
  • 一、前言
  • 二、资料收集
  • 三、STM32CubeMX配置串口
  • 1、配置开启USART1
  • 2、设置usart中断优先级
  • 3、配置外设独立生成.c和.h
  • 四、MDK串口收发代码(中断回调接收后发送接收到的内容)
  • 1、usart.h
  • 2、usart.c
  • 3、stm32f1xx_it.c
  • 五、创建虚拟串口并通过Proteus配置及仿真串口通信
  • 1、创建虚拟串口
  • 2、添加串口元器件及虚拟终端
  • 3、接线配置元器件并烧入hex
  • 4、进行仿真测试
  • 5、可能的问题
  • 六、最后


一、前言

前面我们已经实现点灯,下面就做一些数据交互的内容,先搞一下串口让数据可以用串口打印以及通过虚拟终端显示出来(就相当于有个显示屏可以显示数据了)。

二、资料收集

串口概念:https://zh.wikipedia.org/zh-cn/%E4%B8%B2%E8%A1%8C%E7%AB%AF%E5%8F%A3

STM32CubeMX配置串口:https://www.st.com/resource/zh/user_manual/um1718-stm32cubemx-for-stm32-configuration-and-initialization-c-code-generation-stmicroelectronics.pdf


Proteus8配置串口元器件和虚拟终端:

虚拟串口工具:VSPD(https://www.eltima.com/products/vspdxp/)或者HHD Software Virtual
Serial Port Tools(免费:https://freevirtualserialports.com/

串口工具:SSCOM、XCOM、微软商店的串口调试工具等(推荐https://apps.microsoft.com/detail/9NBLGGH43HDM?rtc=1&hl=zh-cn&gl=CN

三、STM32CubeMX配置串口

1、配置开启USART1

  • 开启USART1,配置为异步模式,并设置全局中断,就可以看到右侧的引脚PA9、PA10为TX和RX(设置底板的时候也可以通过这里来确认引脚位置,避免搞反了):

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_嵌入式硬件


设置属性为9600比特率、8个数据位、一个停止位,无奇偶校验:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_02

2、设置usart中断优先级

  • 设置优先级:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_嵌入式硬件_03

3、配置外设独立生成.c和.h

  • 配置外设生成独立的.c和.h(否则我们后面就找不到usart.c和usart.h了,都在main.c中了,这种结构太差了,所以建议这里都勾选一下):

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_04


参数设置我们使用默认的即可,所以这里最简单的串口配置就完成了(时钟我们这里也暂时不配置使用HSE)。

可以直接右上角 GENERATE CODE生成代码,然后打开MDK工程了。

四、MDK串口收发代码(中断回调接收后发送接收到的内容)

MDK中主要改三个地方,usart.c、usart.h、stm32f1xx_it.c:

1、usart.h

usart.h我们在用户可添加的位置增加相关宏和全局变量(这里设置了接收中断的缓存大小为1,一个字节一个字节接收处理):

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    usart.h
  * @brief   This file contains all the function prototypes for
  *          the usart.c file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern UART_HandleTypeDef huart1;

/* USER CODE BEGIN Private defines */
#define USART_REC_LEN            200
#define EN_USART1_RX             1
          
extern uint8_t  USART_RX_BUF[USART_REC_LEN];
extern uint16_t USART_RX_STA;

#define RXBUFFERSIZE    (1)
extern uint8_t aRxBuffer[RXBUFFERSIZE];

/* USER CODE END Private defines */

void MX_USART1_UART_Init(void);

/* USER CODE BEGIN Prototypes */

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __USART_H__ */

2、usart.c

usart.c增加中断处理以及中断回调,在回调中处理接收内容(HAL_UART_RxCpltCallback回调中我这里是根据报文头和报尾确定一包数据后进行业务处理调用,这里暂时收到什么就发送什么):

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    usart.c
  * @brief   This file provides code for the configuration
  *          of the USART instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* USER CODE BEGIN 0 */
#include <string.h>
/* USER CODE END 0 */

UART_HandleTypeDef huart1;

/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
    //弿启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
  /* USER CODE END USART1_Init 2 */

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        //printf("uart recv now:%02x ", aRxBuffer[0]);
        //printf("\r\n");
        HAL_UART_Transmit(&huart1, aRxBuffer, 1, 1000);
        
        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) != SET);
    }
}
/* USER CODE END 1 */

3、stm32f1xx_it.c

stm32f1xx_it.c中根据全局中断的回调判断串口状态并调用接收中断:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32f1xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usart.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */

/* USER CODE END TD */

/* 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 */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t aRxBuffer[RXBUFFERSIZE];
/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN EV */

/* USER CODE END EV */

/******************************************************************************/
/*           Cortex-M3 Processor Interruption and Exception Handlers          */
/******************************************************************************/
/**
  * @brief This function handles Non maskable interrupt.
  */
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
    while (1)
    {
    }

  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Memory management fault.
  */
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
}

/**
  * @brief This function handles Prefetch fault, memory access fault.
  */
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Undefined instruction or illegal state.
  */
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
}

/**
  * @brief This function handles System service call via SWI instruction.
  */
void SVC_Handler(void)
{
  /* USER CODE BEGIN SVCall_IRQn 0 */

  /* USER CODE END SVCall_IRQn 0 */
  /* USER CODE BEGIN SVCall_IRQn 1 */

  /* USER CODE END SVCall_IRQn 1 */
}

/**
  * @brief This function handles Debug monitor.
  */
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
  * @brief This function handles Pendable request for system service.
  */
void PendSV_Handler(void)
{
  /* USER CODE BEGIN PendSV_IRQn 0 */

  /* USER CODE END PendSV_IRQn 0 */
  /* USER CODE BEGIN PendSV_IRQn 1 */

  /* USER CODE END PendSV_IRQn 1 */
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f1xx.s).                    */
/******************************************************************************/

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
    uint32_t timeout = 0;
    uint32_t maxDelay = 0x1FFFF;
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
    timeout = 0;

    while (HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY)//等待就绪
    {
        timeout++; //超时处理

        if(timeout > maxDelay) break;
    }

    timeout = 0;

    memset(aRxBuffer, '\0', sizeof(aRxBuffer));
    while(HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//丿次处理完成之后,重新弿启中断并设置RxXferCount丿1
    {
        timeout++; //超时处理

        if(timeout > maxDelay) break;
    }

  /* USER CODE END USART1_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

之后mdk进行编译生成hex即可,这个之前已经章节已经说过了,不再赘述。

五、创建虚拟串口并通过Proteus配置及仿真串口通信

1、创建虚拟串口

参考我这里推荐的串口工具创建一组虚拟串口:
或者使用其它虚拟串口工具也可以,只要保证后续有串口可用即可。

2、添加串口元器件及虚拟终端

P后搜索COMPIM后添加:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_05


添加虚拟终端,在仪器栏选择VIRTUAL TERMINAL即虚拟终端后添加:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_06

3、接线配置元器件并烧入hex

上节的LED灯我们先可以不动,然后P9、P10对应的口接TXD、RXD,相当于将STM32的TX和RX映射到电脑的虚拟串口上,然后虚拟终端的RX链接串口的RX即可,这样我们通过虚拟串口工具虚拟两个串口,一个串口分配给STM32来映射,一个用来通过串口工具在电脑上进行收发模拟和STM32的串口进行收发。

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_串口_07


对于串口原件还需要选择一下串口,设置一下波特率、停止位这些:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_08


虚拟终端也需要配置一下:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_09


之后在STM32元器件上配置一下hex和时钟频率:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_10

4、进行仿真测试

开始仿真并运行,然后通过串口工具定时发送即可:

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#include_11

5、可能的问题

  • 1、虚拟终端的串口有时候无法弹出,根据这里顺利解决了(调试-》恢复弹出窗口):


  • 2、此外,似乎STM32回显返回给串口的内容总是和发送给STM32的内容不一致,发送的时候是对的,但是返回的时候是乱码,最后发现接收中断的地方没有对接收空间进行memset导致了乱码(此外,还可能和时钟频率有关系,适当调高时钟频率):

stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_#define_12


stm32学习总结:4、Proteus8+STM32CubeMX+MDK仿真串口收发_嵌入式硬件_13

六、最后

这样子基于串口通信的STM32应用开发基本就入门了,串口通信由于比较常见,所以这里先简要总结了一下,后续的内容就可以通过串口来打印日志了,STM32F103有两组串口,一组我们可以用来打印日志,一组用来和外部通信做交互。接下来我们接着去总结一下按键、蜂鸣器、定时器、看门狗等内容,再考虑继续往下总结I2C、ADC、SPI等接口来读取一些传感器信息以及读写flash等。


标签:MDK,BEGIN,CODE,END,Proteus8,USER,串口,USART1
From: https://blog.51cto.com/xiaoyaoyou10/8981909

相关文章

  • 基于python的cat1模块的AT指令串口通信解析
    一前记使用cat1模块做产品的过程中,遇到了不少问题。其中很重要的一个就是怎么测试单个模块的好坏。这里笔者专门写了一个工具,来测试cat1模块的是否好用,这里做一个分享吧。 二源码解析这个是一个完全可以工作的程序,只需要改成你的模块的即可;#-*-coding:utf-......
  • 深入理解串口通信原理及应用
    串口通信作为一种异步串行通信方式,被广泛地应用在计算机与外部设备之间的数据交互上。本文将详细介绍串口的工作原理、数据格式、通信协议、常见应用等内容。一、串口通信原理串口通信是利用串行通信协议在计算机与外部设备之间进行异步通信的一种技术。串行通信是按照时间顺序,按......
  • Qt/C++控件设计器/属性栏/组态/可导入导出/中文属性/串口网络/拖曳开发
    一、功能特点自动加载插件文件中的所有控件生成列表,默认自带的控件超过120个。拖曳到画布自动生成对应的控件,所见即所得。右侧中文属性栏,改变对应的属性立即应用到对应选中控件,直观简洁,非常适合小白使用。独创属性栏文字翻译映射机制,效率极高,可以非常方便拓展其他语言的属性......
  • ESP32在Arduino环境下使用QUEUE接收串口数据帧
    ESP32在Arduino环境下的串口数据帧接收测试平台ESP32-WROOM测试语言Arduino@PlatformIO注意事项需要添加Queue的库函数作者:SMFSWPlatformIO环境配置文件-platformio.ini[env:esp32doit-devkit-v1]platform=espressif32board=esp32doit-devkit-v1framewo......
  • Qt程序接收串口数据存在延迟解决办法
    问题在调试接收串口数据的Qt程序中发现,数据存在延迟和粘包现象。下位机发送数据包频率是100Hz,一包56字节,波特率115200,在打印port->readAll()的值的时候发现并不是每10ms读到一包数据,而是大概每50ms左右一次接收到5包数据,在其他电脑上调试,以及下载其他串口助手调试后发现存在同样......
  • 《安富莱嵌入式周报》第328期:自主微型机器人,火星探测器发射前失误故障分析,微软推出12
     更新一期视频教程:【实战技能】单步运行源码分析,一期视频整明白FreeRTOS内核源码框架和运行机制,RTOSTrace链表功能展示视频版:https://www.bilibili.com/video/BV1Rw411b7M1/ 1、自主无电池无线微型机器人https://millimobile.cs.washington.edu/millimobile-compressed.pdf(2.......
  • 串口调试工具、方法和步骤
    串口调试工具、方法和步骤魏智勇​爱自控,爱科学,爱读书,爱生活​关注他 4人赞同了该文章串口是工业自动化系统中非常重要的通讯方式,自问世至今,以RS232、RS485为主的串口通讯方式,在工业自动化通讯系统始终占据非常重要的地位。对自动化工程师来说......
  • Virtual Serial Port虚拟串口软件无法删除和修改已有串口怎么办?
    之前用的9.2版本,试用期过后绑定的端口都掉了,导致串口通讯报错6.9永久版下载:VirtualSerialPortDriverPro汉化破解版下载(附注册码)v6.9-软件学堂(xue51.com)下载后里面有两个版本,推荐安装6.9版本,7.0版本无Crack文件下载后如果还是无法删除已经绑定的虚拟串口或实际串口......
  • 串口实现modbus通讯
    代码#include"sys.h"#include"485.h"#include"delay.h"#include"modbus.h"voidRS485_Init(u32bound){//GPIO端口设置GPIO_InitTypeDefGPIO_InitStructure;USART_InitTypeDefUSART_InitStructure;N......
  • Qt之modbus_slave例程的底层串口数据分析
    一.参考网址1. qCDebug输出到日志文件2. HowtoredirectqDebug,qWarning,qCriticaletcoutput?二.问题1. 如何查看slave底层收到的主机发送的消息和回复的消息?解决办法:在main.cpp代码中取消注释 注:QLoggingCategory::setFilterRules函数不能重复使用,其只能最后......