STM32F103VE RTT打印及错误代码打印实现

26 篇文章 1 订阅
10 篇文章 0 订阅
  • RTT LOG功能实现

首先要将rtt文件加入工程,如下

新建一个sdk_config.h加入工程,并加入以下内容



#ifndef SDK_CONFIG_H
#define SDK_CONFIG_H

	
#define STM_MODULE_ENABLED(module) \
    ((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0)

// <<< Use Configuration Wizard in Context Menu >>>\n



//##############################################################################################################################################
//																			以下是nRF_Segger_RTT仿真器打印配置
//##############################################################################################################################################
// <h> nRF_Segger_RTT仿真器打印配置菜单 

//==========================================================
// <h> segger_rtt - SEGGER RTT

//==========================================================
// <o> SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. 
// <i> Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE
// <i> or this value is actually used. It depends on which one is bigger.

#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP
#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512
#endif

// <o> SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Maximum number of upstream buffers. 
#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS
#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2
#endif

// <o> SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of downstream buffer. 
#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN
#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16
#endif

// <o> SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Maximum number of downstream buffers. 
#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS
#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2
#endif

// <o> SEGGER_RTT_CONFIG_DEFAULT_MODE  - RTT behavior if the buffer is full.
 

// <i> The following modes are supported:
// <i> - SKIP  - Do not block, output nothing.
// <i> - TRIM  - Do not block, output as much as fits.
// <i> - BLOCK - Wait until there is space in the buffer.
// <0=> SKIP 
// <1=> TRIM 
// <2=> BLOCK_IF_FIFO_FULL 

#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE
#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0
#endif

// </h> 
//==========================================================

// </h> 
//==========================================================


// <h> DEBUG配置
// <q> DEBUG使能
#ifndef DEBUG_ENABLED
#define DEBUG_ENABLED 1
#endif


// <q> ASSERT参数检查使能
#ifndef USE_FULL_ASSERT
#define USE_FULL_ASSERT 	1
#endif


// </h>

// <<< end of configuration section >>>
#endif //SDK_CONFIG_H

新建一个stm_log.h加入工程,并加入以下内容

#include "sdk_config.h"
#include "SEGGER_RTT.h"
#include "stdio.h"
#ifndef STM_LOG_H__
#define STM_LOG_H__


#ifdef __cplusplus
extern "C" {
#endif

#if STM_MODULE_ENABLED(DEBUG)




/**
* @brief RTT打印宏
* @note 
* - 最多不能超过128个字符否则出错
*/
#define NRF_LOG_INFO(fmt,args...) \
      do					\
			{						\
				sprintf(_SEGGER_RTT.aUp->pBuffer,fmt,##args); \
				SEGGER_RTT_WriteString(0, _SEGGER_RTT.aUp->pBuffer);	\
				SEGGER_RTT_WriteString(0,"\r\n");  \
			}while(0)

#define NRF_LOG_DEBUG(fmt,args...) \
      do					\
			{						\
				sprintf(_SEGGER_RTT.aUp->pBuffer,fmt,##args); \
				SEGGER_RTT_WriteString(0, _SEGGER_RTT.aUp->pBuffer);	\
			}while(0)			
      
#define RTT_INIT()  \
SEGGER_RTT_Init()			
			
#else
#define NRF_LOG_INFO(fmt,args...) ((void)0)
#define NRF_LOG_DEBUG(fmt,args...) ((void)0)     
			
#define RTT_INIT()  ((void)0)
	
#endif


		
#ifdef __cplusplus
}
#endif
		
#endif
			

在主函数中调用RTT_INIT()宏进行初时化RTT打印,调用NRF_LOG_INFO宏就可以打印信息


/**
  * @brief  主函数,程序的入口
  *        
  *         
  * @param  None
  * @retval int:不用理会,对于嵌入式系统,永远都不会返回
  */
int main(void)
{
	//------------初时化RTT打印--------------------------	
	RTT_INIT();
	
	NRF_LOG_INFO("program is running!");
	//--------独立看门狗配置-----------------------------------
	IWDG_Configuration();  /*!<配置并启动独立看门狗功能*/
  
	for(;;)
	{
		IWDG_ReloadCounter();   /*!< 喂狗*/
		
	}
}
  • ASSERT功能实现

将sdk_config.h中的USE_FULL_ASSERT宏值设置成1,DEBUG_ENABLED也设成1


// <h> DEBUG配置
// <q> DEBUG使能
#ifndef DEBUG_ENABLED
#define DEBUG_ENABLED 1
#endif


// <q> ASSERT参数检查使能
#ifndef USE_FULL_ASSERT
#define USE_FULL_ASSERT 	1
#endif


// </h>

在assert_failed函数中加入打印


#if USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
	NRF_LOG_INFO("file path is %s,line=%d\n",file,line);
	while(1);
}
#endif 

在stm32f10x_conf.h中修改成以下内容

#ifdef  USE_FULL_ASSERT

/**
  * @brief  The assert_param macro is used for function's parameters check.
  * @param  expr: If expr is false, it calls assert_failed function which reports 
  *         the name of the source file and the source line number of the call 
  *         that failed. If expr is true, it returns no value.
  * @retval None
  */
  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
  void assert_failed(uint8_t* file, uint32_t line);
	
	
	#define ASSERT(expr)  assert_param(expr)
	
	#define APP_ERROR_CHECK(expr)  \
	do													 \
	{											\
		if(expr)					\
		{									\
			NRF_LOG_INFO("error code %d",expr);				\
			assert_param(0);			\
		}									\
	}while(0)		
#else
  #define assert_param(expr) ((void)0)
	
	#define APP_ERROR_CHECK(expr) ((void)0)
	
	#define ASSERT(expr)  ((void)0)
#endif /* USE_FULL_ASSERT */

在主函数中可以调用ASSERT宏测试一下

在主函数中可以调用APP_ERROR_CHECK宏测试一下

  • HardFault_Handler打印信息实现

新建一个error_handler.c文件,加入以下内容

#include "error_handler.h"
#include "stm_log.h"

#if DEBUG_ENABLED
/* Private typedef -----------------------------------------------------------*/
enum { r0, r1, r2, r3, r12, lr, pc, psr};

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern __IO uint16_t ADC_InjectedConvertedValueTab[32];
uint32_t Index = 0;

/* Private function prototypes -----------------------------------------------*/
void Hard_Fault_Handler(uint32_t stack[]);

/* Private functions ---------------------------------------------------------*/

static void printUsageErrorMsg(uint32_t CFSRValue)
{
    NRF_LOG_INFO("Usage fault: ");
    CFSRValue >>= 16; // right shift to lsb

    if((CFSRValue & (1<<9)) != 0) {
        NRF_LOG_INFO("Divide by zero ");
    }
    if((CFSRValue & (1<<8)) != 0) {
        NRF_LOG_INFO("Unaligned access ");
    }
}

static void printBusFaultErrorMsg(uint32_t CFSRValue)
{
    NRF_LOG_INFO("Bus fault: ");
    CFSRValue = ((CFSRValue & 0x0000FF00) >> 8); // mask and right shift to lsb
}

static void printMemoryManagementErrorMsg(uint32_t CFSRValue)
{
    NRF_LOG_INFO("Memory Management fault: ");
    CFSRValue &= 0x000000FF; // mask just mem faults
}

static void stackDump(uint32_t stack[])
{

    NRF_LOG_INFO("R0 = 0x%08x", stack[r0]);
		NRF_LOG_INFO("R1 = 0x%08x", stack[r1]); 
		NRF_LOG_INFO("R2 = 0x%08x", stack[r2]); 
	  NRF_LOG_INFO("R3 = 0x%08x", stack[r3]); 
    NRF_LOG_INFO("R12 = 0x%08x", stack[r12]); 
		NRF_LOG_INFO("LR = 0x%08x", stack[lr]); 
		NRF_LOG_INFO("PC = 0x%08x", stack[pc]); 
    NRF_LOG_INFO("PSR = 0x%08x", stack[psr]); 
}

void Hard_Fault_Handler(uint32_t stack[])
{

			//if((CoreDebug->DHCSR & 0x01) != 0) {
		 NRF_LOG_INFO("In Hard Fault Handler");
		 NRF_LOG_INFO("SCB->HFSR = 0x%08x", SCB->HFSR);

		if ((SCB->HFSR & (1 << 30)) != 0) {
			NRF_LOG_INFO("Forced Hard Fault");
		NRF_LOG_INFO("SCB->CFSR = 0x%08x", SCB->CFSR );

		if((SCB->CFSR & 0xFFFF0000) != 0) {
			printUsageErrorMsg(SCB->CFSR);
		}
		if((SCB->CFSR & 0xFF00) != 0) {
			printBusFaultErrorMsg(SCB->CFSR);
		}
		if((SCB->CFSR & 0xFF) != 0) {
			printMemoryManagementErrorMsg(SCB->CFSR);
    }
}
		stackDump(stack);
		__ASM volatile("BKPT #01");
		//}
	
}


__ASM void HardFault_Handler_a(void)
{
   IMPORT Hard_Fault_Handler

   TST lr, #4
   ITE EQ
   MRSEQ r0, MSP
   MRSNE r0, PSP
   B Hard_Fault_Handler
}
#endif


在stm32f10x_it.c中的HardFault_Handler中断函数加入以下内容

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
 #if DEBUG_ENABLED
	HardFault_Handler_a();
	
#else
   NVIC_SystemReset();
#endif
  
}

在主函数中测试一下,现使用一个空指针操作来演示出错打印

DEMO下载地址:

https://download.csdn.net/download/mygod2008ok/11959924

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

对于驱动电机,你可以参考以下步骤: 1. 首先,你需要创建一个STM32F103C8T6的工程,并配置时钟树。你可以使用STM32CubeMX来创建并调整工程结构\[1\]。 2. 接下来,你需要编写GPIO驱动程序,以控制电机的引脚。你可以参考《STM32F10xxx闪存编程手册》中的GPIO章节来了解如何编写GPIO驱动程序\[2\]。 3. 在编写GPIO驱动程序之后,你可以编写延时函数,以实现电机的延时操作。你可以详细了解Systick定时器,并编写相应的延时函数\[1\]。 4. 最后,你可以使用RTT(Real Time Transfer)技术进行串口通信,以便进行电机的测试和调试。RTT是SEGGER公司推出的一种共享内存技术,可以方便地进行串口数据测试\[3\]。 需要注意的是,以上步骤只是一个简单的指导,具体的驱动电机的实现还需要根据你的具体需求和电机的类型进行相应的调整和编写。 #### 引用[.reference_title] - *1* *2* [从头开始写STM32F103C8T6驱动库(二)——编写系统初始化程序,配置时钟树](https://blog.csdn.net/Pluto0617/article/details/122615354)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [STM32F103C8T6单片机简介](https://blog.csdn.net/fantastic_sky/article/details/110229474)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风雨依依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值