文章目录
STM32的串口重定向,便于Debug
uPrint.h
#ifndef __U_PRINT_H_
#define __U_PRINT_H_
void PrintfDebug(const char *fmt, ...);
#endif // __U_PRINT_H_
uPrint.c
不使用微库
#include "u_print.h"
#include "stdint.h"
#include "stdarg.h"
#include "stdio.h"
#include "usart.h"
#define CONSOLEBUF_SIZE 64
void PrintfDebug(const char *fmt, ...)
{
char Uart_buf[CONSOLEBUF_SIZE];
uint16_t len = 0;
va_list args;
va_start(args, fmt);
len = vsprintf(Uart_buf, fmt, args);
va_end(args);
HAL_UART_Transmit(&huart1, (uint8_t *)Uart_buf, len, 0xf);
}
使用微库
点击“魔术棒” Target标签下有个Use MicroLIB—勾选。
#include "u_print.h"
#include "stdint.h"
#include "stdarg.h"
#include "stdio.h"
#include "usart.h"
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
编译后若出现一下错误,则需要更改启动文件的堆栈大小
注:
//HAL库函数的Transmit的第一个参数为所使用的串口名称的句柄
HAL_UART_Transmit(&huart1, (uint8_t *)Uart_buf, len, 0xf);
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
usart.c
extern uint8_t arrBuffer[1]; //串口接收数据缓冲区
void MX_USART1_UART_Init(void)
{
/* MX CODE BEGIN USART1_Init 0 */
//。。。。。。。。。。。。。。。
/* MX CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init */
HAL_UART_Receive_IT(&huart1, arrBuffer, 1);
/* USER CODE END USART1_Init */
}
stm32g4xx_it.c
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
while(HAL_UART_Receive_IT(&huart1, arrBuffer, 1) != HAL_OK) //所以这里要重新使能,同时接收
{
//当接收错误会卡死在这
}
/* USER CODE END USART1_IRQn 1 */
}
定时器框架
uTimer.h
#ifndef _U_TIMER_H_
#define _U_TIMER_H_
#include "main.h"
extern uint8_t s_2msFalg;
extern uint8_t s_1sFalg;
typedef enum
{
FALSE = 0,
TURE
}E3_MODE;
uint8_t Get2msFlag(void); //获取2ms标志位的值
void Clr2msFlag(void); //清除2ms标志位
uint8_t Get1SecFlag(void); //获取1s标志位的值
void Clr1SecFlag(void); //清除1s标志位
#endif //_U_TIMER_H_
uTimer.c
#include "u_Timer.h"
uint8_t s_2msFalg;
uint8_t s_1sFalg;
uint8_t Get2msFlag(void) //获取2ms标志位的值
{
return s_2msFalg;
}
void Clr2msFlag(void) //清除2ms标志位
{
s_2msFalg = FALSE;
}
uint8_t Get1SecFlag(void) //获取1s标志位的值
{
return s_1sFalg;
}
void Clr1SecFlag(void) //清除1s标志位
{
s_1sFalg = FALSE;
}
tim.c
void MX_TIM7_Init(void)
{
//溢出时间为1ms
/* USER CODE BEGIN TIM17_Init 2 */
HAL_TIM_Base_Start_IT(&htim7);
/* USER CODE END TIM17_Init 2 */
}
stm32g4xx_it.c
void TIM7_DAC_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim7);
static uint16_t s_cnt2ms;
if(__HAL_TIM_GET_ITSTATUS(&htim7, TIM_IT_UPDATE) == SET) //TIM7产生中断信号
{
__HAL_TIM_CLEAR_IT(&htim7, TIM_FLAG_UPDATE); //清除中断信号
}
s_cnt2ms++; //2ms计数值
if(s_cnt2ms >= 2) //2ms时间
{
s_cnt2ms = 0; //清除2ms计数值
s_2msFalg = TURE; //2ms标志位
}
}
main.c
static void Proc1sTask(void); //1s任务
static void Proc2msTask(void); //2ms任务
void LEDFlicker(uint16_t cnt);
static void Proc1sTask(void) //1s任务
{
if(Get1SecFlag())
{
Clr1SecFlag();
}
}
static void Proc2msTask(void) //2ms任务
{
if(Get2msFlag())
{
LEDFlicker(500); //500msLD2闪烁
Clr2msFlag();
}
}
void LEDFlicker(uint16_t cnt) //板载LED闪烁
{
static uint16_t s_iCnt; //定义静态变量s_iCnt作为计数器
s_iCnt++; //计数器的计数值加1
if(s_iCnt >= cnt) //计数器的计数值大于cnt
{
s_iCnt = 0; //重置计数器的计数值为0
HAL_GPIO_TogglePin(GPIOF, LEDR_Pin|LEDG_Pin|LEDB_Pin);
}
}