串口通信(下)

本文详细介绍了在STM32F10x平台上的串口初始化、数据发送、接收以及使用中断处理HEX和文本数据包的函数实现,包括发送字节、数组、字符串、数字和自定义printf函数的应用。
摘要由CSDN通过智能技术生成

串口发送数据:

#include "stm32f10x.h"                  // Device header
#include "stdio.h"
#include "stdarg.h"
/**
  * 函    数:串口初始化
  * 参    数:无
  * 返 回 值:无
  */
void Serial_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	/*GPIO口初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);					//引脚将Pin_9初始化为复用推挽输出模式
	
	/*USART1初始化*/
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate= 9600;				//波特率,
	USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;		//硬件流控制,这里关闭
	USART_InitStructure.USART_Mode= USART_Mode_Tx;			//串口模式 ,选择发送模式
	USART_InitStructure.USART_Parity= USART_Parity_No;		//奇偶校验位,选择不需要
	USART_InitStructure.USART_StopBits= USART_StopBits_1;	//停止位,选择1位
	USART_InitStructure.USART_WordLength= USART_WordLength_8b;//字长,选择8b
	USART_Init(USART1,&USART_InitStructure);				//读入结构体,初始化串口
	
	USART_Cmd(USART1,ENABLE);
}
/**
  * 函    数:发送字节
  * 参    数:要发送的字节,字长为8位
  * 返 回 值:无
  */
void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1,Byte);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}

/**
  * 函    数:发送数组
  * 参    数:*Array:数组首地址,Length:数组长度
  * 返 回 值:无
  */
void Serial_SendArray(uint8_t *Array,uint16_t Length)
{
	uint16_t i;
	for(i=0;i<Length;i++)
	{
		Serial_SendByte(Array[i]);
	}
}

/**
  * 函    数:发送字符串
  * 参    数:*String:字符串首地址
  * 返 回 值:无
  */
void Serial_SendString(char *String)
{
	uint16_t i;
	for(i=0;String[i]!='\0';i++)
	{
		Serial_SendByte(String[i]);
	}
}

/**
  * 函    数:X的Y立方
  * 参    数:X:底数 Y:次方数
  * 返 回 值:Result=X^Y;
  */
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result=1;
	while(Y--)
	{
		Result*=X;
	}
	return Result;
}

/**
  * 函    数:发送数字
  * 参    数:Number:要发送的数字 Length: 发送多少位的数字
  * 返 回 值:无
  */
void Serial_SendNumber(uint32_t Number ,uint8_t Length)
{
	uint16_t i;
	for(i=0;i<Length;i++)
	{
		Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+0x30);
	}
}

/**
  * 函    数:使用printf需要重定向的底层函数
  * 参    数:保持原始格式即可,无需变动
  * 返 回 值:保持原始格式即可,无需变动
  */
int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);			//将printf的底层重定向到自己的发送字节函数
	return ch;
}

/**
  * 函    数:自己封装的prinf函数
  * 参    数:format 格式化字符串
  * 参    数:... 可变的参数列表
  * 返 回 值:无
  */
void Serial_Printf(char *format, ...)
{
	char String[100];				//定义字符数组
	va_list arg;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中
	va_end(arg);					//结束变量arg
	Serial_SendString(String);		//串口发送字符数组(字符串)
}

串口发送和接收数据:

#include "stm32f10x.h"                  // Device header
#include "stdio.h"
#include "stdarg.h"

uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
/**
  * 函    数:串口初始化
  * 参    数:无
  * 返 回 值:无
  */
void Serial_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	/*GPIO口初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);								//将Pin_9引脚初始化为复用推挽输出模式
	
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);								//将Pin_10引脚初始化为上拉输入模式
	
	/*USART1初始化*/
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate= 9600;							//波特率,
	USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;		//硬件流控制,这里关闭
	USART_InitStructure.USART_Mode= USART_Mode_Tx|USART_Mode_Rx;		//串口模式 ,选择发送与接收模式
	USART_InitStructure.USART_Parity= USART_Parity_No;					//奇偶校验位,选择不需要
	USART_InitStructure.USART_StopBits= USART_StopBits_1;				//停止位,选择1位
	USART_InitStructure.USART_WordLength= USART_WordLength_8b;			//字长,选择8b
	USART_Init(USART1,&USART_InitStructure);							//读入结构体,初始化串口
	
	USART_Cmd(USART1,ENABLE);
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);						//使能USART_IT_RXNE标志位的中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 					//为什么分到第二组???
	
	NVIC_InitTypeDef NCIC_InitStructure;
	NCIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;					//选择中断通道
	NCIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;						//使能中断通道
	NCIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;			//抢占优先级
	NCIC_InitStructure.NVIC_IRQChannelSubPriority= 2;					//响应优先级
	NVIC_Init(&NCIC_InitStructure);										//初始化NVIC
	
	
	
}
/**
  * 函    数:发送字节
  * 参    数:要发送的字节,字长为8位
  * 返 回 值:无
  */
void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1,Byte);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);			//等待发送完成
}
/**
  * 函    数:获取收到数据标志位 1:收到 0:未收到
  * 参    数:无
  * 返 回 值:标志位
  */
uint8_t Serial_GetRxFlag(void)
{
	if(Serial_RxFlag == 1)
	{
		Serial_RxFlag=0;
		return 1;
	}
	return 0;
}
/**
  * 函    数: 获取串口收到的数据
  * 参    数: 无
  * 返 回 值: 收到的数据
  */
uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;
}
/**
  * 函    数:发送数组
  * 参    数:*Array:数组首地址,Length:数组长度
  * 返 回 值:无
  */
void Serial_SendArray(uint8_t *Array,uint16_t Length)
{
	uint16_t i;
	for(i=0;i<Length;i++)
	{
		Serial_SendByte(Array[i]);
	}
}

/**
  * 函    数:发送字符串
  * 参    数:*String:字符串首地址
  * 返 回 值:无
  */
void Serial_SendString(char *String)
{
	uint16_t i;
	for(i=0;String[i]!='\0';i++)
	{
		Serial_SendByte(String[i]);
	}
}

/**
  * 函    数:X的Y立方
  * 参    数:X:底数 Y:次方数
  * 返 回 值:Result=X^Y;
  */
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result=1;
	while(Y--)
	{
		Result*=X;
	}
	return Result;
}

/**
  * 函    数:发送数字
  * 参    数:Number:要发送的数字 Length: 发送多少位的数字
  * 返 回 值:
  */
void Serial_SendNumber(uint32_t Number ,uint8_t Length)
{
	uint16_t i;
	for(i=0;i<Length;i++)
	{
		Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+0x30);
	}
}

/**
  * 函    数:使用printf需要重定向的底层函数
  * 参    数:保持原始格式即可,无需变动
  * 返 回 值:保持原始格式即可,无需变动
  */
int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);			//将printf的底层重定向到自己的发送字节函数
	return ch;
}

/**
  * 函    数:自己封装的prinf函数
  * 参    数:format 格式化字符串
  * 参    数:... 可变的参数列表
  * 返 回 值:无
  */
void Serial_Printf(char *format, ...)
{
	char String[100];				//定义字符数组
	va_list arg;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中
	va_end(arg);					//结束变量arg
	Serial_SendString(String);		//串口发送字符数组(字符串)
}
/**
  * 函    数:USART1的中断函数
  * 参    数:无
  * 返 回 值:无
  */
void USART1_IRQHandler(void)
{
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET )		//判断是否由USART_IT_RXNE标志位产生的中断
	{															//SET表示USART_IT_RXNE产生中断
		Serial_RxData= USART_ReceiveData(USART1);				//取出收到的数据
		Serial_RxFlag=1;										//标志位置1表示收到数据 0则表示未收到数据
		USART_ClearITPendingBit(USART1, USART_IT_RXNE); 		//清除中断挂起标志位
	}
}

串口发送HEX数据包:

#include "stm32f10x.h"                  // Device header
#include "stdio.h"
#include "stdarg.h"

uint8_t Serial_RxFlag;
uint8_t Serial_RxPacket[] = {0,0,0,0};
uint8_t Serial_TxPacket[] = {0,0,0,0};
/**
  * 函    数:串口初始化
  * 参    数:无
  * 返 回 值:无
  */
void Serial_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	/*GPIO口初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);								//将Pin_9引脚初始化为复用推挽输出模式
	
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	/*USART1初始化*/
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate= 9600;							//波特率,
	USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;		//硬件流控制,这里关闭
	USART_InitStructure.USART_Mode= USART_Mode_Tx|USART_Mode_Rx;		//串口模式 ,选择发送与接收模式
	USART_InitStructure.USART_Parity= USART_Parity_No;					//奇偶校验位,选择不需要
	USART_InitStructure.USART_StopBits= USART_StopBits_1;				//停止位,选择1位
	USART_InitStructure.USART_WordLength= USART_WordLength_8b;			//字长,选择8b
	USART_Init(USART1,&USART_InitStructure);							//读入结构体,初始化串口
	
	USART_Cmd(USART1,ENABLE);
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);						//使能USART_IT_RXNE标志位的中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 					//为什么分到第二组???
	
	NVIC_InitTypeDef NCIC_InitStructure;
	NCIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;					//选择中断通道
	NCIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;						//使能中断通道
	NCIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;			//抢占优先级
	NCIC_InitStructure.NVIC_IRQChannelSubPriority= 2;					//响应优先级
	NVIC_Init(&NCIC_InitStructure);										//初始化NVIC
	
	
	
}
/**
  * 函    数:发送字节
  * 参    数:要发送的字节,字长为8位
  * 返 回 值:无
  */
void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1,Byte);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);			//等待发送完成
}
/**
  * 函    数:获取收到数据标志位 1:收到 0:未收到
  * 参    数:无
  * 返 回 值:标志位
  */


uint8_t Serial_GetRxFlag(void)
{
	if(Serial_RxFlag == 1)
	{
		Serial_RxFlag=0;
		return 1;
	}
	return 0;
}
/**
  * 函    数: 获取串口收到的数据
  * 参    数: 无
  * 返 回 值: 收到的数据
  */

/**
  * 函    数:发送数组
  * 参    数:*Array:数组首地址,Length:数组长度
  * 返 回 值:无
  */
void Serial_SendArray(uint8_t *Array,uint16_t Length)
{
	uint16_t i;
	for(i=0;i<Length;i++)
	{
		Serial_SendByte(Array[i]);
	}
}

/**
  * 函    数:发送字符串
  * 参    数:*String:字符串首地址
  * 返 回 值:无
  */
void Serial_SendString(char *String)
{
	uint16_t i;
	for(i=0;String[i]!='\0';i++)
	{
		Serial_SendByte(String[i]);
	}
}
/**
  * 函    数:发送数据包
  * 参    数:无
  * 返 回 值:无
  */
void Serial_SendPacket()
{
	Serial_SendByte(0xFF);					//发送包头
	Serial_SendArray(Serial_TxPacket, 4);	//发送数据
	Serial_SendByte(0xFE);					//发送包尾
}

/**
  * 函    数:X的Y立方
  * 参    数:X:底数 Y:次方数
  * 返 回 值:Result=X^Y;
  */
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result=1;
	while(Y--)
	{
		Result*=X;
	}
	return Result;
}

/**
  * 函    数:发送数字
  * 参    数:Number:要发送的数字 Length: 发送多少位的数字
  * 返 回 值:
  */
void Serial_SendNumber(uint32_t Number ,uint8_t Length)
{
	uint16_t i;
	for(i=0;i<Length;i++)
	{
		Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+0x30);
	}
}

/**
  * 函    数:使用printf需要重定向的底层函数
  * 参    数:保持原始格式即可,无需变动
  * 返 回 值:保持原始格式即可,无需变动
  */
int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);			//将printf的底层重定向到自己的发送字节函数
	return ch;
}

/**
  * 函    数:自己封装的prinf函数
  * 参    数:format 格式化字符串
  * 参    数:... 可变的参数列表
  * 返 回 值:无
  */
void Serial_Printf(char *format, ...)
{
	char String[100];				//定义字符数组
	va_list arg;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中
	va_end(arg);					//结束变量arg
	Serial_SendString(String);		//串口发送字符数组(字符串)
}
/**
  * 函    数:USART1的中断函数
  * 参    数:无
  * 返 回 值:无
  */
void USART1_IRQHandler(void)
{
	static uint8_t Rx_State =0;							//静态变量 	仅在此函数有效
	static uint8_t pRxPacket =0;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET )//判断是否由USART_IT_RXNE标志位产生的中断
	{													//SET表示收到数据,RESET表示未收到数据
		uint8_t RxData = USART_ReceiveData(USART1);		//将收到的数据传给RxData
		/*使用状态机来进行数据接收处理*/
		if(Rx_State == 0)								//状态0 
		{
			if(RxData == 0xFF)							//判断是否接收到包头
			{
				Rx_State = 1;							//接收到包头	状态切换为1
				pRxPacket= 0;							//数据接收数组下标清零
			}
		}
		else if(Rx_State == 1)							//状态1	接收数据
		{
			Serial_RxPacket[pRxPacket] = RxData;		//将接收到的数据缓存到Serial_RxPacket数组
			pRxPacket++;								//数据写入到数组后自动移位
			if(pRxPacket == 3)							//一个数据包的数据写入完成
			{
				Rx_State = 2;							//切换为状态2
			}
		}
		else if(Rx_State == 2)							//状态2
		{
			if(RxData == 0xFE)							//判断是否收到包尾
			{
				Rx_State = 0;							//切换为状态0 为接收下一个数据包做准备
				Serial_RxFlag = 1;						//数据包接收完毕 标志位置1

			}
		}
	}
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);		//手动清除终端挂起标志位
}

串口发送文本数据包:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值