STM32F407串口通信

本文是基于江科大B站视频编写,参考各种资料进行学习。
在这里插入图片描述

1、USART串口协议

在这里插入图片描述
在这里插入图片描述
硬件电路(接线)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、USART串口外设

在这里插入图片描述
常用波特率为9600、115200
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
必须对应特定引脚,才能实现通信,如果引脚冲突,看看有没有重映射来改变引脚。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
fpclk频率是指SPI所在的APB总线频率,APB1为fpclk1,APB2为fpclk2。
在这里插入图片描述

3、串口发送程序

(1)接线

在这里插入图片描述
为什么选用PA9、10这两个引脚,如下图:
在这里插入图片描述
实物:
在这里插入图片描述

(2)代码

(a)main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "serial.h"

int main(void)
{	
	Serial_Init();
	
	Serial_SendByte(0x41);
	
	uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45};
	Serial_SendArray(MyArray, 4);
	
	Serial_SendString("\r\nNum1=");
	
	Serial_SendNumber(111, 3);
	
	printf("\r\nNum2=%d", 222);
	
	char String[100];
	sprintf(String, "\r\nNum3=%d", 333);
	Serial_SendString(String);
	
	Serial_Printf("\r\nNum4=%d", 444);
	Serial_Printf("王哈哈\r\n");
	
	while (1)
	{
		
	}
}

(c)serial.c

#include "stm32f4xx.h"
#include "serial.h"
#include <stdio.h>
#include <stdarg.h>

void SERIAL_Init(void)
{
	  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
 
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
	
	//USART1端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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); //初始化串口1
	
  USART_Cmd(USART1, ENABLE);  //使能串口1 
	
} 

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

int fputc(int ch, FILE *f)//为下面的函数做准备
{
	Serial_SendByte(ch);
	return ch;
}

void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}



(c)serial.h

#ifndef __SERIAL_H 
#define __SERIAL_H 

#include <stdio.h>

void Serial_Init(void);//初始化
void Serial_SendByte(uint8_t Byte);//打印单个字符
void Serial_SendArray(uint8_t *Array, uint16_t Length);//打印数组
void Serial_SendString(char *String);//打印字符串(但只能选定一个USRATx)
void Serial_SendNumber(uint32_t Number, uint8_t Length);//发送数字
void Serial_Printf(char *format, ...);//打印字符串(可以发送多个USRATx)

#endif

(d)代码说明

1、 Serial_Printf("王哈哈\r\n"); //“\r\n”为换行符
打印中文还需要以下操作,二选其一(选第一比较容易操作):
在这里插入图片描述
然后关闭main.c,再打开,编译下载。
在这里插入图片描述
记得选择GBK即可打印中文

第二个操作(比较麻烦):
选UTF-8,同上,不过多了下面的步骤:
在这里插入图片描述

(3)实物效果

A的ASCII码为41,复位一次STM32发送一个A。
在这里插入图片描述

4、串口发送&接收程序

第一种方法(非中断,不建议用)

其他函数跟《串口发送程序》的一样
在这里插入图片描述

在这里插入图片描述

第二种方法(中断,建议采用)

(a)main.c

#include "stm32f4xx.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "beep.h"
#include "key.h"
#include "servomotor.h"
#include "stepmotor.h"
#include "waterpump.h"
#include "electromagnet.h"
#include "oled.h"
#include "serial.h"


u8 RxData;

int main(void)
{
	delay_init(168);//必须加上,否则下面的初始化不成功
	
	OLED_Init();
	LED_Init();
	OLED_ShowString(0, 0, "RxData:");
	
	SERIAL_Init();
	
	while (1)
	{
		if (Serial_GetRxFlag() == 1)
		{
			RxData = Serial_GetRxData();
			Serial_SendByte(RxData);
			if(RxData == 1)
			{
				LED1=0;
			}else 				LED1=1;

			OLED_ShowNum(0, 2, RxData, 2, 16);
		}
	}
}

(b)serial.c

#include "stm32f4xx.h"
#include "serial.h"
#include <stdio.h>
#include <stdarg.h>

u8 Serial_RxData;
u8 Serial_RxFlag;

void SERIAL_Init(void)
{
	  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
 
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
	
	//USART1端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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); //初始化串口1
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART1, ENABLE);  //使能串口1 
} 

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	u16 i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	u8 i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

u32 Serial_Pow(u32 X, u32 Y)
{
	u32 Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(u32 Number, u8 Length)
{
	u8 i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}

void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}

u8 Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)
	{
		Serial_RxFlag = 0;
		return 1;
	}
	return 0;
}

u8 Serial_GetRxData(void)
{
	return Serial_RxData;
}

void USART1_IRQHandler(void)
{
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		Serial_RxData = USART_ReceiveData(USART1);
		Serial_RxFlag = 1;
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

(c)serial.h

#ifndef __SERIAL_H 
#define __SERIAL_H 


#include "stdio.h"

#define bound 9600;//设置串口波特率

void Serial_Init(void);
void Serial_SendByte(u8 Byte);
void Serial_SendArray(u8 *Array, u16 Length);
void Serial_SendString(char *String);
void Serial_SendNumber(u32 Number, u8 Length);
void Serial_Printf(char *format, ...);

u8 Serial_GetRxFlag(void);
u8 Serial_GetRxData(void);

#endif  


(d)代码说明

只能在单个数字里面才有效,且发送类型为HEX不能为文本,接收类型也为hex。
赶着做毕设,代码还需要很多完善,结合江科大B站视频:https://www.bilibili.com/video/BV1th411z7sn?p=27&vd_source=fb8dcae0aee3f1aab700c21099045395
在这里插入图片描述

(e)实物效果

在这里插入图片描述

5、USART串口数据包

上面的代码只能同时发送单个字符,下面可以发送多个。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
程序现象,如下:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值