串口通讯学习

1.物理层

1.1电平标准

通常有TTL和RS232电平标准

在这里插入图片描述

2.协议层

2.1数据包

通常由起始位、8位数据位、校验位、停止位,一共11位。

2.2波特率

我们经常使用的是Uart也就是异步通讯,因为没有时钟线连接,所以需要约定好单位时间内发送的数据量。
通常使用9600、115200

3.实现目标:单片机串口收发

3.0串口配置

这里使用串口5,即UART5

void uart5_init(u32 bps)
{
				
	
        NVIC_InitTypeDef 	NVIC_InitStruct;
        USART_InitTypeDef USART_InitStructure;
        GPIO_InitTypeDef 	GPIO_InitStructure;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
				
	//复用为UART5
				GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_5);
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_5);
	
	//UART5端口配置
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOC, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOD, &GPIO_InitStructure);
        
        

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

        NVIC_InitStruct.NVIC_IRQChannel = UART5_IRQn;
        NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStruct.NVIC_IRQChannelSubPriority = 4;
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStruct);

        USART_InitStructure.USART_BaudRate = bps;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
				USART_Init(UART5, &USART_InitStructure);
				
				
        //USART_DeInit(UART5);
        /*	使能串口接收中断	*/
        
        
//        UART5->CR1 |= 0x10;
       // USART_ClearFlag (UART5,USART_FLAG_TC|USART_FLAG_IDLE);

        USART_Cmd(UART5, ENABLE);
				
}

初始化配置,多使用几遍就会熟悉,大家不要害怕。

3.1串口发送

3.1.1串口发送单字符

//发送单字符
//因为一个汉字就占用一个字节,也就是8位数据,所以使用uint8_t
void Usart_SendByte(USART_TypeDef *pUSARTx,uint8_t dat)
{
	USART_SendData(pUSARTx,dat);
	//若数据未传输到移位寄存器,即数据未传输完成
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE)!=SET);
}

代码分析

在STM32F30xx_usart.h标准库函数中定义USART_SendData()

发送数据,即对DR寄存器进行写操作


/**
  * @brief  Transmits single data through the USARTx peripheral.
  * @param  USARTx: Select the USART peripheral. This parameter can be one of the 
  *         following values: USART1 or USART2 or USART3 or UART4 or UART5.
  * @param  Data: the data to transmit.
  * @retval None
  */
void USART_SendData(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->TDR = (Data & (uint16_t)0x01FF);
}

通过数据寄存器DR进行发送数据,寄存器大小[31:0],规定数据位[8:0],一共9位,所以当对TDR进行写操作时
USARTx->TDR = (Data & (uint16_t)0x01FF);
在这里插入图片描述
数据寄存器是包含了TDR(发送)和RDR(接收)两个寄存器,
当我们对DR(数据寄存器)写操作就是发送,读操作就是接收

接收数据,即对DR寄存器进行读操作

/**
  * @brief  Returns the most recent received data by the USARTx peripheral.
  * @param  USARTx: Select the USART peripheral. This parameter can be one of the 
  *         following values: USART1 or USART2 or USART3 or UART4 or UART5.
  * @retval The received data.
  */
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));

  /* Receive Data */
  return (uint16_t)(USARTx->RDR & (uint16_t)0x01FF);
}

返回从RDR寄存器中读到的数据,uint16_t返回数据大小两个字节

while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE)!=SET);

在STM32F30xx_usart.h标准库函数中定义USART_GetFlagStatus()

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint32_t USART_FLAG)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_FLAG(USART_FLAG));
  
  if ((USARTx->ISR & USART_FLAG) != (uint16_t)RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  return bitstatus;
}

在这里插入图片描述在这里插入图片描述
单字符发送完成时,即数据已经从TDR寄存器传输到移位寄存器时,USART_TXE标志位置1,USART_GetFlagStatus函数返回SET。

3.1.2 串口发送字符串



//发送字符串
//写法1
void Usart_SendByte1(USART_TypeDef *pUSARTx, char *str)
{
	uint8_t i=0;
	do{
		Usart_SendBit(pUSARTx,*(str+i));
		i++;
	}while(*(str+i)!='\0');
}
//写法2
void Usart_SendByte2(USART_TypeDef *pUSARTx,uint8_t *str)
{
	uint8_t i=0;
	do{
		Usart_SendBit(pUSARTx,str[i]);
		i++;
	}while(str[i]!=0);
}

上面的两种写法说明了一点,char字符串在存储方式类似于字符数组,因为他们都具有可以单独取出一串中的其中一个。

字符串使用指针自增访问每一个子串。
字符数组通过数组位号访问每一个字符。

main.c

int main(void)
{
	 SystemCoreClockUpdate();
	 SysTickInit();
	 uart5_init(115200);
	 uint8_t test[] = "这是字符串写法2的输出\r\n";
	 Usart_SendByte1(UART5,"这是字符串写法1的输出\r\n");
	 Usart_SendByte2(UART5,test);
	 while()
	 {
	 }
}

发送结果

在这里插入图片描述

3.2串口接收

前面配置串口的时候已经使能了串口接收中断,通过
USART_ITConfig(USART_TypeDef* USARTx, uint32_t USART_IT, FunctionalState NewState)

三个参数,串口号,串口中断类型,开启或关闭

使用例

USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);//开启串口5接收中断

通过UART5句柄函数,当发生接收中断时,将数据使用USART_SendData()函数返还到串口5TDR寄存器发送出去。

void UART5_IRQHandler(void)
{
	//因为recei函数返回2个字节大小,所以使用uint16_t
	uint16_t temp;
	//发生接收中断
	if(USART_GetFlagStatus(UART5,USART_IT_RXNE)!=RESET)
	{
		//接收到的数据,赋值给temp临时变量
		temp = USART_ReceiveData(UART5);
		USART_SendData(UART5,temp);
	}
}

接收函数USART_ReceiveData()和发送函数USART_SendData()的详情前面已经贴出来了,任然感觉不清楚可以返回前面再看看。

接收结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值