[STM32F1] STM32串口及printf

[复制链接]
1327|11
 楼主| primojones 发表于 2024-5-28 09:00 | 显示全部楼层 |阅读模式
1,开启串口相关的时钟,GPIO,USART的时钟

2,配置GPIO,注TX引脚AF的(OD和PP试过都没啥问题),RX浮空输入

3,配置USART的结构体,NVIC的分组和结构体成员,

4,选择串口通信的中断触发信号;usart_itconfig()确定中断源

5,使能串口  CMD函数;

注意;USART_GetFlagStatus函数可检测串口标志位,通过检测串口的标志位防止串口掉帧,确保数据发生或者接收完,具体标志查看手册。

USART_GetITStatus();函数可检测串口是否产生中断标志,防止误动作。

void usart1_init(void)

{

GPIO_InitTypeDef GPIORX_InitStruct;//GPIORX结构体名称

NVIC_InitTypeDef NVIC_InitStruct;//NVIC结构体名称

USART_InitTypeDef USART_InitStruct;//串口结构体名称

GPIO_InitTypeDef GPIOTX_InitStruct;//GPIOTX结构体名称

//时钟开启

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

//TX引脚初始化

GPIOTX_InitStruct.GPIO_Mode= GPIO_Mode_AF_OD;

GPIOTX_InitStruct.GPIO_Pin=GPIO_Pin_9;

GPIOTX_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIOTX_InitStruct);

//rX引脚初始化

GPIORX_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;

GPIORX_InitStruct.GPIO_Pin=GPIO_Pin_10;

GPIORX_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIORX_InitStruct);

//NVIC分组

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

//NVIC成员配置

NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn ;

NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;

NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;

NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;

NVIC_Init(&NVIC_InitStruct);

//串口结构体成员配置

USART_InitStruct.USART_BaudRate=9600;

USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

USART_InitStruct.USART_Mode= USART_Mode_Rx|USART_Mode_Tx;

USART_InitStruct.USART_Parity=USART_Parity_No;

USART_InitStruct.USART_StopBits=USART_StopBits_1;

USART_InitStruct.USART_WordLength=USART_WordLength_8b;

USART_Init(USART1,&USART_InitStruct);

//串口中断源选择

USART_ITConfig( USART1, USART_IT_RXNE,ENABLE);

//使能

USART_Cmd(USART1,ENABLE);

}

//print函数重定向

int fgetc(FILE *f)

{  

while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

return (int)USART_ReceiveData(USART1);

}

//选择窗口通信打印 不可打印中文,要加#include "stdio.h"      #include "stdarg.h"  #include "string.h"

//打印为void u1_printf(char* fmt,...) 函数

//PRINTF的核心函数  

void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data)

{

/* Check the parameters */

assert_param(IS_USART_ALL_PERIPH(USARTx));

assert_param(IS_USART_DATA(Data));  

     /* Transmit Data */

USARTx->DR = (Data & (uint16_t)0x01FF);

while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);

}

//串口1printf函数 可根据串口改变函数参数 使用要在头文件声明

__align(8) char USART1_TxBuff[256];  

void u1_printf(char* fmt,...)  

{  

unsigned int i =0,length=0;

va_list ap;

va_start(ap,fmt);

vsprintf(USART1_TxBuff,fmt,ap);

va_end(ap);

length=strlen((const char*)USART1_TxBuff);

while(i<length)

{

USART_SendByte(USART1,USART1_TxBuff[i]);  

i++;  

}

while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);

}



使用 u1_printf("%d\n",a[i]);在函数中进行串口打印

串口中断服务函数

void USART1_IRQHandler(void)//只要读数据寄存器非空,就会进入中断函数

{

if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))//也可以用USART_GetITStatus();来判断

{

USART_SendData(USART1, a++);//

while(USART_GetFlagStatus(USART1,USART_FLAG_TC));//确定发送完了信息,才出中断服务。

  }

USART_ClearFlag(USART1,USART_FLAG_RXNE);

}




y1n9an 发表于 2024-7-25 13:06 | 显示全部楼层
STM32微控制器通过其串口(UART)外设可以实现与其他设备的数据通信
su1yirg 发表于 2024-7-25 14:10 | 显示全部楼层
printf函数是C标准库中的一个函数,用于格式化输出。
tax2r6c 发表于 2024-7-25 15:16 | 显示全部楼层
在STM32项目中,你可以重定向printf函数到串口,从而通过串口发送格式化数据
kaif2n9j 发表于 2024-7-25 16:20 | 显示全部楼层
需要在STM32上配置串口。这通常涉及到初始化GPIO引脚、配置UART外设、设置波特率等。然后就可以使用了
d1ng2x 发表于 2024-7-25 17:23 | 显示全部楼层
为了将printf重定向到串口,你需要实现一个_write函数,并将其与__io_putchar函数关联
cen9ce 发表于 2024-7-25 18:33 | 显示全部楼层
确保你的开发环境(如STM32CubeIDE)已经正确配置,并且包含了必要的库文件
q1d0mnx 发表于 2024-7-26 10:00 | 显示全部楼层
在某些情况下,你可能需要禁用半主机模式(semihosting),特别是在使用调试器时
b5z1giu 发表于 2024-7-26 10:00 | 显示全部楼层
确保你的串口连接正确,并且波特率设置与接收设备匹配
lix1yr 发表于 2024-7-26 11:03 | 显示全部楼层
正常keil的话用microlib要勾选才行吧
Bowclad 发表于 2024-7-26 12:10 | 显示全部楼层
也可以不用printf
liu96jp 发表于 2024-7-26 13:00 | 显示全部楼层
这个重定义其实不用配置开发环境也行,用代码能实现
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

1559

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部