历史上的今天
返回首页

历史上的今天

今天是:2024年08月25日(星期日)

正在发生

2021年08月25日 | 51单片机-单独文件封装

2021-08-25 来源:eefocus

1.再遇多文件编程

因为定时器经常在后面的教程中使用到,所以我们也把这部分功能代码单独使用文件封装起来。


在第六章的教程中已经教过大家多文件创建,这里点到为止。


创建好“timer.c”和“timer.h”

8.6.png?imageView2/2/w/550


添加进工程中

8.7.png?imageView2/2/w/550


2.timer.c的代码

#include  

#include //详见第六章第8讲

   

u8 T0RH,T0RL,T1RH,T1RL;

   

void TIM0_Init(u32 us,int trim)//trim:微调

{

    u32 tmp;  //临时变量

     

    tmp = 11059200 / 12;            //定时器计数频率

    tmp = ( tmp * (us/100) )/10000; //计算所需的计数值

    tmp = 65536 - tmp;              //计算定时器重载值

    tmp = tmp+trim;                 //微调计数值使其定时更精确到我们想要的定时时间

    T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节  

    T0RL = (unsigned char)tmp;

    TMOD &= 0xF0; //清0低四位 

    TMOD |= 0x01; //设置定时器0为工作模式1   

    TH0 = T0RH;   //加载T0重载值   

    TL0 = T0RL;

    ET0 = 1;      //闭合定时器0中断的开关        

    TR0 = 1;      //启动定时器0         

}  

  

void TIM1_Init(u32 us,int trim)//trim:微调

{

    u32 tmp;  //临时变量

     

    tmp = 11059200 / 12;            //定时器计数频率

    tmp = ( tmp * (us/100) )/10000; //计算所需的计数值

    tmp = 65536 - tmp;              //计算定时器重载值

    tmp = tmp+trim;                 //微调计数值使其定时更精确到我们想要的定时时间

    T1RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节    

    T1RL = (unsigned char)tmp;

    TMOD&=0x0F;//清0高四位

    TMOD|=0x10;//设置定时器1为工作模式1 

    TH1 = T1RH;//加载T1重载值     

    TL1 = T1RL;

    ET1 = 1;   //闭合定时器1中断的开关        

    TR1 = 1;   //启动定时器1         

}


“TMOD&=0xF0;”的作用跟数码管显示小数点的代码技巧一样,保持前面4位的值不变,清0后四位,然后“TMOD|=0x01;”就是不改变原来高四位的值,然后把低四位设成 0001。


如果在TIM0_Init()函数中只写“TMOD=0x01;”


在TIM1_Init()函数中只写“TMOD=0x10;”


然后初始化时像这样按顺序来写


TIM0_Init(20000,20);//定时20ms,20微调使定时精度更高


TIM1_Init(50000,20);//定时50ms,20微调使定时精度更高


那么执行TIM1_Init()的函数内容时就会执行“TMOD=0x10;”把人家低四位给清0了,原本想让定时器0工作在模式1,现在低2位的值变了也就不是工作在模式1了。


所以“TMOD&=0x0F; TMOD|=0x10;”的写法是不干涉互相的位。


我们定义了“T0RH,T0RL,T1RH,T1RL”四个8位的全局变量(R:reload)用来在中断函数里重新赋值。


因为工作模式1都是需要在中断函数中重新赋初值,所以这四个变量是存取初始化时给THx和TLx的初值。


3.timer.h的代码


#ifndef __TIMER_H__

#define __TIMER_H__

   

extern u8 T0RH,T0RL,T1RH,T1RL;

  

void TIM0_Init(u32 us,int trim);//trim:微调 

void TIM1_Init(u32 us,int trim);//trim:微调 

 

#endif


4.main.c的代码


这样,实现间隔50ms的流水灯在书写上就相当简洁了


#include  

#include //详见第六章第8讲

#include

 

void main()

{

    LED_Init();         //初始化LED硬件模块

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

    TIM0_Init(50000,20);//用定时器0定时50ms,20是微调使中断函数里的i均匀地50.00ms后自加,精度更高

    while(1);

}

 

void TIM0_IRQHandler() interrupt 1

{

    static u8 i; 

    TH0 = T0RH;  //重新加载重载值

    TL0 = T0RL;

 

    P0=~(0x01<    i++;

    if(i>=8)i=0; 

}


推荐阅读

史海拾趣

问答坊 | AI 解惑

用ARM运行FFT,速度怎样?

涉及产品造型问题。无庸置疑,做FFT,DSP是首选,但ARM也有其很诱人的优势,想请教一下用ARM做过FFT的朋友,其速度如何?请告知一下所用的芯片型号、振荡器频率、FFT点数及运行时间。谢谢各位。…

查看全部问答>

频率变化时电源板上的变压器会发出响声是什么原因?

大侠,为什么很多IP整合电源在开关频率发生变化时变压器会发出较大的声音???…

查看全部问答>

学习型电脑,平民化配置

CPU:E2200 主板:技嘉GA-G31M(板载X3100显卡,intel G31芯片组)(因为技嘉,华硕价格较贵,可以微星,昂达等G31芯片组的二组主板代替) 内存:金士顿2G,DDR2/800(或金邦,建议不要用威刚,威刚兼容性较差) 显卡:(如有需要可另配,但学习 ...…

查看全部问答>

BIOS与引导区探究群,群号67286087,欢迎加入啊!

联络一切对BIOS与引导区技术感兴趣的人士,注重理论与实践的结合,交流技术资料与实践心得,对重要贡献者给予现金等奖励!当 前以80X86为主要探究方向!…

查看全部问答>

请教wince中加载自己的开机界面问题

  我想在我的开机界面上加载一幅自己的图片,打开开发板电源系统启动显示我的开机界面是是我自己设计的图片,谢谢!…

查看全部问答>

关于开放式数控系统

要做一个开放式数控铣床这么一个系统,PC上位机 单片机是下位机,要实现数控系统的基本的插补功能...那现在是这么个思路,在PC上建立人机交互界面,如果输入数控代码,自动实现译码,刀补,差补..进而与单片机通信 去控制步进电机的运动.那译码,刀补,差补 ...…

查看全部问答>

STM32F107的通用定时器频率是多少?

                                 STM32F107中,用TIM3的PWM模式,预分频数为0,重装载值为3600,按道理说TIM3的最大频率为36MHz,那么PWM的频率应该 ...…

查看全部问答>

STM8L操作DS18B20失败,求范例

                                 郁闷啊,今天弄了一天DS18B20,先是18B20的初始化都不通过,发送了低电平之后释放,等待DS18B20的低电平应答都检测 ...…

查看全部问答>

LPC810 ISP无法下载了

前两天我发了个帖子,说明LPC810如何用SWD方式(J-LINK)下载 于是我写了下程序,就是点亮那个LED的程序 #include \"lpc8xx.h\" int main(){          LPC_SYSCON->SYSAHBCLKCTRL |= (1DIR0|=1…

查看全部问答>