串口发送&串口发送+接收&串口收发HEX数据包&串口收发文本数据包----USART

目录

printf函数移植方法

显示汉字

串口发送

串口发送+接收

串口收发HEX数据包

串口收发文本数据包


printf函数移植方法

  1.  printf只能一个串口使用且需要重定向到串口
//重定向到串口
int fputc(int ch,FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}

2. 多串口可以使用sprintf

    char String[100];
	sprintf(String,"Num=%d\r\n",666);//可以指定打印位置,不涉及重定向
	Serial_SendString(String);

3. 封装sprintf

头文件

/**
  * @brief 
  * @param  参数1:格式化字符串  参数二:接受可变参数列表
  * @retval 
  */
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);	
}

显示汉字

方法1:keil和串口助手都选择utf-8,且keil加上--no-multibyte-chars参数

方法2:都是用GB开头的中文编码格式,参数不用加

串口发送

#include "stm32f10x.h"                  // Device header
#include 
#include 
void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  //USART1在APB2上
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

	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);

	USART_InitTypeDef USART_InitStruct;
	//写完波特率,init函数内部会自动算好波特率对应的分频系数写到BRR寄存器
	USART_InitStruct.USART_BaudRate=9600;
	USART_InitStruct.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode=USART_Mode_Tx;
	USART_InitStruct.USART_Parity=USART_Parity_No;
	USART_InitStruct.USART_StopBits=USART_StopBits_1;
	USART_InitStruct.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStruct);
	
	USART_Cmd(USART1,ENABLE);

}

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

串口发送+接收

定义一个结构体变量但要分别调用    GPIO_Init(GPIOA,&GPIO_InitStructure);

	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);
	
	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);

只支持1字节的接收

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;  浮空输入或上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;

 1.查询模式

if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)//可读取
{
		data=USART_ReceiveData(USART1);
		OLED_ShowHexNum(1,1,data,2);
}

2.中断模式

初始化代码

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启到NVIC通道
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	
	NVIC_Init(&NVIC_InitStruct);

uint8_t Serial_GetRxFlag(void)
{
	if(Serial_RxFlag==1)
	{
		Serial_RxFlag=0;
		return 1;
	}
	return 0;
}
uint8_t 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);
	}
}

主函数

if (Serial_GetRxFlag() == 1)
{
		RxData = Serial_GetRxData();
		Serial_SendByte(RxData);
		OLED_ShowHexNum(1, 8, RxData, 2);
}

串口收发HEX数据包

在上述代码基础上根据状态图在中断里进行接收数据 存入Serial_RXPacket[];(固定包长)

//状态机
void USART1_IRQHandler(void)
{
	static uint8_t s=0;
	static uint8_t pRXPacket=0;
	if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
	{
		uint16_t data=USART_ReceiveData(USART1);
		if(s==0)
		{
			if(data==0XFF)
			{
				s=1;
				pRXPacket=0;
			}
		}
		else if(s==1)
		{
			Serial_RXPacket[pRXPacket]=data;
			pRXPacket++;
			if(pRXPacket>=4)
			{
				s=2;
			}
		}
		else if(s==2)
		{
			if(data==0xFE)
			{
				s=0;
				Serial_RxFlag=1;
			}
		}
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}
}
//发送数据包
void Serial_SendPacket(void)
{
	Serial_SendByte(0xFF);
	Serial_SendArray(Serial_TXPacket,4);
	Serial_SendByte(0xFE);
}

串口收发文本数据包

(可变包长)实现控制LED的亮灭

发送部分可以sendstring或者直接打印

//状态机
void USART1_IRQHandler(void)
{
	static uint8_t s=0;
	static uint8_t pRXPacket=0;
	if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
	{
		uint16_t data=USART_ReceiveData(USART1);
		if(s==0)
		{
			//主函数里完成操作后置0,所以当主函数完成后才进行接收下一个数据包
			if(data=='@'&& Serial_RxFlag == 0)  
			{
				s=1;
				pRXPacket=0;
			}
		}
		else if(s==1)
		{
			if(data=='\r')
			{
				s=2;
			}
			else
			{
				Serial_RXPacket[pRXPacket]=data;
				pRXPacket++;
			}
			
		}
		else if(s==2)
		{
			if(data=='\n')
			{
				s=0;
				Serial_RXPacket[pRXPacket]='\0';  //字符串结束
				Serial_RxFlag=1;
			}
		}
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}
}

主函数

	while(1)
	{
		if(Serial_RxFlag==1)  //收到完整的了,可以读出数据了
		{
			if(strcmp(Serial_RXPacket,"LED_ON")==0)
			{
				LED_ON(GPIO_Pin_1);
				Serial_SendString("LED_ON_OK\r\n");
				OLED_ShowString(1,1,"           ");
				OLED_ShowString(1,1,"LED_ON");

			}
			else if(strcmp(Serial_RXPacket,"LED_OFF")==0){
				LED_OFF(GPIO_Pin_1);
				Serial_SendString("LED_OFF_OK\r\n");
				OLED_ShowString(1,1,"           ");
				OLED_ShowString(1,1,"LED_OFF");

			}
			else{
				Serial_SendString("ERROR\r\n");
				OLED_ShowString(1,1,"           ");
				OLED_ShowString(1,1,"ERROR");
			}
			Serial_RxFlag=0;
		}
		
	}   

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