jinyingfly 发表于 2009-3-9 16:43:30

用C8051F310控制产生一个周期6s、脉宽20us的脉冲信号,用示波器观察时,脉宽正确,周期总

这是我的毕业设计做的信号源部分,程序如下:
#include <C8051F310.H>      /*取4u定时*/
typedef unsigned char unchar;
idata unchar time;
idata unchar period=1500000; //周期6s
idata unchar high=5;         //脉宽5*4=20us
sbit P1_0=P1^0;
void Port_Init (void);      // Port initialization routine函数声明
void Timer0_Init (void);   // Timer0 initialization routine
void config(){
CLKSEL=0x00;               //系统时钟配置,采用内部晶振,系统时钟频率10MHZ
OSCICL=0x45;
OSCICN=0xC2;
}

void main(void)
{config();
PCA0MD &= ~0x40;         // Clear watchdog timer enable
Timer0_Init ();         // Initialize the Timer0
Port_Init ();         // Init Ports
EA=1;                  // Enable global interrupts
do{} while(1);}

void Timer0_Init(void)
{
TH0=(65536-10)/256;
TL0=(65536-10)%256;
TMOD=0x01;
CKCON=0x01;//系统时钟4分频
ET0=1;       // Timer0 interrupt enabled
TCON = 0x10;   // Timer0 ON
}

void Port_Init (void)
{
XBR0=0x00;
XBR1 = 0x40;                        // Enable crossbar
P1MDOUT = 0x1D;                     // Set push-pull
}

void Timer0_ISR (void) interrupt 1 //timer0() interrupt 1 using 1
{
TH0=(65536-10)/256;
TL0=(65536-10)%256;
if(++time==high)
P1_0=1;
else if(time==period)
{
time=0;
P1_0=0;}
}
我不知道是不是示波器显示20us时,显示不了6S,还是屏幕长度就是一个周期!
帮帮忙!非常感谢!

new007 发表于 2009-3-9 16:57:14

idata unchar period=1500000;有问题

Jnny_CN 发表于 2009-3-9 16:59:26

f310内部并没有10M的时钟阿,

http://cache.amobbs.com/bbs_upload782111/files_13/ourdev_424633.jpg
(原文件名:2009-03-09_165846.jpg)

jinyingfly 发表于 2009-3-9 17:18:53

CLKSEL=0x00;               //系统时钟配置,采用内部晶振,系统时钟频率10MHZ
OSCICL=0x45;
OSCICN=0xC2;
这几条语句晶振计算出来是20MHZ,我在一本书上看到的,这样正好是整数好算,系统时钟再二分频就是10MHZ了

Jnny_CN 发表于 2009-3-9 17:30:35

OSCICL=0x45;f310无须设定此值,出厂校准好的,不是用来设定频率的

OSCICN=0xC2;内部2分频24.5/2=12.25MHz

jinyingfly 发表于 2009-3-9 21:18:56

怎么按照楼上说的改了还是不对呢?我改了好多次,用示波器看还是有问题

new007 发表于 2009-3-9 21:20:08

你真按我说的查过了吗?

jinyingfly 发表于 2009-3-9 21:26:01

恩那,我把idata unchar period=1500000 改为idata long period=1500000 了
#include <c8051F310.h>   /*取8u定时*/
int i,j;
typedef unsigned char unchar;
typedef unsignedint unint;
typedef unsignedlong unlong;
#define INIT 0x29 //专用初始化命令字0010 1001
#define OSCon 0x01 //开振荡器:0000 0001
#define LCMon 0x03 //开显示器:0000 0011
sbit LCM_CS=P1^2; //端口定义
sbit LCM_WR=P1^3;
sbit LCM_DATA=P1^4;
unchar DisData={0x06,0x06,0x07,0x0d,0x07,0x0d,0x07,0x0d};//从左到右
idata unlong time;
idata unlong period=10; //周期40us
idata unlong high=2;         //脉宽2*8=16us
sbit P1_0=P1^0;
void Port_Init (void);      // Port initialization routine函数声明
void Timer0_Init (void);   // Timer0 initialization routine
void config(){
CLKSEL=0x00;               //系统时钟配置,采用内部晶振,系统时钟频率10MHZ
OSCICL=0x45;
OSCICN=0xC2;      //为内部晶振2分频
}
void L_Write(void);
void L_Disp(unchar D);
void delay1us(unint t)
{
unint i;
unint j;
for(i=0;i<t;i++){
for(j=0;j<300;j++);}
}
void main(void)
{
config();
PCA0MD &= ~0x40;      // Disable Watchdog timer
Timer0_Init ();         // Initialize the Timer0   
Port_Init ();         // Init Ports// Clear watchdog timer enable(以上两行后加)
EA=1;                  // Enable global interrupts
L_Disp(INIT);//写初始化命令字
L_Disp(0x18);//定义RC振荡方式:选内部振荡器
L_Disp(OSCon);//开振荡器
L_Disp(LCMon);//开显示器
L_Write();//连续写数据,地址
do{} while(1);
//while(1);
}
void L_Write(void)//写数据,地址
{   
    LCM_CS=0;
        LCM_WR=0;
      delay1us(10);
    LCM_DATA=1;          //发101表示数据
          delay1us(10);
    LCM_WR=1;            //产生写脉冲
          delay1us(10);
    LCM_WR=0;            //写脉冲结束
      delay1us(10);
    LCM_DATA=0;
          delay1us(10);
    LCM_WR=1;            //产生写脉冲
          delay1us(10);
        LCM_WR=0;            //写脉冲结束
      delay1us(10);
    LCM_DATA=1;
          delay1us(10);
    LCM_WR=1;            //产生写脉冲
          delay1us(10);
        for(i=0;i<6;i++)      //6位地址00000
        {
                  LCM_WR=0;
             delay1us(10);
          LCM_DATA=0;
                     delay1us(10);
          LCM_WR=1;
                     delay1us(10);
         }
                for(i=0;i<8;i++)         //数据32位
                {
                  for(j=0;j<4;j++)
                  {
             LCM_WR=0;
             delay1us(1);
             if(DisData&0x01)
                       {
                          LCM_DATA=1;
                       }
                       else
                       {
                           LCM_DATA=0;
                     }
                       DisData>>=1;
                       delay1us(1);
             LCM_WR=1;
                     delay1us(1);
                  }
                }
                LCM_CS=1;
}
               
//   对显示器的命令也很重要,命令格式是:
//100 C7 C6 C5 C4 C3 C2 C1 C0 0   共12位
//   具体命令方法如下:
void L_Disp(unchar D)
{
int i;
    LCM_CS=0;
                delay1us(1);
        LCM_WR=0;         //发100,表示命令
                delay1us(1);
    LCM_DATA=1;
                delay1us(1);
    LCM_WR=1;          //产生写脉冲
                delay1us(1);
    LCM_WR=0;          //写脉冲结束
      delay1us(1);
    LCM_DATA=0;               //发送一位数据
               delay1us(1);
    LCM_WR=1;                  //产生写脉冲
               delay1us(1);
    LCM_WR=0;                   //写脉冲结束
         delay1us(1);
    LCM_DATA=0;
               delay1us(1);
    LCM_WR=1;                   //产生写脉冲
               delay1us(1);
//--------发送命令----------------
    for(i=0;i<8;i++)
                {
                  LCM_WR=0;
      delay1us(1);
                  if(D & 0x80)            //高位在先
                  {
                     LCM_DATA=1;
                   }
                  else
                  {
                     LCM_DATA=0;         //发送一位数据
                   }
                  D<<=1;                  //数据左移一位
                  delay1us(1);
          LCM_WR=1;
                  delay1us(1);
               }
                   LCM_WR=0;                //写脉冲结束
         delay1us(1);
         LCM_DATA=0;            //以0结束
                   delay1us(1);
       LCM_WR=1;                //产生写脉冲
                   delay1us(1);
                   LCM_CS=1;
               delay1us(1);
                }
void Timer0_Init(void)
{
TH0=(65536-25)/256;
TL0=(65536-25)%256;
TMOD=0x01;
CKCON=0x01;//系统时钟4分频
ET0=1;       // Timer0 interrupt enabled
TCON = 0x10;   // Timer0 ON
}
void Port_Init (void)
{
XBR0=0x00;
XBR1 = 0x40;                        // Enable crossbar
P1MDOUT = 0x1D;                     // Set push-pull
}
void Timer0_ISR (void) interrupt 1 //timer0() interrupt 1 using 1
{
TH0=(65536-25)/256;//TH0=(65536-10)/256;10是4,5是2us
TL0=(65536-25)%256;//TL0=(65536-10)%256;
if(++time==high)
P1_0=0;
else if(time==period)
{
time=0;
P1_0=1;}
}


改成这样了,出来之后脉宽为50us,周期250us

jinyingfly 发表于 2009-3-9 21:31:02

OSCICN=0xC2;内部2分频24.5/2=12.25MHz
按这个来做,要是8us计数中断一次的话TH0=(65536-25)/256;
TL0=(65536-25)%256; 上语句就改成65536-25 了
晕了,一天都在做这个了,咋就不对呢

jinyingfly 发表于 2009-3-10 11:12:41

void Timer0_ISR (void) interrupt 1 //timer0() interrupt 1 using 1
{
TH0=(65536-25)/256;//TH0=(65536-10)/256;10是4,5是2us
TL0=(65536-25)%256;//TL0=(65536-10)%256;
if(++time==high)
P1_0=0;
else if(time==period)
{
time=0;
P1_0=1;}
}
这似乎有问题,但是不知道怎么改?

jia1983 发表于 2009-3-10 22:05:42

周期有问题?看是具体什么问题了。一般来说,示波器很难测量这样低频的周期。原先我用老式的示波器测量十来赫兹的频率,死活不能正常显示波形及频率。你再研究研究,建议换个方法测,不用示波器。

Friendz 发表于 2009-3-10 23:53:09

给你个方案:

找一个I/O, 每计数到1024个脉冲再输出,连接一个小蜂鸣器,用秒表计算时间,再除以1024即可算出周期。当然128也可以,看你的耐心了。

flyunlimit 发表于 2009-3-11 08:50:17

我看楼主要学的,不是单片机编程了。
是示波器的使用。6S能用示波器看出来吗?
然后,内部晶振是有误差的,6S累计下来很大的。

lovelywwei 发表于 2010-8-25 15:45:26

貌似310有PCA模块,可以直接输出方波
页: [1]
查看完整版本: 用C8051F310控制产生一个周期6s、脉宽20us的脉冲信号,用示波器观察时,脉宽正确,周期总