论坛风格切换切换到宽版
  • 3640阅读
  • 7回复

写了个自动键程序,请各位指教 [复制链接]

上一主题 下一主题
离线VR2KW
 
发帖
3110
只看楼主 倒序阅读 0楼 发表于: 2007-03-10
用picc写了个自动键的控制程序,带点划记忆,请各位指教

//pic16f877a
//晶体震荡频率4mhz,hs震荡模式,关闭看门狗
//ra0设置为adc输入,ra1设置为电键输出
//rb4设置为dot输入,rb5设置为da输入

//加载头文件
#include <pic.h>

//定义变量
unsigned int ratio;      //点划比例 1:3=30, 1:3.5=35
unsigned int dot_speed;      //点长度
unsigned int da_speed;      //划长度
unsigned int delay_count1;
unsigned int delay_count2;
unsigned int delay_count3;
bit dot_in;
bit da_in;

//函数宣告
void initial(void);      //初始化子程序
void interrupt irq_int(void);      //中断子程序
void delay(void);            //延时子程序
void send_dot(void);            //点发送子程序
void send_da(void);            //划发送子程序

void initial(void)            //*** 初始化
{
     adcon0=0x41;
     adcon1=0x0e;
     trisa=0xfd;
     trisb=0xff;
     trisc=0x00;
     rbpu=0;            //开启 rb 口弱上拉
     portc=0;
     ra1=0;
     ratio=30;            
     dot_speed=70;            
     da_speed=dot_speed/10*ratio;            
     adgo=1;
     dot_in=1;
     da_in=1;
}

void delay(void)      //***延时
{
     while(--delay_count1)
     {
           delay_count3=delay_count2;
           while(--delay_count3) {;}
           if(rb4==0) dot_in=0;
           if(rb5==0) da_in=0;
     }
}

void send_dot(void)
{
     ra1=1;
     delay_count1=dot_speed;
     delay_count2=adresh/2+14;
     delay();
     ra1=0;
     delay_count1=dot_speed;
     delay_count2=adresh/2+14;
     delay();
     dot_in=1;
}

void send_da(void)
{
     ra1=1;
     delay_count1=da_speed;
     delay_count2=adresh/2+14;
     adgo=1;
     delay();
     ra1=0;
     delay_count1=dot_speed;
     delay_count2=adresh/2+14;
     adgo=1;
     delay();
     da_in=1;
}

void main(void)
{
     initial();
     while(1)
     {
           if(adif==1) adgo=1;
           if(rb4==0) send_dot();
           if(da_in==0) send_da();
           if(dot_in==0) send_dot();
           if(rb5==0) send_da();
     }
}
离线bd1es
发帖
2096
只看该作者 1楼 发表于: 2007-04-24
似乎有点儿问题,在自动键中需要寄存点划的下一个状态,要不发出的字符就不连续了。寄存点划的方法是设置两个标志(位变量),在外部中断或者定时器中断中检测paddle有没有被压下,如果有就给寄存器置位。

我的做法是在定时器中断中检测并置位点划寄存器,在实际的点或者划发完后再复位相应的寄存器。使用定时器中断的好处是可以同时完成产生测音、控制实际的发报速度这些工作,因为那些都是定时器操作。

程序中的部分代码如下,这可以实现一个与收发机里面完全一样的自动键。可惜不是pic,而是2051的。:):)

// timer0 routine, a global clock generator.
void timer0(void) interrupt tf0_vector using 1
{

  // sample paddle status.
  dot_register&=pin_dot;
  dash_register&=pin_dash;
  auto_space=dot_register&dash_register;

  // generate side tones.
  if(hf_key_on){
    pin_hf_side=hf_side;
    hf_tone_mask++;
  }else{
    pin_hf_side=1;
    hf_tone_mask=0;
  }

  // generate keying delay.
  if(delay_start==1){
    // decrease the delay counter to 0, then notify to stop the delay routine.
    if((--delay_counter)==0){
        delay_start=0;
    }
  }

     ......
}


void main()
{
  ......

  // clear dot/dash registers.
  dot_register=1;
  dash_register=1;

  // paddle keyer process.
  for(;;){
    // convert voltage sampling result to cw speed:
    speed_index=cw_speed[sample_result];

    // send dot:
    if(dot_register==0){
        // key on the transmitter.
        do_key_on();
        do_dot_delay(1);
        // key off the transmitter.
        do_key_off();
        do_dot_delay(1);
        // clear paddle status.
        dot_register=1;
        // automatic character space.
        if(auto_space==1){
          do_dot_delay(2);
        }
    }

    // send dash:
    if(dash_register==0){
        // key on the transmitter.
        do_key_on();
        do_dot_delay(3);
        // key off the transmitter.
        do_key_off();
        do_dot_delay(1);
        // clear paddle status.
        dash_register=1;
        // automatic character space.
        if(auto_space==1){
          do_dot_delay(2);
        }
    }

    // async keyer.
    asy_keyer();
  }
}
离线VR2KW
发帖
3110
只看该作者 2楼 发表于: 2007-04-25
'
似乎有点儿问题,在自动键中需要寄存点划的下一个状态,要不发出的字符就不连续了。寄存点划的方法是设置两个标志(位变量),在外部中断或者定时器中断中检测paddle有没有被压下,如果有就给寄存器置位。
我的做法是在定时器中断中检测并置位点划寄存器,在实际的点或者划发完后再复位相应的寄存器。使用定时器中断的好处是可以同时完成产生测音、控制实际的发报速度这些工作,因为那些都是定时器操作。
程序中的部分代码如下,这可以实现一个与收发机里面完全一样的自动键。可惜不是pic,而是2051的。:):)
'

哈哈,一下子就指出问题了,现在程序已经基本调通了,程序是按照winkey的指令编写的,同时也对winkey不满意的地方作出了修改,因为writelog对winkey的支持存在缺陷,writelog我没法修改,我只好在编写keyer程序里做出修改,但这个修改并不会因为writelog以后更新有所影响。
原版winkey有32个控制指令,好几个返回指令(我还没有完全偷出来
离线bd1es
发帖
2096
只看该作者 3楼 发表于: 2007-04-25
哈哈,大大的利害!要是来个winkey的小小版肯定很爽的。:):)

索性我把全部代码贴出来,有些例程也许有用,贴着玩吧。不过别笑话俺,一是注释里面有错别字,二是这程序是我自己实验用的,没打算实用,所以搞笑的地方挺多, 。再纠正注释里面的一个错误,俺把小码每分钟写成wpm了,实际的值应该除5才对。这段程序可以用自动键发出10-30wpm的码子,用电脑控制可以发到50wpm,

电路图压根儿就没有,是自己在面包板上搭的。不过看注释应能想象出电路图,a/d转换部分参考一下atmel的89c2051数据表就知道咋接了。其中fm收发机控制部分原本有一个外接的波表,是用gal写的,就16个正弦波的值,没啥用,不贴咧。
附件: keyer.zip (0 K) 下载次数:137
离线VR2KW
发帖
3110
只看该作者 4楼 发表于: 2007-04-25
老哥,谢谢你了,我那个程序还在修改,太多重复部分了,暂时就不贴出来了
离线HiXGod
发帖
1608
只看该作者 5楼 发表于: 2007-04-25
vr2kw会用dspic吗?想用来做tnc,可以利用其dsp功能作音频信号滤波……
离线VR2KW
发帖
3110
只看该作者 6楼 发表于: 2007-04-26
对不起,暂时我只会用16f87x系列的,其他的都没有玩过。
离线BG6QCB
发帖
5262
只看该作者 7楼 发表于: 2007-04-26