FM33LC0X系列,需要使用UART5作为调试串口,使用UART5打印数据,使用重定向printf打印和不使用重定向UART5_printf打印

本文介绍了如何在复旦微FM33LC0X系列单片机上使用UART5作为调试串口,通过重定向printf函数和自定义UART5_printf函数实现数据打印。提供了相关代码示例,包括重定向printf的实现和非重定向的UART5_printf函数的编写。
摘要由CSDN通过智能技术生成

FM33LC0X系列,需要使用UART5作为调试串口,使用UART5打印数据,使用重定向printf打印和不使用重定向UART5_printf打印

自述

前面使用的都是ST系列的单片机,在转战复旦微之后有点忐忑,担心自己做不出来,担心自己做不好,但是还是咬牙顶上了,这次使用的是复旦微的低功耗系列FM33LC0x系列单片机,前面使用STM32和GD32的时候都习惯使用printf打印调试,在做复旦微的单片机后依然习惯使用printf调试打印,自己在参照STM32代码的基础上,写了使用重定向printf打印和不使用重定向UART5_printf打印的函数

1.使用重定向printf打印

这个没有什么多说的,写过STM32的都知道这个重定向。


#if 1
#pragma import(__use_no_semihosting)                          
struct __FILE 
{ 
    int handle; 
};
FILE __stdout;       

void _sys_exit(int x) 
{ 
    x = x;
} 

int fputc(int ch, FILE *f)
{
	UART5->TXBUF = ch;
    while (!(UART5->ISR & (0x1 << 0)));
    UART5->ISR |= (0x1 << 0);
    
    return ch;
}
#endif

2.不使用重定向printf打印

这个代码也是参照其他人的改的,代码中的变量i是没有多的时间来写了,直接用i来代替了,不喜勿喷,谢谢,

void UART5_printf (char *fmt, ...) 
{ 
	char buffer[UART5_SEND_LEN+1];  
	int i = 0; 

	va_list arg_ptr; 
	va_start(arg_ptr, fmt);   
	vsnprintf(buffer, UART5_SEND_LEN+1, fmt, arg_ptr);
	while ((i < UART5_SEND_LEN) && buffer[i]) 
	{ 
					FL_UART_WriteTXBuff(UART5, (uint8_t) buffer[i++]); 
	while(FL_SET != FL_UART_IsActiveFlag_TXShiftBuffEmpty(UART5));       //等待发送完成
	} 
	va_end(arg_ptr); 
}

3.完整代码

print.c文件完整代码

#include "print.h"




#if 1
#pragma import(__use_no_semihosting)                          
struct __FILE 
{ 
    int handle; 
};
FILE __stdout;       

void _sys_exit(int x) 
{ 
    x = x;
} 

int fputc(int ch, FILE *f)
{
	UART5->TXBUF = ch;
    while (!(UART5->ISR & (0x1 << 0)));
    UART5->ISR |= (0x1 << 0);
    
    return ch;
}
#endif



/**
  * @brief  UART0 Initialization function
  * @param  void
  * @retval None
  */
void MF_UART5_Init(void)
{
    FL_GPIO_InitTypeDef    GPIO_InitStruct;

    FL_UART_InitTypeDef    UART5_InitStruct;

    GPIO_InitStruct.pin = FL_GPIO_PIN_4;
    GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_ENABLE;
    GPIO_InitStruct.remapPin = FL_ENABLE;
    FL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.pin = FL_GPIO_PIN_5;
    GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_DISABLE;
    GPIO_InitStruct.remapPin = FL_ENABLE;
    FL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    UART5_InitStruct.clockSrc = NULL;
    UART5_InitStruct.baudRate = 115200;
    UART5_InitStruct.dataWidth = FL_UART_DATA_WIDTH_8B;
    UART5_InitStruct.stopBits = FL_UART_STOP_BIT_WIDTH_1B;
    UART5_InitStruct.parity = FL_UART_PARITY_NONE;
    UART5_InitStruct.transferDirection = FL_UART_DIRECTION_TX_RX;

    FL_UART_Init(UART5, &UART5_InitStruct);    
}


//#define UART5_printf(...)		printf(...)



void UART5_printf (char *fmt, ...) 
{ 
	char buffer[UART5_SEND_LEN+1];  
	int i = 0; 

	va_list arg_ptr; 
	va_start(arg_ptr, fmt);   
	vsnprintf(buffer, UART5_SEND_LEN+1, fmt, arg_ptr);
	while ((i < UART5_SEND_LEN) && buffer[i]) 
	{ 
					FL_UART_WriteTXBuff(UART5, (uint8_t) buffer[i++]); 
	while(FL_SET != FL_UART_IsActiveFlag_TXShiftBuffEmpty(UART5));       //等待发送完成
	} 
	va_end(arg_ptr); 
}



print.h文件完整代码

#ifndef __PRINT_1_H__
#define __PRINT_1_H__

#include "fm33lc0xx_fl.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>

void MF_UART5_Init(void);
void UART5_printf (char *fmt, ...) ;
#define UART5_SEND_LEN  300


#endif



结语

这个有参照别人的代码,并非是自己的原创,我做出来只是分享给大家,大家可以更快捷的使用printf函数,你自己花费一定的时间也可以写出来。

FM33lc026n是一款基于ARM Cortex-M0+内核的微控制器,支持多种外设,包括UART和DMA。要实现不定长度的数据接收,可以采用空闲中断加DMA加UART的方式。 首先,在UART接收数据时,需要开启空闲中断。当接收到一帧数据后,UART会产生空闲中断,表示数据接收完成。在空闲中断中,可以获取接收到的数据长度,并将接收到的数据存储到缓冲区中。 接下来,使用DMA将数据UART的接收缓冲区中传输到指定的内存地址。在配置DMA时,需要设置传输长度为接收到的数据长度,并开启循环模式,以便在下一次接收数据时继续传输。 最后,可以在DMA传输完成中断中进行一些操作,比如通知主程序数据已经接收完成。 以下是一个简单的代码示例: ```c #include "fm33lc0xx_fl_dma.h" #include "fm33lc0xx_fl_uart.h" #define BUFFER_SIZE 1024 uint8_t uart_rx_buffer[BUFFER_SIZE]; volatile uint32_t uart_rx_length = 0; void UART_IDLE_IRQHandler(void) { if (FL_UART_IsActiveFlag_IDLE(FL_UART1)) { FL_UART_ClearFlag_IDLE(FL_UART1); uart_rx_length = BUFFER_SIZE - FL_DMA_GetCurrDataCounter(DMA1, FL_DMA_CH3); } } void DMA1_Channel3_IRQHandler(void) { if (FL_DMA_IsActiveFlag_TC(DMA1, FL_DMA_CH3)) { FL_DMA_ClearFlag_TC(DMA1, FL_DMA_CH3); // do something after data transfer completed } } int main(void) { // initialize UART and DMA FL_UART_InitTypeDef uart_init_struct = {0}; uart_init_struct.UART_BaudRate = 115200; FL_UART_Init(UART1, &uart_init_struct); FL_DMA_InitTypeDef dma_init_struct = {0}; dma_init_struct.Init.Priority = FL_DMA_PRIORITY_HIGH; dma_init_struct.Init.PeriphDataAlignment = FL_DMA_DATA_WIDTH_BYTE; dma_init_struct.Init.MemDataAlignment = FL_DMA_DATA_WIDTH_BYTE; dma_init_struct.Init.PeriphInc = FL_DMA_PERIPH_INC_DISABLE; dma_init_struct.Init.MemInc = FL_DMA_MEM_INC_ENABLE; dma_init_struct.Init.Mode = FL_DMA_MODE_NORMAL; dma_init_struct.Init.Dir = FL_DMA_DIR_PERIPH_TO_MEM; dma_init_struct.Init.DataSize = FL_DMA_DATA_WIDTH_BYTE; dma_init_struct.Init.Ndtr = BUFFER_SIZE; dma_init_struct.Init.PBurst = FL_DMA_BURST_SINGLE; dma_init_struct.Init.MBurst = FL_DMA_BURST_SINGLE; FL_DMA_Init(DMA1, FL_DMA_CH3, &dma_init_struct); // configure DMA transfer FL_DMA_SetPeriphAddress(DMA1, FL_DMA_CH3, (uint32_t)&(UART1->DR)); FL_DMA_SetMemoryAddress(DMA1, FL_DMA_CH3, (uint32_t)uart_rx_buffer); FL_DMA_EnableIT_TC(DMA1, FL_DMA_CH3); // enable UART idle interrupt FL_UART_EnableIT_IDLE(UART1); FL_IRQ_Enable(UART1_IDLE_IRQn); // enable DMA channel and interrupt FL_DMA_EnableChannel(DMA1, FL_DMA_CH3); FL_IRQ_Enable(DMA1_Channel3_IRQn); while (1) { // do something else } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HTIAN1

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

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

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

打赏作者

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

抵扣说明:

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

余额充值