串口(USART)

串口(USART)

注意 需禁用syscalls.c

(和main.c在同一目录下)

替换为retarget

retarget.c位置在Core下的Src文件夹下

retarget.h位置在Core下的Inc文件夹下

使用方法
CUBEMX USART1 选择异步模式【Asynchronous】

/* USER CODE BEGIN 2*/

此处写代码(初始化函数后)

/*USER CODE END 2 */

RetargetInit(&huart1); //将printf()函数映射到USART1串口上
HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_NewData,1);//开启串口1接收中断
while(1)
if(KEY_1()) //按键KEY1判断为1时按键按下
			  {
				  LED_1(1);//LED1灯控制(1点亮,0熄灭)
				  LED_2(1);//LED2灯控制(1点亮,0熄灭)
				  BUZZER_SOLO1();//蜂鸣器输出单音的报警音(样式1:HAL库的精准延时函数)
				  RELAY_1(1);//继电器的控制程序(c=0继电器放开,c=1继电器吸合)
			      HAL_UART_Transmit(&huart1,(uint8_t*)&"KEY1\r\n",6,0xffff);//串口发送:串口号1,内容"ABC",数量3,溢出时间0xffff
			  }
			  if(KEY_2()) //按键KEY2判断为1时按键按下
			  {
				  LED_1(0);//LED1灯控制(1点亮,0熄灭)
				  LED_2(0);//LED2灯控制(1点亮,0熄灭)
				  BUZZER_SOLO2();//蜂鸣器输出单音的报警音(样式2:CPU微秒级延时)
				  RELAY_1(0);//继电器的控制程序(c=0继电器放开,c=1继电器吸合)
				  printf("KEY2\r\n");//向USART1串口发送字符串
			  }
			  if(USART1_RX_STA==0x0001){//串口1判断中断接收标志位&0xC000(回车)==0x0001(不等待回车,判断标志位是否等于1)
				  if(USART1_RX_BUF[0]=='1'){
					  LED_1(1);//LED1灯控制(1点亮,0熄灭)
					  LED_2(1);//LED2灯控制(1点亮,0熄灭)
					  BUZZER_SOLO1();//蜂鸣器输出单音的报警音(样式1:HAL库的精准延时函数)
					  RELAY_1(1);//继电器的控制程序(c=0继电器放开,c=1继电器吸合)
				  }
				  if(USART1_RX_BUF[0]=='0'){
					  LED_1(0);//LED1灯控制(1点亮,0熄灭)
					  LED_2(0);//LED2灯控制(1点亮,0熄灭)
					  BUZZER_SOLO2();//蜂鸣器输出单音的报警音(样式2:CPU微秒级延时)
					  RELAY_1(0);//继电器的控制程序(c=0继电器放开,c=1继电器吸合)
				  }
				  USART1_RX_STA=0;//串口接收标志清0,即开启下一轮接收
			  }
usart.c
#include "usart.h"

uint8_t USART1_RX_BUF[USART1_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART1_RX_STA=0;//接收状态标记//bit15:接收完成标志,bit14:接收到0x0d,bit13~0:接收到的有效字节数目
uint8_t USART1_NewData;//当前串口中断接收的1个字节数据的缓存

uint8_t USART2_RX_BUF[USART2_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART2_RX_STA=0;//接收状态标记//bit15:接收完成标志,bit14:接收到0x0d,bit13~0:接收到的有效字节数目
uint8_t USART2_NewData;//当前串口中断接收的1个字节数据的缓存
uint8_t RS485orBT;//当RS485orBT标志位为1时是RS485模式,为0时是蓝牙模式

uint8_t USART3_RX_BUF[USART3_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART3_RX_STA=0;//接收状态标记//bit15:接收完成标志,bit14:接收到0x0d,bit13~0:接收到的有效字节数目
uint8_t USART3_NewData;//当前串口中断接收的1个字节数据的缓存

void  HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart)//串口中断回调函数
{
	uint8_t a;
	if(huart ==&huart1)//判断中断来源(串口1:USB转串口)
    {
       printf("%c",USART1_NewData); //把收到的数据以 a符号变量 发送回电脑
       if((USART1_RX_STA&0x8000)==0){//接收未完成
           if(USART1_RX_STA&0x4000){//接收到了0x0d
               if(USART1_NewData!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
               else USART1_RX_STA|=0x8000;   //接收完成了
           }else{ //还没收到0X0D
               if(USART1_NewData==0x0d)USART1_RX_STA|=0x4000;
               else{
                  USART1_RX_BUF[USART1_RX_STA&0X3FFF]=USART1_NewData; //将收到的数据放入数组
                  USART1_RX_STA++;  //数据长度计数加1
                  if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收
               }
           }
       }
       HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_NewData,1); //再开启接收中断
    }
    if(huart ==&huart2)//判断中断来源(RS485/蓝牙)
    {
    	if(RS485orBT){//判断当RS485orBT标志位为1时是RS485模式,为0时是蓝牙模式
		   USART2_RX_BUF[0]=USART2_NewData;//收到数据放入缓存数组(只用到1个数据存放在数组[0])
		   USART2_RX_STA++;//数据接收标志位加1
		   HAL_UART_Receive_IT(&huart2,(uint8_t *)&USART2_NewData, 1); //再开启接收中断
    	}else{
		   if((USART2_RX_STA&0x8000)==0){//接收未完成(将USART2_RX_STA最高位1位规定是接收完成标志位)
			   if(USART2_NewData==0x5A)//如收到0x5A表示接收到结束符(手机APP“蓝牙调试器”回复数据以0x5A为结束符)
			   {
				   USART2_RX_STA|=0x8000;//收到0x0A,接受完成
			   }
			   else{ //如没有收到0x0A则继续接收数据内容并把数量加1
				  USART2_RX_BUF[USART2_RX_STA&0X7FFF]=USART2_NewData; //将收到的数据放入数组
				  USART2_RX_STA++;  //数据长度计数加1
				  if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
			   }
		   }
		   HAL_UART_Receive_IT(&huart2,(uint8_t *)&USART2_NewData,1); //再开启接收中断
    	}
    }
	if(huart ==&huart3)//判断中断来源(串口3:WIFI模块)
	{
	   //【原始数据内容】字符:+IPD,1:A  十六进制:0D 0A 2B 49 50 44 2C 31 3A 41(其中1是数量,A是数据内容)
	   //【数据接收原理】当接收到0x0A(即“回车”中的“\r“)时触发接下来的数据采集程序,
	   //首先清空USART3_RX_BUF[]寄存器,然后将USART3_RX_STA的16位中最高位第2位置1(01000000  00000000)
	   //此时开始采集接下来收到的数据,当收到前6个数据是“+IPD,1:”,且第7个数据不等于0时,表示成功收完数据
	   //然后将接收的第7位的一个字节数据内容放入USART3_RX_STA寄存器低8位,并将16位中最高位置1(10000000 xxxxxxxx)。
	   //【调用方法】在主函数中用if语句判断(USART_RX_STA&0x8000),为真时表示成功收到数据。
	   //然后读USART_RX_STA寄存器低14位的内容(USART_RX_STA&0x3FFF),即是数据的内容(1个字节)。
	   //主函数处理完数据后要将USART_RX_STA清0,才能开启下一次数据接收。
	   if(USART3_RX_STA&0x4000){//判断开始标志位为1时(16位中高位第2位)进入数据采集处理
		   USART3_RX_BUF[USART3_RX_STA&0x3FFF]=USART3_NewData;//将
		   USART3_RX_STA++;
		   if(USART3_RX_BUF[0]=='+'&& //判断返回字符前几位是不是“+IPD,1:”
			   USART3_RX_BUF[1]=='I'&&
			   USART3_RX_BUF[2]=='P'&&
			   USART3_RX_BUF[3]=='D'&&
			   USART3_RX_BUF[4]==','&&
			   USART3_RX_BUF[5]=='1'&&//限定只接收1个数量的数据(可根据实际要求的数量修改)
			   USART3_RX_BUF[6]==':'&&
			   USART3_RX_BUF[7]!=0){ //同时判断第1个数据内容是否为0,为0表示还没有收到数据
			   USART3_RX_STA =  USART3_RX_BUF[7]+0x8000;//将数据内容写入寄存器,16位最高位置1表示接收完成
		   }
	   }
	   if(USART3_NewData==0x0A && !(USART3_RX_STA&0x8000)){//判断是否收到“回车”中的“\r“(0x0A)
		   USART3_RX_STA=0x4000;//将开始采集标志位置1(16位中最高位第2位)
		   for(a=0;a<200;a++){//循环200次
			   USART3_RX_BUF[a]=0;//将数据寄存器清0
		   }
	   }
		HAL_UART_Receive_IT(&huart3,(uint8_t *)&USART3_NewData,1); //再开启串口3接收中断
	}
}

usart.h
#ifndef INC_USART_H_
#define INC_USART_H_

#include "stm32f1xx_hal.h" //HAL库文件声明
#include <string.h>//用于字符串处理的库
#include "../inc/retarget.h"//用于printf函数串口重映射

extern UART_HandleTypeDef huart1;//声明USART1的HAL库结构体
extern UART_HandleTypeDef huart2;//声明USART2的HAL库结构体
extern UART_HandleTypeDef huart3;//声明USART2的HAL库结构体

#define USART1_REC_LEN  200//定义USART1最大接收字节数
#define USART2_REC_LEN  200//定义USART1最大接收字节数
#define USART3_REC_LEN  200//定义USART1最大接收字节数

extern uint8_t  USART1_RX_BUF[USART1_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern uint16_t USART1_RX_STA;//接收状态标记
extern uint8_t USART1_NewData;//当前串口中断接收的1个字节数据的缓存

extern uint8_t  USART2_RX_BUF[USART2_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern uint16_t USART2_RX_STA;//接收状态标记
extern uint8_t USART2_NewData;//当前串口中断接收的1个字节数据的缓存
extern uint8_t RS485orBT;//当RS485orBT标志位为1时是RS485模式,为0时是蓝牙模式

extern uint8_t  USART3_RX_BUF[USART3_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern uint16_t USART3_RX_STA;//接收状态标记
extern uint8_t USART3_NewData;//当前串口中断接收的1个字节数据的缓存

void  HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart);//串口中断回调函数声明

#endif /* INC_USART_H_ */
retarget.c
#include <_ansi.h>
#include <_syslist.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/times.h>
#include <limits.h>
#include <signal.h>
#include <../Inc/retarget.h>
#include <stdint.h>
#include <stdio.h>
#if !defined(OS_USE_SEMIHOSTING)
#define STDIN_FILENO  0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

UART_HandleTypeDef *gHuart;

void RetargetInit(UART_HandleTypeDef *huart)  {
  gHuart = huart;
  /* Disable I/O buffering for STDOUT  stream, so that
   * chars are sent out as soon as they are  printed. */
  setvbuf(stdout, NULL, _IONBF, 0);
}
int _isatty(int fd) {
  if (fd >= STDIN_FILENO && fd <=  STDERR_FILENO)
    return 1;
  errno = EBADF;
  return 0;
}
int _write(int fd, char* ptr, int len) {
  HAL_StatusTypeDef hstatus;
  if (fd == STDOUT_FILENO || fd ==  STDERR_FILENO) {
    hstatus = HAL_UART_Transmit(gHuart,  (uint8_t *) ptr, len, HAL_MAX_DELAY);
    if (hstatus == HAL_OK)
      return len;
    else
      return EIO;
  }
  errno = EBADF;
  return -1;
}
int _close(int fd) {
  if (fd >= STDIN_FILENO && fd <=  STDERR_FILENO)
    return 0;
  errno = EBADF;
  return -1;
}
int _lseek(int fd, int ptr, int dir) {
  (void) fd;
  (void) ptr;
  (void) dir;
  errno = EBADF;
  return -1;
}
int _read(int fd, char* ptr, int len) {
  HAL_StatusTypeDef hstatus;
  if (fd == STDIN_FILENO) {
    hstatus = HAL_UART_Receive(gHuart,  (uint8_t *) ptr, 1, HAL_MAX_DELAY);
    if (hstatus == HAL_OK)
      return 1;
    else
      return EIO;
  }
  errno = EBADF;
  return -1;
}
int _fstat(int fd, struct stat* st) {
  if (fd >= STDIN_FILENO && fd <=  STDERR_FILENO) {
    st->st_mode = S_IFCHR;
    return 0;
  }
  errno = EBADF;
  return 0;
}

#endif //#if !defined(OS_USE_SEMIHOSTING)

retarget.h
#ifndef INC_RETARGET_H_
#define INC_RETARGET_H_

#include "stm32f1xx_hal.h"
#include "stdio.h"//用于printf函数串口重映射
#include <sys/stat.h>

void RetargetInit(UART_HandleTypeDef  *huart);

int _isatty(int fd);
int _write(int fd, char* ptr, int len);
int _close(int fd);
int _lseek(int fd, int ptr, int dir);
int _read(int fd, char* ptr, int len);
int _fstat(int fd, struct stat* st);

#endif /* INC_RETARGET_H_ */
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值