打印
[STM32F4]

【Nucleo设计分享】一种新型泊车计费系统的设计

[复制链接]
1661|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 聿怀嘿嘿 于 2015-2-26 18:58 编辑



1.目的
       近年来,随着人们生活水平的提高以及我国城镇化进程的加快,我国机动车的保有量急剧上升,但停车位的规划却相对落后,停车难问题逐渐呈。
2.基本思路
       停车问题日益突出,某些车主因为一时找不到车位,贪图方便等原因路边随便停放车辆,造成马路秩序的混乱,对此某些城市根据路段的实际情况,在城市的若干道路两旁设立的咪表停车位,来缓解停车难问题。然而,在某些停车需求较大的区域停车,往往需要花费一定的时间来寻找空闲车位。对此,提出了一种新型的泊车计费系统的设计。
    该设计采用RFID射频识别技术,识别泊车系统的一卡通,方式持有城市一卡通的用户,均可在此泊车系统内停车,车辆信息,卡内余额通过加密后存放在一卡通的某个块中,出入匝时,通过RFID识别读取,并通过stm32的rtc模块来计时扣费写卡,并将所有信息显示在TFT液晶上。于此同时每一个装有该泊车系统的停车场地均可通过联网,将停车场地的实时信息上传云平台。在停车场地的液晶显示屏上显示空闲车位。急需寻找停车场地的车主也可以通过web或者手机app来查询附近哪些停车场地有空闲车位,这将会大大方便车主,并减少城市随地停车的现象。

3.实现功能

智能一卡通识别
停车场地一体化
收费标准可调整
TFT显示车辆缴费信息
TFT显示空闲车位
TFT滚动显示当前日期
联网同步
手机APP实时查询
WEB平台实时查询
4.效果图片
待机页面显示当前空闲车位、并在屏幕上方滚动显示日期、广告等信息
刷卡扣费页面
通过yeelink平台web查询显示当前空闲车位
5.程序
应用主程序:
void App_main(void)    
{
  ili_LCD_Init();        //初始化屏幕
  InitializeSystem();  //初始化RFID
  rtcinit();                //初始化RTC
  USART1_Config();
  tft();
  while(1)
  {
    Delay_ms(200);
    findreadcard();      //读卡
    rtctimeshow();     
    GD_app();
    if(tftsta==1)
    {
    tft();
    texttft();
    tftsta=0;
    }  
    if(rwcard==1)
    {
     if(UserBUffer[9]==0)  //Èë
     {
       UserBUffer[9]=1;
       if(PcdWrite(arr,&UserBUffer[0])) //дʧ°Ü
       {
          if(PcdWrite(arr,&UserBUffer[0]))
          {errortft();}      
          else
          {readtftin(); carnum--;}
       }
       else
       {
        readtftin();
        carnum--;
        
       }
     }
     else {
       UserBUffer[9]=0;   
       carvalue=carvalue-payvalue;
       UserBUffer[10]=carvalue%255;
       UserBUffer[11]=carvalue/255;
       if(PcdWrite(arr,&UserBUffer[0])) //дʧ°Ü
       {
        if(PcdWrite(arr,&UserBUffer[0]))
        {errortft();}
        else
        {readtftout(); carnum++;}
       }
       else                              //д³É¹¦
       {
        readtftout();
        carnum++;
       }
     }
     tftsta=2;
     rwcard=2;
  } }}
寻卡验证密码:
u8 findreadcard(void)
{
   u8 state=0;
   
   state = PcdRequest(0x26,&RevBuffer[0]);
   if(state!=MI_OK)
   {
   state=PcdRequest(0x26,&RevBuffer[0]);
    if(state!=MI_OK)
    { rwcard=0;
      if(tftsta==2) tftsta=1;
      return 0xb1;}
    }
   
   state = PcdAnticoll(&RevBuffer[2]);
   if(state!=MI_OK)  return 0xb2;
   
   memcpy(MLastSelectedSnr,&RevBuffer[2],4);
   
   state=PcdSelect(MLastSelectedSnr);
   if(state!=MI_OK)  return 0xb3;
   
   state=PcdAuthState(0x60,arr,PassWd,MLastSelectedSnr);
   if(state!=MI_OK)
   {
   state=PcdAuthState(0x60,arr,PassWd,MLastSelectedSnr);
   if(state!=MI_OK)  return 0xb4;
   }      
   if(rwcard==0)
   {      
           state=PcdRead(arr,&RevBuffer[0]);
           if(state!=MI_OK)
           {
           state=PcdRead(arr,&RevBuffer[0]);
           if(state!=MI_OK) {state=0xa1;}   
           }
           if(state==MI_OK)
           {
           memcpy(UserBUffer,&RevBuffer[0],16);
           memcpy(UID,&UserBUffer[3],6);
           carvalue=UserBUffer[10]+UserBUffer[11]*255;
           rwcard=1;
           }           
   }
   return state;
}
配置RTC:
void rtcinit(void)
{
  RTC_InitTypeDef  RTC_InitStructure;
  RTC_TimeTypeDef  RTC_TimeStructure;
  RTC_DateTypeDef   RTC_DateStructure;  
   /* Enable the PWR clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

  /* Allow access to RTC */
  PWR_BackupAccessCmd(ENABLE);
   
  /* Reset RTC Domain */
  RCC_BackupResetCmd(ENABLE);
  RCC_BackupResetCmd(DISABLE);

  /* Enable the LSE OSC */
  RCC_LSEConfig(RCC_LSE_ON);

  /* Wait till LSE is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }

  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  /* Enable the RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC APB registers synchronisation */
  RTC_WaitForSynchro();
  
  /* Configure the RTC data register and RTC prescaler */
  /* ck_spre(1Hz) = RTCCLK(LSI) /(AsynchPrediv + 1)*(SynchPrediv + 1)*/
  RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
  RTC_InitStructure.RTC_SynchPrediv  = 0x30;
  RTC_InitStructure.RTC_HourFormat   = RTC_HourFormat_24;
  RTC_Init(&RTC_InitStructure);
  
  /* Set the time to 00h 00mn 00s AM */
  RTC_TimeStructure.RTC_H12     = RTC_H12_AM;
  RTC_TimeStructure.RTC_Hours   = 18;
  RTC_TimeStructure.RTC_Minutes = 2;
  RTC_TimeStructure.RTC_Seconds = 0;  
  RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure);
  
    /* Set the Date */
  RTC_DateStructure.RTC_Month = RTC_Month_February;
  RTC_DateStructure.RTC_Date = 26;  
  RTC_DateStructure.RTC_Year = 15;
  RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Thursday;
  RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure);
}
显示时间:
void rtctimeshow(void)
{
    RTC_TimeTypeDef  RTC_TimeStructure;
    u8 timetemp[5];
    RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
   
    timetemp[2]=':';
    timetemp[0]=RTC_TimeStructure.RTC_Hours/10+0x30;   
    timetemp[1]=RTC_TimeStructure.RTC_Hours%10+0x30;
    timetemp[3]=RTC_TimeStructure.RTC_Minutes/10+0x30;
    timetemp[4]=RTC_TimeStructure.RTC_Minutes%10+0x30;
   
    LCD_Fill(180,300,220,316,BLACK);
    Show_Str(180,300,RED,BLACK,timetemp,16,1);
}
显示滚动信息:
void GD_app(void)
{
u8 gdapp_temp[50];
RTC_DateTypeDef   RTC_DateStructure;
RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);   
sprintf((char *)gdapp_temp,"今天是20%01d%01d年%01d%01d月%01d%01d日",RTC_DateStructure.RTC_Year/10,
                                                                    RTC_DateStructure.RTC_Year%10,
                                                                    RTC_DateStructure.RTC_Month/10,
                                                                    RTC_DateStructure.RTC_Month%10,
                                                                    RTC_DateStructure.RTC_Date/10,
                                                                    RTC_DateStructure.RTC_Date%10);
Show_StrGD(RED,BLACK,gdapp_temp);  
}
void Show_StrGD(u16 fc, u16 bc, u8 *str)实现信息的滚动播放、入口参赛fc为字体颜色,bc为背景颜色,str为显示字符串;
int16_t GD_x=232,GD_y=13;
void Show_StrGD(u16 fc, u16 bc, u8 *str)
{        int16_t  x=GD_x;
    int16_t  y=GD_y;   
    int16_t  x0,x1,x11;
    u16 y0,y1;
    u8 pos,t,num,temp;
        u16 colortemp=POINT_COLOR;      
          u8 bHz=0,    //字符或者中文
       size=16;
    u8 i,j;
        u16 k;
        u16 HZnum;
    HZnum=sizeof(tfont16)/sizeof(typFNT_GB16);        //自动统计汉字数目
    LCD_Fill(0,10,240,32,bc);
    LCD_DrawLine(50, 10, 190, 10);
    LCD_DrawLine(50, 32, 190, 32);
    while(*str!=0)//数据未结束
    {
        if(!bHz)
        {
                if(*str>0x80)bHz=1;//中文
                else              //字符
                {
             x0=x;y0=y;               
                 num=*str-' ';//得到偏移后的值
            for(pos=0;pos<size;pos++)
                    {
                         temp=asc2_1608[num][pos];                 //调用1608字体
                         for(t=0;t<size/2;t++)
                     {                  
                                POINT_COLOR=fc;   
                if( ((x0+t)<(lcddev.width-size/2)) && ((x0+t)>size/2) )   
                {                    
                        if(temp&0x01)ili_LCD_DrawPoint(x0+t,y0+pos);//画一个点   
                }   
                        temp>>=1;   
             }
                     }
                                        x+=size/2; //字符,为全字的一半
                                    str++;      
                }
        }else//中文
        {           
            bHz=0;//有汉字库   
                        x1=x;y1=y;
            x11=x1;
                for (k=0;k<HZnum;k++)
                {
                  if ((tfont16[k].Index[0]==*(str))&&(tfont16[k].Index[1]==*(str+1)))
                  {         
                        for(i=0;i<16*2;i++)
                        {
                                  for(j=0;j<8;j++)
                             {   
                                          POINT_COLOR=fc;
                      if( ((x1)<(lcddev.width-size/2)) && ((x1)>size/2) )
                     {
                                          if(tfont16[k].Msk[i]&(0x80>>j))        ili_LCD_DrawPoint(x1,y1);//画一个点
                     }
                                          x1++;
                                          if((x1-x11)==16)
                                          {
                        x1=x11;
                                                y1++;
                                                break;
                                          }
                             }
                                }        
                          }
              continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
                    }                                          
               
        str+=2;
            x+=size;//下一个汉字偏移            
    }                                                
    }
  POINT_COLOR=colortemp;
  GD_x-=3;
  if(GD_x<(-100))
  {GD_x=232;
  }      
}
下面的程序用来构造一个报文来与云平台(YEELINK)同步信息
sprintf((char *)postCAR,    "POST /v1.0/device/xxxxx/sensor/xxxxx/datapoints HTTP/1.1\r\n"
                            "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:9.0.1) Gecko/20100101 Firefox/9.0.1\r\n"   
                            "Host: api.yeelink.net\r\n"
                            "Accept: */*\r\n"
                            "U-ApiKey:xxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n"
                            "Content-Length: 12\r\n"
                            "Content-Type: application/x-www-form-urlencoded\r\n"
                            "{\"value\":%02d}\r\n",num);
下面是工程文件
STM32.zip (830.49 KB)
       接下来的工作是不断完善功能、改善显示界面的友好度。
最后要感谢21ic和st公司以及小跑堂、小管家哈哈、幸苦了!

沙发
王栋春| | 2015-2-26 19:41 | 只看该作者
资料不错呀,看来楼主是软件高手呀

使用特权

评论回复
板凳
mmuuss586| | 2015-2-26 20:27 | 只看该作者

不错;

使用特权

评论回复
地板
powerful1| | 2015-2-26 22:03 | 只看该作者
有模块图,也有代码,讲的很详细

使用特权

评论回复
5
vigous1| | 2015-2-26 22:40 | 只看该作者
资料不错,值得好好借鉴学习

使用特权

评论回复
6
搞IT的| | 2015-2-28 18:31 | 只看该作者
有硬件电路分享吗??

使用特权

评论回复
7
aliceqiulijun| | 2015-4-21 09:41 | 只看该作者
看起来好强大

使用特权

评论回复
8
benbpig| | 2015-4-21 09:44 | 只看该作者
代码都码完了?!

使用特权

评论回复
9
lsdavid| | 2015-4-22 14:17 | 只看该作者
代码就只有贴出来的这些?!:L

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

451

帖子

5

粉丝