查看: 931|回复: 0
打印 上一主题 下一主题

电波钟就要好了pic16f877a+8MHZ+LCD12864+DS1302+DS18B20+pic ccs

[复制链接]
跳转到指定楼层
沙发
发表于 2015-6-14 16:51:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
<br>1、输出脚接10k电阻,再通过音频线输入笔记本的音频输入插孔;
<br>2、打开GoldWave V5.06,进行录音。
<br>   a.打开笔记本无输入显示;
<br>   b.合上笔记本听到秒信号的声音,开始录制信号波形。
<br>结论:笔记本的显示器对接收机信号影响较大。
<br>3、录制波形图:
<br>
<br>GoldWave V5.06录制的BPC码波形图 <font color=green>(原文件名:全图.jpg)
<br></font>
从上图可以明显看到时间为20秒各帧的分界限。
<br>4、对信号进行分析的过程
<br>  a.连续的两帧进行对比如图:
<br>
<br>连续的两帧对比分析图 <font color=green>(原文件名:连续的两帧对比分析图.jpg) </font>
b.在GoldWave V5.06中放大时间轴,看第一秒如图:
<br>
<br>第一秒的波形分析 <font color=green>(原文件名:第一秒.jpg)
<br>第二帧第一秒很明显为100毫秒的脉冲,代表为一分钟的01秒开始,那么第一帧应该是一分钟的41秒,应该为300毫秒的脉冲,本人分析可能由于电脑中音频处理引起波形的畸变所导致了失真。<br><br>本贴被 dyydyydyy 编辑过,最后修改时间:2010-07-02,21:26:52.</font>
      c.分别分析各脉冲宽度,标注如图
<br>

<br>两帧的脉冲宽度 <font color=green>(原文件名:连续的两帧的脉冲宽度.jpg)
<br>
<br>由脉冲宽度计算4进制数传分别为:
<br>                   秒  保留  时  分   星期 上下午   日    月   年  校检
<br>脉冲宽(100毫秒)   3   1    13  323   22      4     113   24  133   1
<br>4进制               2   0    02  212   11      3     002   13  022    0     
<br> 信息:10年7月2日2时38分41秒,星期五。
<br>脉冲宽(100毫秒)   1   1    13  324  22       4     113   24  133   1
<br>4进制               0   0    02  213   11      3     002   13  022   0   
<br>
<br>信息:10年7月2日2时39分01秒,星期五。
<br>应为下午,我不知道怎么根据鉴别位判断上下午。
<br>
<br>下面我会陆续把自己的电波钟制作及时上传,只是时间有限,可能需要段时间!!本人邮箱dyydyydyy@126.com,有兴趣的朋友交流啊!!<br><br>本贴被 dyydyydyy 编辑过,最后修改时间:2010-07-02,21:25:59.</font>
  综合网上资料和自己的分析,BPC码编码规则如下:
<br>

<br>BPC时码格式 <font color=green>(原文件名:bpc码格式.jpg)
<br>注意:上图有些错误,19位下半位为11-18位的校检。

我的做好了!!
pic16f877a+8MHZ+LCD12864+DS1302+DS18B20+pic ccs 基本完成,但显示中偶尔出现错行的问题。
(乾龙胜  ql200 pic单片机实验版)
实验板和接收模块 (原文件名SCN0597.JPG)
说明:1\为拍摄,天线和显示液晶很近,有干扰,收不到信号。接收电波时大概离20厘米即可。
2\液晶显示中的粗i代表电波钟模块正在校时。细的i代表接收的有效脉冲,依次显示19个脉冲右移。
3\203930代表20点39分30秒校时成功。(因为时间在前10个有效脉冲中已经测量完毕,后20个是日期。故显示的不是0秒或20秒或40秒而是30秒)图中显示到第7个脉冲。
捕捉中断处理和初始函数,供参考。
//电波接收中断处理函数
//主要根据20个脉冲的协议分别判断和处理(计算脉冲宽度、判断同步、计算日期时间)
void dbjs()
{
   set_timer1(0x0000);//计数器1清零,配合捕捉中断进行下一次测量
   Width=(long)n*262+CCP_1/250;//脉冲宽度
   n=0;//将计数器周期清零
   //-----------------------------//获取同步,如果不同步,一直测量两个上升沿之间宽度为2秒,认为找到了帧同步
   if (flag_tb==0)    //如果不同步
   {

      if ((width>1960)&&(width<2040))//两个上升沿(只有帧同步前的两个上升沿为2秒,其他为1秒)之间宽是否为2秒,是2秒表示捕捉到同步
      {flag_lstb=1;//记录同步状态,判断同步是否改变,以和flag_tb比较,如果flag_tb=0并且flag_lstb=1,说明接收中失去同步,则删除最后的同步显示
         flag_tb=1;//同步标志
         setup_ccp1(CCP_CAPTURE_FE); flag_dp=1;//改为下降沿捕捉,flag_dp=1,代表准备捕捉的是高电平
         count=0;//测量的脉冲序列复位,准备测量第一个高电平宽度
      }
   }


   else//已经同步
   {
      if (flag_dp==1) //flag_dp=1,代表准备捕捉的是高电平,现在对测量的高电平宽度进行处理
      {  setup_ccp1(CCP_CAPTURE_RE);flag_dp=0; //上升沿捕捉,flag_dp=0,代表准备捕捉的是低电平
         Pulse_zs=width/100;//求取宽度的整百毫秒部分。
         Pulse_wc=width%100;//获取非整百部分,就是测量误差,并进行误差处理
         //下面判断语句:测得有效脉冲,有效脉冲范围100-400毫秒,考虑测量误差有效脉冲范围实际取55-445毫秒。
         ////////////////如误差45-55毫秒之间不认为是误差,无法分辨,认为测量错误,重新同步。
         if (((width>55)&&(width<445)) && ((Pulse_wc>55)||(Pulse_wc<45)))
         {
            count++;//记录脉冲的序列
            //if (count>19)  {count=0;flag_tb=0;}
            swidth=width;//记录下高电平宽度,以和接着测量的低电平求和,看是否为1秒。
            if (pulse_wc>55) Pulse_zs=Pulse_zs;//例如接收一个156豪秒的脉冲,就认为是接收的200毫秒脉冲,即四进制1。
            else  Pulse_zs=Pulse_zs-1;         //例如接收一个140毫秒的脉冲,就认为是接收的100毫秒脉冲,即四进制0.

            switch(count)
            {case 1://帧信号(相当于秒信号)
               if (Pulse_zs>2) flag_tb=0;//根据协议该位只能是0、1、2,不能是3否则超出范围,表示接收错误,从新同步,
               else {db_Xj=0;db_sec=Pulse_zs*20+10;//0为10秒(从写入1302计算),1为30秒,2为50秒
                      if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;//效验积累计算,计算效验值,1=01,2=10,所以偶效验值取反,0,3不变
                    }
                                    break;
            case 2://保留
                if (Pulse_zs!=0) flag_tb=0;//根据协议,该位必须为0,否则就是错误,认为丢失同步,故也不需要进行效验积累计算
                break;
            case 3://时*4
               db_Hour=Pulse_zs*4;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;//效验积累计算,计算效验值,1=01,2=10,所以偶效验值取反,0,3不变
               break;
            case 4://时*1
               db_Hour=db_Hour+Pulse_zs;//得出最后的时
               if (db_Hour>23) flag_tb=0;//时不能大于23,否则错误,从新搜索同步
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;//效验积累计算
               break;
            case 5://分*16
               db_min=Pulse_zs*16;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;//效验积累计算
               break;
            case 6://分*4
               db_min=db_min+Pulse_zs*4;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;//效验积累计算
               break;
            case 7://分*1
               db_min=db_min+Pulse_zs;//得出最后的分
               if (db_min>59) flag_tb=0;//分是否符合范围
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;//效验积累计算
               break;
             case 8://星期*4
               if (Pulse_zs>1) flag_tb=0;//该位只能为1或0
               else  {db_Week=Pulse_zs*4;if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;}
               break;
             case 9: //星期*1
               db_Week=db_Week+Pulse_zs;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;//效验积累计算
               if (db_Week==7) db_Week=0;//电波中星期日=7,ds1302中为0,所以进行转换
               if (db_Week>6) flag_tb=0;
               break;
             case 10://上半位为上下午,0是上午,1是下午,后半位为1-9位的校检
               if (Pulse_zs>1) db_Hour=db_Hour+12;//大于1,上半位就是1,时间就是下午
               if ((Pulse_zs==0)||(Pulse_zs==2)) db_Zxj=0; //取出1-9位电波发给的校检值
               ELSE db_Zxj=1;
               if (db_Xj!=db_Zxj) flag_tb=0;//同积累的校检比对失败
               else
               {flag_timeok=1;}//flag_timeok=1,代表一次时间校时完成,在主程序中进行写入1302的操作
               break;
//----------前十个数据接收处理完毕,开始后半组数据接收和处理——————————
             case 11://日*16
               db_Day=Pulse_zs*16;
               db_Xj=0;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               break;
             case 12://日*4
               db_Day=db_Day+Pulse_zs*4;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               break;
             case 13://日*1
               db_Day=db_Day+Pulse_zs;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               if (db_Day>31) flag_tb=0;//判断接收完成的日期符合范围吗
               break;
             case 14://月*4
               db_Month=Pulse_zs*4;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               break;
             case 15://月*1
               db_Month=db_Month+Pulse_zs;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               if (db_Month>12) flag_tb=0;
               break;
             case 16://年*16
               db_Year=Pulse_zs*16;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               break;
             case 17://年*4
               db_Year=db_Year+Pulse_zs*4;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               break;
             case 18://年*1
               db_Year=db_Year+Pulse_zs;
               if ((Pulse_zs==1)||(Pulse_zs==2)) db_Xj=~db_Xj;
               break;
             case 19://后半位为11-18位校检
               count=0;
               if (Pulse_zs==db_Xj)//校检比对成功//输出时间
               {
                  flag_dateok=1;//代表一次校时成功,以进行判断是否刷新最后校时的时间
                            disable_interrupts(INT_TIMER1);//关闭电波校时
                            disable_interrupts(INT_CCP1);
                            flag_dbopen=0;
                            flag_tb=0;
               }
               else flag_tb=0;//校检失败
               break;
            }
         }
         else//测得无效高电平脉冲
          {
            flag_tb=0;
          }

      }
     else    //  对测量的低电平宽度进行处理
      {
         swidth=swidth+width;//同上次测量的高电平脉冲求和看是否为1秒.
         if((swidth<1060)&&(swidth>940))//是1秒低电平正确,
         {
            setup_ccp1(CCP_CAPTURE_FE); flag_dp=1;//下降沿捕捉,测量高电平脉冲宽度
         }
         else
         {
            if ((swidth<2040)&&(swidth>1960)&&(count==19))//如果是2秒为最后一个
            {
               setup_ccp1(CCP_CAPTURE_FE); flag_dp=1;
               count=0;
            }
            else//低电平宽度错误准备收搜索同步
            {
               setup_ccp1(CCP_CAPTURE_RE);flag_dp=0;
               flag_tb=0;
            }

         }

      }
   }

}
/////////////////////////////////////////////////////////////////////////////
//电波接收初始化函数
void db_init()
{
   setup_ccp1(CCP_CAPTURE_RE);  //上升捕捉
   flag_dp=0;                   //代表当前正在捕捉电平
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   set_timer1(0x0000);
   enable_interrupts(INT_TIMER1);//计数器中断开
   enable_interrupts(INT_CCP1);//捕捉中断开
   enable_interrupts(GLOBAL);//全局中断开
   flag_dbopen=1;
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表