STM32F407野火霸天虎系列笔记(三)UART通信

一、前言


        我在学习的过程中,经历过毫无头绪,找到一堆学习资料却不知从何开始的痛苦。我希望我整理的笔记,不光可以方便自己在以后的项目中拿来即用,也希望能够对那些喜欢玩硬件、爱折腾的小伙伴有所帮助。如果你们觉得我的文章对你们有用,欢迎大家点赞+收藏,让我知道,我的工作是有价值的。

        这篇笔记,综合参考了野火、正点原子、st官方以及网络上的一些资料,然后经过我自己的思考、尝试与实践,从而整理出来的。感谢那些愿意在学习的路上分享自己知识与经验的前辈。
 

二、学习笔记

(一)、学习思路

1.初始化GPIO口

2.连接GPIO到复用的映射上

3.配置USART

        串口参数初始化

        串口使能

4.开启中断,初始化NVIC,使能NVIC

5.串口中断服务函数

(二)、理论和代码部分

协议层

起始位(1),位0-位7,校验位(1),停止位(1)

必要函数了解:

获取状态标志位函数

// 获取状态标志位
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
// 清除状态标志位
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
// 获取中断状态标志位
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
// 清除中断状态标志位
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

接收发送数据函数

// 发送数据到串口(通过写USART_DR寄存器发送数据)
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
// 接收数据(从USART_DR寄存器读取接收到的数据)
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

串口配置函数

// 串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
// 使能串口
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
// 使能相关中断
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);

1.初始化GPIO口

PA9为TX,PA10为RX.模式选择复用模式

GPIO_InitTypeDef GPIO_InitStruct;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
	GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	GPIO_InitStruct.GPIO_Speed = GPIO_Low_Speed;
	 
	GPIO_Init(GPIOA, &GPIO_InitStruct);

2.连接GPIO到复用的映射上

	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
	
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

3.串口初始化并且使能串口

注意对应开启的时钟在RCC头文件中找

USART_InitTypeDef USART_InitStruct;

/* 使能 USART 时钟 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  /* 配置串DEBUG_USART 模式 */
  /* 波特率设置:DEBUG_USART_BAUDRATE */
  USART_InitStruct.USART_BaudRate = 9600;
  /* 字长(数据位+校验位):8 */
  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
  /* 停止位:1个停止位 */
  USART_InitStruct.USART_StopBits = USART_StopBits_1;
  /* 校验位选择:不使用校验 */
  USART_InitStruct.USART_Parity = USART_Parity_No;
  /* 硬件流控制:不使用硬件流 */
  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  /* USART模式控制:同时使能接收和发送 */
  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  /* 完成USART初始化配置 */
  USART_Init(DEBUG_USART, &USART_InitStruct); 
//使能串口
USART_Cmd(USART1, ENABLE);

4.配置中断控制器和使能USART接收中断

NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 嵌套向量中断控制器组选择 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART为中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
  /* 抢断优先级为1 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子优先级为1 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
//打开串口1的接收中断,当串口1接收到数据时会触发此中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

5.中断服务函数

注意以下:

1.中断服务函数不能传入参数;

2.中断服务函数不能有返回值;

3.不要在函数中使用printf

 /**
	* @brief  中断接收处理函数
  * @param  无
  * @retval 无
  */	
	
void DEBUG_USART_IRQHandler(void)
{
  uint8_t ucTemp;
	if(USART_GetITStatus(DEBUG_USART,USART_IT_RXNE)!=RESET)// 接收到数据
	{		
		ucTemp = USART_ReceiveData( DEBUG_USART );// 获得串口1接收到的数据
        USART_SendData(DEBUG_USART,ucTemp);    // 通过串口1发送数据
	}	 
}

6。其他函数

/**
	* @brief  由单片机向电脑端发送一个字节
  * @param  pUSARTx是单片机的串口
	* @param	ch是发送的字节
  * @retval 无
  */

void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
	/* 发送一个字节USART */
	USART_SendData(pUSARTx,ch);
		
	/* 等待发送数据寄存器为空 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

 /**
	* @brief  由单片机向电脑端发送一个字节串
  * @param  pUSARTx是单片机的串口
	* @param	str是发送的字节串
  * @retval 无
  */

void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
	unsigned int k=0;
  do 
  {
      Usart_SendByte( pUSARTx, *(str + k) );
      k++;
  } while(*(str + k)!='\0');
  
  /*等待发送完成 */
  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
  {}
}

 /**
	* @brief  由单片机向电脑端发送一个16进制数字
  * @param  pUSARTx是单片机的串口
	* @param	ch是发送的16进制数字
  * @retval 无
  */

void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
	uint8_t temp_h, temp_l;
	
	/* 取出高八位 */
	temp_h = (ch&0XFF00)>>8;
	/* 取出低八位 */
	temp_l = ch&0XFF;
	
	/* 发送高八位 */
	USART_SendData(pUSARTx,temp_h);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
	
	/* 发送低八位 */
	USART_SendData(pUSARTx,temp_l);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到串口 */
		USART_SendData(DEBUG_USART, (uint8_t) ch);
		
		/* 等待发送完毕 */
		while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}

///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
		/* 等待串口输入数据 */
		while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(DEBUG_USART);

你可能感兴趣的:(#,STM32,stm32,嵌入式)