STM32(HAL库)模拟车库进出系统—按键/结构体数组

目录

一、情况说明

二、Cube_MX配置设置

 1.首先查看电路原理图:

 2.配置Cube_MX:

 三、代码详情

1.按键消抖:

2.串口通信及结构体数组储存


一、情况说明

     本次实验代码只有重要部分,并非完整代码,也并未呈现LCD、LED等。将从按键部分、串口输出接收部分、结构体数组储存赋值调取部分来展开;

二、Cube_MX配置设置

 1.首先查看电路原理图:

 2.配置Cube_MX:

1.按照原理图,配置端口功能:(3KEY+LED1+LED3)

2.设置sys:

3.选择高速时钟:(CCR)

 4.对USART1进行设置:

5.设置下载格式:

  6.选择Code,下载最必要的库,减小内存占用

 三、代码详情

1.按键消抖:

    当车库内没有空余车位时,按下KEY1键,蜂鸣器叫一声(按一声叫一声);按下KEY2键,表示即将有车进入车库,通过串口发送ID号(字符+数字),并设置费率,进行储存;按下KEY3键,表示即将有车辆出车库,通过串口输出ID号,显示储存的ID号以及费率;

#include "gpio.h"
#include "stdio.h"

#define KEY1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)
#define KEY2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6)
#define KEY3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5)
#define KEY4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)
#define KEY1_OUT  1
#define KEY2_OUT  2
#define KEY3_OUT  3
int num=0;//现存车辆总数
uint8_t KEY_Scan(uint8_t mode)//按键消抖扫描
{
  static uint8_t key_up=1;
	if(mode) key_up=1; 
  if(key_up&&(KEY1==0||KEY2==0||KEY3==0))
 {
		HAL_Delay(10);
		key_up=0;
		if(KEY1==0) return KEY1_OUT;	
		else if(KEY2==0) 
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);//车进入++;
			HAL_Delay(100);
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);//按键闪烁,确定按下
			num++;
			return KEY2_OUT;
		}
		else if(KEY3==0)
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);//车出去--;
			HAL_Delay(100);
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
			num--;
			return KEY3_OUT;
		}
	 }
 else if(KEY1==1||KEY2==1||KEY3==1) key_up=1;
  return 0;
}

      通过num的数量,确定灯应该处于什么样子的状态:(当车库无空余车位时,按下进入键,显示没有停车位;在停车场无车辆时,按下车辆出去键时,显示error)

void check_car()//检查是否有空车位(LED1/LED3)
{
	while(1)
	{

	 if(num>10)
		{
		  printf("sorry,have no car parking!");
			num=10;
			car_flag=1;
		}
		else if(num<0)
		{
		  printf("error!");
			num=0;
			car_flag=1;
		}
		else break;
  }
}

2.串口通信及结构体数组储存

   HAL库串口通信最大的优势是可以直接接收字符串,不是一个一个字符接收,利用fputc及fgetc直接用printf及scanf接收,这部分代码太简单就不放了。下面是最核心的串口接收后结构体储存函数:

struct car_message
  {
    char id[5];
	char price[20];
	int on_flag;//结构体是否为空数据状态
  };

/***lnt on_flag便于mian.c里面判断结构体是否为空***/
	
extern int num;
float price;
struct car_message str[10];
struct car_message *p=str;//指向str结构体首地址

char now_id[5],now_price[10],car_out[5];
int ID_flag=0,ID_out_flag=0;

void scanf_message(struct car_message str[])//将所有信息存入结构体变量
{
	if(car_flag==0)//正常状态下执行以下指令
	{
	while(1)//判断信息是否重复,重复应重新输入,直到不重复为止
	{
        printf("please give ID:");
	    HAL_Delay(100);
	    scanf("%s",now_id);
	    HAL_Delay(100);
		printf("%s\n",now_id);
	    for(int t=0;t<10;t++)//轮询判断给予ID是否重复
	  {
		  if(strcmp(now_id,str[t].id)==0)
        {
				 ID_flag=1;
				 printf("ID already exists,please input again;\n");
				 break;       //存在相同的ID,flag置1,跳出继续判定,重新输入
				}
			else{ID_flag=0;}
		}
		if(ID_flag==0)break;//没有存在相同的ID,跳出循环输入
	}//已经正确输入ID信息
		printf("please price:");
	  scanf("%s",now_price);//输入费率
	for(int a=0;a<10;a++)
	{
		if(str[a].on_flag==0)//在数组里循环找一个空的结构体存储
		{
			 printf("%d\n",a);//输出储存结构体里的数据PC端直观看到是否储存
			 memcpy(str[a].id,now_id,strlen(now_id)+1);//复制进入结构体数组
			 printf("%s\n",str[a].id);
	         memcpy(str[a].price,now_price,strlen(now_price)+1);
			 printf("%s\n",str[a].price);
			 str[a].on_flag=1;//存储数据进结构体时记得将标识符置1,读取数据记得清0;
			 printf("OK!");//显示储存成功至PC端
			 break;
		}
  }
 }
	else if(car_flag==1) car_flag=0;//异常状态不执行指令,并将异常符号清0,便于下次按下按键
}

        car_flag是‘是否正常按下’标识符,因为前面在check函数里面写了有存在按下错误的可能性(可能是多按没有空余车位存在,也可能是车库内没有车辆却按下car_out),为了避免错误状态下的按下执行接收字符等指令,设置car_flag标识符执行正常车辆范围内的接收存储指令,out输出时同理。把输入函数弄懂之后,读取输出函数便很简单了;

scnaf("%s",x)函数:读取串口输入数据时,如果设置的为char类型数组则不需要加地址符,且存储的方式是,数组内一个位置存下一个字符,所有一定要保障接收字符串够大;如果定义为char变量时,则需要加上地址符号(原因:一个变量内存储了一串字符串),查看接收数据也需要使用到指针;

strcmp(A,B)函数:比较字符串函数,当AB两字符串相等时,返回0值,不等时可能返回-1/1(具体要看具体数值),特别特别重要的是!!!strcmp()函数在检测如遇到相同时,必须同时检测到0(空)时,代表检测结束,return 0;如检测到不同字符串时,检测到第一位不同字符即代表结束;

memcpy(A,B,n)函数:将B内的字符串n位存到A里,具体查看百度百科,在char数组类复制时,不用加地址符,如果是char类型变量时,在复制时需要加地址符。strlen(数组arr or &char变量)可直接计算出该字符串的大小,使用时记得调用String.h!!!

   我在打这个代码时,因为串口输入的id号为4位,因此数组只定义了4位,而导致strcmp字符串比较函数无法返回正常值,再调整数组位数之后,便可以返回正常值,所以在后面找到空结构体储存的时候连用3个printf,为了便于观看是否储存成功。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值