用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,还是屏幕长度就是一个周期!
帮帮忙!非常感谢! idata unchar period=1500000;有问题 f310内部并没有10M的时钟阿,
http://cache.amobbs.com/bbs_upload782111/files_13/ourdev_424633.jpg
(原文件名:2009-03-09_165846.jpg) CLKSEL=0x00; //系统时钟配置,采用内部晶振,系统时钟频率10MHZ
OSCICL=0x45;
OSCICN=0xC2;
这几条语句晶振计算出来是20MHZ,我在一本书上看到的,这样正好是整数好算,系统时钟再二分频就是10MHZ了 OSCICL=0x45;f310无须设定此值,出厂校准好的,不是用来设定频率的
OSCICN=0xC2;内部2分频24.5/2=12.25MHz 怎么按照楼上说的改了还是不对呢?我改了好多次,用示波器看还是有问题 你真按我说的查过了吗? 恩那,我把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 OSCICN=0xC2;内部2分频24.5/2=12.25MHz
按这个来做,要是8us计数中断一次的话TH0=(65536-25)/256;
TL0=(65536-25)%256; 上语句就改成65536-25 了
晕了,一天都在做这个了,咋就不对呢 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;}
}
这似乎有问题,但是不知道怎么改? 周期有问题?看是具体什么问题了。一般来说,示波器很难测量这样低频的周期。原先我用老式的示波器测量十来赫兹的频率,死活不能正常显示波形及频率。你再研究研究,建议换个方法测,不用示波器。 给你个方案:
找一个I/O, 每计数到1024个脉冲再输出,连接一个小蜂鸣器,用秒表计算时间,再除以1024即可算出周期。当然128也可以,看你的耐心了。 我看楼主要学的,不是单片机编程了。
是示波器的使用。6S能用示波器看出来吗?
然后,内部晶振是有误差的,6S累计下来很大的。 貌似310有PCA模块,可以直接输出方波
页:
[1]