STM32使用HAL库,模拟UART输出字符串

测试芯片是STM32F103C8T6,直接封装好了,波特率是 9600

MyDbg.h

cpp 复制代码
#ifndef __MYDBG_H
#define __MYDBG_H
#include "stm32f1xx_hal.h"
#include <stdio.h>
#include <stdarg.h>

/*
	使用GPIO口 模拟 UART 输出字符串
*/
//初始化调试接口
void InitDbg(GPIO_TypeDef  *pGPIO ,uint16_t uPin);
//调试 输出
void DbgPrintf(char *pFmt,...);
#endif 

MyDbg.c

cpp 复制代码
#include "MyDbg.h"

char g_DbgContent[100];
uint32_t g_Freq = 0;
GPIO_TypeDef  *g_DBG_GPIO; 
uint16_t g_Pin;

void Delay_us(uint32_t us) {
  uint32_t uTickCount = 0;
	//重载时间戳
  uint32_t uReloadTick = SysTick->LOAD;
	//转化
  uint32_t uTicks = us * g_Freq; 
  uint32_t uLastTick = SysTick->VAL; 
	while(1){
		//获取当前时间戳
		uint32_t uNowTick = SysTick->VAL;
		if(uNowTick != uLastTick){
			if (uNowTick < uLastTick) {
				uTickCount += uLastTick - uNowTick;
			}else {
				uTickCount += uReloadTick - uNowTick + uLastTick;
			}
			//更新时间戳
			uLastTick = uNowTick;
			//判断是否到时间了
			if (uTickCount >= uTicks){
				break;
			}
		}
	};
}

void UART_SendChar(char ch) {
    uint8_t data = (uint8_t)ch;
	  HAL_GPIO_WritePin(g_DBG_GPIO, g_Pin, GPIO_PIN_RESET); 
	  Delay_us(100); 
    for (int i = 0; i < 8; i++) {  // 8位数据
        if (data & 0x01) {
            HAL_GPIO_WritePin(g_DBG_GPIO, g_Pin, GPIO_PIN_SET);  // 设置高电平
        } else {
            HAL_GPIO_WritePin(g_DBG_GPIO, g_Pin, GPIO_PIN_RESET);  // 设置低电平
        }
        Delay_us(100);  // 延时1微秒(根据实际情况调整)
        data >>= 1;  // 移位到下一个位
    }
    // 发送停止位(通常一个高电平位)
    HAL_GPIO_WritePin(g_DBG_GPIO, g_Pin, GPIO_PIN_SET);  // 高电平停止位
    Delay_us(100);
}

void DbgPrintf(char *pFmt,...) {
	va_list ap;
  va_start(ap,pFmt);
	int n = vsprintf(g_DbgContent,pFmt,ap);
	va_end(ap);
	char *pStr = (char*)&g_DbgContent;
	while (*pStr != 0){
     UART_SendChar(*pStr++);  // 逐个字符发送
  }
}

void InitDbg(GPIO_TypeDef  *pGPIO ,uint16_t uPin){
	g_DBG_GPIO = pGPIO;
	g_Pin = uPin;
	g_Freq = SystemCoreClock / 1000000;
}

难点在于实现微秒级的延迟。

测试代码使用了GPIOA的PIN_1

cpp 复制代码
int main(void){
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_I2C1_Init();
	
  //初始化
  InitDbg(GPIOA,GPIO_PIN_1);
	
  int Count = 0;
  while (1){
	DbgPrintf("Count:%d##",Count);
    Count++;
	HAL_Delay(1000);
  }
}

输出效果:

相关推荐
@晓凡11 小时前
keil5找不到下载器
stm32
Devlab11 小时前
LVGL设计大师——网页版anyui来了!!
嵌入式硬件·物联网·低代码·ui·iot
Dr.kangder15 小时前
嵌入式面试总结(十五)——异常处理
单片机·面试·职场和发展·系统架构·嵌入式
zlinear数据采集卡17 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
ACP广源盛1392462567317 小时前
蚂蚁百灵 Ling‑3.0‑flash 开源 + 昇腾 0‑Day 原生适配@ACP#GSV9001E 在国产算力矩阵中的机会与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
Rocktech_ruixun19 小时前
机器人端侧大模型部署对主板有哪些要求?瑞迅主控板分级方案对比
人工智能·嵌入式硬件·机器人
振南的单片机世界19 小时前
SysTick硬核拆解:既是HAL_Delay的“心跳”,也是RTOS的“节拍器”
arm开发·stm32·单片机·嵌入式硬件
Lzh编程小栈20 小时前
【嵌入式底层】SPI超透彻详解:通信原理、四线结构、四种模式、寄存器底层 + 面试全集
c语言·stm32·单片机·面试·职场和发展
Rocktech_ruixun20 小时前
机器人数据采集能力取决于什么?瑞迅科技RK3588/3576核心板方案深度解析
人工智能·嵌入式硬件·机器人
水果里面有苹果20 小时前
28-DRV8825PWPR步进电机驱动器
单片机