刚学单片机没多久,折腾数码管走了很多弯路,记录一下心得,电路图有的手画,方便点,单片机用的STC91C52RC。
1.先来讲讲单片机的构成,最小的可运行的单片机系统由复位电路,振荡电路等组成。如下图,单片机引脚图就不放了,蓝色部分即复位电路,由单片机RST引脚引出,一路接上10μF电容至VCC(正极),另一路接10K电阻接地。红色部分即振荡电路,由单片机的XTAL1和XTAL1引出,分别串一个20P左右电容,中间串上12MHZ晶振,汇流接地。至于中间的绿色电路,EA/VPP引脚直接接到VCC,目的是读取内部ROM。串口通讯使用CH340芯片,连接方式根据购买指导连接即可。
2.基本电路明白了之后就可以焊接电路了,单片机建议使用插座,如下图的绿色部分所示,为了方便可以将引脚引出来,利用插针(即红色部分两旁的东西)与引脚连在一起,需要用到引脚时用杜邦线接起来即可,方便拆卸,接线,如下图1。
3.明白了最小电路之后,就需要四位数码管了如下图就是一个共阴极四位数码管,共阴极的意思即内部的所有发光二极管都有一个公共端,需要将此公共端接地,数码管才能发光。每个位都有一个公共端。拿到这个数码管之后我们就需要测出每个引脚代表的段数,所谓的段数见图,a~g即数码管的段数,1~4就是公共端。我的是共阴极,用万用表的二极管挡位,黑笔选一个脚位,红笔去碰其他的引脚,如果段数逐一发亮,黑笔所碰的那个引脚就是公共端,记下来黑笔那个引脚位置以及编号,记下段数编号对应的引脚,继续用黑笔去找出其他三个公共端即可。
4.了解了数码管之后,可以试着将数码管直接接到单片机上,我们这里可以使用P1作为段数的选择,直接将a~g引脚依次接到P1口,可以像上图从数码管引出到插针,用杜邦线和P1口连接。1~4直接接地,将P0置1,(P0 = 0XFF) 即可点亮数码管,但是亮度会很低,因为I/O口的输出驱动所有数码管很吃力,所以我们接下来要使用三极管放大电路增强驱动能力。
5.三极管使用的NPN型,我使用的是型号是S8050,如下图,将三极管有字的那一面面向自己,从左到右分别是发射级,基极,集电极,原理这里就不赘述了。接下来讲一下电路的连接。
6.电路的连接,如下图所示。蓝色框是段选电路的连接,这里注意一点,由于P0的特殊构造,输出高电平需要加入上拉电阻,即那个330Ω的排阻,将排阻的公共端接到VCC,分出两路连到P0.0~P0.7以及数码管的a~f引脚。如图,蓝色就是排阻,两边右边接排针连到P0,左边接排针连到数码管。接下来是图5的绿色电路,B(基极)接到P2.0~P2.3,C(集电极)接到数码管的公共端1~4,E(发射级)接地。
7.程序的编写。当P0给出高电平时那一段的二极管亮,例如我们要让它显示数字0,我的数码管对应的段位如下图,除了g和dp是0其他都给1即可,即11111100,换成16进制0XFC,代码就可以写成P0 = 0XFC。代码的解释:我们利用内部T0计数器,这些中断都是需要掌握的,推荐新概念单片机C语言入门这本书。计数20次为一秒,中断20次后再利用一个变量计数60次,即一分钟,让分钟数+1,分别判断分钟数是否60,小时数是否24,分别送入display十位数和个位数。程序以下给出参考:
#include<reg51.h> #include<intrins.h> #define uint unsigned int #define uchar unsigned char void delays(uint); uint i,j; uchar code table1[]={ 0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; //数码显示管0-9 uchar code table2[] = { 0x01,0x02,0x04,0x08}; //位选 uchar num,num1,num2,shi,ge,shi1,ge1,t; void display(uchar,uchar,uchar,uchar); void main() { TMOD = 0X01; //内部定时模式16bit TH0 = (65536-50000)/256; //设置初值 TL0 = (65536-50000)%256; //设置初值 EA = 1; //总中断开 ET0 = 1; //内部定时开 TR0 = 1; //溢出位开 ge1 = 0; //设置时钟的初值,一下同理 shi1 = 2; num1 = 25; ge = 5; shi = 2;
num2 = 20; while(1){ display(shi,ge,shi1,ge1); } } void display(uchar shi,uchar ge,uchar shi1,uchar ge1){ //ÏÔʾº¯Êý //if (num1 > 10) //{ P0 = 0; //消除显示残影 P2 = table2[1]; //位选 P0 = table1[ge]; //段选 delays(5); //延时 P0 = 0; P2 = table2[0]; P0 = table1[shi]; delays(5); P0 = 0; P2 = table2[3]; P0 = table1[ge1]; delays(5); P0 = 0; P2 = table2[2]; P0 = table1[shi1]; delays(5); } void T0_time() interrupt 1 //中断函数 { TH0 = (65536-50000)/256; //设置初值 TL0 = (65536-50000)%256; //设置初值 num++; //计数变量 if(num == 20) //中断20次为一秒 { num = 0; //20次后置0重新开始 t ++; //60次的一秒即一分钟计数变量 if (t == 60){ //检查是否到了60秒 t = 0; num1 ++; //分钟数进1 if(num1 == 60){ //检查分钟数是否60· num1 = 0; //如果是置0 num2 ++; //小时数进1 if (num2 == 24){num2 = 0;} //检查是否过了24小时,是的话置0 shi1 = num2/10; //小时的十位数 ge1 = num2 % 10; //小时的个位数 } shi = num1/10; //分钟的十位数 ge = num1 % 10; //分钟的个位数 } } } void delays(uint xms){ //ÑÓʱº¯Êý1ºÁÃëΪ»ùÖµ uint i,j; for (i = 0;i < xms;i++){ for (j = 83;j > 0;j--); } }