STM32串口数据收发 相关配置+点灯控制

目录

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

1.串口通信

STM32串口数据收发 相关配置+点灯控制_第1张图片
我用的32是stm32f10x最小系统没有UART4和UART5
USART : 通用同步异步收发器
UART : 通用异步收发器
nRTS : 请求发送
nCTS : 请求接收
区别:USART指单片机的一个IO端口模块,可以根据需要配置成同步模式(SPI,IIC),也可以配置成异步模式(UART).可以理解为USART为SPI,IIC对等的”协议”。 UART则不是一个协议,为一个实体。

2.串口的结构体

STM32串口数据收发 相关配置+点灯控制_第2张图片
在这里插入图片描述
Fck : 串口的时钟(APB1 36M / APB2 72M )
USARTDIV : 无符号的定点数

115200= 72 * 1000000/16 * USARTDIV

3.如何配置串口的发送

1.配置时钟: GPIO口的时钟,串口的时钟, 引脚复用的时钟
2.配置GPIO的结构体
3.配置串口的结构体
4.串口的发送
STM32串口数据收发 相关配置+点灯控制_第3张图片

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

STM32串口数据收发 相关配置+点灯控制_第4张图片

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

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

void usart_init(void)
{
	GPIO_InitTypeDef gpio_init;
	USART_InitTypeDef usartStruct;
	//1.初始化相关时钟以及 IO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	//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 "delay.h"
#include "exti.h"
#include "usart.h"

int main()
{
	usart_init();
	while(1)
	{
		USART_SendData(USART1,'n');
		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_ms(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;
	//
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//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);
	
	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 "delay.h"
#include "exti.h"
#include "usart.h"

int main()
{
	usart_init();
	while(1)
	{
		usartSendStr(USART1,"nice !\r\n");
		delay_ms(1000);
	}

}

6.重定向printf串口发送

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

记得要给下图框住的内容打勾哦
STM32串口数据收发 相关配置+点灯控制_第5张图片

stdio.h文件中有一个宏定义fputc,我们需要使用printf只需要重定向fputc就可以使用啦
STM32串口数据收发 相关配置+点灯控制_第6张图片

usart.h

#include "stm32f10x.h"
#include 

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;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//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);
	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 "delay.h"
#include "exti.h"
#include "usart.h"
#include "stdio.h"

int main()
{
	usart_init();
	
	GPIO_SetBits(GPIOA, GPIO_Pin_3);
	GPIO_SetBits(GPIOC, GPIO_Pin_13);
	
	while(1)
	{
		int i = printf("Finny\r\n");
		printf("%d\r\n",i);
		delay_ms(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;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	Led_init.GPIO_Mode 	= GPIO_Mode_Out_PP;
	Led_init.GPIO_Pin = GPIO_Pin_13;
	Led_init.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &Led_init);
}


usart.h

#include "stm32f10x.h"
#include 

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);
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//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);
	
	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 "exti.h"
#include "usart.h"
#include "stdio.h"

int main()
{
	Led_init();
	Relay_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");
		}
	}
}
	

看原文 点这里
请添加图片描述

你可能感兴趣的:(STM32,stm32,单片机,arm,物联网,嵌入式硬件)