stm32串口通信实现风扇控制(中断和非中断方式)

串口通信非中断方式

main.c代码:
#include “main.h”
#include “usart.h”
#include “gpio.h”=
#include “stdio.h”
#include “string.h”

//重定向printf函数实现串口打印
int fputc(int ch, FILE *f)
{
	unsigned char temp[1]={ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return ch;
}


int main(void)
{
  unsigned char ch[20] = {0};
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  HAL_UART_Transmit(&huart1, (uint8_t *)"xfj handsome", strlen("xfj handsome"), 100);

  while (1)
  {

		HAL_UART_Receive(&huart1, ch, 19, 100);//ch留一个空间给'\0'
		//HAL_UART_Transmit(&huart1, ch, strlen(ch), 100);
		//printf(ch);
		printf("%s",ch);
		if(!strcmp((const char *)ch,"open\r\n")){
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
			if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) == GPIO_PIN_RESET){
				printf("风扇已经打开\r\n");
			}
		}else if(!strcmp((const char *)ch,"close\r\n")){
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
			if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) == GPIO_PIN_SET){
				printf("风扇已经关闭\r\n");
			}
		}else{
			if(!(ch[0] == '\0')){
				printf("%s","指令错误!");
			}
		}
		memset(ch, 0, strlen((const char *)ch));
  }

}

中断方式:

串口中断回调函数:
HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数
HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //发送中断回调函数
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //接收中断回调函数

状态标记变量:
USART_RX_STA
从0开始,串口中断接收到一个数据(一个字节)就自增1。当数据读取全部OK时候(回车和换行符号来的时候),那么 USART_RX_STA的最高位置1,表示串口数据接收全部完毕了,然后main函数里面可以处理数据了。

在这里插入图片描述
在这里插入图片描述

stm32CubeMX串口配置图:
在这里插入图片描述

main.c代码:

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "string.h"

//串口接收缓存(1字节)
uint8_t buf=0;

// 接收状态
// bit15, 接收完成标志
// bit14, 接收到0x0d
// bit13-0, 接收到的有效字节数目
uint16_t UART1_RX_STA=0;

//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200

// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];

void SystemClock_Config(void);

//重写接收完成回调函数,收到一个数据后,在这里做处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//判断中断是由那个串口触发的
	if(huart->Instance == USART1){
		//判断是否接收完成(UART1_RX_STA bit15位是否为1)
		if((UART1_RX_STA &0x8000) == 0){
			//如果已经收到回车0x0d
			if(UART1_RX_STA & 0x4000){
				//接着判断是否收到换行(0x0a)
				if(buf == 0x0a){
					//如果0x0d和0x0a都收到,则将bit15的位置置为1
					UART1_RX_STA |= 0x8000;
				}else{
					//否则认为接收错误,重新开始
					UART1_RX_STA = 0;
				}
			}else{
				//如果没有收到回车,则先判断接收的这个字符是否为0x0d(回车)
				if(buf == 0x0d){
					//是回车的话,将bit14位置为1
					UART1_RX_STA |= 0x4000;
				}else{
					//否则将接收到的数据保存在缓存数组里面
					UART1_RX_Buffer[UART1_RX_STA & 0x3fff] = buf;
					UART1_RX_STA++;
					
					//如果接收的数据大于UART1_REC_LEN(200个字节),则重新开始接收
					if((UART1_RX_STA & 0x3fff) > UART1_REC_LEN-1){
						UART1_RX_STA = 0;
					}
					
				}
			
			}
		}
		//重新开启中断
		HAL_UART_Receive_IT(&huart1,&buf,1);
	}
}

**//重定向prinf函数实现串口打印**
int fputc(int ch,FILE *f)
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,1,0xFFFF);
	return ch;
}


int main(void)
{

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();

	//开启接收中断
	HAL_UART_Receive_IT(&huart1,&buf,1);

  while (1)
  {
  
		//判断接收是否完成
		if(UART1_RX_STA & 0x8000){
			printf("收到数据: ");
			if(!strcmp((const char *)UART1_RX_Buffer,"open")){
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
			if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) == GPIO_PIN_RESET){
				printf("风扇已经打开\r\n");
			}
		}else if(!strcmp((const char *)UART1_RX_Buffer,"close")){
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
			if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) == GPIO_PIN_SET){
				printf("风扇已经关闭\r\n");
			}
		}else{
			if(UART1_RX_Buffer[0] != '\0'){
				printf("%s","指令错误!");
			}
		}
		memset(UART1_RX_Buffer, 0, strlen((const char *)UART1_RX_Buffer));//清理掉当前缓存数组里面的内容,防止误判
			printf("\r\n");
			//重新开始下一次接收
			UART1_RX_STA = 0;
		}
		printf("xfj hansome\r\n");
		HAL_Delay(1000);
  }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值