单片机的C语言程序设计与应用
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3 C51编程举例

下面通过MCS-51内部功能部件的简单应用的例子,加深对C51程序结构及单片机的C语言编程的理解。

【例1-5】 Proteus仿真电路如图1-2所示,8个发光二极管D1~D8经限流电阻分别接至P1口的8个引脚,阳极共同接高电平。编程实现发光二极管的流水点亮,即按照D1→D2→…→D8的顺序,每次点亮一个发光二极管,一段时间后熄灭该发光二极管,然后点亮下一个发光二极管,重复循环。

图1-2 例1-5的Proteus仿真电路图

C51源程序如下:

            #include<reg51.h>
            #include<intrins.h>                 //移位库函数包含于此头文件中
            void delay(unsigned int d)          //定义延时子函数
            {  while(--d>0);
            }
            void  main()
            {   unsigned char i,sel;
                while(1)
                {   sel=0xfe;
                    for(i=0;i<8;i++)
                    {   P1=sel;                 //显示变量赋给P1口
                        delay(50000);           //延时
                        sel=_crol_(sel,1);      //改变显示变量
                    }
                }
            }

也可以这样编程:

            #include<reg51.h>
            void delay(unsigned int d)
            {   while(--d>0);}
            void  main()
            {   unsigned char i,sel,a;
                while(1)
                {   sel=0xfe;
                    for(i=0;i<8;i++)
                    {   P1=sel;
                        delay(50000);
                        a=a<<1;
                        sel=sel|0x01;
                    }
            }
            }

【例1-6】 单片机的P1口接8个发光二极管,P0口接8个开关,编程实现当开关动作时,对应的发光二极管亮或灭。

只需把P0口的内容读出后,通过P1口输出即可。

汇编语言源程序如下:

                    ORG     0000H
                    MOV     P0,#0FFH
            LOOP:   MOV     A,P0
                    MOV     P1,A
                    SJMP    LOOP

C51语言源程序如下:

            #include<reg51.h>
            void  main(void)
            {   unsigned  char  i;
                P0=0xff;
                for(;;)
                {   i=P0;
                    P1=i;
                }
            }

【例1-7】 单片机外接12 MHz晶振,用P1.7输出1 kHz和500 Hz的音频信号驱动扬声器,作为报警信号,要求1 kHz信号与500 Hz信号交替进行,P1.0接一个开关S进行控制,当开关合上时,响报警信号,当开关断开时,报警信号停止,Proteus仿真电路如图1-3所示。

图1-3 例1-7的Proteus仿真电路图

C51源程序如下:

            #include<reg51.h>
            #include<intrins.h>             //空操作库函数包含于此头文件
            sbit S=P1^0;                    //定义位变量
            sbit BUZ=P1^7;                  //定义位变量
            unsigned char k;                //定义循环变量
            void delay(void)                //定义延时子函数
            {   unsigned char i;
                for(i=250;i>0;i--)
                {   _nop_();                //空操作
                }
            }
            void main(void)
            {   while(1)
                {   BUZ=0;                  //关闭声音
                    S=1;
                    if(S==0)                //判断开关是否闭合
                    {   BUZ=0;  delay();
                        BUZ=0;  delay();
                        BUZ=1;  delay();    delay();
                        BUZ=0;  delay();    delay();
                    }
                }
            }

注意:此例中的定时和音频信号频率不是很准确,如果实际使用中对周期或定时要求精确度较高,可以采用定时/计数器来实现。

【例1-8】 使用定时/计数器以工作方式2产生100 μs定时,在P1.0口输出周期为200 μs的连续方波,已知晶振频率为6 MHz。

机器周期频率:fcy = f /2/6 = 0.5 MHz,Tcy = 2 μs

定时器预置值(初值)N:28 - N = T/Tcy = T × fcy = 50

N = 206 = 0CEH

定时/计数器0工作于方式2,定时方式,其方式控制字:TMOD=02H。

在程序中,头文件reg51.h中定义了8051的I/O端口、特殊功能寄存器和特殊功能位等符号,这些符号可以像用户变量一样在程序中直接使用。主函数main( )完成定时/计数器0的初始化,CPU开中断,然后进入一无限循环,等待P1.0引脚上的方波输出。

方波输出由中断服务函数timer0( )产生。函数属性interrupt 1将timer0( )声明为定时/计数器0的中断服务函数,而函数属性using 3使中断发生时切换到寄存器组3,这样可以减少中断现场保护的时间,提高中断服务的实时性。

C51源程序清单如下:

            /***********200μs周期方波发生程序**************/
            #define T0_VALUE 0xCE
            #define TMOD_VALUE 0x02         /*定时/计数器0方式控制字*/
            #include<reg51.h>
            void main()
            {   TMOD=TMOD_VALUE;            /*T0按定时方式2*/
                TH0=T0_VALUE;               /*置定时器重装初值寄存器*/
                TL0=T0_VALUE;               /*装计数初值到定时器的8位加法计数器*/
                EA=1;                       /*CPU开中断*/
                ET0=1;                      /*T0允许中断*/
                TR0=1;                      /*启动T0*/
                while(1);                   /*等待P1.0引脚上输出方波信号*/
            }
            void timer0(void) interrupt 1 using 3
            {   P1=P1^0x01;                 /*将P1.0取反后输出*/
            }