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

在没有外部硬件支持时,我们会使用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);

//函数功能:USART1的IO口配置

void USART1_GPIO_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

//设置USART1的APB2外设时钟

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

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//选择PIN9,是USART1的TXD

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,是USART1的RXD

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 //使用UART1的printf功能

//#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个字节对齐有关,如果你知道,请给我留言。

相关推荐
网易独家音乐人Mike Zhou33 分钟前
【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集
c语言·单片机·mcu·物联网·嵌入式·iot·毫米波雷达
qq_4597300336 分钟前
STM32-DMA数据转运
stm32·单片机·嵌入式硬件
RIO小哥1 小时前
【单片机】实现一个简单的ADC滤波器
c语言·嵌入式硬件
不能只会打代码2 小时前
32单片机从入门到精通之数据处理——数学运算(十三)
单片机·嵌入式硬件·32单片机
想要成为计算机高手2 小时前
09.list
c++·经验分享·笔记·算法·list
星迹日2 小时前
数据结构:LinkedList与链表—面试题(三)
数据结构·经验分享·笔记·链表·面试题
佳心饼干-3 小时前
单片机-外部中断
单片机·嵌入式硬件
【0931】3 小时前
TIM的中断
stm32·单片机·学习
冰冰的coco3 小时前
入门嵌入式(六)——定时器
单片机·嵌入式硬件
努力的小雨3 小时前
深入解析 Spring AI 系列:剖析OpenAI接口接入组件
经验分享·源码分析·ai智能