青岛市网站建设,如何做实验室网站,广州番禺网站公司,wordpress 视频课堂本文是《单片机原理及应用》专栏中的最后一篇文章#xff0c;笔者以编译器的安装配置——51单片机简介——LED和数码管外设——开关和按键控制功能切换——外部中断系统——定时器与计数器为知识大纲#xff0c;介绍了C语言编程控制51单片机的入门教程。作为收尾#xff0c;…本文是《单片机原理及应用》专栏中的最后一篇文章笔者以编译器的安装配置——51单片机简介——LED和数码管外设——开关和按键控制功能切换——外部中断系统——定时器与计数器为知识大纲介绍了C语言编程控制51单片机的入门教程。作为收尾我们将一同学习三个定时器/计数器的实际应用不同于之间灯光和按键的组合在这三个应用中都加入了其他外设更复杂也更有创意希望大家对单片机的学习也能兴致盎然、不断进取。
定时器控制P1.0引脚产生1ms方波
首先选用系统时钟为12MHz的单片机 要在P1.0上产生周期为2ms的方波定时器应产生1ms的定时中断定时时间到则在中断服务程序中对P1.0求反。在本案例我们使用定时器T0方式1定时中断GATE不起作用。此外对中断标志位采用查询法查询法不经过中断程序是最简单的IO方式数据在CPU和外设之间的传送完全靠计算机程序控制外设和CPU之间是串行工作CPU效率低。由于查询法效率低于中断函数已经被逐渐淘汰笔者此处仅作为知识补充。
#include reg51.h
sbit P1_0P1^0;
void main(void)
{TMOD0x01; //设置T0为定时器工作方式1TR01; //允许T0中断while(1) {TH00xfc; //赋初值计数1000即溢出X65536-1000TL00x18;do{}while(!TF0); //使用查询法TF0为0原地循环为1则T0溢出往下执行P1_0!P1_0; //P1.0状态求反高低电平转换TF00; //定时器T0溢出标志位TF0清零}
}仿真如图所示为了确认输出波形在proteus中添加了虚拟示波器添加方式是点击左侧菜单栏虚拟仪器模式在弹出的窗口中选择OSCILLIOSCOPE即可。 另外请大家注意左侧按键属于复位电路对方波输出无影响。启动仿真后即可看到示波器图像示波器右侧还有各类参数大家可以自行调整。 定时器控制发出1KHz音频
第二个应用是用定时器T1的中断控制P1.7引脚输出频率为1kHz方波音频信号驱动蜂鸣器发声。单片机系统时钟为12MHz音频信号周期1ms因此T1的定时中断时间为0.5 ms进入中断服务程序后对P1.7求反。原理与应用一大致相同区别在代码构架中采用了中断法且在while循环中多次更改定时器初值。这几个应用或多或少都采用了与众不同的设计思路更贴合实际使用场景。
#includereg51.h
sbit soundP1^7; //将蜂鸣器连接在P1.7引脚上
#define f1(a) (65536-a)/256 //宏定义输入计数值即按表达式输出初值
#define f2(a) (65536-a)%256
unsigned int i500;
unsigned int j0;
void main(void)
{EA1; //开启总中断允许.ET11; //允许定时器T1中断 TMOD0x10; //T设置定时器1工作方式1 TH1f1(i); //初始化计数值i得到初值此时i为500TL1f2(i); TR11; //启动定时器1while(1) { /*i500; //可以改变频率达到不同的声音效果while(j2000);j0;i1000; while(j2000);j0;i3000; while(j2000);j0;*/ //返回第一种频率}}void T1_int(void) interrupt 3 using 0 //定时器T1中断服务函数
{TH1f1(i); //重新赋初值.TL1f2(i); sound~sound; //对P1.7输出求反形成方波j; //用于记录中断次数也就是记录时间
}
仿真如下为了更直观地看到频率的变化在蜂鸣器旁并联了一个示波器虽然会降低幅值但是不影响频率。 定时器控制蜂鸣器发出1KHz音频 蜂鸣器声音较大大家在观看视频演示时需要注意调节音量。
定时器测量INT1引脚正脉冲宽度
第三个应用是计数器测量INT1引脚正脉冲宽度利用门控位GATE1可使T1启动计数受INT1控制当GATE11TR11时只有INT1引脚输入高电平时T1才被允许计数。利用该功能可测量引脚正脉冲宽度并在6位数码管上以机器周期数显示能通过旋转信号源旋钮调整频率。
在中断处理上再次使用了查询法另外需要注意INT1作为外部中断1的引脚并未像之前我们介绍的那样设置TCON用于外部中断允许。作为最后一个应用可能有些难以理解大家了解相关原理内容就好。
#includereg51.h
#define uint unsigned int
#define uchar unsigned char
sbit P3_3P3^3; //读取INT1引脚电平
uchar count_high; //定义计数变量用来读取TH0
uchar count_low; //定义计数变量用来读取TL0
uint num;
uchar shiwan, wan, qian, bai, shi, ge; //定义各数码管显示数位
uchar flag; //控制刷新频率
uchar code table[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //数组记录共阴极数码管段码void delay(uint z) //自变量延时函数
{uint x,y;for(xz;x0;x--)for(y110;y0;y--);
}
void display(uint a,uint b,uint c,uint d,uint e,uint f){P20xfe; P0table[f]; delay(2); //数码管段选位选消影P20xfd; P0table[e]; delay(2); //六个数位对应留个双管P20xfb; P0table[d]; delay(2);P20xf7; P0table[c]; delay(2);P20xef; P0table[b]; delay(2);P20xdf; P0table[a]; delay(2);
}
void read_count() //读取定时寄存器的内容
{do{count_highTH1; //读取高字节count_lowTL1; //读取低字节}while (count_high!TH1);//读取完成后继续往下执行 numcount_high*256count_low; //将16位数据恢复为十进制数字}
void main( )
{while(1){flag0;TMOD0x90; //设置定时器T1工作方式1门控位为1当INT1为高电平时定时器才开始工作TH10; //计数初值为零TL10;while(P3_31); //等待INT1变为低电平TR11; //如果INT1为低电平启动定时器器T1此时未真正开始计数while(P3_30); //等待INT1变为高电平变高后T1真正开始计数while(P3_31); //等待INT1变为低电平变低后T1停止计数TR10;read_count(); //调用函数读取定时寄存器内容的函数shiwannum/100000; //数据分割每一位数码管显示对应数位wannum%100000/10000;qiannum%10000/1000;bainum%1000/100;shinum%100/10;genum%10;while(flag!100) //运行100次显示数值后再读取下一次数值 {flag;display(ge,shi,bai,qian,wan,shiwan); //调用display函数传入相应参数}}
}仿真如下为避免接线混乱采用了之前介绍的总线接法P0端口使用了上拉电阻此时端口为准双向口不存在高阻抗的悬浮状态和示波器一样信号发生器也在虚拟仪器界面选择SIGNAL GENERATOR即可。 大家可以更改信号发生器的参数包括频率、电压和波形观察数码管示数的变化详细的操作教程可以参考51单片机数字频率计开发 定时器测量INT1引脚正脉冲宽度 到此为止这个专栏就算圆满落幕了这部分单片机课程笔者也是学习了一月有余对于非电子专业的同学来说这些知识足够了。以后如果有进一步的机会或许会重启这个专栏。总之感谢陪伴我一同学习的每一个人祝愿大家在新的一年里都能百尺竿头更进一步谢谢大家我们下个专栏再见。