STM32串口发送接收数据

2023-05-16

目录

  • 1.串口通信
  • 2.串口的结构体
  • 3.如何配置串口的发送
  • 4.通过串口向电脑发送ok字符
  • 5.封装发送字符串函数
  • 6.重定向printf串口发送
  • 7.串口输入控制LED灯开关
  • 遇到的问题

1.串口通信

在这里插入图片描述
我用的32是stm32f10x最小系统没有UART4和UART5
USART : 通用同步异步收发器
UART : 通用异步收发器
nRTS : 请求发送
nCTS : 请求接收
区别:USART指单片机的一个IO端口模块,可以根据需要配置成同步模式(SPI,IIC),也可以配置成异步模式(UART).可以理解为USART为SPI,IIC对等的”协议”。 UART则不是一个协议,为一个实体。

2.串口的结构体

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Fck : 串口的时钟(APB1 36M / APB2 72M )
USARTDIV : 无符号的定点数

115200= 72 * 1000000/16 * USARTDIV

3.如何配置串口的发送

1.配置时钟: GPIO口的时钟,串口的时钟, 引脚复用的时钟
2.配置GPIO的结构体
3.配置串口的结构体
4.串口的发送

在这里插入图片描述

4.通过串口向电脑发送ok字符

按照上面的四个步骤进行编写
我们会发现只能一个一个发送字符,比较麻烦,所以后面封装了一个可以发送字符串的函数。
usart.c

#include "usart.h"
#include "stm32f10x.h"

void usart_init(void)
{
	GPIO_InitTypeDef gpio_init;
	USART_InitTypeDef usartStruct;
	
	//1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//2.ÅäÖÃGPIOµÄ½á¹¹Ìå
	//2.1 TX
	gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
	gpio_init.GPIO_Pin = GPIO_Pin_9;
	gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//2.2 RX
	gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpio_init.GPIO_Pin = GPIO_Pin_10;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//3.ÅäÖô®¿ÚµÄ½á¹¹Ìå
	usartStruct.USART_BaudRate = 115200;
	usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	usartStruct.USART_Parity = USART_Parity_No;
	usartStruct.USART_StopBits = USART_StopBits_1;
	usartStruct.USART_WordLength = USART_WordLength_8b;
	
	USART_Init(USART1,&usartStruct);
	USART_Cmd(USART1, ENABLE );
	
}

usart.h

#include "stm32f10x.h"

void usart_init(void);

main.c

#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exti.h"
#include "usart.h"

void delay(uint16_t time)
{
	uint16_t i =0;
	while(time--){
		i=12000;
		while(i--);
	}
}

int main()
{
	usart_init();
	
	while(1)
	{
		USART_SendData(USART1,'n');
		//ÏÂÃæUSART_GetFlagStatusΪÁËÅжÏÊý¾Ý¼Ä´æÆ÷ÊÇ·ñΪ¿Õ
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		USART_SendData(USART1,'t');
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		USART_SendData(USART1,'\n');
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		delay(1000);
	}

}

在这里插入图片描述

5.封装发送字符串函数

注意:在封装发送字符串函数时,while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);是为了把数据发送完
usart.c

#include "usart.h"
#include "stm32f10x.h"

void usart_init(void)
{
	GPIO_InitTypeDef gpio_init;
	USART_InitTypeDef usartStruct;
	
	//1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//2.ÅäÖÃGPIOµÄ½á¹¹Ìå
	//2.1 TX
	gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
	gpio_init.GPIO_Pin = GPIO_Pin_9;
	gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//2.2 RX
	gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpio_init.GPIO_Pin = GPIO_Pin_10;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//3.ÅäÖô®¿ÚµÄ½á¹¹Ìå
	usartStruct.USART_BaudRate = 115200;
	usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	usartStruct.USART_Parity = USART_Parity_No;
	usartStruct.USART_StopBits = USART_StopBits_1;
	usartStruct.USART_WordLength = USART_WordLength_8b;
	
	USART_Init(USART1,&usartStruct);
	USART_Cmd(USART1, ENABLE );
	
}

//·â×°ÁËһϷ¢ËÍ×Ö·û
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data)
{
	USART_SendData(USARTx,Data);
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

}

//·¢ËÍ×Ö·û´®
void usartSendStr(USART_TypeDef* USARTx,char *str)
{
	uint16_t i = 0;
	do{
		usartSendByte(USARTx,*(str+i));
		i++;
	}while(*(str+i) != '\0');

	//ÅжÏÊÇ·ñ·¢ËÍÍê
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}

usart.h

#include "stm32f10x.h"

void usart_init(void);
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data);
void usartSendStr(USART_TypeDef* USARTx,char *str);

main.c

#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exti.h"
#include "usart.h"

void delay(uint16_t time)
{
	uint16_t i =0;
	while(time--){
		i=12000;
		while(i--);
	}
}

int main()
{
	usart_init();
	
	while(1)
	{
		usartSendStr(USART1,"Finny\r\n");
		delay(1000);
	}

}

在这里插入图片描述

6.重定向printf串口发送

要使用printf,我们需要添加#include <stdio.h>头文件(学过c的都应该知道吧)

记得要给下图框住的内容打勾哦
在这里插入图片描述
stdio.h文件中有一个宏定义fputc,我们需要使用printf只需要重定向fputc就可以使用啦
在这里插入图片描述
usart.h

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

void usart_init(void);
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data);
void usartSendStr(USART_TypeDef* USARTx,char *str);

usart.c

#include "usart.h"
#include "stm32f10x.h"

void usart_init(void)
{
	GPIO_InitTypeDef gpio_init;
	USART_InitTypeDef usartStruct;
	
	//1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//2.ÅäÖÃGPIOµÄ½á¹¹Ìå
	//2.1 TX
	gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
	gpio_init.GPIO_Pin = GPIO_Pin_9;
	gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//2.2 RX
	gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpio_init.GPIO_Pin = GPIO_Pin_10;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//3.ÅäÖô®¿ÚµÄ½á¹¹Ìå
	usartStruct.USART_BaudRate = 115200;
	usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	usartStruct.USART_Parity = USART_Parity_No;
	usartStruct.USART_StopBits = USART_StopBits_1;
	usartStruct.USART_WordLength = USART_WordLength_8b;
	
	USART_Init(USART1,&usartStruct);
	USART_Cmd(USART1, ENABLE );
	
}

//·â×°ÁËһϷ¢ËÍ×Ö·û
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data)
{
	USART_SendData(USARTx,Data);
	while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);

}

//·¢ËÍ×Ö·û´®
void usartSendStr(USART_TypeDef* USARTx,char *str)
{
	uint16_t i = 0;
	do{
		usartSendByte(USARTx,*(str+i));
		i++;
	}while(*(str+i) != '\0');

	//ÅжÏÊÇ·ñ·¢ËÍÍê
	while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
}

int fputc(int ch,FILE *f)
{
	USART_SendData(USART1,(uint8_t)ch);
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
	
	return (ch);
}

main.c

#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exti.h"
#include "usart.h"
#include "stdio.h"

void delay(uint16_t time)
{
	uint16_t i =0;
	while(time--){
		i=12000;
		while(i--);
	}
}

int main()
{
	usart_init();
	
	GPIO_SetBits(GPIOA, GPIO_Pin_3);
	GPIO_SetBits(GPIOC, GPIO_Pin_13);
	
	while(1)
	{
//		usartSendStr(USART1,"°ÂÀï¸ø\r\n");
		int i = printf("Finny\r\n");
		printf("%d\r\n",i);
//		putchar('2');
		
		delay(1000);
	}
}

图下为什么i不是5而是7呢,因为\r\n各占了1

重定向fputc不只可以使用printf还可以使用putchar,大伙可以试试呀
在这里插入图片描述

7.串口输入控制LED灯开关

输入o让led灯打开并输出Open LED light success,输入c让led灯关闭并输出Close LED light success

提示: main.c中会看见有外部中断的代码,这是之前做震动感应灯的点此进入 STM32 EXTI(外部中断)
在这里插入图片描述
led.h

#include "stm32f10x.h"
void Led_init(void);

led.c

#include "stm32f10x.h"
#include "led.h"

void Led_init(void)
{
	GPIO_InitTypeDef Led_init;
	
	//1.ʹÄÜAPB2µÄʱÖÓGPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	//2.½á¹¹ÌåÅäÖÃ
	Led_init.GPIO_Mode 	= GPIO_Mode_Out_PP;
	Led_init.GPIO_Pin	  = GPIO_Pin_13;
	Led_init.GPIO_Speed = GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOC, &Led_init);
}

usart.h

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

void usart_init(void);
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data);
void usartSendStr(USART_TypeDef* USARTx,char *str);

usart.c

#include "usart.h"
#include "stm32f10x.h"

void usart_init(void)
{
	GPIO_InitTypeDef  gpio_init;
	USART_InitTypeDef usartStruct;
	NVIC_InitTypeDef  nvic_initStruct;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//1.ÅäÖÃʱÖÓ£ºGPIO¿ÚµÄʱÖÓ£¬Òý½Å¸´ÓõÄʱÖÓ£¬´®¿ÚµÄʱÖÓ
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//2.ÅäÖÃGPIOµÄ½á¹¹Ìå
	//2.1 TX
	gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
	gpio_init.GPIO_Pin = GPIO_Pin_9;
	gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//2.2 RX
	gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpio_init.GPIO_Pin = GPIO_Pin_10;
	
	GPIO_Init(GPIOA,&gpio_init);
	
	//3.ÅäÖô®¿ÚµÄ½á¹¹Ìå
	usartStruct.USART_BaudRate = 115200;
	usartStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usartStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	usartStruct.USART_Parity = USART_Parity_No;
	usartStruct.USART_StopBits = USART_StopBits_1;
	usartStruct.USART_WordLength = USART_WordLength_8b;
	
	USART_Init(USART1,&usartStruct);
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//ÅäÖô®¿ÚÖжÏ
	USART_Cmd(USART1, ENABLE );
	
	nvic_initStruct.NVIC_IRQChannel = USART1_IRQn;
	nvic_initStruct.NVIC_IRQChannelPreemptionPriority = 1;
	nvic_initStruct.NVIC_IRQChannelSubPriority = 1;
	nvic_initStruct.NVIC_IRQChannelCmd = ENABLE;
	
	NVIC_Init(&nvic_initStruct);

	
}

//·â×°ÁËһϷ¢ËÍ×Ö·û
void usartSendByte(USART_TypeDef* USARTx, uint16_t Data)
{
	USART_SendData(USARTx,Data);
	while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);

}

//·¢ËÍ×Ö·û´®
void usartSendStr(USART_TypeDef* USARTx,char *str)
{
	uint16_t i = 0;
	do{
		usartSendByte(USARTx,*(str+i));
		i++;
	}while(*(str+i) != '\0');

	//ÅжÏÊÇ·ñ·¢ËÍÍê
	while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
}

int fputc(int ch,FILE *f)
{
	USART_SendData(USART1,(uint8_t)ch);
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
	
	return (ch);
}

int fgetc(FILE *f)
{
	while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
	
	return (int) USART_ReceiveData(USART1);
}

main.c

#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exti.h"
#include "usart.h"
#include "stdio.h"

void delay(uint16_t time)
{
	uint16_t i =0;
	while(time--){
		i=12000;
		while(i--);
	}
}

int main()
{
	Led_init();
	Relay_Init();
	Shake_init();
	exti_init();
	usart_init();
	
	//³õʼ»¯Òý½Å
	GPIO_SetBits(GPIOA, GPIO_Pin_3);
	GPIO_SetBits(GPIOC, GPIO_Pin_13);

}

void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus( EXTI_Line1 ) != RESET){// ÅжÏÊÇ·ñ·¢ÉúÖжÏ
		GPIO_ResetBits(GPIOA, GPIO_Pin_3);
		usartSendStr(USART1,"Open light success\r\n");
		delay(1000);
		GPIO_SetBits(GPIOA, GPIO_Pin_3);
		usartSendStr(USART1,"Close light success\r\n");
	}

	EXTI_ClearFlag(EXTI_Line1);
	
}

void USART1_IRQHandler(void)
{
	char temp;
	
	if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){
		
		temp = USART_ReceiveData(USART1);

		if(temp == 'o'){
			GPIO_ResetBits(GPIOC, GPIO_Pin_13);
			usartSendStr(USART1,"Open LED light success\r\n");
		}
		
		if(temp == 'c'){
			GPIO_SetBits(GPIOC, GPIO_Pin_13);
			usartSendStr(USART1,"Close LED light success\r\n");
		}
	}
}
	

遇到的问题

评论区中小鲸鱼uu私信我了一个问题,就是他串口输出乱码
为什么senddata不能发送int的数字,因为将数字转换成ASCII码输出了,至于ASCII码表百度一下吧

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32串口发送接收数据 的相关文章

随机推荐

  • 平衡二叉树的一系列操作:删除、插入(在二叉排序树中插入新结点后,如何保持平衡)、调整平衡等等等

    平衡二叉树的插入 xff08 在二叉排序树中插入新结点后 xff0c 如何保持平衡 xff09 1 平衡二叉树的定义2 平衡二叉树的插入 xff08 调整最小不平衡子树A xff09 2 1LL xff08 在A的左孩子的左子树中插入导致不
  • 网络 UDP协议(C++|代码通过udp协议实现客户端与服务端之间的通信)

    这里写目录标题 udp通信编程各端的操作流程 xff1a 服务端操作流程 xff1a 客户端操作流程 xff1a 第2 3步与服务端不同 socket接口介绍udp客户服务端代码实现 推荐阅读 socket套接字编程就是在网络程序中编写代码
  • 网络 TCP协议(C++代码|通过tcp协议实现客户端与服务端之间的通信)

    目录 TCP通信编程各端的操作流程 xff1a 服务端操作流程 xff1a 客户端操作流程 xff1a 推荐先学习UDP协议在学习TCP协议 在UDP协议博客中讲解得更详细 xff0c 看懂UDP协议就很容易理解TCP了 网络 UDP协议
  • Matlab学习-箱型图绘制

    1 箱型图简介 xff1a 参考链接 xff1a boxplot函数用法详解 箱型图简介 箱型图主要包括的数据有 xff1a 最大值 最小值 上四分位数 下四分位数和中位数 xff0c 以及异常值 2 箱型图绘制 X span class
  • Matlab学习-CDF(累积分布函数图)绘制

    累积分布函数图绘制 参考链接 xff1a 1 Matlab官方说明 2 参考链接 3 属性设置 CDF xff1a 累积分布函数图 xff0c 顾名思义就是能够直观的反应某组数列分布的概率情况 xff0c 能够非常直观的反应误差精度大小 图
  • Matlab学习-频率分布直方图绘制

    参考链接 xff1a hist xff08 xff09 函数用法 频率分布直方图 xff1a 在数理统计中 xff0c 会经常使用到频率分布直方图 xff0c 能够直观的反应频率分布的范围大小 xff0c 在直角坐标系中 xff0c 横轴为
  • Matlab学习-经纬度在matlab内置地图显示

    已知经纬度坐标 xff0c 将其显示是地图上 参考链接 xff1a 使用matlab绘制世界地图并根据经纬度绘制点位 附m map的下载与安装说明 wm span class token operator 61 span webmap sp
  • ARM存储格式的“大小端”解析

    ARM储存 大端格式和小端格式 所谓的大端模式 xff0c 是指数据的高位 xff0c 保存在内存的低地址中 xff0c 而数据的低位 xff0c 保存在内存的高地址中 xff0c 这样的存储模式有点儿类似于把数据当作字符串顺序处理 xff
  • UBLOX板卡基础设置--F9P板卡配置(基准站和流动站)

    UBLOX F9P板卡配置 基准站 流动站 UBX F9P模块为双频定位芯片 xff0c 是市场上目前最常用的高精定位模块 xff0c 差分定位精度可达厘米级 xff0c 具体参数详见官方文档 官方文档下载链接 xff1a UBX F9P模
  • GIT学习-常用命令

    2 GIT学习 常用命令 在学习git前首先需要对相关名词和概念有基本了解 xff0c git基础知识学习可参考以下资料 xff1a git基础知识 xff1a GIT学习 1 基础知识git下载与配置 xff1a GIT学习 xff08
  • ROS常用命令

    ROS常用命令 1 将话题数据单独导出 将话题数据单独导出为一个文件 rostopic echo b name name p topic name gt save file name ex rostopic echo b test bag
  • Linux常用命令

    Linux常用命令 1 查看电脑IP地址 ifconfig 2 远程连接其他电脑 xff0c 查看是否连接成功 ping IP address 3 通过IP地址远程连接电脑 ssh lcl 64 IP address 4 文件传输 4 1
  • opencv-3.4.1-x86编译安装 -- 超详细

    相关链接 xff1a opencv 3 4 1 arm编译安装 超详细 opencv 3 4 1 x86编译安装 环境1 安装依赖库2 OpenCV源码获取与解压2 1 获取源码2 2 工作目录准备2 3 解压 3 OpenCV配置编译3
  • Qt编程之单例模式——代码复用,一个类供多个类调用

    什么是单例模式 单例模式是一种对象创建模式 xff0c 用于生产一个对象的实例 xff0c 它可以确保系统中一个类只产生一个实例 xff0c 这样做有两个好处 xff1a 1 对于频繁使用的对象 xff0c 可以省略创建对象所花费的时间 x
  • STM32串口数据接收处理,数据分割为整形浮点型数据。

    简介 通过stm32的串口接收数据 xff0c 通过strstr函数分割数据 xff0c 再将字符数据转化为整形数据或浮点数据 比如 xff1a stm32接收到数据 s555s xff0c 分割数据为 555 xff0c 然后转化为int
  • 抛出异常时将异常信息返给前端

    全局异常处理器负责将抛出的异常 xff0c 以统一的格式返给前端 在这里起主要作用的注解是 64 RestControllerAdvice 64 RestControllerAdvice主要配合 64 ExceptionHandler使用
  • 关于入栈和出栈的理解

    关于入栈和出栈的理解 xff1a 假设程序在运行 xff0c 这个时候就会涉及到下面要说到的几个核心的寄存器 xff08 对栈进行操作 xff09 就是PC寄存器 xff08 为了能够准确地记录各个线程正在执行的当前字节码指令地址 xff0
  • 原生 css 实现进度条

    方案一 xff1a 通过data控制它的样式 1 首先搭建dom结构 lt div class 61 34 home left top content div 34 v for 61 34 item index in PowerAAcces
  • 实现开发板、电脑(无线网卡)与虚拟机三者通过网络连接(三者都可以上外网)

    借鉴文章 xff1a https blog csdn net dongtaintailiang article details 106314689 spm 61 1001 2014 3001 5501 因为项目需要 xff0c 找到这篇文章
  • STM32串口发送接收数据

    目录 1 串口通信2 串口的结构体3 如何配置串口的发送4 通过串口向电脑发送ok字符5 封装发送字符串函数6 重定向printf串口发送7 串口输入控制LED灯开关遇到的问题 1 串口通信 我用的32是stm32f10x最小系统没有UAR