学习STM32第九天

学习STM32第七天

一、USART串口数据包

  • HEX数据包
    HEX数据包里数据都是以原始的字节数据呈现,有两种类型
    1、包长固定,含包头包尾;2、包长可变,含包头包尾。
    HEX数据包
    上图表示一种以FF为包头,FE为包尾的HEX数据包格式。如果数据中有FFFE数据时,可以对数据进行限幅,只取所需要范围内的数据;也可以使用固定长度的数据包,通过包头包尾对齐数据;还可以增加包头包尾的数量。对于各种数据转换为字节流的问题,数据内部还是由一个个字节组成,需要指针指向对应的数据,将其当作一个字节数组发送即可。

  • 文本数据包
    文本数据包里数据经过编码译码以文本字符呈现,有两种类型
    1、包长固定,含包头包尾;2、包长可变,含包头包尾。
    文本数据包
    上图表示一种以@为包头,回车键和换行符为包尾的文本数据包格式。

  • HEX数据包发送/接收

  1. 数据包发送
    对于HEX数据包发送,可定义数组,用于填充数据以进行发送;对于文本数据包,可定义字符串,用以填充数据以进行发送。
  2. 数据包接收
    HEX数据包接收
    对于固定包长的HEX数据包,每接收到一个字节,程序会进一遍中断,在中断函数里可得到这一个字节数据,得到后需退出中断。因此每得到一个字节数据都是一个独立的过程,数据包具有前后关联性,对于包头、数据和包尾需要配置不同的处理逻辑,在不同状态执行不同的操作,同时进行状态的合理转移。即采用状态机思维编程。
    文本数据包接收
    对于不固定包长的文本数据包,由于包长不固定所以在第二个状态下要时刻等待包尾的接收。这里继续设置一个状态接收包尾是为了避免数据错位的现象。

二、案例实验

  1. 定长Hex数据包发送加接收
    这里HEX数据包包头为0xFF包尾为0xFE,数据长度为4,采用中断接收,配置代码如下
void Serial_Init()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	//USART1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
	//配置引脚
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	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;//8位长度
	USART_Init(USART1, &USART_InitStructure);
	//配置中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	USART_Cmd(USART1, ENABLE);
}

相关函数如下

void Serial_SendPacket(void)
{
	Serial_SendByte(0xFF);
	Serial_SendArray(Serial_TxPacket, 4);
	Serial_SendByte(0xFE);
}

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

void USART1_IRQHandler(void)
{
	static uint8_t RxState = 0;
	static uint8_t pRxPacket = 0;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		uint8_t RxData = USART_ReceiveData(USART1);
		if (RxState == 0)
		{
			if (RxData == 0xFF)
			{
				RxState = 1;
				pRxPacket = 0;
			}
		}
		else if (RxState == 1)
		{
			Serial_RxPacket[pRxPacket] = RxData;
			pRxPacket ++;
			if (pRxPacket >= 4)
			{
				RxState = 2;
			}
		}
		else if (RxState == 2)
		{
			if (RxData == 0xFE)
			{
				RxState = 0;
				Serial_RxFlag = 1;
			}
		}
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

main函数代码如下

uint8_t KeyNum;
uint8_t TxPacket[4];
int main()
{
	LED_Init();
	Key_Init();
	Serial_Init();
	OLED_Init();
	OLED_ShowString(1, 1, "TxPacket");
	OLED_ShowString(3, 1, "Rxpacket");
	TxPacket[0] = 0x11;
	TxPacket[1] = 0x21;
	TxPacket[2] = 0x31;
	TxPacket[3] = 0x41;
	while(1)
	{
		KeyNum = Key_GetNum();
		if(KeyNum == 1)
		{
			OLED_ShowHexNum(2, 1, TxPacket[0], 2);
			OLED_ShowHexNum(2, 4, TxPacket[1], 2);
			OLED_ShowHexNum(2, 7, TxPacket[2], 2);
			OLED_ShowHexNum(2, 10, TxPacket[3], 2);
			Serial_SendHexPacket(TxPacket);
		}
		if(Serial_GetRxFlag() == 1)
		{
			OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);
			OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);
			OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);
			OLED_ShowHexNum(4, 10, Serial_RxPacket[3], 2);
		}
	}
}
  1. 不定长文本数据包发送加接收
    这里只需修改中断函数,代码如下
void USART1_IRQHandler(void)
{
	static uint8_t RxState = 0;
	static uint8_t pRxPacket = 0;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		uint8_t RxData = USART_ReceiveData(USART1);
		
		if (RxState == 0)
		{
			if (RxData == '@' && Serial_RxFlag == 0)
			{
				RxState = 1;
				pRxPacket = 0;
			}
		}
		else if (RxState == 1)
		{
			if (RxData == '\r')
			{
				RxState = 2;
			}
			else
			{
				Serial_RxPacket[pRxPacket] = RxData;
				pRxPacket ++;
			}
		}
		else if (RxState == 2)
		{
			if (RxData == '\n')
			{
				RxState = 0;
				Serial_RxPacket[pRxPacket] = '\0';
				Serial_RxFlag = 1;
			}
		}
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

main函数如下

int main(void)
{
	OLED_Init();
	LED_Init();
	Serial_Init();
	
	OLED_ShowString(1, 1, "TxPacket");
	OLED_ShowString(3, 1, "RxPacket");
	
	while (1)
	{
		if (Serial_RxFlag == 1)
		{
			OLED_ShowString(4, 1, "                ");
			OLED_ShowString(4, 1, Serial_RxPacket);
			
			if (strcmp(Serial_RxPacket, "LED_ON") == 0)
			{
				LED1_ON();
				Serial_SendString("LED_ON_OK\r\n");
				OLED_ShowString(2, 1, "                ");
				OLED_ShowString(2, 1, "LED_ON_OK");
			}
			else if (strcmp(Serial_RxPacket, "LED_OFF") == 0)
			{
				LED1_OFF();
				Serial_SendString("LED_OFF_OK\r\n");
				OLED_ShowString(2, 1, "                ");
				OLED_ShowString(2, 1, "LED_OFF_OK");
			}
			else
			{
				Serial_SendString("ERROR_COMMAND\r\n");
				OLED_ShowString(2, 1, "                ");
				OLED_ShowString(2, 1, "ERROR_COMMAND");
			}
			
			Serial_RxFlag = 0;
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值