ARM课作业八:USART串口通信

一、引言

介绍

USART(Universal Synchronous Asynchronous Receiver Transmitter)是一种常见的串口通信协议,广泛应用于嵌入式系统和通信设备中。它可以实现同步或异步的串口数据传输,并支持全双工通信,即同时进行发送和接收数据。

工作原理

USART串口通信的工作原理基于其名称中的同步(Synchronous)和异步(Asynchronous)两种模式。在同步模式下,数据的传输是以时钟信号的同步节拍进行的,发送方和接收方需要使用相同的时钟信号来保持同步。而在异步模式下,数据的传输不依赖于时钟信号,而是通过起始位、数据位、校验位和停止位来进行数据的解析和传输。在发送数据时,USART会先发送起始位,然后发送数据位和校验位(如果启用),最后发送停止位;在接收数据时,USART会检测起始位,然后按照数据位的格式解析数据,并根据校验位进行数据的验证,最后接收停止位。USART串口通信的工作原理简单而灵活,使其成为许多嵌入式系统中常用的通信方式。

二、代码

1.main.c

先初始化usartx模块,开启接收中断,连接成功后在XCOM中显示“连接成功请输入数据”

usRxCount 用于记录接收到的数据的数量,当接收到一个完整的命令帧后,会将接收计数器清零,以便开始接收下一个命令帧的数据

之后进入循环:

1.通过 if(Rxflag) 判断是否有数据被接收到。如果 Rxflag 为真,表示接收到了数据,则执行接下来的逻辑

2.在接收到数据时,先判断接收计数器 usRxCount 是否小于接收缓冲区 ucaRxBuf 的大小(即数组的长度)。如果小于,则将接收到的数据 ucTemp 存入接收缓冲区 ucaRxBuf 中,并将接收计数器 usRxCount 加1。这样可以避免数据溢出

3.如果接收计数器 usRxCount 大于等于接收缓冲区的大小,则将接收计数器清零,以防止数据溢出

4.然后判断接收到的数据是否为换行字符 0x0A,如果是换行字符,则表示接收到一个完整的命令帧。此时调用 Usart_SendStr_length() 函数发送接收到的命令帧数据,然后将接收计数器 usRxCount 清零,以便接收下一个命令帧的数据

5.最后将接收标志位 Rxflag 置为0,表示当前数据已被处理完毕

USARTx_IRQHANDLER(void)为中断服务函数,通过检查 USART_IT_RXNE 中断标志位判断是否接收到了数据,如果接收到数据,则将接收标志位 Rxflag 置为1,并将接收到的数据存入 ucTemp 变量中。

这段代码了实现通过 USART 串口通信与电脑进行数据的发送和接收,并且使用简单的通信协议(以换行字符为命令结束符)来解析和处理接收到的数据。

//功能: 使用串口通信实现发送数据到电脑以及接收电脑端发送的数据
#include "stm32f10x.h"
#include "usartx.h"

uint8_t Rxflag=0;
uint8_t ucTemp;

/**
  * 函数功能: 主函数.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
int main(void)
{  
  uint8_t ucaRxBuf[256];
	uint16_t usRxCount;
	
  /* USART 配置模式为 115200 8-N-1,中断接收 */
  USARTx_Init();
  
  Usart_SendString((uint8_t *)"连接成功\n");
	Usart_SendString((uint8_t *)"请输入数据\n");
  
	/* 简单的通信协议,遇到回车换行符认为1个命令帧 */  
	usRxCount = 0;
  
  /* 无限循环 */
  while (1)
  { 
   	/** 
			* 接收COM的数据,分析并处理 
			* 可以将此段代码封装为一个函数,在主程序其它流程调用
		  */
		if(Rxflag)
		{
			if (usRxCount < sizeof(ucaRxBuf))
			{
				ucaRxBuf[usRxCount++] = ucTemp;
			}
			else
			{
				usRxCount = 0;
			}
			
			/* 遇到换行字符,认为接收到一个命令 */
			if (ucTemp == 0x0A)	/* 换行字符 */
			{		
				Usart_SendStr_length(ucaRxBuf,usRxCount);
				usRxCount = 0;
			}
			Rxflag=0;
		}
  }
}

void USARTx_IRQHANDLER(void)
{
	if(USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET)
	{ 	
	  Rxflag=1;		
		ucTemp = USART_ReceiveData(USARTx);
	} 
}


2.usartx.c

解析见代码注释,这些函数共同完成了对 USART 串口的初始化配置和数据发送操作,使得用户能够方便地使用 USART 串口进行数据通信。USART模块为波特率115200,数据位8,校验位无,停止位1模式

//功 能: 串口底层驱动程序
#include "usartx.h" 
/**
  * 函数功能: 配置NVIC,设定USART接收中断优先级.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure; 
	 /* 嵌套向量中断控制器组选择 */  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	
   /* 配置USART为中断源 */
	NVIC_InitStructure.NVIC_IRQChannel = USARTx_IRQn;	 
	 /* 抢断优先级为0 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	 /* 子优先级为1 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	 /* 使能中断 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	 /* 初始化配置NVIC */
	NVIC_Init(&NVIC_InitStructure);
}

/**
  * 函数功能: 串口参数配置.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:使用宏定义方法代替具体引脚号,方便程序移植,只要简单修改bsp_led.h
  *           文件相关宏定义就可以方便修改引脚。
  */
void USARTx_Init(void)
{
  /* 定义IO硬件初始化结构体变量 */
  GPIO_InitTypeDef GPIO_InitStructure;
  /* 定义USART初始化结构体变量 */
	USART_InitTypeDef USART_InitStructure;
  
  /* 配置NVIC,设定USART接收中断优先级 */
  NVIC_Configuration();
  
  /* 使能USART时钟 */
  USARTx_ClockCmd(USARTx_CLK,ENABLE);
  /* 使能USART功能GPIO时钟 */
  USARTx_GPIO_ClockCmd(USARTx_TX_CLK | USARTx_RX_CLK | RCC_APB2Periph_AFIO,ENABLE);
  
	/* 调试USART功能GPIO初始化 */
	/* 设定USART发送对应IO编号 */
	GPIO_InitStructure.GPIO_Pin =  USARTx_TX_PIN;
  /* 设定USART发送对应IO模式:复用推挽输出 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  /* 设定USART发送对应IO最大操作速度 :GPIO_Speed_50MHz */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  /* 初始化USART发送对应IO */
	GPIO_Init(USARTx_TX_PORT, &GPIO_InitStructure);    
  
	/* 设定USART接收对应IO编号 */
	GPIO_InitStructure.GPIO_Pin = USARTx_RX_PIN;
  /* 设定USART发送对应IO模式:浮空输入 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  /* 其他没有重新赋值的成员使用与串口发送相同配置 */
  /* 初始化USART接收对应IO */
	GPIO_Init(USARTx_RX_PORT, &GPIO_InitStructure);	
			
	/* USART工作环境配置 */
  /* USART波特率:115200 */
	USART_InitStructure.USART_BaudRate = USARTx_BAUDRATE;
  /* USART字长(有效位):8位 */
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  /* USART停止位:1位 */
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
  /* USART校验位:无 */
	USART_InitStructure.USART_Parity = USART_Parity_No ;
  /* USART硬件数据流控制(硬件信号控制传输停止):无 */
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	/* USART工作模式使能:允许接收和发送 */
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  /* 初始化USART */
	USART_Init(USARTx, &USART_InitStructure);
  
	/* 使能接收中断 */
  USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);	
  
  /* 使能USART */
	USART_Cmd(USARTx, ENABLE);
 /* 清除发送完成标志 */
	USART_ClearFlag(USARTx, USART_FLAG_TC|USART_FLAG_TXE|USART_FLAG_RXNE);
}

/**
  * 函数功能: 串口发送一个字节数据 
  * 输入参数: ch:待发送字符
  * 返 回 值: 无
  * 说    明:无
  */
void Usart_SendByte(uint8_t ch)
{
  /* 发送一个字节数据到USART1 */
  USART_SendData(USARTx,ch);

  /* 等待发送完毕 */
  while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);	
}

/**
  * 函数功能: 串口发送指定长度的字符串
  * 输入参数: str:待发送字符串缓冲器
  *           strlen:指定字符串长度
  * 返 回 值: 无
  * 说    明:无
  */
void Usart_SendStr_length(uint8_t *str,uint32_t strlen)
{
  unsigned int k=0;
  do 
  {
    Usart_SendByte(*(str + k));
    k++;
  } while(k < strlen);
}

/**
  * 函数功能: 串口发送字符串,直到遇到字符串结束符
  * 输入参数: str:待发送字符串缓冲器
  * 返 回 值: 无
  * 说    明:无
  */
void Usart_SendString(uint8_t *str)
{
	unsigned int k=0;
  do 
  {
    Usart_SendByte(*(str + k));
    k++;
  } while(*(str + k)!='\0');
}

3.usartx.h

头文件,提供宏定义和函数声明

#ifndef __USARTX_H__
#define __USARTX_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include <stm32f10x.h>

/* 类型定义 ------------------------------------------------------------------*/
/* 宏定义 --------------------------------------------------------------------*/
#define USARTx_BAUDRATE                        115200

#define USARTx_ClockCmd                        RCC_APB2PeriphClockCmd
#define USARTx_CLK                             RCC_APB2Periph_USART1

#define USARTx_GPIO_ClockCmd                   RCC_APB2PeriphClockCmd
    
#define USARTx_TX_PORT                         GPIOA   
#define USARTx_TX_PIN                          GPIO_Pin_9
#define USARTx_TX_CLK                          RCC_APB2Periph_GPIOA 

#define USARTx_RX_PORT                         GPIOA 
#define USARTx_RX_PIN                          GPIO_Pin_10
#define USARTx_RX_CLK                          RCC_APB2Periph_GPIOA

#define USARTx_IRQHANDLER                      USART1_IRQHandler
#define USARTx_IRQn                            USART1_IRQn
#define USARTx                                 USART1

/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
void USARTx_Init(void);
void Usart_SendByte(uint8_t ch);
void Usart_SendStr_length(uint8_t *str,uint32_t strlen);
void Usart_SendString(uint8_t *str);

#endif 

三、实验结果

实现了USART串口通信的发送和接受

作业八

四、XCOM下载

XCOM串口调试软件的安装与使用(附串口及驱动资源包)-CSDN博客

五、总结

这次作业让我更好地了解了USART串口通信,在老师给的代码基础上进行修改,顺利完成了本次作业,锻炼了我的动手实践能力,拓展了专业知识,令我受益匪浅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值