突击蓝桥杯嵌入式(三)——串口收发

突击蓝桥杯嵌入式(三)——串口收发(以第十二届蓝桥杯真题停车场串口部分为例)

本文的话主要练习串口的收发,包括串口发送,接收数据的处理,我们还是简单的实现一个小例子,题目如下:

设计一个有8个车位的停车场装置,通过串口来分辨车辆的进出和待de1时间,如果车辆出去,就用串口发送收费情况(一小时2块,未满一个小时按照一个小时算)和时间,例子如下:

A01202203191500 表明编号为A01的车辆在2022年3月19日下午15时进入停车场。

A01202203191800 表明编号为A01的车辆在2022年3月19日下午18时出去停车场。

其收费应该是3*2=6元。

此节涉及到对于字符串的处理,以及一些结构体,所以我们分为 C语言基础、STM32串口操作简单使用和例题实现。

1.C语言基础(结构体与字符串处理)

(1)结构体

定义:

struct Postion
{
	int num1[8];
	int num2[8];
};
struct Postion car_postion;

调用:

int main() 
{
	car_postion.num1[0] = 1;
	printf("%d",car_postion.num1[0]);
}

(2)字符串处理

函数1int strcmp(*num1,*num2);
          头文件#include <string.h>
          如果返回值小于 0,则表示 str1 小于 str2。
          如果返回值大于 0,则表示 str1 大于 str2。
          如果返回值等于 0,则表示 str1 等于 str2。
用法:
        char num1[4] = "A01";
        char num2[4] = "A01";

        int main() 
        {
            if (strcmp(num1, num2) == 0) //若他俩相等
            {
                printf("1");
            }
        }
函数2atoi(*str)
		头文件#include <stdlib.h>
		将字符串中的char类型数字转化成int类型
用法:   char date[16] = "A01202203191500";
        char year[5];
        int year_num;
        int main() 
        {
            year[4] = '\0';
            for(int i=3;i<7;i++)
            {
                year[i - 3] = date[i];
            }
            year_num = atoi(year);
            printf("year_num is %d\n", year_num);
        }

2.简单串口通信演示(定长接收中断与发送)

我们实现一个小例子:用串口助手发送长度为10个字节的数据,并发送后5位

(1)CUBEMX配置

由于上节已经演示过,故不在演示,直接进入代码部分。

(2)定义变量

串口的收发都需要提供一个缓存地址
uint8_t rx_buff[255];
uint8_t tx_buff[255];

(3)在主函数中开启接收中断:

HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_buff,10);

(4)编写接收中断回调函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	for(int i=5;i<10;i++)
	{
		tx_buff[i-4] = rx_buff[i];
	}
	HAL_UART_Transmit(&huart1,tx_buff,6,1000);
	HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_buff,10);	//注意,要在回调函数里再次开启接收中断
}

3.例题实现

这个停车场项目的实现比较考察逻辑,首先如果是我的话,我会先设置一个车位结构体,里面包括的变量有车位编号,车位状态,起始占用时间,末尾离开时间,以及已经在其中的车辆的编号。

struct Postion
{
    int num[8];
    int state[8];
    
    uint8_t id[25];
    
    int StartTimeYear[8];
    int StartTimeMonth[8];
    int StartTimeDay[8];
    int StartTimeHour[8];
    int StartTimeMin[8];
    
    int ExitTimeYear[8];
    int ExitTimeMonth[8];
    int ExitTimeDay[8];
    int ExitTimeHour[8];
    int ExitTimeMin[8];
};
struct Postion car_postion;

具体逻辑的话,我们先判断这辆车在不在停车场内,如果已经在的话,我们直接解算费用,把车位标志位置0;如果不在的话,我们判断停车场内有没有车位,有车位,计入信息,标志位置1,如果没有,我们告诉他已无车位,请离开。

逻辑分析完了,我们来分析程序的具体实现,首先车辆信息是通过串口发送的,我们就在串口中断函数里完成车辆id的判断和数据的解析存储。

整体逻辑如下:

uint8_t rx_buff[255];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)			//rx_buff里存储这车辆的信息
{
	static int i;
	static uint8_t id_check[4];
	id_check[3] = '\0';
	for(int i=0;i<3;i++)		//解析车辆id
	{
		id_check[i] = rx_buff[i];
	}
	id_flag = check_id(id_check);
	if(id_flag != 1)
	{
		if((postion_flag = check_state())== 0)
		{
			printf("There is no postion in here,please exit");
		}
  	    else		//有车位的话,将信息存入结构体
   		 {
     		 for(i=0;i<8;i++)
    		 {
                if(car_postion.state[i] == 0)
                {
                  printf("your car in %d postion",i);
                  get_date_start(i);
                  break;
                }
			  }
		  }
	}
	HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_buff,15);
}

检查汽车是否在停车场内,如果在,计入末尾数据,解算费用,如果不在,返回0

int check_id(uint8_t * id_check)	//判断汽车现在在不在停车场内,在的话返回1,反之0
{
	static uint8_t id[4];
	static int money;
	static int i;
	static int j;
	id[3] = '\0';
	for(i=0;i<8;i++)	//对比各车位ID
	{
		for(int j=0;j<3;j++)		//读取已有车位车位ID
		{
			id[j] = car_postion.id[i*3+j];
		}
		printf("%s",id);
		if(strcmp((char *)id,(char *)id_check) == 0)
		{
			get_date_end(i);
			money = get_money(i);
			printf("you need pay %d yuan",money);
			printf("the car in %d postion is exit",i);
			return 1;
		}
	}
}

如果在停车场内,获取结束数据

void get_date_end(int k)
{
    static uint8_t Year[5];
		static uint8_t Month[3];
    static uint8_t Day[3];
    static uint8_t Hour[3];
		static uint8_t Min[3];
		static int i;
	
		Year[4] = '\0';
		Month[2] = '\0';
		Day[2] = '\0';
		Hour[2] = '\0';
		Min[2] = '\0';
	
		for(i=0;i<3;i++)	//销毁对应ID
		{
			car_postion.id[k*3+i] = '9';
		}
    for(i=3;i<7;i++)	//采集年份信息
    {
       Year[i-3] = rx_buff[i];
    }
    for(i=7;i<9;i++)	//采集月份信息
    {
       Month[i-7] = rx_buff[i];
    }
    for(i=9;i<11;i++)	//采集日信息
    {
       Day[i-9] = rx_buff[i];
    }
    for(i=11;i<13;i++)	//采集小时信息
    {
       Hour[i-11] = rx_buff[i];
    }
    for(i=13;i<15;i++)	//采集分钟信息
    {
       Min[i-13] = rx_buff[i];
    }
   // 写入结构体:
    car_postion.ExitTimeYear[k] = atoi((char *)Year);
    car_postion.ExitTimeMonth[k] = atoi((char *)Month);
    car_postion.ExitTimeDay[k] = atoi((char *)Day);
    car_postion.ExitTimeHour[k] = atoi((char *)Hour);
    car_postion.ExitTimeMin[k] = atoi((char *)Min);
    
    car_postion.state[k] = 0;		//标志位
}

检查车位状态函数:

int check_state()		//检查是否有车位
{
	static int sum=0;
	static int i;
	static int k;
	for(k=0;k<8;k++)
	{
		sum += car_postion.state[k];
	}
	if(sum == 8)
	{
		return 0;				//无车位返回 0
	}
  else
  {
		return 1;				//有车位返回 1
  }
}

如果有车位,停入,获取起始数据:

void get_date_start(int k)			//获取汽车进入时的数据
{
    static uint8_t Year[5];
	static uint8_t Month[3];
    static uint8_t Day[3];
    static uint8_t Hour[3];
	static uint8_t Min[3];
	
	static int i;
	Year[4] = '\0';
	Month[2] = '\0';
	Day[2] = '\0';
	Hour[2] = '\0';
	Min[2] = '\0';
	
	for(i=0;i<3;i++)	//读入ID
	{
		car_postion.id[k*3+i] = rx_buff[i];
	}
    for(i=3;i<7;i++)	//采集年份信息
    {
       Year[i-3] = rx_buff[i];
    }
    for(i=7;i<9;i++)	//采集月份信息
    {
       Month[i-7] = rx_buff[i];
    }
    for(i=9;i<11;i++)	//采集日信息
    {
       Day[i-9] = rx_buff[i];
    }
    for(i=11;i<13;i++)	//采集小时信息
    {
       Hour[i-11] = rx_buff[i];
    }
    for(i=13;i<15;i++)	//采集分钟信息
    {
       Min[i-11] = rx_buff[i];
    }
   // 写入结构体:
    car_postion.StartTimeYear[k] = atoi((char *)Year);
    car_postion.StartTimeMonth[k] = atoi((char *)Month);
    car_postion.StartTimeDay[k] = atoi((char *)Day);
    car_postion.StartTimeHour[k] = atoi((char *)Hour);
    car_postion.StartTimeMin[k] = atoi((char *)Min);
    
    car_postion.state[k] = 1; //已被占用
}

解算费用函数:

int get_money(int i)
{
	static int money_year;
	static int money_month;
  static int money_day;
  static int money_hour;
  static int money_min;
  int money_sum;
    
    money_year = (car_postion.ExitTimeYear[i] -  car_postion.StartTimeYear[i])*365*24*2;
    money_month = (car_postion.ExitTimeMonth[i] -  car_postion.StartTimeMonth[i])*30*24*2;
    money_day = (car_postion.ExitTimeDay[i] - car_postion.StartTimeDay[i])*24*2;
    money_hour = (car_postion.ExitTimeHour[i] - car_postion.StartTimeHour[i])*2;
    money_min = (car_postion.ExitTimeMin[i] - car_postion.StartTimeMin[i]);
    if(money_min <= 0)
    {
        money_sum = money_year + money_month + money_day + money_hour;
        return money_sum;
    }
    if(money_min > 0)
    {
        money_sum = money_year + money_month + money_day + money_hour + 2;
        return money_sum;
    }
}

main函数里记得初始化

int main(void)
{
	int v;
	/* USER CODE BEGIN 1 */

 	 /* USER CODE END 1 */

 	 /* MCU Configuration--------------------------------------------------------*/

 	 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	  HAL_Init();

 	 /* USER CODE BEGIN Init */

 	 /* USER CODE END Init */

 	 /* Configure the system clock */
	  SystemClock_Config();

  	/* USER CODE BEGIN SysInit */

  	/* USER CODE END SysInit */

 	 /* Initialize all configured peripherals */
  	MX_GPIO_Init();
  	MX_USART1_UART_Init();
  	/* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_buff,15);
	for(v=0;v<24;v++)
	{
		car_postion.id[v] = '9';
	}
	for(v=0;v<8;v++)
	{
		car_postion.state[v] = 0;
	}
	/*gure the system clock */
	  SystemClock_Config();

  	/* USER CODE BEGIN SysInit */

  	/* USER CODE END SysInit */

 	 /* Initialize all configured peripherals */
  	MX_GPIO_Init();
  	MX_USART1_UART_Init();
  	/* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_buff,15);
	for(v=0;v<24;v++)
	{
		car_postion.id[v] = '9';
	}
	for(v=0;v<8;v++)
	{
		car_postion.state[v] = 0;
	}
}

你可能感兴趣的:(蓝桥杯,stm32,蓝桥杯,嵌入式硬件)