单片机定时器程序
- 格式:doc
- 大小:34.50 KB
- 文档页数:2
单片机定时器程序编写单片机的定时器要用到中断机制,所以在编写程序时要先开启中断,设置中断优先级和中断服务函数,然后再配置定时器。
以下是编写单片机定时器程序的步骤:1.开启中断:要想使用定时器,必须开启单片机的中断功能,可使用如下命令开启:` __enable_irq(;`。
该函数将开启全局中断。
2.设置中断优先级:中断优先级用于解决多个中断同时发生时的执行顺序问题。
一般来说,定时器中断的优先级比较低,因为可能同时有其他更重要的中断需要执行。
`NVIC_SetPriority(TIMER某_IRQn, 2);`。
上面命令将设置定时器的中断优先级为2。
3.定义中断服务函数:中断服务函数是中断发生时自动执行的一段程序。
每种中断都需要一个相应的中断服务函数。
```。
void TIMER某_IRQHandler(void)。
//中断处理程序。
}。
```。
上面代码定义了一个定时器中断服务函数。
4.配置定时器:配置定时器的过程包括选择时钟源、设定计数值、选择计数方向等。
这里我们选择外部时钟源和计数器模式。
```。
//打开定时器时钟。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM某, ENABLE);。
//定时器参数设置。
TIM_TimeBaseInitTypeDef TIM_InitStruct;。
TIM_InitStruct.TIM_Prescaler = 16; // 预分频值。
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式。
TIM_InitStruct.TIM_Period = 999; // 溢出值。
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;。
TIM_TimeBaseInit(TIM某, &TIM_InitStruct); // 设置定时器参数。
51单片机的定时器_计数器的C51编程相关知识点:1、单片机的定时器/计数器,实质是按一定时间间隔、自动在系统后台进行计数的。
2、当被设定工作在定时器方式时,自动计数的间隔是机器周期(12个晶振振荡周期),即计数频率是晶振振荡频率的1/12;3、当定时器被启动时,系统自动在后台,从初始值开始进行计数,计数到某个终点值时(方式1时是65535),产生溢出中断,自动去运行定时中断服务程序;注意,整个计数、溢出后去执行中断服务程序,都是单片机系统在后台自动完成的,不需要人工干预!4、定时器的定时时间,应该是(终点值-初始值)x机器周期。
对于工作在方式1和12MHz时钟的单片机,最大的计时时间是(65535-0)x1uS=65.535ms。
这个时间也是一般的51单片机定时器能够定时的最大定时时间,如果需要更长的定时时间,则一般可累加多定时几次得到,比如需要1秒的定时时间,则可让系统定时50ms,循环20次定时就可以得到1s的定时时间。
5、定时器定时得到的时间,由于是系统后台自动进行计数得到的,不受主程序中运行其他程序的影响,所以相当精确;6、使用定时器,必须先用TMOD寄存器设定T0/T1的工作方式,一般设定在方式1的情况比较多,所以可以这样设定:TMOD=0x01(仅设T0为方式1,即16位)、TMOD=0x10(仅设T1为方式1,即16位)、TMOD=0x11(设T0和T1为方式1,即都为16位)。
7、使用定时器,必须根据需要的定时时间,装载相应的初始值,而且在中断服务程序中,很多情况下得重新装载初始值,否则系统会从零开始计数而引起定时失败;8、要使用定时器前,还必须打开总中断和相应的定时中断,并启动之:EA=1(开总中断)、ET0=1(开定时器0中断)、TR0=1(启动定时器0)、ET1=1(开定时器1中断)、TR1=1(启动定时器1);9、注意中断服务程序尽可能短小精干,不要让它完成太多任务,尤其尽量避免出现长延时,以提高系统对其他事件的响应灵敏度.//定时器基本例程-1(未使用定时器,一个灯每隔500ms亮灭一次)//这是个特意安排的例程,以便与下面的例程2进行对比#include <reg52.h>sbit led=P2^7;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led=1; //上电初始化,led灯不亮while(1){led=!led;delay_ms(500);}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------//定时器基本例程-2(使用定时器,一个灯每隔500ms亮灭一次)#include <reg52.h>sbit led=P2^7;unsigned char num;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led=1; //上电初始化,led灯不亮TMOD=0x01; //设定定时器0为工作方式1TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL0=(65536-50000)%256; //EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0while(1){delay_ms(8000);}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------void led_flash() interrupt 1 //使用了定时中断0的led闪烁子函数{ TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000 TL0=(65536-50000)%256; //num++;if(num==10){num=0;led=!led;}}////定时器基本例程-3//(使用定时器T1,单片机整个口接的8个灯每隔500ms亮灭一次)#include <reg52.h>#define led_port P0 //宏定义,具体的端口尽量不要出现在主函数和主函数中unsigned char num;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led_port=0xff; //上电初始化,所有led灯不亮TMOD=0x10; //设定定时器1为工作方式1(16位方式)TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //EA=1; //开总中断ET1=1; //开定时器1中断TR1=1; //启动定时器1while(1){delay_ms(8000); //这句表明定时中断的运行是在系统后台自动运行的,不需要主函数“操心”}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------void led_flash() interrupt 3 //使用了定时中断1的8灯闪烁子函数{ TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //num++; //计数if(num==10) //计够10次,时间就是10x50ms=500ms{num=0; //清零,以便进行下一次500ms的10次计数led_port=~led_port; //整个口接的led灯亮灭状态翻转}}//-------------------------------------------------//定时器基本例程-4//(同时使用定时器T0和定时器T1,单片机某个口的灯和某个口接的8个灯每隔500ms亮灭一次)#include <reg52.h>sbit led=P2^7;#define led_port P0 //宏定义,具体的端口尽量不要出现在主函数和主函数中unsigned char num_0,num_1;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led=1; //上电初始化,led灯不亮led_port=0xff; //上电初始化,该口所有led灯不亮TMOD=0x11; //设定定时器0和定时器1都为工作方式1(16位方式)TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL0=(65536-50000)%256; //TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0ET1=1; //开定时器1中断TR1=1; //启动定时器1while(1){delay_ms(8000); //这句表明定时中断的运行是在系统后台自动运行的,不需要主函数“操心”}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------void led_flash() interrupt 1 //使用了定时中断0的led闪烁子函数{ TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL0=(65536-50000)%256; //num_0++; //计数if(num_0==10) //计够10次,时间就是10x50ms=500ms{num_0=0; //清零,以便进行下一次500ms的10次计数led=!led; //led灯亮灭状态翻转}}//-------------------------------------------------void led_all_flash() interrupt 3 //使用了定时中断1的8灯闪烁子函数{ TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //num_1++; //计数if(num_1==10) //计够10次,时间就是10x50ms=500ms{num_1=0; //清零,以便进行下一次500ms的10次计数led_port=~led_port; //整个口接的led灯亮灭状态翻转}}//-------------------------------------------------//定时器基本例程-5//设定定时器T0工作在方式1的计数应用状态,//单片机T0口(P3.4)接一个按键充当外部脉冲源,//系统对进来的脉冲(每按一次键得一脉冲)进行计数,//计数的结果用接在单片机P0口的8个LED灯表示出来//(大家也可以改成用1602LCD来显示,这样更直观)//广西民大物电学院李映超2010年4月14日#include <reg52.h>#define led_port P0 //宏定义,具体的端口尽量不要出现在主函数和主函数中//=================================================void main(){TMOD=0x05; //设定定时器0为工作方式1、计数器TH0=0; //清零TL0=250; //TR0=1; //启动定时器0进行计数while(1){led_port=TL0; //将计数结果送去显示(用8个LED灯显示),//这里仅显示16位计数器的低8位}}定时器0仍旧工作在计数器状态,增加定时器1工作在定时状态,得到1s的定时时间,定时时间到后,将定时器0计数得到的脉冲数去显示,则这个脉冲数就是所输入的外部信号的频率,从而构成一个简单而准确的频率计!!不过,这个简单的“频率计”能够计量的信号频率(脉冲数),受单片机中断响应速度的影响,一般只能达到单片机系统时钟晶振的1/24,所以要能够测量更高的频率,必须使用前置分频器,对更高频率的待测输入信号进行预分频!。
51单片机定时器工作方式
51单片机的定时器有两种工作方式:。
1.定时计数器模式。
单片机定时器通过定时计数器模式实现定时功能,定时器会计数,当
计数到预设值时,定时器就会触发中断或者标志位,从而实现定时功能。
单片机的定时器可以通过外部晶振或者内部时钟源提供时钟信号进行计数,计数值可以根据不同的定时需求进行设置,比如毫秒级,微秒级等精度的
定时。
2.脉冲捕获模式。
单片机定时器通过脉冲捕获模式实现测量外部事件的时间,脉冲捕获
模式可以捕获外部脉冲的高低电平信号,并将捕获到的数值存入定时器计
数器中,从而实现对脉冲的测量功能。
脉冲捕获模式主要应用于测量高速
事件的脉冲信号,比如汽车发动机的转速测量,超声波传感器的距离测量等。
名称:定时器0#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义sbit LED=P1^2; //定义LED端口/*-----------------------定时器初始化子程序------------*/void Init_Timer0(void){TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响TH0=0x00; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出TL0=0x00;EA=1; //总中断打开ET0=1; //定时器中断打开TR0=1; //定时器开关打开}/*--------主程序-----------*/main(){Init_Timer0();while(1);}/*--------- 定时器中断子程序--------*/void Timer0_isr(void) interrupt 1 using 1{TH0=0x00; //重新赋值TL0=0x00;LED=~LED; //指示灯反相,可以看到闪烁}/*---------- 名称:定时器1----*/#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义sbit LED=P1^2; //定义LED端口/*---定时器初始化子程序----*/void TIM2Inital(void){RCAP2H = (65536-60000)/256;//晶振12M 10ms 16bit 自动重载RCAP2L = (65536-60000)%256;ET2=1; //打开定时器中断EA=1; //打开总中断TR2=1; //打开定时器开关}/*-----主程序---*/main(){TIM2Inital();while(1);}/*--------定时器中断子程序-----*/void TIM2(void) interrupt 5 using 1//定时器2中断{TF2=0;LED=~LED; //指示灯反相}名称:外部中断0电平触发#include<reg52.h>/*------主程序-*/main(){P1=0x55; //P1口初始值EA=1; //全局中断开EX0=1; //外部中断0开IT0=0; //电平触发while(1){//在此添加其他程序}}/*---------外部中断程序--------*/void ISR_Key(void) interrupt 0 using 1{P1=~P1;}名称:外部中断1#include<reg52.h>main(){P1=0x55; //P1口初始值EA=1; //全局中断开EX1=1; //外部中断0开IT1=1; //边沿触发,IT1=0表示电平触发while(1){//在此添加其他程序}}/*-------外部中断程序-*/void ISR_Key(void) interrupt 2 using 1{//在此处可以添加去抖动程序,防止按键抖动造成错误P1=~P1;}名称:遥控器红外解码LCD1602液晶显示#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的#include<stdio.h>#include<intrins.h>#define TURE 1#define FALSE 0sbit IR=P3^2; //红外接口标志sbit RS = P2^4;//Pin4sbit RW = P2^5;//Pin5sbit E = P2^6;//Pin6#define Data P0//数据端口unsigned int hour,minute,second,count;char code Tab[16]="0123456789ABCDEF";char data TimeNum[]=" ";char data Test1[]=" ";/* 变量声明*/unsigned char irtime;//红外用全局变量bit irpro_ok,irok;unsigned char IRcord[4]; //处理后的红外码,分别是客户码,客户码,数据码,数据码反码unsigned char irdata[33]; //33个高低电平的时间数据/* 函数声明*/void Ir_work(void);void Ircordpro(void);void ShowString (unsigned char line,char *ptr);/* 定时器0中断服务函数*/void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数{irtime++; //用于计数2个下降沿之间的时间}/* 外部中断0函数*/void ex0_isr (void) interrupt 0 using 0//外部中断0服务函数{static unsigned char i; //接收红外信号处理static bit startflag; //是否开始处理标志位if(startflag){if(irtime<63&&irtime>=33)//引导码TC9012的头码,9ms+4.5msi=0;irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1irtime=0;i++;if(i==33){irok=1;i=0;}}else{irtime=0;startflag=1;}}/* 定时器0初始化*/void TIM0init(void)//定时器0初始化{TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值TH0=0x00; //重载值TL0=0x00; //初始化值ET0=1; //开中断TR0=1;}/* 外部中断初始化*/void EX0init(void){IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)EX0 = 1; //使能外部中断EA = 1; //开总中断}/* 红外键值处理*/void Ir_work(void) //红外键值散转程序{TimeNum[5] = Tab[IRcord[0]/16]; //处理客户码并显示TimeNum[6] = Tab[IRcord[0]%16];TimeNum[8] = Tab[IRcord[1]/16]; //处理客户码并显示TimeNum[9] = Tab[IRcord[1]%16];TimeNum[11] = Tab[IRcord[2]/16]; //处理数据码并显示TimeNum[12] = Tab[IRcord[2]%16];TimeNum[14] = Tab[IRcord[3]/16]; //处理数据反码并显示TimeNum[15] = Tab[IRcord[3]%16];ShowString(1,TimeNum);//显示处理过后的码值irpro_ok=0; //处理完成后清楚标志位}/* 红外解码函数处理*/void Ircordpro(void)//红外码值处理函数{unsigned char i, j, k;unsigned char cord,value;k=1;for(i=0;i<4;i++) //处理4个字节{for(j=1;j<=8;j++) //处理1个字节8位{cord=irdata[k];if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差{value=value|0x80;}else{value=value;}if(j<8){value=value>>1;}k++;}IRcord[i]=value;value=0;} irpro_ok=1;//处理完毕标志位置1}/* 微秒延时函数*/void DelayUs(unsigned char us)//delay us{unsigned char uscnt;uscnt=us>>1;/* Crystal frequency in 12MHz*/while(--uscnt);}/* 毫秒函数声明*/void DelayMs(unsigned char ms)//delay Ms{while(--ms){DelayUs(250);DelayUs(250);DelayUs(250);DelayUs(250);}}/* 写入命令函数*/void WriteCommand(unsigned char c){DelayMs(5);//操作前短暂延时,保证信号稳定E=0;RS=0;RW=0;_nop_();E=1;Data=c;E=0;}/*写入数据函数*/void WriteData(unsigned char c){DelayMs(5); //操作前短暂延时,保证信号稳定E=0;RS=1;RW=0;_nop_();E=1;Data=c;E=0;RS=0;}/*写入字节函数*/void ShowChar(unsigned char pos,unsigned char c) {unsigned char p;if (pos>=0x10)p=pos+0xb0; //是第二行则命令代码高4位为0xc elsep=pos+0x80; //是第二行则命令代码高4位为0x8 WriteCommand (p);//写命令WriteData (c); //写数据}/*写入字符串函数*/void ShowString (unsigned char line,char *ptr){unsigned char l,i;l=line<<4;for (i=0;i<16;i++)ShowChar (l++,*(ptr+i));//循环显示16个字符}/* 初始化函数*/void InitLcd(){DelayMs(15);WriteCommand(0x38); //display modeWriteCommand(0x38); //display modeWriteCommand(0x38); //display modeWriteCommand(0x06); //显示光标移动位置WriteCommand(0x0c); //显示开及光标设置WriteCommand(0x01); //显示清屏}/*主函数*/void main(void){EX0init(); //初始化外部中断TIM0init();//初始化定时器InitLcd(); //初始化液晶DelayMs(15);sprintf(Test1," "); //显示第一行固定信息ShowString(0,Test1);sprintf(TimeNum,"Code ");//显示第二行固定信息ShowString(1,TimeNum);while(1)//主循环{if(irok) //如果接收好了进行红外处理{Ircordpro();irok=0;}if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键显示对应的数字等{Ir_work();}}}/*-----------------------------------------------名称:遥控器红外解码数码管显示#include<reg52.h>#include<stdio.h>#include<intrins.h>#define TURE 1#define FALSE 0sbit IR=P3^2; //红外接口标志unsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};/*变量声明*/unsigned char irtime;//红外用全局变量bit irpro_ok,irok;unsigned char IRcord[4];unsigned char irdata[33];/* 函数声明*/void Delay(unsigned char mS);void Ir_work(void);void Ircordpro(void);/*定时器0中断服务函数*/void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数{irtime++; //用于计数2个下降沿之间的时间}/*外部中断0函数*/void ex0_isr (void) interrupt 0 using 0//外部中断0服务函数{static unsigned char i; //接收红外信号处理static bit startflag; //是否开始处理标志位if(startflag){if(irtime<63&&irtime>=33)//引导码TC9012的头码,9ms+4.5msi=0;irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1irtime=0;i++;if(i==33){irok=1;i=0;}}else{irtime=0;startflag=1;}}/* 定时器0初始化*/void TIM0init(void)//定时器0初始化{TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值TH0=0x00; //重载值TL0=0x00; //初始化值ET0=1; //开中断TR0=1;}/*外部中断初始化*/void EX0init(void){IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)EX0 = 1; //使能外部中断EA = 1; //开总中断}/*红外键值处理*/void Ir_work(void)//红外键值散转程序{switch(IRcord[2])//判断第三个数码值{case 0:P0=dofly[1];break;//1 显示相应的按键值case 1:P0=dofly[2];break;//2case 2:P0=dofly[3];break;//3case 3:P0=dofly[4];break;//4case 4:P0=dofly[5];break;//5case 5:P0=dofly[6];break;//6case 6:P0=dofly[7];break;//7case 7:P0=dofly[8];break;//8case 8:P0=dofly[9];break;//9}irpro_ok=0;//处理完成标志}/* 红外解码函数处理*/void Ircordpro(void)//红外码值处理函数{unsigned char i, j, k;unsigned char cord,value;k=1;for(i=0;i<4;i++) //处理4个字节{for(j=1;j<=8;j++) //处理1个字节8位{cord=irdata[k];if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差{value=value|0x80;}else{value=value;}if(j<8){value=value>>1;}k++;}IRcord[i]=value;value=0;} irpro_ok=1;//处理完毕标志位置1}void main(void){EX0init(); //初始化外部中断TIM0init();//初始化定时器P2=0x00;//1位数码管全部显示while(1)//主循环{if(irok) //如果接收好了进行红外处理{Ircordpro();irok=0;}if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等{Ir_work();}}}名称:与电脑串口通信内容:连接好串口或者usb转串口至电脑,下载该程序,打开电源打开串口调试程序,将波特率设置为9600,无奇偶校验晶振11.0592MHz,发送和接收使用的格式相同,如都使用字符型格式,在发送框输入hello,I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确#include<reg52.h> /void main (void){SCON = 0x50; /* SCON: 模式1, 8-bit UART, 使能接收*/ TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */TH1 = 0xFD; /* TH1: reload value for 9600 baud @ 11.0592MHz */ TR1 = 1; /* TR1: timer 1 run */ EA = 1; /*打开总中断*/ES = 1; /*打开串口中断*/while (1) /*主循环不做任何动作*/{}}*/串口中断程序*/void UART_SER (void) interrupt 4 //串行中断服务程序{unsigned char Temp; //定义临时变量if(RI) //判断是接收中断产生{RI=0; //标志位清零Temp=SBUF; //读入缓冲区的值P1=Temp; //把值输出到P1口,用于观察SBUF=Temp; //把接收到的值再发回电脑端}if(TI) //如果是发送标志位,清零TI=0;}/*-----------------------------------------------名称:红外收发内容:*红外测试程序,用单片机通过发射管发射38K的调制频率码,由一体化接收并解码由发光管显示。
单片机定时器近年来,随着科技的发展,单片机作为一种重要的电子元器件,在各个领域得到了广泛的应用。
其中,定时器作为单片机的重要功能之一,在各种电子设备中发挥着重要的作用。
本文将对单片机定时器进行介绍和探讨。
一、什么是定时器定时器是单片机中常见的一个重要功能模块,用于产生或计数精确的时间间隔。
通过定时器,我们可以实现各种实时控制和时间测量功能。
在单片机的内部结构中,定时器通常由一个或多个计数器、比较器和控制逻辑电路组成。
二、单片机定时器的工作原理单片机定时器的工作原理主要可以分为计数模式和比较模式两种。
1. 计数模式在计数模式下,定时器会根据系统时钟的信号来进行计数操作。
当计数器达到设定的值后,会产生一个中断信号,从而触发系统执行相应的操作。
计数模式可以通过设置定时器的计数值和时钟频率来实现不同的时间间隔。
2. 比较模式在比较模式下,定时器会将计数器的值与设定的比较器进行比较。
当计数器的值等于比较器的值时,会产生一个中断信号。
比较模式常用于周期性的定时任务,如PWM信号的生成等。
三、单片机定时器的应用领域单片机定时器广泛应用于各个领域,如工业控制、通信设备、汽车电子、家电等。
以下是定时器在几个常见应用领域的具体应用。
1. 工业控制在工业控制领域,单片机定时器常用于实现定时开关、定时测量以及触发控制等功能。
通过设置不同的定时器参数,可以实现对生产过程的精确控制。
2. 通信设备在通信设备中,单片机定时器被广泛应用于协议的处理和时序控制。
通过定时器的精确计时功能,可以实现数据传输的同步和时序的控制。
3. 汽车电子在汽车电子领域,单片机定时器主要用于发动机的点火控制和喷油控制。
通过定时器的精确计时功能,可以实现对发动机点火和喷油的精确控制,提高汽车的燃油利用率和性能。
4. 家电在家电领域,单片机定时器主要用于电器的定时开关和节能控制。
通过设置定时器的参数,可以实现电器的定时开关,从而提高家电的智能化程度和能源利用效率。
PIC 单片机定时器代码#include <pic.h>/*#define PORTAIT(add,bit)((unsigned)(&add)*8+(bit))static bit PORTA_0 @PORTAIT(PORTA,0);//PIC16F84Astatic bit PORTA_1 @PORTAIT(PORTA,1);static bit PORTA_2 @PORTAIT(PORTA,2);static bit PORTA_3 @PORTAIT(PORTA,3);static bit PORTA_4 @PORTAIT(PORTA,4);*/unsigned int ttr=0;// 无符号整型变量ttr ,并赋值0unsigned char x=0,y=0,sign_a=0;// 无符号字符型变量void key_server(); // 键值服务函数void display(unsigned int x);// 带形参的显示函数void display_set(unsigned int x);// 键值显示函数void delay_1m(); // 按键延时函数-1mvoid delay(unsigned long int k ) // 延时函数{unsigned long int i; // 无符号字符型变量ifor(i=0;i<=k;i++) // rov 语句continue; // 继续循环}void display(unsigned int x)// 带形参X 的显示函数(开始){unsigned int d=49,unit_bit,ten_bit,hund_bit,thou_bit;// 无符号整型变量 d 和位(个、十、百、千) unsigned char SEG7[10]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 并初始化unit_bit=x%10; // picc 编译器可识别的个位ten_bit=x/10%10; // picc 可识别的十位hund_bit=x/100%10; // picc 可识别的百位thou_bit=x/1000%10; // picc 可识别的千位while(d>0) // while 语句{PORTA=0x1f; //关显示PORTB=SEG7[unit_bit]; // 个位段码送 B 口RA3=0; // 显示个位delay(200); // 延时RA3=1; // 关个位显示delay(2); // 延时PORTB=SEG7[ten_bit]; //十位段码送 B 口RA2=0; // 显示十位delay(200); // 延时RA2=1; // 关十位显示delay(2); // 延时PORTB=SEG7[hund_bit]; //百位段码送 B 口RA1=0; // 显示百位delay(200); // 延时RA1=1; // 关百位显示delay(2); // 延时PORTB=SEG7[thou_bit]; // 千位段码送 B 口RA0=0; // 显示千位delay(200); /// 延时RA0=1; // 关百位显示delay(2); // 延时d--; // d 从2900 开始自减量if( RA4==0) // K1 按下?{ // 未按下退出执行上程序while(1){if( RA4==1) //按下,执行以下程序{sign_a=1; d=0;break; // 跳出循环} } } } } void main( ) // 主程序{TRISB=0x00; // A 口初始化TRISA=0x10;PORTB=0x40; INTCON=0x00;//PORTA=0x10;ttr=0; // 给ttr 赋值0while(1) // while 循环语句开始{while(x<24) // 限制时钟最大为24(时) {y=0; //给y赋值0while(y<60) // 限制时钟最大60(分){ttr=x*100+y; // 算术运算符表达式display(ttr); // 调显示函数key_server(); // 调键值服务程序y++; //分(y)自增量ttr=0; // 给ttv 赋值0}x++; //时(X)自增量}x=0; //给X 赋值0y=0; // 给Y 赋值0}}void key_server()// 键值服务程序{unsigned char k=0; // 记录按键次数变量unsigned int value=0; // 存储显示值变量while(sign_a==1){display_set(value); // 调键值显示函数if((RA4==0)&&(k==0)) //第一次按下K1 {while(1) // 设定时钟的分值{y++; // K1 未放开,分从0~59 累加if(y>59)y=0; // 分值大于59,Y 清0 value=x*100+y;//将X (时)和Y (分)按显示格式display_set(value); // 整合计算,再显示delay_1m(); // 按键延时,以便观察if(RA4==1) // 如果K1 放开{ // 进入小时设定,K=1k=1; // 小时设定开始break; // 跳出分钟设定循环}}}if((RA4==0)&&(k==1))// 第二次按下K1{ // K=1 ,进入小时设定循环x++;// 24 小时制,K1 未放开,X 一直累加到23 if(x>23) // X>23 ,X 清0x=0;value=x*100+y;// 整合计算设定值display_set(value); // 调键值显示delay_1m(); // 延时display_set(value); // 调键值显示while(1) // 重复{x++;if(x>23)x=0;value=x*100+y;display_set(value);delay_1m();display_set(value);if(RA4==1) // 如果K1 放开{sign_a=0; // 清0 设定时间标志位y=y-1;break; // 跳出设定循环返回}}}}}void display_set(unsigned int x)// 键值显示程序{thou_bit;unsigned char SEG7[10]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 这里的注释与显示displa 的函数相似unit_bit=x%10;ten_bit=x/10%10;hund_bit=x/100%10;thou_bit=x/1000%10;while(d>0){PORTA=0x1F; //63;PORTB=SEG7[unit_bit];RA3=0;delay(200);RA3=1;delay(2);PORTB=SEG7[ten_bit];RA2=0;delay(200);RA2=1;delay(2);PORTB=SEG7[hund_bit];RA1=0;delay(200);RA1=1;delay(2);PORTB=SEG7[thou_bit];RA0=0;delay(200);RA0=1;delay(2);d--;}}void delay_1m()//按键K1,延时函数开始{unsigned long int k; // 说明语句for(k=0;k<4;k++) // for 语句{display_set(x*100+y); // 调键值显示函数。
单片机定时器定时原理
单片机的定时器定时原理是通过内部的时钟源产生一定的时钟脉冲,然后根据预设的定时时间来计数,在达到预设的计数值时触发相应的中断或执行相应的操作。
具体的实现过程如下:
1. 设置定时器的工作模式:通常有定时器模式和计数器模式可供选择。
2. 配置定时器的计数值:根据所需的定时时间,设置定时器的计数值。
计数值决定了定时器中断或操作触发的时间点。
3. 配置定时器的时钟源:选择适合的时钟源供给定时器,一般可以选择外部晶振或内部时钟源。
4. 启动定时器:通过设置相关寄存器,启动定时器开始计数。
5. 定时器中断/操作触发:当定时器的计数值达到预设的值时,会产生中断或执行相应的操作,例如改变引脚状态、修改寄存器值等。
6. 清除中断标志位:处理完定时器中断或操作之后,需要手动清除中断标志位,以便下一次定时器能够正常工作。
通过以上步骤,单片机的定时器可以实现一定精度的定时功能。
根据不同的应用需求,可以选择合适的定时模式和计数值,以实现各种各样的定时操作。
51单片机内部定时器和中断系统以及编写第一个简单的定时器实验程序上讲通过讲述用单片机控制一个外部的LED闪烁实验来向读者介绍了单片机的工作原理与开发流程。
这一讲将介绍单片机内部非常重要的两个资源——定时/ 计数器和中断系统。
通过该讲,读者可以掌握定时器的工作原理和单片机的中断系统。
从而设计定时器计数程序和中断服务程序。
一、原理简介首先让我们举闹钟为例,将它定时在一分钟后闹铃,这就需要秒针走一圈(60 次)。
即一分钟时间转化为秒针走的次数,也就是计数的次数,计数到了60 次然后闹铃,而每一次计数的时间是1 秒。
单片机内部的定时/ 计数器跟闹钟类似,可以通过编程来设定要定时的时间、定时时间到了进行相应的操作。
那么在单片机内部计数一次的时间是多少呢,51 单片机输入的时钟脉冲是由晶体振荡器的输出经12 分频后得到的,所以定时器也可看作是对计算机机器周期的计数器。
因为每个机器周期包含12 个振荡周期,故每一个机器周期定时器加1,可以把输入的时钟脉冲看成机器周期信号。
故其频率为晶振频率的1/12。
如果晶振频率为12MHz,则定时器每接收一个输入脉冲的时间刚好为1μs。
在本实验套件中采用的是11.0592M 的晶振,故每接收一个输入脉冲的时间约为1.085μs。
实现精确定时在实际项目应用中非常重要,因为往往需要用到精确定时一段时间,然后定时时间到的时刻做相应的任务。
那如何编程实现定时时间呢?首先先简单介绍下本实验板上单片机(STC89C52)内的定时器资源。
STC89C52 内有三个定时/ 计数器,分别为T0、T1 和T2。
其中T0、T1 工作方式一样,一并介绍。
T2 的工作方式稍有区别,这里不做介绍,实验套件光盘中有实际应用程序。
同时,单片机中的定时器和计数器是复用的,计数器是记录外部脉冲的个数,而定时器则是由单片机内部时钟提供的一个非常稳定的计数源。
本讲中,以T0、T1 作为定时器来进行实例介绍使用。
51单⽚机定时器(⼆)书接上回,下⾯是定时器的其他⼯作⽅式。
⼀、⼯作⽅式1:(还是拿t0做说明)定时/ 计数器的⼯作⽅式1⾃⼰经验是⽤的⽐较多的,它的结构图如下:TH0的⼋位和TL0的⼋位构成⼀个16位定时/计数器,可以定时时间最长在⼯作⽅式1下,计数器的计数值范围是:1—65536(216)当为定时⼯作⽅式1时,定时时间的计算公式为:(216—计数初值)╳晶振周期╳12或(216—计数初值)╳机器周期其时间单位与晶振周期或机器周期相同。
如果单⽚机的晶振选为6.000MHz,则最⼩定时时间为:[213—(216—1)]╳1/6╳10-6╳12=2╳10-6(s)=2(us)(216—0)╳1/6╳10-6╳12=131072╳10-6(s)=131072(us)。
⼯作⽅式1的使⽤,和⽅式0完全⼀样,不必赘⾔。
⼆、⼯作⽅式2⼯作⽅式2的结构图如下:从图中可以看出来,计数寄存器变成了⼀个——TL0,⼯作⽅式2下多了⼀个重装载寄存器,也就是原来的TH0。
在⼯作⽅式2下,如果TL0中的数据溢出,那么原先存储在TH0中的数据就会⾃动的装载到TL0中去,这是由单⽚机的硬件实现的,这样我们就不⽤在⼿动给定时器赋初值,⽽且硬件重装载不会耽误时间,所以⼯作⽅式2的计时是最准确的。
但是就是这样⼀来的计数结构只有8位,计数值有限,最⼤只能到255。
所以这种⼯作⽅式很适合于那些重复计数的应⽤场合。
例如我们可以通过这样的计数⽅式产⽣中断,从⽽产⽣⼀个固定频率的脉冲。
也可以当作串⾏数据通信的波特率发送器使⽤。
⼯作⽅式2下的其他使⽤和⼯作⽅式0,1相同。
三、⼯作⽅式3之前的3种⼯作⽅式中,定时器t0和t1的⼯作⽅式完全相同,⽽在⼯作⽅式3中终于有了个性的发挥不在相同了。
下⾯是⼯作⽅式3情况下t0的结构图。
可以看出,t0被分成了2个定时器,每个⼋位,定时/计数器0的TL0拆成的定时器和之前⽅式0,1⼀样,不过TH0拆成的就“因霸”了,它把原先定时器1的溢出标志位给占⽤了,⽽且还不受GATE门控的控制,这样以来,如果定时器0的TH0构成的8位定时器在使⽤,定定时器1就憋屈了,没有溢出位使⽤。
单片机汇编中断程序(定时器中断)
;首相,介绍一下51 单片机的定时计数器,51 有两个定时计数器,分别为
T0,T1,基本一样,
;有一点不同,下面我们介绍定时计数器T0
;了解8051 的timer0 中断的程序写法,用中断法产生定时
;上面显示的是proteus 仿真图,下面的是源程序
;说明:(源程序中的终端入口地址很重要(这个是固定的),程序中断时,
会在对应中断固定的
;入口地址进入,因为规定的相隔入口间的空进有限,只能用跳转指令跳转,最终用RETI 强制返回
;这个程序把所有的中断入口地址都写上了,没有用到的,用RETI 直接屏蔽)
;运行结果是使led 灯明一下,暗一下。
COUNT EQU9217;对于11.0592 的晶振来说,延时10ms
LEDEQUP1.1
ORG0000H
LJMP RESET;开始时跳转转到初始化程序中
ORG0003H;外部中断0
RETI
ORG000BH;定时器/计数器T0 入口地址
LJMP INT_TIMER0;跳转到定时器/计数器中断服务程序中去
ORG0013H;外部中断1。
C语言单片机定时器计数器程序1. 简介C语言是一种被广泛应用于单片机编程的高级编程语言,它可以方便地操作单片机的各种硬件模块,包括定时器和计数器。
定时器和计数器是单片机中常用的功能模块,它们可以用来实现精确的时间控制和计数功能。
本文将介绍如何使用C语言编程实现单片机的定时器计数器程序。
2. 程序原理在单片机中,定时器和计数器通常是以寄存器的形式存在的。
通过对这些寄存器的操作,可以实现定时器的启动、停止、重载以及计数器的增加、减少等功能。
在C语言中,可以通过对这些寄存器的直接操作来实现对定时器和计数器的控制。
具体而言,可以使用C语言中的位操作和移位操作来对寄存器的各个位进行设置和清零,从而实现对定时器和计数器的控制。
3. 程序设计在编写单片机定时器计数器程序时,首先需要确定定时器的工作模式,包括定时模式和计数模式。
在定时模式下,定时器可以按照设定的时间间隔生成中断,从而实现定时功能;在计数模式下,定时器可以根据外部的脉冲信号进行计数。
根据不同的应用需求,可以选择不同的工作模式,并根据具体情况进行相应的配置。
4. 程序实现在C语言中,可以通过编写相应的函数来实现对定时器和计数器的控制。
需要定义相关的寄存器位置区域和位掩码,以便于程序对这些寄存器进行操作。
编写初始化定时器的函数、启动定时器的函数、停止定时器的函数、重载定时器的函数等。
通过这些函数的调用,可以实现对定时器的各种操作,从而实现定时和计数功能。
5. 示例代码以下是一个简单的单片机定时器计数器程序的示例代码:```c#include <reg52.h>sbit LED = P1^0; // 定义LED连接的引脚void InitTimer() // 初始化定时器{TMOD = 0x01; // 设置定时器0为工作在方式1TH0 = 0x3C; // 设置初值,定时50msTL0 = 0xAF;ET0 = 1; // 允许定时器0中断EA = 1; // 打开总中断void Timer0_ISR() interrupt 1 // 定时器0中断服务函数{LED = !LED; // 翻转LED状态TH0 = 0x3C; // 重新加载初值,定时50msTL0 = 0xAF;}void m本人n(){InitTimer(); // 初始化定时器while(1){}}```以上代码实现了一个简单的定时器中断程序,当定时器计数到50ms 时,会触发定时器中断,并翻转LED的状态。
实验十一定时器实验三
一、实验要求
1.将P2口和四个数码管的数据口相连,P1口和位选线相连接,电路用共阳极;
2.数码管显示4位从前两位分钟、后两位为秒;分钟和秒的值从00到59增加;
3.实现定时器1S的定时,每1S时间到时,使秒钟加一,当秒钟为60时,显示为00
秒,分钟加一;当分钟为60时,显示为00分,从新开始一个小时的计时。
#include <reg51.h> //定义8051寄存器头文件
#define SEG7P P2 //定义数码管就接口在P2口
#define SCANP P1 //定义P3口为数码管位选口unsigned char TAB[]={ 0xc0,0xf9,0xa4,0xb0,0x99, //数字0~4的码值
0x92,0x83,0xf8,0x80,0x98 }; //数字5~9的码值unsigned int show_s,show_m; //定义变量show_s,show_m void Get_disp(char show_s1,char show_m1); //声明赋值函数
void Display(); //声明显示函数
void delay_ms(int x); //声明延时函数
char disp[4]; //定义显示数字数组
char scan[4]={0xfe,0xfd,0xfb,0xf7}; //定义位选扫描数组
main() //主程序的开始
{
SEG7P=0xff; //赋初值关闭数码管
IE=0x82; //开启中断总开关和定时器0开关
TMOD=0x01; //设置模式为1
TR0=1; //开启定时器0
TH0=(65535-50000)/256; //设置定时器初值,计数高八位
TL0=(65535-50000)%256; //计数低八位
while(1) //无穷循环
{
Get_disp(show_s,show_m); //调用赋值函数
Display(); //调用显示函数}
}
/*****定时器0中断子函数*****/
void TF_0(void) interrupt 1
{
int T;
TH0=(65535-50000)/256; //重新转载定时器的初值
TL0=(65535-50000)%256;
T++; //计数自增
if(T==20) //判断T
{
T=0; //T回到初值
show_s++; //秒自增
if(show_s>=60) //秒计到60
{
show_s=0; //秒回到0
show_m++; //分自增
if(show_m>=60)
show_m=0;
}
}
}
/*****disp数组赋值函数*****/
void Get_disp(char show_s1,char show_m1)
{
disp[0]=show_m1/10; //显示千位
disp[1]=show_m1%10; //显示百位
disp[2]=show_s1/10; //显示十位
disp[3]=show_s1%10; //显示个位
}
/*****显示函数*****/
void Display() //声明延迟函数
{
char i; //声明变量
for(i=0;i<4;i++) //for语句开始 {
SCANP=scan[i]; //扫描位选
SEG7P=TAB[disp[i]]; //赋值到数码管
delay_ms(5); //延时5ms }
}
/******延时函数******/
void delay_ms(int x) //延迟函数开始。