解决“KEIL5软件模拟仿真无法打印浮点数”之问题

news/2025/1/8 22:44:44/

在没有外部硬件支持时,我们会使用KEIL5软件模拟仿真,这是是仿真必须要掌握的技巧。

1、点击“Project”,然后点击“Options for target '项目名字'”,点击“Device”,选择CPU型号。

2、点击“OK”

3、点击“Target”,勾选“Use Micro LIB”。注意:如果不勾选,软件仿真时,会出现无法打印浮点数,或者不打印小数点

4、点击“OK”

5、点击“Debug”,配置如下:

注意:绿线左边属于软件仿真配置,绿线右边属于硬件仿真配置。

6、点击“OK”

7、重定义fputc函数,编写一个“USART1.c”,文件如下:

#include "USART1.h"

#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()

void USART1_GPIO_Config(void);

void USART1_NVIC_Cpnfig(void);

void USART1_Mode_Cpnfig(unsigned int bound);

void USART1_SendByte(  unsigned char ch );

void USART1_SendString(  char *str);

void USART1_Serial_Interface_Enable(unsigned int bound);

//函数功能:USART1IO口配置

void USART1_GPIO_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

//设置USART1APB2外设时钟

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9;//选择PIN9,USART1TXD

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//设置引脚为复用推挽输出          

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  //设置引脚的最高工作速率为50MHz

  GPIO_Init(GPIOA, &GPIO_InitStructure);

        

         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10; //选择PIN10,USART1RXD

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;       //设置引脚为输入悬浮 

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  //设置引脚的最高工作速率为50MHz

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

//函数功能:USART1 NVIC 配置

void USART1_NVIC_Cpnfig(void)

{

         NVIC_InitTypeDef NVIC_InitStructure;

         //NVIC_PriorityGroup_4设置NVIC中断分组4:表示抢占优先级为4,取值为0~15,没有响应优先级,取值为0

  //NVIC_PriorityGroup_3设置NVIC中断分组3:表示抢占优先级为3,取值为0~7,响应优先级只有1,取值为0~1

         //NVIC_PriorityGroup_2设置NVIC中断分组2:表示抢占优先级为2,取值为0~3,响应优先级只有2,取值为0~3

         //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4

         NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

    //选择中断源为USART1_IRQn

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;

  //设置抢先优先级为13

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置响应优先级为0

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

//函数功能:USART1配置:波特率为bound,数字为8,停止位为1,无奇偶校验,允许发送和接收数据,允许中断,使能串口模块

void USART1_Mode_Cpnfig(unsigned int bound)

{

         USART_InitTypeDef USART_InitStructure;

        

         USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;

         USART_InitStructure.USART_WordLength = USART_WordLength_8b;

         USART_InitStructure.USART_StopBits = USART_StopBits_1;

         USART_InitStructure.USART_Parity = USART_Parity_No ;

         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

         USART_Init(USART1, &USART_InitStructure);

        

         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启接收中断

//当开启串口中断,一定要写其中断服务程序,否则可能会导致FreeRTOS的任务不执行

        

         USART_Cmd(USART1, ENABLE); //使能串口

}

//函数功能:串口1发送一个字节

void USART1_SendByte(  unsigned char ch )

{

  USART_SendData(USART1, ch);

  while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);

  //等待发送完成标志位被置1       

}

//函数功能:串口1发送字符串

void USART1_SendString(  char *str)

{

  unsigned int k=0;

  do{

      USART1_SendByte(  *(str + k) );

      k++;

    }while(*(str + k)!='\0');

}

//函数功能:USART1配置

void USART1_Serial_Interface_Enable(unsigned int bound)

{

         USART1_GPIO_Config();

  USART1_NVIC_Cpnfig();

  USART1_Mode_Cpnfig(bound);

}

//函数功能:USART1中断服务函数

void USART1_IRQHandler(void)

{

         unsigned char temp;

         (void)temp;//不让temp产生警告

         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

         {

                   temp=USART_ReceiveData(USART1); //GSM串口读取一个字节;

         }

         if(USART_GetFlagStatus(USART1,USART_FLAG_PE) != RESET)

         {

                   USART_ReceiveData(USART1);//读串口

                   USART_ClearFlag(USART1, USART_FLAG_PE);

         }

  if(USART_GetFlagStatus(USART1,USART_FLAG_ORE) != RESET)

  {

                   USART_ReceiveData(USART1);//读串口

    USART_ClearFlag(USART1,USART_FLAG_ORE); //清除溢出中断

  }

         if(USART_GetFlagStatus(USART1,USART_FLAG_FE) != RESET)

         {

                   USART_ReceiveData(USART1);//读串口

                   USART_ClearFlag(USART1,USART_FLAG_FE);

         }

}

//加入以下代码,支持printf函数

//在进行硬件仿真时,可不需要选择“use MicroLIB

//但在进行软件仿真时,必须勾选“use MicroLIB”,否则,无法打印“浮点数”

#if VirtualSerialPort == 1

#pragma import(__use_no_semihosting)

//标准库需要的支持函数

struct __FILE

{

         int handle;

};

FILE __stdout;

//定义_sys_exit()以避免使用半主机模式

void _sys_exit(int x)

{

         x = x;

}

//重定义fputc函数

//函数功能:发送ch的值给USART1串口

int fputc(int ch, FILE *f)

{

  USART_SendData(USART1, (unsigned char) ch);

  while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);

  //等待发送完成标志位被置1       

         return ch;

}

#else

#define ITM_Port8(n)    (*((volatile unsigned char *)(0xE0000000+4*n)))

#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))

#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))

#define DEMCR           (*((volatile unsigned long *)(0xE000EDFC)))

#define TRCENA          0x01000000

struct __FILE

{

  int handle; /* Add whatever you need here */

};

FILE __stdout;

FILE __stdin;

int fputc(int ch, FILE *f)

{

         if (DEMCR & TRCENA)

         {

    while (ITM_Port32(0) == 0);

   ITM_Port8(0) = ch;

  }

  return(ch);

}

#endif

8、“USART1.h”文件如下:

#ifndef __USART1_H

#define   __USART1_H

#include "stm32f10x.h"

//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t

#define VirtualSerialPort  1   //使用UART1printf功能

//#define VirtualSerialPort  0 //使用JLINK虚拟串口的printf功能

extern void USART1_SendByte(  unsigned char ch );

extern void USART1_SendString(  char *str);

extern void USART1_Serial_Interface_Enable(unsigned int bound);

#endif /* __USART1_H */

#include "stm32f10x.h"

//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t

#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()

#include "USART1.h"

//注意:"USART1.h"要放在 "stdio.h" 包含文件之后,如果这个位置颠倒了,业不能打印浮点数

void Print_Float(void)

{

         float f;

         f=10.5;

         printf("f=%0.2f\r\n", f);

}

int main(void)

{

         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4

         USART1_Serial_Interface_Enable(115200);//初始化串口1

         printf("\r\nCPU reset\r\n");

    Print_Float();

while(1)

 {

 }

}

9、点击“Debug”,点击“View”,点击“Serial Windows”,点击“UART#1”,就可以打开KEIL中的串口1,见下图:

10、点击“Debug”菜单中的“Run”,就可以仿真了。

注意:"USART1.h"要放在 "stdio.h" 包含文件之后,如果这个位置颠倒了,业不能打印浮点数。 这个可能和8个字节对齐有关,如果你知道,请给我留言。


http://www.ppmy.cn/news/1561653.html

相关文章

前端状态管理的智能化革命:告别混乱,拥抱高效

引言 现代前端应用日益复杂,交互日趋精细,随之而来的是前端状态管理的巨大挑战。庞大的数据流、错综复杂的组件交互以及频繁的数据更新,让开发者疲于应付代码的冗余和难以维护的问题,严重影响了开发效率和项目进度。 面对这种现状…

模型 九屏幕分析法

系列文章 分享 模型,了解更多👉 模型_思维模型目录。九屏幕法:全方位分析问题的系统工具。 1 九屏幕分析法的应用 1.1 新产品研发的市场分析 一家科技公司计划开发一款新型智能手机,为了全面评估市场潜力和风险,他们…

RabbitMQ如何实现队列持久化

RabbitMQ的持久化机制是一种确保数据在RabbitMQ服务重启或异常情况下不会丢失的重要特性。在生产环境中,消息代理的稳定性和可靠性至关重要,而队列持久化正是实现这一目标的关键手段之一。以下将详细介绍RabbitMQ如何实现队列持久化。 一、RabbitMQ持久…

【QT-QTableView实现鼠标悬浮(hover)行高亮显示+并设置表格样式】

1、自定义委托类 HoverDelegate hoverdelegate.h #ifndef HOVERDELEGATE_H #define HOVERDELEGATE_H#include <QObject> #include <QStyledItemDelegate>class hoverdelegate : public QStyledItemDelegate {Q_OBJECT // 添加 Q_OBJECT 宏public:explicit hoverde…

Linux入门攻坚——43、keepalived入门-1

Linux Cluster&#xff08;Linux集群的类型&#xff09;&#xff1a;LB、HA、HPC&#xff0c;分别是负载均衡集群、高可用性集群、高性能集群。 LB&#xff1a;lvs&#xff0c;nginx HA&#xff1a;keepalived&#xff0c;heartbeat&#xff0c;corosync&#xff0c;cman HP&am…

Opencv实现Sobel算子、Scharr算子、Laplacian算子、Canny检测图像边缘

图像边缘检测 目录 图像边缘检测1 Sobel算子1.1概念1.2 两个卷积矩阵1.3 函数及参数理解1.4 灰度图实际测试1.5 BGR图测试 2 Scharr算子2.1概念2.2 实际测试 3 Laplacian算子3.1概念3.2 函数3.3 实际测试 4 Canny边缘检测4.1 概念4.2 步骤4.3 优点4.4 函数及参数理解4.5 实际测…

C# 中的命名空间与Java和Python中的导入

在 C#、Java 和 Python 这三种语言中&#xff0c;命名空间和导入机制都是用来组织和管理代码及其依赖的工具&#xff0c;但它们在具体实现和使用方式上存在一些差异。 1、问题背景 在 Java 和 Python 世界中&#xff0c;我们可以通过查看源文件来了解所有导入的来源&#xff0…

OpenCV 4.5至4.10版本更新概述

OpenCV 4.5至4.10版本更新概述 OpenCV 从 4.5 到 4.10 版本的更迭中&#xff0c;每个版本都引入了新功能、优化和修复。以下是主要版本的更新内容概述&#xff1a; OpenCV 4.5.x 系列 4.5.0 (2020年10月) 新增对 YOLOv4 的支持。引入 DNN 模块的改进&#xff0c;包括对 ONNX …