admin管理员组

文章数量:1558963

        使用USART串口通信,通过上位机串口助手发送关键字符串给STM32执行LED灯点亮熄灭操作的流程。

        基本的配置如下所示,GPIO口配置的为PA9推挽输出,用于LED灯的操作。其余注意USART_ITConfig和USART_Cmd开启USART接收中断和使能USART运行。

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

void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//开启USART1的时钟,USART1总线在APB2上,
               									//其余的都在APB1上,注意区分
	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_InitStructure;
	USART_InitStructure.USART_BaudRate=9600;//设置波特率
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制
	USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;//USART模式,发送接收全设置
	USART_InitStructure.USART_Parity=USART_Parity_No;//校验位
	USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长
	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);
}

        接下来要进行发送字符串LED_ON和LED_OFF分别执行点亮和熄灭的操作,比如串口在接受LED_ON这个字符串后,通过程序将接收到的该字符串进行比照,例如使用 strcmp()进行判断,如果接收到的字符串与设置好的字符串相同则执行对应的操作,注意strcmp()包含在#include<string.h>中,需要添加该头文件才能使用。

        可以使用数组进行接收字符串,在中断函数里使用状态机的形式进行数据的头尾判断和接收存储。

        进入中断后,将串口接收到的字符用一个数组RxData[]暂存,进入if的条件再定义一个RxState 进行判断,初始值赋0,在里面又进行判断接收到的数据是不是用于判断的头字符,定义判断字符为@,同时为了保证数据是重新开始的,加上Serial_RxFlag == 0用且判断,接收到的为@则进入接收数据的部分,注意使用else if判断,里面判断是不是尾字符(用于结束),如果不是的话就进行数据的正式接收,将接收到的字符用数组形式存放在RxData里,然后接收到结束字符后进入最后的收尾工作。

        使用"\n"进行判断进入第三步,在里面进行状态重置,记得使用USART_ClearITPendingBit进行标志位清零。状态机部分的代码到此结束。

void USART1_IRQHandler(void)
{
	static uint8_t RxState = 0;		//定义表示当前状态机状态的静态变量
	static uint8_t pRxPacket = 0;	//定义表示当前接收数据位置的静态变量
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)	//判断是否是USART1的接收事件触发的中断
	{
		uint8_t RxData = USART_ReceiveData(USART1);			//读取数据寄存器,存放在接收的数据变量
		
		/*使用状态机的思路,依次处理数据包的不同部分*/
		
		/*当前状态为0,接收数据包包头*/
		if (RxState == 0)
		{
			if (RxData == '@' && Serial_RxFlag == 0)		//如果数据确实是包头,并且上一个数据包已处理完毕
			{
				RxState = 1;			//置下一个状态
				pRxPacket = 0;			//数据包的位置归零
			}
		}
		/*当前状态为1,接收数据包数据,同时判断是否接收到了第一个包尾*/
		else if (RxState == 1)
		{
			if (RxData == '\r')			//如果收到第一个包尾
			{
				RxState = 2;			//置下一个状态
			}
			else						//接收到了正常的数据
			{
				Serial_RxPacket[pRxPacket] = RxData;		//将数据存入数据包数组的指定位置
				pRxPacket ++;			//数据包的位置自增
			}
		}
		/*当前状态为2,接收数据包第二个包尾*/
		else if (RxState == 2)
		{
			if (RxData == '\n')			//如果收到第二个包尾
			{
				RxState = 0;			//状态归0
				Serial_RxPacket[pRxPacket] = '\0';			//将收到的字符数据包添加一个字符串结束标志
				Serial_RxFlag = 1;		//接收数据包标志位置1,成功接收一个数据包
			}
		}
		
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);		//清除标志位
	}
}

        接下来是main函数里的程序代码:

        主函数中的LED代码之前的LED代码有介绍这里不再赘述。if用strcmp进行比较,如果相同则进入循环内部执行对应要实现的操作。可以使用Serial_SendString来发送对应反馈信息给串口助手。

#include "stm32f10x.h"                  // Device header
#include "Serial.h"
#include "LED.h"
#include "string.h"//包含strcmp函数的代码

int main(void)
{
	/*模块初始化*/
	LED_Init();			//LED初始化
	Serial_Init();		//串口初始化
	

	while (1)
	{
		if (Serial_RxFlag == 1)		//如果接收到数据包
		{		
			/*将收到的数据包与预设的指令对比,以此决定将要执行的操作*/
			if (strcmp(Serial_RxPacket, "LED_ON") == 0)			//如果收到LED_ON指令
			{
				LED1_ON();										//点亮LED
				Serial_SendString("LED_ON_OK\r\n");				//串口回传一个字符串LED_ON_OK
 			}
			else if (strcmp(Serial_RxPacket, "LED_OFF") == 0)	//如果收到LED_OFF指令
			{
				LED1_OFF();										//熄灭LED
				Serial_SendString("LED_OFF_OK\r\n");			//串口回传一个字符串LED_OFF_OK

			}
			else						//上述所有条件均不满足,即收到了未知指令
			{
				Serial_SendString("ERROR_COMMAND\r\n");			//串口回传一个字符串ERROR_COMMAND

			}
			
			Serial_RxFlag = 0;			//处理完成后,需要将接收数据包标志位清零,否则将无法接收后续数据包
		}
	}
}

(此时LED灯亮起)

本文标签: 串口助手过程代码简单