将一个用for循环实现的流水灯C程序模块化
2015-09-24 00:18
218 查看
1、原来所有的代码都被编写在一个.c文件中。创建keil project(89C52)并且仿真流水灯
一旦代码复杂,会很难修改。而且如果延时函数常用,也不方便移植。将延时函数模块化,可以使延时函数变得容易移植。
2、将延时子函数delay_ms模块化。创建delay.c 和 delay.h。delay.c 存放子函数,delay.h 存放函数声明。并且将delay.c 添加到项目工程中,以及指明delay.h的路径。
2.1 delay.h
2.2 delay.c
2.3 并且将delay.c 添加到项目工程中,以及指明delay.h的路径。
2.3.1将delay.c 添加到项目工程中
![](http://img.blog.csdn.net/20150924065625206)
![](http://img.blog.csdn.net/20150924065659712)
2.3.2指明delay.h的路径。依次点击图中1,2,3,4,5,6,选择delay.h所在的文件夹”delay”
![](http://img.blog.csdn.net/20150924065752666)
2.4在test.c 中添加头文件#include”delay.h”。test.c 代码为:
改善——将延时函数delay 更换成调用定时器的功能
延时函数delay_ms的延时的时间是不准确的。调用单片机的定时器可以使延时函数的延时效果准确。
定时器的C语言模块如下:
timer.h
timer.c
test.c就可以写成
C51 单片机内部设置两个16位定时器/计数器T0和T1。它的本质是对脉冲计数。如果计数脉冲来自系统时钟(将C/T 置0),则为定时,每12个或者6个时钟得到一个计数脉冲。如果计数脉冲来自外部(将C/T 置1),则每个脉冲加一(每一个脉冲都是计数脉冲,不分频)。
如果使用定时器的功能,每来一个计数脉冲,TL0 会加1,一旦TL0加满,就会进位TH0。TH0进位,TF0/TF1就会为1,然后继续执行后面的程序,从而达到定时的效果。
![](http://img.blog.csdn.net/20150926010650095?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
定时器/计数器相关的寄存器:
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 此定时器/计数器无效。
所以
表示
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 中。
最后,使TR0 = 1,开始计数。
调用一次timer_ms()延时1ms,那么调用1000次,延时1s,所以在for循环1000次。
一旦代码复杂,会很难修改。而且如果延时函数常用,也不方便移植。将延时函数模块化,可以使延时函数变得容易移植。
#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();
相关文章推荐
- 设置TestCpp使用BOX2d
- git - add commit diff
- 越狱机器SSH安装与使用
- onLowMemory()与onTrimMemory()
- CF577B Modulo Sum 好题
- 华为配置设备作为STelnet客户端连接SSH服务器的实验
- 终于搭建成功Xamarin for Android平台
- window自动任务实现数据库定时备份
- 析构函数使用不当造成操作野指针程序coredump
- Xcode插件
- LAMP搭建
- 最小生成树之Prime算法(基于优先队列)
- email 发送机制
- [LeetCode]Palindrome Linked List
- 极光推送基本写法
- 浅谈——用宏封装单例
- 编写struts.xml文件时提示帮助信息
- Linux补丁学习笔记
- java.sql.SQLException的常见原因
- Codeforces Round #321 (Div. 2) E Kefa and Watch (线段树维护Hash)