用STC15W404AS单片机的方波发生器程序.docx

上传人:b****6 文档编号:5042427 上传时间:2022-12-12 格式:DOCX 页数:16 大小:17.83KB
下载 相关 举报
用STC15W404AS单片机的方波发生器程序.docx_第1页
第1页 / 共16页
用STC15W404AS单片机的方波发生器程序.docx_第2页
第2页 / 共16页
用STC15W404AS单片机的方波发生器程序.docx_第3页
第3页 / 共16页
用STC15W404AS单片机的方波发生器程序.docx_第4页
第4页 / 共16页
用STC15W404AS单片机的方波发生器程序.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

用STC15W404AS单片机的方波发生器程序.docx

《用STC15W404AS单片机的方波发生器程序.docx》由会员分享,可在线阅读,更多相关《用STC15W404AS单片机的方波发生器程序.docx(16页珍藏版)》请在冰豆网上搜索。

用STC15W404AS单片机的方波发生器程序.docx

用STC15W404AS单片机的方波发生器程序

/**************************************************

**方波发生器程序朱铮南编写

**单片机STC15W404AS方波输出端P1.1时钟频率20MHz

**F<80KHz占空比80%--20%

**F>80KHz占空比50%

**占空比分辨率:

1%

**方波频率分辨率:

**0--999Hz1Hz

**1KHz--9.99KHz0.01KHz

**10KHz--99.9KHz0.1KHz

**100KHz--200KHz1KHz

**设定的频率和占空比保存在EEPROM,不会丢失

**频率保存在第一扇区,占空比保存在第二扇区

**外部中断0--3,分别用于频率增减和占空比增减

**************************************************/

#include

#include

#defineucharunsignedchar

#defineuintunsignedint

#defineulongunsignedlong

ulongfreq;//Hz,输出方波频率

ucharduty;//%,占空比

sbitint0=P3^2;//输出频率增

sbitint1=P3^3;//输出频率减

sbitint2=P3^6;//输出占空比增

sbitint3=P3^7;//输出占空比减

sbitD7=P1^5;//1602数据线

sbitD6=P1^4;

sbitD5=P1^3;

sbitD4=P1^2;

sbitRS=P5^4;//1602数据/命令选择端

sbitEN=P5^5;//1602使能信号端

//RW接地

uchartable0[]="F:

0000Hz";

uchartable1[]="D:

00%";

/**************************************************

**延时1ms

**************************************************/

voiddelay1ms(ucharx)//@20.000MHz

{

uchari,j;

do

{

i=113;

j=20;

do

{

while(--i);

}while(--j);

}while(--x);

}

/**************************************************

**向LCD1602写指令或数据

**************************************************/

voidlcd_write(ucharcom,date)//com=0则写指令,com=1则写数据

{

delay1ms(3);

RS=com;

EN=1;

D7=date>>7;

D6=date>>6&0x1;

D5=date>>5&0x1;

D4=date>>4&0x1;

EN=0;//RW=0,EN从1跳到0时LCD1602执行写入

delay1ms(3);

EN=1;

D7=date>>3&0x1;

D6=date>>2&0x1;

D5=date>>1&0x1;

D4=date&0x1;

EN=0;

}

/**************************************************

**LCD1602初始化

**************************************************/

voidlcd_init(void)

{

lcd_write(0,0x28);

EN=1;//四线时没有这两行会乱码

EN=0;

lcd_write(0,0x28);

lcd_write(0,0x28);

lcd_write(0,0x0c);//显示开,无光标

}

/**************************************************

**LCD1602显示

**************************************************/

voidlcd_display(void)

{

uchari;

if(freq<=9)

{

table0[3]=freq+'0';

table0[4]='';

table0[5]='H';

table0[6]='z';

table0[7]='';

table0[8]='';

table0[9]='';

table0[10]='';

}

else

{

if(freq<=99)

{

table0[3]=freq/10+'0';

table0[4]=freq%10+'0';

table0[5]='';

table0[6]='H';

table0[7]='z';

table0[8]='';

table0[9]='';

table0[10]='';

}

else

{

if(freq<=999)

{

table0[3]=freq/100+'0';

table0[4]=freq%100/10+'0';

table0[5]=freq%10+'0';

table0[6]='';

table0[7]='H';

table0[8]='z';

table0[9]='';

table0[10]='';

}

else

{

table0[7]='';

table0[8]='K';

table0[9]='H';

table0[10]='z';

if(freq<=9999)

{

table0[3]=freq/1000+'0';

table0[4]='.';

table0[5]=freq%1000/100+'0';

table0[6]=freq%100/10+'0';

}

else

{

if(freq<=99999)

{

table0[3]=freq/10000+'0';

table0[4]=freq%10000/1000+'0';

table0[5]='.';

table0[6]=freq%1000/100+'0';

}

else

{

table0[3]=freq/100000+'0';

table0[4]=freq%100000/10000+'0';

table0[5]=freq%10000/1000+'0';

table0[6]='';

table0[7]='K';

table0[8]='H';

table0[9]='z';

table0[10]='';

}

}

}

}

}

table1[3]=duty/10+'0';

table1[4]=duty%10+'0';

lcd_write(0,0x00|0x80);//指定第一行的位置

for(i=0;i<11;i++)lcd_write(1,table0[i]);//写入第一行

lcd_write(0,0x40|0x80);//指定第二行的位置

for(i=0;i<7;i++)lcd_write(1,table1[i]);//写入第二行

}

/**************************************************

**频率写入EEPROM

**************************************************/

voidf_write(ulongdat)

{

uchari;

IAP_CMD=3;//擦除命令

IAP_ADDRL=0x0000;//擦除扇区的地址

IAP_ADDRH=0x0000>>8;

IAP_TRIG=0x5A;//激活命令

IAP_TRIG=0xA5;

IAP_CMD=2;//写入命令

for(i=0;i<3;i++)

{

switch(i)

{

case2:

IAP_DATA=dat;break;//要写入的数据

case1:

IAP_DATA=dat>>8;break;

case0:

IAP_DATA=dat>>16;

}

IAP_ADDRL=0x0000+i;//写入的地址

IAP_ADDRH=(0x0000+i)>>8;

IAP_TRIG=0x5A;//激活命令

IAP_TRIG=0xA5;

}

}

/**************************************************

**从EEPROM读出频率

**************************************************/

voidf_read(void)

{

uchari;

IAP_CMD=1;//读出命令

for(i=0;i<3;i++)

{

IAP_ADDRL=0x0000+i;//写入的地址

IAP_ADDRH=(0x0000+i)>>8;

IAP_TRIG=0x5A;//激活命令

IAP_TRIG=0xA5;

_nop_();

freq=freq<<8|IAP_DATA;//将读出的数据存入频率

}

}

/**************************************************

**占空比写入EEPROM

**************************************************/

voidd_write(uchardat)

{

IAP_CMD=3;//擦除命令

IAP_ADDRL=0x0200;//擦除扇区的地址

IAP_ADDRH=0x0200>>8;

IAP_TRIG=0x5A;//激活命令

IAP_TRIG=0xA5;

IAP_CMD=2;//写入命令

IAP_DATA=dat;//要写入的数据

IAP_ADDRL=0x0200;//写入的地址

IAP_ADDRH=0x0200>>8;

IAP_TRIG=0x5A;//激活命令

IAP_TRIG=0xA5;

}

/**************************************************

**从EEPROM读出占空比

**************************************************/

voidd_read(void)

{

IAP_CMD=1;//读出命令

IAP_ADDRL=0x0200;//读出的地址

IAP_ADDRH=0x0200>>8;

IAP_TRIG=0x5A;//激活命令

IAP_TRIG=0xA5;

_nop_();

duty=IAP_DATA;//将读出的数据存入占空比

}

/**************************************************

**初始化定时器0

**************************************************/

voidinit_time0(uchari)//@20MHz1T

{

AUXR|=0x80;//定时器0时钟工作在1T模式

TMOD&=0xF0;//设置定时器0工作在16位自动重载模式

switch(i)

{

case1:

//20MHz

{

TL0=0xFF;

TH0=0xFF;

}break;

case2:

//2MHz

{

TL0=0xF6;

TH0=0xFF;

}break;

case3:

//200KHz

{

TL0=0x9C;

TH0=0xFF;

}break;

case4:

//20KHz

{

TL0=0x18;

TH0=0xFC;

}

}

TR0=1;//定时器0开始计时

}

/**************************************************

**主函数

**************************************************/

voidmain(void)

{

ulongS_freq;//PCA计数源频率

ulongcycle;//输出方波的周期

uintplus;//输出方波的正半周

uintminus;//输出方波的负半周

uintV;//存放正负半周的临时变量

bitj=1;//输出方波的正负半周标志

uchark;//传递给初始化定时器0函数的实参

lcd_init();//1602初始化

EA=1;//中断总开关开

CMOD=0x04;//PCA计数源选定为定时器0的溢出

IT0=1;//外部中断0下降沿触发

IT1=1;//外部中断1下降沿触发

EX0=1;//允许外部中断0

EX1=1;//允许外部中断1

INT_CLKO|=0x30;//允许外部中断2、3

IAP_CONTR=0x82;//允许对EEPROM读写

d_read();//从EEPROM读出占空比

f_read();//从EEPROM读出频率

if(freq>80000)duty=50;

lcd_write(0,0x01);//清屏

lcd_display();//显示

//选择定时器0的溢出频率,保证输出方波周期在65535内

if(freq>=306){k=1;S_freq=20000000;}

if(freq<306&&freq>=31){k=2;S_freq=2000000;}

if(freq<31&&freq>=4){k=3;S_freq=200000;}

if(freq<4){k=4;S_freq=20000;}

init_time0(k);//初始化定时器0

cycle=S_freq/freq;//输出方波周期

plus=cycle*duty/100;//计算正半周值。

第一步cycle*=duty

//第二步cycle/=100,

//第三步plus=cycle,

//从第一步看出cycle必须是long类型

minus=cycle-plus;//负半周值

V=plus;

CCAP0L=V;//置正半周值

CCAP0H=V>>8;

CCAPM0=0x4C;//使能CCP0的比较、匹配、翻转

CL=0;//置PCA计数器初值

CH=0;

CR=1;//启动PCA计数器

while

(1)

{

if(CCF0)//要在短的半周内执行完以下代码

//(约占计数源40T),PWM才能产生

//50KHz时,极限占空比是10%。

//50KHz-70KHz时,占空比可以是15%。

//80KHz时,极限占空比是20%。

//占空比50%时,最高可输出200KHz。

{

j=~j;

if(j)V+=plus;//交替递增正半周和负半周的值

elseV+=minus;

CCAP0L=V;

CCAP0H=V>>8;

CCF0=0;

}

}

}

/**************************************************

**外部中断0(输出频率增)

**************************************************/

voidInt0_Routine(void)interrupt0

{

while(!

int0)//频率递增

{

if(freq<=999)freq+=1;

else

{

if(freq<=9999)freq+=10;

else

{

if(freq<=99999)freq+=100;

elseif(freq<200000)freq+=1000;

}

}

lcd_display();//显示

delay1ms(250);//延时1秒

delay1ms(250);

delay1ms(250);

delay1ms(250);

while(!

int0)//1秒后转成快速递增

{

if(freq<=999)freq+=5;

else

{

if(freq<=9999)freq+=50;

else

{

if(freq<=99999)freq+=500;

elseif(freq<200000)freq+=1000;

}

}

lcd_display();//显示

}

}

f_write(freq);//写入EEPROM

IAP_CONTR=0x20;//单片机软复位

}

/**************************************************

**外部中断1(输出频率减)

**************************************************/

voidInt1_Routine(void)interrupt2

{

while(!

int1)//频率递减

{

if(freq>100000)freq-=1000;

else

{

if(freq>10000)freq-=100;

else

{

if(freq>1000)freq-=10;

elseif(freq>1)freq-=1;

}

}

lcd_display();//显示

delay1ms(250);//延时1秒

delay1ms(250);

delay1ms(250);

delay1ms(250);

while(!

int1)//1秒后转成快速递减

{

if(freq>100000)freq-=1000;

else

{

if(freq>10000)freq-=500;

else

{

if(freq>1000)freq-=50;

else

{

if(freq>100)freq-=5;

elseif(freq>1)freq-=1;

}

}

}

lcd_display();//显示

}

}

f_write(freq);//写入EEPROM

IAP_CONTR=0x20;//单片机软复位

}

/**************************************************

**外部中断2(输出占空比增)

**************************************************/

voidInt2_Routine(void)interrupt10

{

while(!

int2)

{

if(duty<80)duty+=1;//占空比递增

lcd_display();//显示

delay1ms(250);

}

d_write(duty);//写入EEPROM

IAP_CONTR=0x20;//单片机软复位

}

/**************************************************

**外部中断3(输出占空比减)

**************************************************/

voidInt3_Routine(void)interrupt11

{

while(!

int3)

{

if(duty>20)duty-=1;//占空比递减

lcd_display();//显示

delay1ms(250);

}

d_write(duty);//写入EEPROM

IAP_CONTR=0x20;//单片机软复位

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1