您的位置:首页 > 其它

将一个用for循环实现的流水灯C程序模块化

2015-09-24 00:18 218 查看
1、原来所有的代码都被编写在一个.c文件中。创建keil project(89C52)并且仿真流水灯

一旦代码复杂,会很难修改。而且如果延时函数常用,也不方便移植。将延时函数模块化,可以使延时函数变得容易移植。

#include <reg52.h>
void delay_ms(unsigned int t);
unsigned char tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

void main(void)
{
unsigned char i;

while(1)
{
for(i=0;i<8;i++)
{
P2=tab[i];
delay_ms(5000);
}
}
}

void delay_ms(unsigned int t)
{
unsigned int x,y;
for(x=t;x>0;x--)
for(y=50;y>0;y--);
}


2、将延时子函数delay_ms模块化。创建delay.c 和 delay.h。delay.c 存放子函数,delay.h 存放函数声明。并且将delay.c 添加到项目工程中,以及指明delay.h的路径。

2.1 delay.h

#ifndef __DELAY_MS_H__
#define __DELAY_MS_H__

void delay_ms(unsigned int t);

#endif

2.2 delay.c

#include"delay.h"
void delay_ms(unsigned int t)
{
unsigned int x,y;
for(x=t;x>0;x--)
for(y=50;y>0;y--);
}

2.3 并且将delay.c 添加到项目工程中,以及指明delay.h的路径。

2.3.1将delay.c 添加到项目工程中





2.3.2指明delay.h的路径。依次点击图中1,2,3,4,5,6,选择delay.h所在的文件夹”delay”



2.4在test.c 中添加头文件#include”delay.h”。test.c 代码为:

#include <reg52.h>
#include "delay.h"
unsigned char tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

void main(void)
{
unsigned char i;

while(1)
{
for(i=0;i<8;i++)
{
P2=tab[i];
delay_ms(5000);
}
}
}


改善——将延时函数delay 更换成调用定时器的功能

延时函数delay_ms的延时的时间是不准确的。调用单片机的定时器可以使延时函数的延时效果准确。

定时器的C语言模块如下:

timer.h

#ifndef __TIMER_H__
#define __TIMER_H__

void timer_ms(void);

#endif

timer.c

#include"timer.h"
#include<reg52.h>

void timer_ms(void)
{
TMOD = 0x01;
TH0 = (65536-1000)/256;
TL0 = (65536-1000)%256;
TR0 = 1;
}

test.c就可以写成

#include <reg52.h>
#include "timer.h"
unsigned char tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned int a;

void main(void)
{
unsigned char i;

while(1)
{
for(i=0;i<8;i++)
{
P2=tab[i];
for(a=0;a<1000;a++)
timer_ms();
}
}
}


C51 单片机内部设置两个16位定时器/计数器T0和T1。它的本质是对脉冲计数。如果计数脉冲来自系统时钟(将C/T 置0),则为定时,每12个或者6个时钟得到一个计数脉冲。如果计数脉冲来自外部(将C/T 置1),则每个脉冲加一(每一个脉冲都是计数脉冲,不分频)。

如果使用定时器的功能,每来一个计数脉冲,TL0 会加1,一旦TL0加满,就会进位TH0。TH0进位,TF0/TF1就会为1,然后继续执行后面的程序,从而达到定时的效果。



定时器/计数器相关的寄存器:

TF1:定时器/计数器T1溢出标志。T1被允许计数后,从初值开始加1计数。当最高位产生溢出时,由硬件置“1” TF1,向CPU请求中断,一直保持到CPU响应中断时,才由硬件清0。TF0是T0 的溢出标志。TF0/TF1 也可以由程序清零。

TR1:定时器T1的运行控制位。如下图,当GATE = 0 , TR1 =1 时允许计数。而当GATE = 1 时,TR1 = 1 且 INT0 输入高电平的时候才可以计数。TR0 是T0的运行控制位。

GATE的作用如上述。

C/T =0 时,T1 用作定时器;C/T =1 时,T1 用作计数器;

M1 M0 定时器/计数器 模式选择

0 0 13 位定时器/计数器。低位(TL0/TL1)有5位,高位(TH0/TH1)有8位

0 1 16 位定时器/计数器。

1 0 8位自动重装载定时器,当溢出时将高位的值自动装入低位。

1 1 此定时器/计数器无效。

所以

TMOD = 0x01;


表示

GATE = 0 ,那么TR0/TR1 =1 时允许计数。

C/T = 0 , 工作为定时器。

M1 M0 为 0 1, 使用16 位定时器/计数器。TL0/TL1 8位,TH0/TH1 8位。

假设晶振型号的频率是12 MHz,使用12分频,则计数脉冲的频率为1 MHz,所以一个计数脉冲的时间间隔是1 微秒。所以要设置定时器定时1ms,只需要给TL0/TL1 或者 TH0/TH1 赋初值,使在计数1000次后溢出即可。所以将65536-1000截取高8位和低8位分别存储在 TH0 和 TL0 中。

TH0 = (65536-1000)/256;
TL0 = (65536-1000)%256;

最后,使TR0 = 1,开始计数。

调用一次timer_ms()延时1ms,那么调用1000次,延时1s,所以在for循环1000次。

for(a=0;a<1000;a++)
timer_ms();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: