#define uchar unsigned char #define uint unsigned intsbit OutPut=P1^7; //矩形波输出口 sbit input=P1^0;
float fosc=12000000; //系统时钟频率 float length=65536; //方式1计数长度 uchar flag,i=8,kz; uchar ZKB;
//状态键标志
//频率
//占空比
uint PL,TT=50,TTT=50; //T0和T1的定时初值 uchar code tabl[11]=
uchar TIMER0_L,TIMER0_H,TIMER1_L,TIMER1_H;
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0}; //LED共阴极代码
/*****************************************
9 9
延时子程序
*****************************************/ void delay1ms(uint n) { uchar j; while(n--) for(j=0;j<122;j++) { ; } }
/***************************************** 系统初始化
*****************************************/ void system_init(void ) {
SCON=0x00; flag=0; PL=20; ZKB=50; TL0=0xb0; TH0=0x3c; TL1=0x58; TH1=0x9e;
TMOD=0x11; //T0和T1为工作方式1的定时模式 IT0=1; //选择INT0为下降沿触发方式 IT1=1; //选择INT1为下降沿触发方式 EX0=1;
EX1=1; //外部中断0允许
ET0=1; //定时器1和定时器0中断允许 ET1=1;
EA=1; //系统中断允许
TR0=1; //定时器1和定时器0开始定时 TR1=1;
TIMER0_L=0xb0; TIMER0_H=0x3c;
//初始占空比50定时0.025s
//初始频率20Hz定时0.05s
//延时n ms
10
TIMER1_L=0x58; TIMER1_H=0x9e; }
/***************************************** 显示子程序
*****************************************/ void display(uint PL,uchar ZKB) {
uchar b,f,d,e,m,n,k; b=PL/10000; PL=PL%10000; f=PL/1000; PL=PL%1000; d=PL/100; PL=PL%100; e=PL/10; k=PL%10;
m=ZKB/10;
n=ZKB%10; if(PL==0) b=f=d=e=k=10; if(ZKB==0)
m=n=10;
P2=~0x01; P0=tabl[b]; delay1ms(2); P2=~0x02; P0=tabl[f]; delay1ms(2); P2=~0x04; P0=tabl[d]; delay1ms(2); P2=~0x08;
//分离频率的各位数值 //分离占空比各位数值11
P0=tabl[e]; delay1ms(2); P2=~0x10; P0=tabl[k]; delay1ms(2); P2=~0x40; P0=tabl[m]; delay1ms(2); P2=~0x80; P0=tabl[n]; delay1ms(2); }
/***************************************** 键盘扫描
*****************************************/ void Key_Scan() { float TC0,TC1; flag++; if(flag==3) { flag=0; }
void Key_Scan1() {
TIMER0_H=(uint)TC0/256; //计算T0和T1的初值 TIMER0_L=(uint)TC0%256; TIMER1_H=(uint)TC1/256; TIMER1_L=(uint)TC1%256;
//清状态标志位
TC0=(length-(fosc*(100-ZKB))/(12*100*PL));
TC1=(length-(fosc*ZKB)/(12*100*PL)); //占空比定时初值
//状态返回,正常工作
}
12
if(flag==1) {
PL+=10; //按键频率加5 if(PL>10000) PL=50; }
if(flag==2)
//状态2下对占空比进行调整
display(PL,ZKB);
{
ZKB+=5;
if(ZKB>99) ZKB=5;
} if(flag==3)
{
flag=0;
display(PL,ZKB);
}
display(PL,ZKB); }
void ccdd() interrupt 0 { EX0=0; kz=kz<<1; i--; if(input) kz=kz|0x01; if(~input) kz=kz&0xfe; if(~i) {
if(kz==0xaa) Key_Scan(); if(kz==0xbb) Key_Scan1();
//按键占空比加5 //状态2下对占空比进行调整
13
i=8; } }
/***************************************** 定时器中断子程序
*****************************************/
void Timer0_PL() interrupt 1 //频率T0中断 {TR0=0; TR1=1;
//启动T1,占空比定时
TL0=TIMER0_L; TH0=TIMER0_H; OutPut=1; }
void Timer1_PL() interrupt 3 //占空比T1中断 {TR0=1; TR1=0;
//T1停止
TL1=TIMER1_L; TH1=TIMER1_H; OutPut=0; }
/***************************************** 主函数
*****************************************/ void main() {
uint PL0=0; uchar ZKB0=0;
system_init(); while(1) {
if(flag==0) //状态0时,正常显示频率和占空比 display(PL,ZKB);
if(flag==1) //状态1时,频率调整状态,频率闪烁
//系统初始化
//死循环,显示频率和占空比
//输出高电平
//输出高电平
EX0=1;
14
{
display(PL0,ZKB); TT--; if(TT==0) { {
display(PL,ZKB); } TT=50; } }
if(flag==2) //状态2时,占空比调整状态,占空比闪烁 {
display(PL,ZKB0); TTT--; if(TTT==0) { {
display(PL,ZKB); } TTT=50; } } }
TTT=50;
while(TTT--)
TT=50;
while(TT--)
六、设计总结
这次单片机课程设计不仅巩固了以前所学过的知识,而且学到了很多在书本上没有学到过的知识,掌握了一种系统的研究方法,可以进行一些简单的编程。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远
15
远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,从而提高自己的实际动手能力和思考的能力。同时在设计的过程中发现了自己的不足之处,例如对C52芯片的引脚,在使用Protel画图时,有了更加深刻的了解。
经过我们的努力,顺利的完成了单片机设计。这是一个磨练意志的过程,从课题的选择开始,频率发生器的设计、硬件和软件系统的设计到最后实验验收结束,这其中经历了很多困难,但是更重要的是在这个过程中我得到了很大的锻炼。通过C51单片机等一些器件的设计让我学习和掌握了单片机技术的基础知识和技术要点,也使以前学的很多知识都得到了运用。
在此我特别感谢我的指导老师和帮助过我的同学们,是老师的耐心指导和同学们的细心讲解才使得我更好的完成了这次小学期。
七、参考文献
[1] 高峰.单片微型计算机原理与接口技术.科学出版社,2007.
[2] 李勋.单片机微型计算机大学读本.北京航空航天大学出版社,2002. [3] 张毅刚.单片机原理及应用 .高等教育出版社,2004.
16