| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 489 人关注过本帖
标题:功能实现了,可我自己却迷糊了。。。。
只看楼主 加入收藏
wengege
Rank: 2
等 级:论坛游民
帖 子:148
专家分:93
注 册:2012-7-23
结帖率:89.47%
收藏
已结贴  问题点数:20 回复次数:8 
功能实现了,可我自己却迷糊了。。。。
最近工作应项目需要写了一程序, 涉及的都是些简单的语句,没有什么算法。整个程序就400行的样子 可是全局变量就有十几个, 考虑这个软件的整体思路的时候可能一开始就方法不对,导致最后函数内部封装 全部混乱,让整个程序缺少条理性! 可是仔细思考还是找不到更好的方法来架构软件,无奈。 恳请高手谈谈软件架构的思路!
搜索更多相关主题的帖子: 软件 项目 
2012-10-19 21:21
w675182057
Rank: 2
等 级:论坛游民
帖 子:14
专家分:31
注 册:2012-10-14
收藏
得分:10 
我是个新手,不懂,亦求高手解答!
2012-10-19 21:43
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:10 
是怎样的程序啊?

授人以渔,不授人以鱼。
2012-10-19 22:01
wengege
Rank: 2
等 级:论坛游民
帖 子:148
专家分:93
注 册:2012-7-23
收藏
得分:0 
回复 3楼 TonyDeng
一个单片机语音菜单程序: 比如接通电话后 单片机或者微控制器发主菜单语音提示,主菜单语音内容(1、定位,2、车载电话,3、系统设置) 之后等待对方按相应的数字键(1,2,3)等选择相应的功能。  假如对方选择3则进入下一级菜单此时微控制器发出从菜单语音提示, 从菜单内容(1、设置号码1 , 2、设置号码2 ,3、设置号码三)之后等待对方按相应的数字键设置相应的号码 。假如对方选择1则就会进入下一级菜单。。 整个流程就是每前进一步后面的功能就不能重复执行,这样我的思路就是每进入一级菜单就要禁止前一级语音播放 和禁止在前一级里的按键值功能的函数,因为程序不能死等所以每个模块执行一次就要退出去执行其他的功能 这样我就要设置很多全局变量。

打好基础,学会站在巨人的肩膀上!
2012-10-19 23:14
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
菜单驱动型的程序,不需要很多全局变量的呀。你的菜单怎么实现的?

授人以渔,不授人以鱼。
2012-10-19 23:25
wengege
Rank: 2
等 级:论坛游民
帖 子:148
专家分:93
注 册:2012-7-23
收藏
得分:0 
就是每播放一级播音菜单 然后就等对方按键值输入(不是死等),然后根据按键值执行相应的功能, 根据按键值判断执行的功能用的 switch语句 因为每一级菜单功能不一样 所以用了多个 switch语句。

打好基础,学会站在巨人的肩膀上!
2012-10-19 23:46
wengege
Rank: 2
等 级:论坛游民
帖 子:148
专家分:93
注 册:2012-7-23
收藏
得分:0 
u8  RingCount = 0,
    CALLING = 0, //通话中
    SetNuming = 0,
    verifying = 0,
    decideing = 0,
    NpCountStart = 0,
    NpCountEnd = 0,
    NumberAddress,
   MainMenu=0,//主菜单播放使能标志
   SubMenu=0, //从菜单播放使能标志
   MainScanf=0,//主菜单下按键输入使能标志
   SubScanf=0,//主菜单7键子菜单下按键输入使能标志
   KeyCount=0;
   

u8 SetNum_buff[15];



//函数功能:接听电话中处理所有的功能
//待解决问题:怎么读取一个正确稳定的DTMF值

void receive_tell(void)
{
  
  if(String_Search(USART1_RxBuffer,250,"CLIP:",5)==1)
       Save_DWnumber();
  if(String_Search(USART1_RxBuffer,10,"RING:",5)==1 && CALLING==0)
       get_tell();//接电话
  play_report();
  scanf_key();
  scanf_calling();
  ScanfOutTime();
  

}

// 超时机制30秒无键值,自动挂机
void ScanfOutTime(void)
{
  if(OutTime == 1)
  {
    send("ATH");
    CALLING=0; //通话结束
    MainMenu=0;
    MainScanf = 0;
    SubMenu = 0;
    SubScanf = 0;
  }
   
}

//MainMenu==0:主菜单使能
//CALLING==1:接通电话才能播放主菜单。
//AP89_DI_STATUS==0:必须等待子菜单播放完才能开始播放主菜单
//SubMenu == 1:使能主菜单下的 7 键:播报报警电话号码、密码、设置间隔时间、使能报警等。
//verifying == 1: 使能播放需要设置的报警号码
void play_report(void)
{
  if(CALLING == 1 && MainMenu == 1 && AP89_DI_STATUS == 0)
  {            
      KeyCount++;
      if( KeyCount > 20)
      {
        KeyCount = 0;
        MainMenu=0; //禁止重复播放主菜单
        MainScanf = 1;//每次播放主菜单后使能扫描主菜单下的按键
        Play_MainMenu();   
      }
      
  }
  
  if(SubMenu == 1 && CALLING==1 && AP89_DI_STATUS == 0)
  {
 //   Submen = 0;//禁止子菜单重复播放
        KeyCount++;
      if( KeyCount > 20)
      {
         KeyCount = 0;
         Play_SubMenu();
      }
   
  }
     
   
  if(NpCountStart < NpCountEnd )
  {
    if(AP89_DI_STATUS == 0 && verifying == 1)
    {
      KeyCount++;
      if( KeyCount > 100)
      {
            KeyCount = 0;
         switch(SetNum_buff[NpCountStart])
          {
            case 10: txbyte(COM_PLAY,ZERO) ;//0
                    break;
            case 1: txbyte(COM_PLAY,ONE) ;//1
                    break;      
            case 2: txbyte(COM_PLAY,TWO) ;//2
                    break;
            case 3: txbyte(COM_PLAY,THREE) ;//3
                    break;
            case 4: txbyte(COM_PLAY,FOUR) ;//4
                    break;
            case 5: txbyte(COM_PLAY,FIVE) ;//5
                    break;
            case 6: txbyte(COM_PLAY,SIX) ;//6
                    break;
            case 7: txbyte(COM_PLAY,SEVEN) ;//7
                    break;
            case 8: txbyte(COM_PLAY,EIGHT) ;//8
                    break;
            case 9: txbyte(COM_PLAY,NINE) ;//9
                    break;
            default:;
              
          }
            NpCountStart++;
      }
      
    }
   
  }
  else if(verifying == 1)
  {
   
    NpCountStart = 0;
    NpCountEnd = 0;
    verifying = 0; //禁止语音校验输入号码
    decideing = 1;
    txbyte(COM_PLAY,OK_ENTER) ;//确认输入
   
  }
  
}


//DTMF_status==0:按键下降沿处理,避免重复执行按键功能
//MainMenu==1:主菜单命令
//DTMF_Value!=0: 没有键值0
//SubMenu==0": 没有播放子菜单
//SetNuming == 1:设置报警号码输入中
void scanf_key(void)
{
   if(DTMF_status == 0 && MainScanf == 1) //执行主菜单按键功能
   {
       switch(DTMF_Value)
        {
          case 0:  //DTMF_Value==0:没有按键      
                break;      
          case 1:  MAIN_key1();
                break;
          case 2:  MainMenu=1;DTMF_Value=0; //空脚键无效退出
                break;
          case 3:  MainMenu=0;DTMF_Value=0;
                break;
          case 4:  MAIN_key4();
                break;
          case 5:  MainMenu=0;DTMF_Value=0;
                break;
          case 6:  MainMenu=0;DTMF_Value=0;
                break;
          case 7:  MAIN_key7();
                break;
          case 8:  MainMenu=0;DTMF_Value=0;
                break;
          case 9:  MainMenu=0;DTMF_Value=0;
                break;
          case 0X0A: MAIN_key0();
                break;  
        default:   MainMenu=0;DTMF_Value=0;   //a-f键值被屏蔽        
            break;
           
       }
   }
 
  if(SubScanf == 1 && DTMF_status == 0) //执行主菜单下 7 键下的子菜单功能  
  {
      switch(DTMF_Value)
      {
          case 0: //DTMF_ValuE==0没有键值
                 break;
          case 1: SUB_key1();NumberAddress=EEPROM_NUMBER1_Address;
                 break;
          case 2: SUB_key1();NumberAddress=EEPROM_NUMBER2_Address;
                 break;
          case 3: //SUB_key1(EEPROM_NUM3_Address);  
                 break;
          case 4: DTMF_Value=0;  
                 break;
          case 5:DTMF_Value=0 ;
                 break;
          case 6:DTMF_Value=0 ;
                 break;
          case 7:DTMF_Value=0 ;
                 break;
          case 8:DTMF_Value=0 ;
                 break;
          case 9:DTMF_Value=0 ;
                 break;
          case 0X0A:return_key();
                 break;
          default:DTMF_Value=0 ; //a-f键值被屏蔽     
                 break;
      }
  }
  
  if(SetNuming == 1 && DTMF_status == 0 && DTMF_Value != 0)//设置报警号码
    set_number();

  if( decideing == 1 && DTMF_status == 0 && DTMF_Value != 0)//确认是否重新输入报警号码
  {
      
      switch(DTMF_Value)
      {
          case 1:save_number();
                break;
          case 2:SUB_key1();
                break;
          case 0X0A:return_key();
                break;
      }
  }
      
}

//函数功能:主菜单0键。
void MAIN_key0(void)
{
  MainMenu = 1 ;//使能主菜单语音播放
  DTMF_Value=0;//清空键值
  txbit(COM_PAUSE) ;//有确定的按键,不管有无播放主菜单立即发送停止指令
  Play_MainMenu();
}


//函数功能:主菜单1键:查询GPS功能。
void MAIN_key1(void)
{
  
  MainMenu=1;
  DTMF_Value=0;//清空键值
  txbit(COM_PAUSE) ;    //有确定的按键,不管有无播放主菜单立即发送停止指令
  if(GPS_JC==0)
  {
     txbyte(COM_PLAY,GPS) ;    //
     Delay_ms(30);
     txbyte(COM_PREFETCH,OK_SIGNAL) ;    //
     Delay_ms(10);
  }
  else
  {
   
     txbyte(COM_PLAY,GPS) ;      //
     Delay_ms(30);
     txbyte(COM_PREFETCH,NO_SIGNAL) ;   //
     Delay_ms(30);
  }
  
}

/********************************************
函数功能:主菜单4键 GPS定位。
函数参数:
*********************************************/
void MAIN_key4(void)
{
  
  MainMenu=0;
  DTMF_Value=0;//清空键值
  txbit(COM_PAUSE) ;    //有确定的按键,不管有无播放主菜单立即发送停止指令
  DingWei_BZ=1;  
  txbyte(COM_PLAY,LOCATIONED) ;   //
  txbyte(COM_PREFETCH,NO_SPEAKER) ;   //
  Delay_ms(10);
  
}

//函数功能:主菜单7键:播放子菜单
void MAIN_key7(void)
{
  MainScanf = 0; //进入主菜单7键子菜单后 禁止主菜单按键输入
  MainMenu = 0;//进入子菜单后禁止播放主菜单语音
  SubScanf = 1 ;//使能子菜单下子键输入
  
  DTMF_Value=0; //清空键值
  txbit(COM_PAUSE);
  Play_SubMenu();//播放主菜单7键下的语音提示
}

//函数功能:播放主菜单
void Play_MainMenu(void)
{
  txbyte(COM_PLAY,MAIN_MENU) ;      
  Delay_ms(20);
}

//函数功能:播放子菜单
void Play_SubMenu(void)
{
  txbyte(COM_PLAY,SUB_MENU) ;      
  Delay_ms(20);
}

//函数功能:子菜单1键:设置第一个报警电话
void SUB_key1(void)
{
  decideing = 0;
  SubScanf = 0 ;//等待输入待设置的电话号码,禁止子菜单输入
  DTMF_Value = 0;//清空键值
  txbit(COM_PAUSE) ;//有确定的按键,不管有无播放主菜单立即发送停止指令
  txbyte(COM_PLAY,PLEASE_PUT_NUM) ;      //请输入号码以#结束
  SetNuming=1; //使能设置报警号码
}

//函数功能:主菜单7键->1键: 设置报警号码,紧急呼叫电话
void set_number(void)
{
  if(NpCountStart < 12  &&  DTMF_Value != 0X0C)
  {
   SetNum_buff[NpCountEnd] = DTMF_Value;  
   DTMF_Value = 0;
   NpCountEnd++;
  }
  else
  {
    DTMF_Value = 0;
    NpCountStart = 0;
    txbyte(COM_PLAY,VERIFY_NUM) ;//您输入的电话号码是。
    SetNuming = 0; //禁止设置报警号码
    verifying = 1;//使能播放输入的报警电话号码
  }
   
}

//保存输输入的报警号码
void save_number(void)
{
  
    DTMF_Value=0; //清空键值
    decideing = 0;
   
    I2C_EE_SequentialWrite(SetNum_buff,NumberAddress,11);  
    SetNuming=0;//禁止设置报警号码
    memset(SetNum_buff,0x00,sizeof(SetNum_buff));//清零字符串
    return_key();
   
}

//函数功能:主菜单0键:返回主菜单
void return_key(void)
{
  DTMF_Value = 0;//清空键值
  
  decideing = 0;
  SubMenu = 0; //进入主菜单禁止子菜单语音播放
  SubScanf = 0;//禁止子菜单按键输入
  MainScanf = 1; //使能主菜单下按键输入
  
  txbit(COM_PAUSE) ; //有确定的按键,不管有无播放主菜单立即发送停止指令
  Play_MainMenu();
}

//函数功能:检测是否挂机
void scanf_calling(void)
{
  
  if(String_Search(USART1_RxBuffer,10,"ZCEND",5)==1) //挂电话
    {
     
        CALLING=0; //通话结束
        MainMenu=0;
        MainScanf = 0;
        SubMenu = 0;
        SubScanf = 0;
        txbit(COM_PDN2);  //挂电话语音下电指令
    }

}

//函数功能:保存手机号码
void Save_DWnumber(void)
{
   u8  Bufferss[20],
   Buffers1[20];
   
   CLR_String(Bufferss,20);
   Copy_String_NumStart_End(3,'"','"',Bufferss,USART1_RxBuffer,250); //电话号码保存起来
   CLR_String(Buffers1,20);
   Copy_String(Bufferss,Buffers1,11);   
   CLR_String(Bufferss,20);
   String_DianDao(Buffers1,DingWei_TEL);    //将电话号码颠倒后放到DingWei_TEL
   TIM2_DWCount=59;      //1秒后上传定位信息
   
}

//函数功能:接电话
void get_tell(void)
{
  CALLING=1; //通话中
  USART_Send_String(1, "AT+SPEAKER=1\r"); //选择耳机通道
  Delay_ms(100);
  USART_Send_String(1, "ATA\r"); //接电话
  Delay_ms(500);
  txbit(COM_PUP2);//语音上电指令
  Delay_ms(500);
  MainMenu = 1; //接电话后使能主菜单播放
  CLR_WDT(); //喂狗
}

打好基础,学会站在巨人的肩膀上!
2012-10-19 23:47
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
我不清楚电话按键的检测是否与键盘按键的机制相似(即有一个函数扫描是否有按键发生),在通常的菜单驱动程序中,都是一个死循环(类似Windows的消息处理例程)在控制程序的运行,根据按键发送消息驱动各个函数。当case选择较多的时候,一般用函数指针跳转,不用写很长的switch语句。唯一要设置全局作用域的,是那个消息表(可以在外部文件读入)。

授人以渔,不授人以鱼。
2012-10-20 00:00
wengege
Rank: 2
等 级:论坛游民
帖 子:148
专家分:93
注 册:2012-7-23
收藏
得分:0 
回复 7楼 wengege
能加我QQ吗? 我的qq  649276108

打好基础,学会站在巨人的肩膀上!
2012-10-22 13:13
快速回复:功能实现了,可我自己却迷糊了。。。。
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.051069 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved