【嵌入式】STM32的串口通信—USART

一、实验目的

本次实验主要完成使用usart完成stm32的串口通信,以下为具体要求:

1)设置波特率为115200,1位停止位,无校验位。
2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。
3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。

二、串口和usart

首先,来认识认识串口和usart
在这里插入图片描述
+  DCD:载波检测,

USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。有别与USART,还有一个UART,它在USART基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是
UART。 串口通信一般是以帧格式传输数据,即一帧一帧传输,每帧包含有起始信号、数据信息、停止信息,可能还有校验信息。 USART
满足外部设备对工业标准 NRZ 异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART
支持同步单向通信和半双工单线通信;还支持局域互连网络 LIN、智能卡(SmartCard)协议与 lrDA(红外线数据协会) SIR
ENDEC规范。 USART支持使用 DMA,可实现高速数据通信。

以下即为stm32芯片和USB-转串口的连接方式。
在这里插入图片描述
使用杜邦线将核心板与USB转TTL接口相连

在这里插入图片描述
而我使用的是野火指南者,直接连usb即可
在这里插入图片描述

三、相关代码

Keil5创建一个新的工程,引入固件库后新建三个文件
main.c

#include "stm32f10x.h"
#include "bsp_usart.h"


// 接收缓冲,最大100个字节
uint8_t USART_RX_BUF[100];
// 接收状态标记位
uint16_t USART_RX_FLAG=0;


/*********************************************************
    					串口中断函数
**********************************************************/
void DEBUG_USART_IRQHandler(void)
{
	uint8_t temp;
	//接收中断
	if(USART_GetFlagStatus(DEBUG_USARTx, USART_IT_RXNE) != RESET)
	{
		// 读取接收的数据
		temp = USART_ReceiveData(DEBUG_USARTx);
		//接收未完成
		if((USART_RX_FLAG & 0x8000)==0)
		{
			//接收到了0x0d
			if(USART_RX_FLAG & 0x4000)
			{
				// 接收错误,重新开始
				if(temp != 0x0a) USART_RX_FLAG=0;
				// 接收完成
				else USART_RX_FLAG |= 0x8000;
			}
			// 还未接收到0x0d
			else
			{
				if(temp == 0x0d) USART_RX_FLAG |= 0x4000;
				else
				{
					USART_RX_BUF[USART_RX_FLAG & 0x3FFF]=temp;
					USART_RX_FLAG++;
					//接收数据错误,重新开始接收
					if(USART_RX_FLAG > 99) USART_RX_FLAG=0;
				}
			}
		}
	}
}


int main(void)
{
	uint8_t len=0;
	uint8_t i=0;
	// USART初始化
	USART_Config();
	while(1)
	{
		if(USART_RX_FLAG & 0x8000)
		{
			// 获取接收到的数据长度
			len = USART_RX_FLAG & 0x3FFF;
			printf("你发送的消息为:");
			for(i=0; i<len;i++)
			{
				// 向串口发送数据
				USART_SendData(DEBUG_USARTx, USART_RX_BUF[i]);
				//等待发送结束
				while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TC)!=SET);
			}
			printf("\n\n");
			if(strcmp((char *)USART_RX_BUF,"Stop,stm32!")==0)
			{
				printf("stm32已停止发送!");
				break;
			}
			USART_RX_FLAG=0;
			memset(USART_RX_BUF,0,sizeof(USART_RX_BUF));
		}
		else
		{
			printf("hello windows!\n");
			delay_ms(800);
		}
	}
}

bsp_usart.h

#ifndef __BSP_USART_H__
#define __BSP_USART_H__

#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>

/******************************************************
		串口的宏定义:总线时钟宏和GPIO的宏
*******************************************************/

// 串口USART1
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200


// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler


// 函数
void USART_Config(void);
void Usart_SendByte(USART_TypeDef * pUSARTx, uint8_t ch);
void Usart_SendString(USART_TypeDef * pUSARTx, char *str);
void delay_ms(uint16_t delay_ms);
	
#endif /*__BSP_USART_H__*/

bsp_usart.c

#include "bsp_usart.h"


/**************************************************
		配置嵌套向量中断控制器NVIC
**************************************************/
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  // 嵌套向量中断控制器组选择
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  // 配置USART为中断源
  NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
  // 抢断优先级
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  // 子优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  // 使能中断
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  // 初始化配置NVIC
  NVIC_Init(&NVIC_InitStructure);
}


/**************************************************
			USART初始化配置
**************************************************/
void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打开串口GPIO的时钟
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
	
	// 打开串口外设的时钟
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

	// 将USART Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

    // 将USART Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	// 配置串口的工作参数
	// 配置波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	// 配置 针数据字长
	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(DEBUG_USARTx, &USART_InitStructure);
	
	// 串口中断优先级配置
	NVIC_Configuration();
	
	// 使能串口接收中断
	USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);	
	
	// 使能串口
	USART_Cmd(DEBUG_USARTx, ENABLE);
}


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


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


/**************************************************
				微秒级的延时
**************************************************/
void delay_us(uint32_t delay_us)
{    
  volatile unsigned int num;
  volatile unsigned int t;
 
  
  for (num = 0; num < delay_us; num++)
  {
    t = 11;
    while (t != 0)
    {
      t--;
    }
  }
}


/**************************************************
				毫秒级的延时
**************************************************/
void delay_ms(uint16_t delay_ms)
{    
  volatile unsigned int num;
  for (num = 0; num < delay_ms; num++)
  {
    delay_us(1000);
  }
}


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


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

四、结果与演示

使用mcuisp将程序烧录进指南者板子中
在这里插入图片描述
接下来就可以使用串口调试助手进行验证了
在这里插入图片描述
可以看到输入“Stop,stm32!”后板子停止发送“hello windows!”。

五、参考

STM32串口通信USART学习笔记
stm32串口通信 —— USART通信实践
STM32系统学习——USART(串口通信)

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的嵌入式stm32f103串口232通讯程序: ```c #include "stm32f10x.h" #include <stdio.h> USART_InitTypeDef USART_InitStructure; void USART1_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; 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(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } void USART1_SendChar(char ch) { while (!(USART1->SR & USART_SR_TXE)); USART1->DR = ch; } void USART1_SendString(char* str) { while (*str) { USART1_SendChar(*str); str++; } } char USART1_ReceiveChar(void) { while (!(USART1->SR & USART_SR_RXNE)); return USART1->DR; } int main(void) { USART1_Init(); char str[100]; sprintf(str, "Hello World!\n"); USART1_SendString(str); while (1) { char ch = USART1_ReceiveChar(); sprintf(str, "Received character: %c\n", ch); USART1_SendString(str); } } ``` 这个程序使用了USART1来进行串口通讯,使用了PA9和PA10引脚作为USART1的TX和RX引脚。程序中包含了USART1的初始化函数和发送和接收字符的函数。在主函数中,程序首先发送了一个字符串“Hello World!”,然后不断接收字符并将接收到的字符原样发送回去。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值