#include void main(void) { TMOD=0x01;// 使用定时器 T0 的模式 1 TH0=(65536-46083)/256; // 定时器 T0的高 8 位赋初值 TL0=(65536-46083)%256; // 定时器 T0的低 8 位赋初值 TR0=1; // 启动定时器 T0 TF0=0; //清定时器溢出标志位 P2=0xff; while(1)// 无限循环等待查询 { while(TF0==0); TF0=0; P2=~P2;//按位取反 TH0=(65536-46083)/256; // 定时器 T0 的高 8 位赋初值 TL0=(65536-46083)%256; // 定时器 T0 的低 8 位赋初值 } } 分析:新的寄存器出现了,它们分别是TMOD、TH0、TL0、TR0、TF0,只要掌握调用顺序就可以玩好定时器了。 实例 43 :用定时器 T1 查询方式控制单片机发出 1KHz 音频 #include sbit sound=P3^7; void main(void) { TMOD=0x10;// 使用定时器 T1 的模式 1 TH1=(65536-921)/256; // 定时器 T1 的高 8 位赋初值 TL1=(65536-921)%256; // 定时器 T1 的低 8 位赋初值 TR1=1; TF1=0; // 启动定时器 T1 while(1)// 无限循环等待查询 { while(TF1==0); TF1=0; sound=~sound; // 将 P3.7引脚输出电平取反 TH1=(65536-921)/256; // 定时器 T0的高 8 位赋初值 TL1=(65536-921)%256; // 定时器 T0的低 8 位赋初值 } } 实例 44:将计数器 T0 计数的结果送 P1 口 8 位 LED 显示 #include sbit S=P3^4; // 将 S位定义为 P3.4引脚 void main(void) { // EA=1; // 开总中断 // 定时器 T0 中断允许 // ET0=1; TMOD=0x02;// 使用定时器 T0 的模式 2 TH0=256-156; // 定时器 T0的高 8 位赋初值 TL0=256-156; // 定时器 T0 的高 8 位赋初值 TR0=1; // 启动定时器 T0 while(1)// 无限循环等待查询 { while(TF0==0) // 如果未计满就等待 { if(S==0) // 按键 S按下接地,电平为 0 P1=TL0; //计数器 TL0加 1 后送 P1口显示 } TF0=0; // 计数器溢出后,将 TF0清 0 } } 分析:理论结合实例,效果很好吧。 实例 45:用定时器 T0 的中断控制 1 位 LED 闪烁 #include sbit D1=P2^0; // 将 D1 位定义为 P2.0引脚 void main(void) { EA=1;// 开总中断 ET0=1;// 定时器 T0 中断允许 TMOD=0x01;// 使用定时器 T0 的模式 1 TH0=(65536-46083)/256; //定时器 T0 的高 8 位赋初值 TL0=(65536-46083)%256; //定时器 T0的高 8 位赋初值 TR0=1; // 启动定时器 T0 while(1); } /************************************************************** 函数功能:定时器 T0 的中断服务程序 **************************************************************/ void Time0(void) interrupt 1 using 0 //寄存器 { D1=~D1; // 按位取反操作,将 P2.0引脚输出电平取反 TH0=(65536-46083)/256; //定时器 T0 的高 8 位重新赋初值 TL0=(65536-46083)%256; //定时器 T0的高 8 位重新赋初值 } 实例 46:用定时器 T0 的中断实现长时间定时 #include sbit D1=P2^0; // 将 D1 位定义为 P2.0引脚 unsigned char Countor; //设置全局变量,储存定时器 T0 中断次数 void main(void) { EA=1; ET0=1; TMOD=0x01; TH0=(65536-46083)/256; //定时器 T0的高 8 位赋初值 TL0=(65536-46083)%256; //定时器 T0的低 8 位赋初值 TR0=1; // 启动定时器 T0 Countor=0; // 从 0 开始累计中断次数 while(1); } /************************************************************** 函数功能:定时器 T0 的中断服务程序 **************************************************************/ void Time0(void) interrupt 1 using 0 { Countor++; // 中断次数自加 1 if(Countor==20) // 若累计满 20 次,即计时满 1s { D1=~D1; // 按位取反操作,将 P2.0引脚输出电平取反 Countor=0; // 将 Countor 清 0,重新从 0 开始计数 } TH0=(65536-46083)/256; //定时器 T0 的高 8 位重新赋初值 TL0=(65536-46083)%256; //定时器 T0的高 8 位重新赋初值 } 分析:这就是外存库,之前整理的中断和定时器没想到就是这里的片段。 实例 47:用定时器 T1 中断控制两个 LED 以不同周期闪烁 #include sbit D1=P2^0; // 将 D1 位定义为 P2.0引脚 sbit D2=P2^1; // 将 D2 位定义为 P2.1引脚 unsigned char Countor1; //设置全局变量,储存定时器 T1 中断次数 unsigned char Countor2; //设置全局变量,储存定时器 T1 中断次数 void main(void) { EA=1;// 开总中断 ET1=1; // 定时器 T1 中断允许 TMOD=0x10; // 使用定时器 T1 的模式 1 TH1=(65536-46083)/256; //定时器 T1 的高 8 位赋初值 TL1=(65536-46083)%256; //定时器 T1的高 8 位赋初值 TR1=1; // 启动定时器 T1 Countor1=0; // 从 0 开始累计中断次数 Countor2=0; while(1); } void Time1(void) interrupt 3 using 0 { Countor1++; //Countor1 自加 1 Countor2++;//Countor2 自加 1 if(Countor1==2) // 若累计满 2 次,即计时满 100ms { D1=~D1; // 按位取反操作,将 P2.0引脚输出电平取反 Countor1=0; // 将 Countor1 清 0,重新从 0 开始计数 } if(Countor2==8) // 若累计满 8 次,即计时满 400ms { D2=~D2; // 按位取反操作,将 P2.1引脚输出电平取反 Countor2=0; // 将 Countor1 清 0,重新从 0 开始计数 } TH1=(65536-46083)/256; //定时器 T1 的高 8 位重新赋初值 TL1=(65536-46083)%256; //定时器 T1的高 8 位重新赋初值 } 分析:慢慢欣赏吧,有问题欢迎评论。 实例 50-1 :输出 50 个矩形脉冲 #include sbit u=P1^4; // 将 u 位定义为 P1.4 /************************************************* 函数功能:延时约 30ms (3*100*100=30 000μ s =30m *************************************************/ void delay30ms(void) { unsigned char m,n; for(m=0;m<100;m++) for(n=0;n<100;n++); } void main(void) { unsigned char i; u=1; // 初始化输出高电平 for(i=0;i<50;i++) //输出 50 个矩形脉冲 { u=1; delay30ms(); u=0; delay30ms(); } while(1); } 啦啦啦 实例 50-2:计数器 T0统计外部脉冲数 #include void main(void) { TMOD=0x06; // TMOD=0000 0110B,使用计数器 T0 的模式 2 EA=1; ET0=0; // 不使用定时器 T0 的中断 TR0=1; // 启动 T0 TH0=0; // 计数器 T0 高 8 位赋初值 TL0=0;// 计数器 T0 低 8 位赋初值 while(1) // 无限循环,不停地将 TL0计数结果送 P1口 P1=TL0; } 啊啊啊 实例 51-2 :定时器 T0 的模式 2 测量正脉冲宽度 #include sbit ui=P3^2; // 将 ui 位定义为 P3.0( INT0)引脚,表示输入电压 void main(void) { TMOD=0x0a; // TMOD=0000 1010B,使用定时器 T0 的模式 2, GATE置 1 EA=1; // 开总中断 ET0=0;// 不使用定时器 T0 的中断 TR0=1;// 启动 T0 TH0=0; // 计数器 T0 高 8 位赋初值 TL0=0; // 计数器 T0 低 8 位赋初值 while(1) // 无限循环,不停地将 TL0计数结果送 P1口 { while(ui==0) //INT0 为低电平, T0 不能启动 TL0=0; //INT0 为高电平,启动 T0 计时,所以将 TL0清 0 while(ui==1) // 在 INT0 高电平期间,等待,计时 P1=TL0; // 将计时结果送 P1口显示 } } 哈哈哈 实例 53:用外中断 0 的中断方式进行数据采集 #include sbit S=P3^2;// 将 S位定义为 P3.2 void main(void) // 包含 51 单片机寄存器定义的头文件 { EA=1; // 开放总中断 EX0=1; // 允许使用外中断 IT0=1; // 选择负跳变来触发外中断 P1=0xff; while(1); } void int0(void) interrupt 0 using 0 // 外中断 0 的中断编号为 0 { P1=~P1; // 每产生一次中断请求, P1取反一次。 } 呐呐呐 实例 54-1 :输出负脉宽为 200 微秒的方波 #include sbit u=P1^4;// 将u位定义为P1.4 void main(void) { TMOD=0x02; //TMOD=0000 0010B,使用定时器 T0 的模式 2 EA=1;// 开总中断 ET0=1;// 定时器 T0 中断允许 TH0=256-200; // 定时器 T0 的高 8 位赋初值 TL0=256-200; // 定时器 T0 的高 8 位赋初值 TR0=1; // 启动定时器 T0 while(1);// 无限循环,等待中断 } void Time0(void) interrupt 1 using 0 //"interrupt" 声明函数为中断服务函数 { u=~u; // 将 P1.4引脚输出电平取反,产生方波 } 嗯嗯嗯 实例 54-2 :测量负脉冲宽度 #include sbit u=P3^2;// 将 u 位定义为 P3.2 void main(void) { TMOD=0x02; //TMOD=0000 0010B,使用定时器 T0 的模式 2 EA=1; // 开放总中断 EX0=1; // 允许使用外中断 IT0=1; // 选择负跳变来触发外中断 ET0=1; // 允许定时器 T0 中断 TH0=0; // 定时器 T0 赋初值 0 TL0=0; // 定时器 T0 赋初值 0 TR0=0; // 先关闭 T0 while(1) ; // 无限循环, 不停检测输入负脉冲宽度 } void int0(void) interrupt 0 using 0 // 外中断 0 的中断编号为 0 { TR0=1; // 外中断一到来,即启动 T0 计时 TL0=0; // 从 0 开始计时 while(u==0)// 低电平时,等待 T0 计时 P1=TL0; //将结果送 P1口显示 TR0=0; // 关闭 T0 } 咯咯咯 实例 55:方式 0 控制流水灯循环点亮 #include #include unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; // 流水灯控制码,该数组被定义为全局变量 sbit P17=P1^7; /************************************************************** 函数功能:延时约 150ms **************************************************************/ void delay(void) { unsigned char m,n; for(m=0;m<200;m++) for(n=0;n<250;n++); } /************************************************************** 函数功能:发送一个字节的数据 **************************************************************/ void Send(unsigned char dat) { P17=0;//P1.7 引脚输出清 0 信号,对 74LS164清 0 _nop_(); // 延时一个机器周期,保证清 0 完成 P17=1; // 结束对 74LS164的清 0 _nop_(); // 延时一个机器周期 SBUF=dat; // 将数据写入发送缓冲器,启动发送 while(TI==0); // 若没有发送完毕,等待 TI=0;// 发送完毕, TI被置“ 1”,需将其清 0 } /******************************************* 函数功能:主函数 ******************************************/ void main(void) { unsigned char i; SCON=0x00; //SCON=0000 0000B,使串行口工作于方式 0 while(1) { for(i=0;i<8;i++) { Send(Tab[i]); // 发送数据 delay(); // 延时 } } } 略略略 打开串口调试程序,将波特率设置为9600,无奇偶校验晶振11.0592MHz,发送和接收使用的格式相同,如都使用字符型格式,在发送框输入hello, I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确, include void main (void) { SCON = 0x50; //SCON:模式 1,8-bit UART,使能接收V TMOD = 0x20; /*TMOD: timer 1, mode 2,8-bit reload*/ TH1 =0xFD;// TH1:重新加载值为9600波特 TR1 = 1;// 启动定时器1 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; } #include void ConfigUART(unsigned int baud); void main () { ConfigUART(9600); //配置波特率为9600 while(1) { while (!RI); //等待接收完成 RI = 0; //清零接收中断标志位 SBUF = SBUF + 1; //接收到的数据+1后,发送回去; //等号左边的SBUF实际上就是发送SBUF,因为对它的操作是“写”; //等号右边的是接收SBUF,因为对它的操作是“读”。 while (!TI); //等待发送完成