打印

新手做的方波信号发生器,望大家给点宝贵意见。

[复制链接]
3046|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
fa2008|  楼主 | 2007-11-9 18:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面是一个输出频率在1Hz-1KHz间可调的程序。频率越高精度越低,现正在改进。
望各位高手们对我的程序给点意见。
我是新手,这是我的第一个C程序。多多包涵。

对了,还有一个问题老是搞不懂,用PROTEUS仿真的时候为什么数值在256以下的时候显示都正常,超过256后个位显示就不正常了。十位百位都正常
。最下面有仿真的文件下载,大虾们帮我看下,感谢了!
/****************************************************
名称:方波信号发生器
作者:小发
日期:2007年11月1日
邮箱:fabest@yahoo.cn
****************************************************/

#include<reg52.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbit P20=0xA0;
sbit P21=0xA1;
sbit P22=0xA2;
sbit P23=0xA3;
sbit P10=0x90;
sbit P11=0x91;
sbit P12=0x92;
sbit P13=0x93;
sbit Output=0xB7;       //P3.7为输出

bit Fast_Key;
uint Timercount,Hz_data,nCount, KeyCount;


void Delay1ms(uint count)
{
   uint i,j;
   for(i=0;i<count;i++)
   for(j=0;j<120;j++);
}
/******** 定时器初始化 ********************/
void InitialTimer0(viod)
{
   TMOD=0x02;                              //工作方式2,自动重装
   TH0=0xcd;                     //50us定时
   TL0=0xcd;
   ET0=1;
   EA=1;
   TR0=1;
   
}
/*********** 寄存器初始化 *****************/
void InitialCPU(void)

   Timercount=0;
   Hz_data=1;
   nCount=10000;
   P1=0xff;
   P2=0xff;
}
/********** 定时器中断函数  *****************/
void Timer0_overflow() interrupt 1 using 0
{  
   Timercount++;                           //定时器中断计数器
   if(Timercount>nCount)                    //注意,这里不能用等号,否则可能永远也满足不了条件
   {
       Timercount=0;                
       Output=!Output;                    //输出取反
       
    }

}

/************** 检测键盘并处理 ******************

说明:短按时加1,当长按超过2秒时,快速连加

*************************************************/
GetKey_Dispose()
{  
   if(P1==0xff)
   {
      Fast_Key=0;
      KeyCount=0;                //按键释放清除快加控制位
      return;
    }
   Delay1ms(10);
   if(P1==0xff)return;            //延时消抖
   if((P10==0)&&(Hz_data<1000))
   {  
           if(!Fast_Key)
           {
              Fast_Key=1;              //当第一次按下时置标志位
              Hz_data++;
              nCount=10000/Hz_data;
            } 
           else
            {
              KeyCount++;
              if(!(KeyCount==50))return;     //这里的常数设定进入快加的时间,越大延时越长.
              KeyCount-=1;                   //这里的常数设定快加时的速度,越大越慢.
              Hz_data++;
              nCount=10000/Hz_data;
            }
    }


   if((P11==0)&&(Hz_data>1))
   {  
            if(!Fast_Key)
           {
              Fast_Key=1;             
              Hz_data--;
              nCount=10000/Hz_data;
            } 
           else
            {
              KeyCount++;
              if(!(KeyCount==50))return;
              KeyCount-=1;
              Hz_data--;
              nCount=10000/Hz_data;
            }       
   }
   return;
}



/************** 显示当前频率 ****************/
uchar code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void  DISPLAY(void)
{
   uint nTemp,nIndex;
   nTemp=Hz_data;
   P20=0;
   nIndex=nTemp%10;
   P0=tab[nIndex];
   Delay1ms(1);
   P20=1;                             //显示最低个位
   nTemp/=10;
   P21=0;
   nIndex=nTemp%10;
   P0=tab[nIndex];
   Delay1ms(1);
   P21=1;                            //显示十位
   nTemp/=10;
   P22=0;
   nIndex=nTemp%10;
   P0=tab[nIndex];
   Delay1ms(1);
   P22=1;                           //显示百位
   nTemp/=10;
   P23=0;
   nIndex=nTemp%10;
   P0=tab[nIndex];
   Delay1ms(1);
   P23=1;                           //显示千位
}    

/*************** 主函数 *********************/
void main(void)
{  
   
   
   InitialCPU();
   InitialTimer0();

   while(1)
   {
     DISPLAY();
     GetKey_Dispose();              //读键并处理

   }
  
}
相关链接:https://bbs.21ic.com/upfiles/img/200711/2007119181231419.rar

相关帖子

沙发
5880527| | 2007-11-9 18:17 | 只看该作者

不要怀疑,要精度高只有汇编做

使用特权

评论回复
板凳
fa2008|  楼主 | 2007-11-9 18:20 | 只看该作者

是想过用汇编,但除法难实现。

不知哪位有没有好方法。
不吝赐教。

使用特权

评论回复
地板
5880527| | 2007-11-9 18:24 | 只看该作者

晕,你需要几十字节除几十字节的?

你可以去搜索一下,有一个单片机子程序库,里面有4字节除两字节,一般情况都够用了

使用特权

评论回复
5
fa2008|  楼主 | 2007-11-9 18:34 | 只看该作者

我程序的误差主要是在于除法后只取了整

频率输出用的定时器中断,在叫断程序中取反,这里应该是没有什么问题。

问题是中断次数那里

定时器是50uS中断一次
那么中断次数我用的是10000/Hz
也就是说当频率为1000Hz时和990Hz时除得的结果是一样的。

使用特权

评论回复
6
5880527| | 2007-11-9 18:47 | 只看该作者

看了你的程序

你思路不对,你把分辨率整到了50us还咋精确,原始的1us都觉得粗糙了

使用特权

评论回复
7
fa2008|  楼主 | 2007-11-9 19:02 | 只看该作者

楼上能不能说详细点

1us。。
楼上能不能说详细。
中断程序就有好几个机器周器。
难道用延时,不用定时器??

使用特权

评论回复
8
5880527| | 2007-11-9 19:08 | 只看该作者

要用定时器啊

你把当前频率所需要的初始值赋给定时器的重装值也可以的呀,再想精确点得考虑用我以前发过的一个帖子里说的方法修正,或是硬件PWM功能

使用特权

评论回复
9
fa2008|  楼主 | 2007-11-9 19:30 | 只看该作者

多谢楼上大哥。

我改下试试

楼上热心的大哥。

使用特权

评论回复
10
5880527| | 2007-11-9 22:19 | 只看该作者

完了,粗心了一下

再看了一下你的程序发现需要1HZ的频率,这个问题还需要认真做一下的,PWM不行。一次定时能完成的自然是好办,十几Hz低频时定时器不够长了,可以把尾巴并到最后一次定时里。你最高频率1KHz,最低1Hz,所以在定时中断里最短都有一毫秒,有足够的时间对高低频率进行分类修正。

使用特权

评论回复
11
xwj| | 2007-11-9 22:26 | 只看该作者

分段处理啊,就算精确到一个周期内都是可以的

使用特权

评论回复
12
5880527| | 2007-11-9 22:38 | 只看该作者

这个1个周期的精度还是有点难度

得精雕细琢

使用特权

评论回复
13
ayb_ice| | 2007-11-10 08:06 | 只看该作者

好点单片机可以直接输出高精度的方波信号

精度直接取决于晶振的精度

使用特权

评论回复
14
5880527| | 2007-11-10 08:38 | 只看该作者

回LS,可是LZ需要1Hz的方波,硬件咋输出

另外我上面的最短时间1毫秒应该是最短500us哈

使用特权

评论回复
15
ayb_ice| | 2007-11-10 09:11 | 只看该作者

比如你可以再用外部中断配合

使用特权

评论回复
16
5880527| | 2007-11-10 09:18 | 只看该作者

中断又需要考虑响应不一致了吧

不对,这个频率精度的帖子以前讨论过

使用特权

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

本版积分规则

2

主题

14

帖子

1

粉丝