首页-达尔闻    全部    毕业设计| STM32+UART HMI,玩扫雷游戏

毕业设计| STM32+UART HMI,玩扫雷游戏

每年毕设,STM32出现的频率最高,很多都是“老实本分”的设计,但也有不走寻常路,比如今天分享的这个毕设——扫雷游戏。不知道这位同学在毕业答辩时,有没有被老师为难,当着这么多评委老师,来几盘扫雷,是不是很刺激
收藏
  • 每年毕设,STM32出现的频率最高,很多都是“老实本分”的设计,但也有不走寻常路,比如今天分享的这个毕设——扫雷游戏。不知道这位同学在毕业答辩时,有没有被老师为难,当着这么多评委老师,来几盘扫雷,是不是很刺激

     

     

    先上2张游戏中照片:

     

    系统的硬件:指南者开发板和4.2英寸的UATRT HMI串口屏组成,其实可以用最小的核心板,单片机外设也就用到了串口而已,但是要求使用开发板,只好有点浪费了。

     

    软件部分:软件部分是这个项目的核心。

    刚开始参考了网上一些扫雷代码。在单片机上很多地方不一样,但大体思路还是一样的,主要解决的就是与串口屏之间的通信协议,贴一段简单的通信代码。

     

    具体完成功能:

    1.扫雷基本功能

    2.当周围的雷都标记完时,打开剩余未标记的格子

    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    //串口接收中断
    void USART1_IRQHandler(void)
    {
    if(huart1.Instance->SR&(1<<5))//如果接收到了数据
      {
       buf=huart1.Instance->DR;
    /接收选择的格子串口通信协议 
      if(id_flag==1) 
      { 
        if(buf==0xff)  
       { 
          id_flag=0; 
          count=0; 
          select_id=buff[0]; 
          select_flag=1;
         } 
        else 
        { 
          buff[count++]=buf;
         }
       }
       if(buf==0xaa)
       {
         id_flag=1;
       }
    }
    /接收选择的格子串口通信协议
    /打开一个安全格子串口通信协议
    if(buf==0xbb)

      safe_flag=1;
    }
    /打开一个安全格子串口通信协议
      /重新开始串口通信协议
    if(buf==0xcc) 
    {
       refreshall_flag=1;
    }
    /重新开始安全格子串口通信协议
      /标记炸弹串口通信协议
    if(buf==0xdd)

      zhadan_flag=~zhadan_flag;  //屏幕点击一次标记炸弹就取反一次,如点击一次表示开始标记炸弹,点击第二次表示取消标记炸弹 
    }
    /标记炸弹安全格子串口通信协议
    }

     

    与串口屏的通信协议,使用的hal库,用cubemx辅助开发。串口屏的开发有专门的软件就叫UART HMI。再贴一个自己写的的串口屏通信代码(适用于hal库)。

    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    /*
    UART HMI 串口屏通信函数 HMISendnum1,2,3分别是不同的字符串与数字的拼接后面的参数是串口号,适用于hal库
    */
    void HMISendnum1(char *str1,int nums,UART_HandleTypeDef uart)
          { 
    HAL_StatusTypeDef Flag;
      uint8_t b=0xff,i;
    char buf1[10]; 
    sprintf(buf1, "%s%d", str1, nums);
      Flag=HAL_UART_Transmit(&uart,(uint8_t*)buf1,strlen(buf1),0xffffffff);
    while(Flag!=HAL_OK);
    for(i=0;i<3;i++)
    {
       if(b!=0)
        {
         HAL_UART_Transmit(&uart,&b,1,0xff);
         while(Flag!=HAL_OK);
       } 
      else
          return ;
    }
    }
    void HMISendnum2(char *str1,int nums,char *str2,UART_HandleTypeDef uart)
          { 
    HAL_StatusTypeDef Flag;
      uint8_t b=0xff,i;
    char buf1[10]; 
    sprintf(buf1, "%s%d%s", str1, nums,str2);
    Flag=HAL_UART_Transmit(&uart,(uint8_t*)buf1,strlen(buf1),0xffffffff);
    while(Flag!=HAL_OK);
    for(i=0;i<3;i++)

      if(b!=0)
        { 
        HAL_UART_Transmit(&uart,&b,1,0xff);
         while(Flag!=HAL_OK);
       }
       else  
        return ;
    }
    }
    void HMISendnum3(char *str1,int nums1,char *str2,int nums2,UART_HandleTypeDef uart)
          {
    HAL_StatusTypeDef Flag;
    uint8_t b=0xff,i;
    char buf1[10]; 
    sprintf(buf1, "%s%d%s%d", str1, nums1,str2,nums2);
    Flag=HAL_UART_Transmit(&uart,(uint8_t*)buf1,strlen(buf1),0xffffffff);
    while(Flag!=HAL_OK); 
    for(i=0;i<3;i++)
      { 
      if(b!=0) 
       {    
    HAL_UART_Transmit(&uart,&b,1,0xff);
         while(Flag!=HAL_OK);
       }
       else
          return ;
    }
    }
    //控制串口屏的文本控件,輸入字符串命令,后面是通信的串口号
    void HMISendtxt(char *str,UART_HandleTypeDef uart)
          {
    HAL_StatusTypeDef Flag; 
    uint8_t b=0xff,i;
    Flag=HAL_UART_Transmit(&uart,(uint8_t*)str,strlen(str),0xff); 
    while(Flag!=HAL_OK);
      for(i=0;i<3;i++) 
    {
       if(b!=0)
        { 
        HAL_UART_Transmit(&uart,&b,1,0xffffffff); 
        while(Flag!=HAL_OK); 
      } 
      else
          return ;
    }
    }

     

    其他的具体代码就暂时不贴了,如果你对这个项目感兴趣,可以加QQ:943874487,一起交流。也可以看young0219同学的博客:

    https://blog.csdn.net/weixin_43793057/article/details/106158063

     

    分享一个有关keil不能使用time函数的点:

    keil不支持time()函数,让我苦恼了很久。因为地雷的产生需要使用的随机函数,就需要随机种子,必须要使用到time()函数,很久的尝试之后还是无法使用这个函数,所以去问了一位很厉害的学长,才告诉我keil不支持time函数(如果可以使用各位可以告诉我,感谢),同时提出了另一种解决方案,用定时器的数值作为随机种子,刚开始还是不行,因为初始化地雷每次到达程序段的时间都是一样的,所以随机种子的值也是一样的,但是最后加了界面之后,进入到游戏的时间就随机了,算是成功解决了这个问题。

Control Render Error!ControlType:productSlideBind,StyleName:Style1,ColorName:Item0,Message:InitError, ControlType:productSlideBind Error:未将对象引用设置到对象的实例。