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);
}