[文档下载] 用51单片机制作时间控制继电器

[复制链接]
2569|10
 楼主| 奥德赛 发表于 2015-11-16 20:54 | 显示全部楼层 |阅读模式


此继电器由一颗 STC15S204EA芯片为主构成,使用3位数码管(LD_3361AS)静态共阴极显示,带动松乐5V继电器工作。
其中输入电路使用317P280-1光耦做隔离,输出使用9012和S8550做继电器驱动。
整机功耗在50mA左右,输入电压在3.6-5V之间工作。可使用串口P11,P12写入程序。
STC15S204EA参数:CPU类型:单时钟8051兼容。内置时钟:33MHz,可通过内部设置调整工作频率。2-16bitTimer,256BRAM,4KROM,1KEEPROM。内置看门狗电路。8路10bitADC.5-ExtInt.不支持IAP,但支持ISP(串口编程)。
硬件原理图:

当前管脚分配:
Pin1(P1.2):外部触发输入信号(已经过光耦隔离).
Pin2_3_4(P1.3,P1.4,P1.5):按键检测端口,分别连接至功能选择,数码位选择,数字调整等3个功能。
Pin5_Pin6(P1.6,P1.7):闲置未用。用作监控信号输出,或该做串口使用。
Pin7(P0.0/P5.4):输出信号,用作继电器控制信号。
Pin8(VDD),Pin10(VSS):电源信号。
Pin11(P3.0/Rx),Pin12(P3.1/Tx):串口信号。可通过设置端口控制寄存器重新映射到未使用的端口P1.6/P1.7(Pin5/Pin6)
Pin9(P0.1/P5.5):数码管1阴极。
Pin19(P1.1):数码管2阴极。
Pin20(P1.0):数码管3阴极。
Pin15(P3.4):数码管字段A.
Pin17(P3.6):数码管字段B.
Pin14(P3.3):数码管字段C.
Pin12(P3.1):数码管字段D.
Pin11(P3.0):数码管字段E.
Pin16(P3.5):数码管字段F.
Pin18(P3.7):数码管字段G.
Pin13(P3.2):数码管字段DP.
在以上硬件连接的基础上,实现多步可重定义的开关定时开关功能。主要简述如下:
1. 系统时钟频率选择 :为了便于和PC通讯,以及和受控设备通讯,选择系统主频M=11.0592MHz。这样可以使用115200,n,8,1的串口参数与PC或受控设备通讯。
2. 定时中断的应用:
Timer0:用作显示扫描或串口通讯时的波特率发生器。用作显示扫描时,在11.0592MHz主频下,扫描频率设置到33Hz ,可消除人眼可见的闪烁。
Timer1: 用于定时(1ms准确定时),按键信号检测,输入触发信号检测等。在11.0592MHz主频下,扫描频率设置到4KHz,可以保证短时延时的准确性,输入触发信号的最高可分辨频率可达到100Hz。
3. EEPROM的应用
STC15F204EA的1K EEPROM按照512字节大小分为2个Bank。Bank0用来记录系统配置数据(程序初始化时写入,包括不同主频下的中断配置信息等),Bank1用来记录用户所需要的通断序列,每个动作序列由顺序号,继电器闭合时间,继电器断开时间,本动作重复次数等4个整数组成,共占8个字节。在512个字节内,可以存放最多63组动作(最后一个动作序列全0,表示动作结束)。
系统上电后,程序完成初始化动作,然后逐步从EEPROM中读出一个动作序列执行。用户可以控制在整个动作执行多少次以后,继电器停止动作,完全处于待机状态。也可以无限重复循环执行。动作时间以0.1s为时间基准,每个动作的时间长度可由0-6553.5s之间变化。
4. 用户数据的写入
在系统启动后,用户通过按键,进入与PC联机模式,然后用PC端给继电器写入要执行的动作序列。写入完成后,即可开始执行。
 楼主| 奥德赛 发表于 2015-11-16 20:54 | 显示全部楼层
5. 与PC的实时通讯
因Timer0正常应用为LED显示控制,如果用户选择使用PC联机通讯,则把Timer0设置为波特率发生器(LED关闭),用户可以通过串口,直接将执行状态显示在PC上,随时执行停止或启动,或执行更长,更复杂的命令序列,并记录执行结果。因为STC15F204EA中仅一个UART通道,无法同时执行与被控设备通信和PC通讯,只能选择。
6. 关于外部触发的控制信号
因为该继电器使用了双向光耦作为输入与单片机引脚的隔离,而输入信号是直接与光耦的输入端相连,因此需要保证输入信号(需要让光耦中的LED工作,电流2-5mA)足够驱动光耦工作,否则结果不可靠。
7. 关于松乐5V继电器。
使用这个继电器的好处是使用单一5V电源就可工作,但是会对系统的电源稳定性造成影响。在继电器闭合器件,在电源上形成一个约2.5us的电源纹波(PP:3.8 - 6.3V)。如果在单片机设置上设置为4.05V自动复位,有可能导致系统自动复位。
8. 关于使用I/O管脚直接驱动LED显示
使用I/O驱动LED的好处是外围电路最为简单,但是增加了系统的电流负载。对于这种 共阴极LED数码管,需要输出较大的工作电流才能达到正常的显示亮度。因此使用了STC单片机的I/O模式控制寄存器PxM0,PxM1将输出模式设置为推挽输出方式。此时每个I/O管脚可提供20mA以上电流,但是在LED上需要串接一个330-470ohm的限流电阻,防止LED烧毁。
9. 定时的准确程度
单片机使用内部RC振荡器工作,频率范围在5-33MHz(产品手册是35MHz,但不知如何设置到35MHz)内调节,精度1%以内。但是当I/O口工作与推挽模式,并且有电流输出时,I/O口的速度会降低很多,使得循环的定时精度极大变化,不能用作通用定时使用(工作频率越高,这个现象越明显)。

该单片机与51系列兼容性高,因此可以使用Proteus做完全仿真,比起每次把程序写进单片机看运行效果要方便很多。对于问题的Debug,大部分情况下,可以直接使用Keil C51下的模拟器进行,使用便捷有效。对于类似的小型应用系统,是一个很好的选择。

 楼主| 奥德赛 发表于 2015-11-16 20:55 | 显示全部楼层
单片机控制的定时计数继电器 - 软件部分这个 软件部分按照开发过程的顺序,分为显示部分、定时部分和外部触发信号的检测部分。

1. 显示驱动:
   这个电路中使用的3位共阴极7段式LED(LD-3361AS)共11个管脚,经过网上搜索,查找了其基本电路连接关系。为了便于在Proteus中进行仿真,因此就利用Proteus元件库中带点的1位数码管3只,外加一个接口,自己构成了这个显示元件。这样就方便使用Proteus直接仿真运行。
  
下一步是显示字模的组成。因为它的字段a-g与单片机P3口的连接顺序并不是按照P3.0-P3.7这样的顺序一一对应,因此,需要按照连接的顺序,建立在P3口上显示每个字符时的字模表。

上图是一般7段数码管的笔画定义,如果要显示字符0,则需要a,b,c,d,e,f都要点亮,标记为1. 如果显示字符1,则需要b、c点亮即可。其它可显示的字符也是按照这个方法定义。因此,在这个实际电路中,字符的定义如下:
LED显示控制端口连接及字符字形定义:

 楼主| 奥德赛 发表于 2015-11-16 20:56 | 显示全部楼层
  1. /* 显示字符字模定义表
  2. 端口P3: 7  6 5 4 3 2  1 0
  3.   7SEG: G  B F A C DP D E  
  4.   字符                     字码定义
  5.   0: 0  1 1 1 1 0  1 1 7B
  6.   1: 0  1 0 0 1 0  0 0 48
  7.   2: 1  1 0 1 0 0  1 1 D3
  8.   3: 1  1 0 1 1 0  1 0 DA

  9.   4: 1  1 1 0 1 0  0 0 E8
  10.   5: 1  0 1 1 1 0  1 0 BA
  11.   6: 1  0 1 1 1 0  1 1 BB
  12.   7: 0  1 0 1 1 0  0 0 58
  13.   
  14.   8: 1  1 1 1 1 0  1 1 FB
  15.   9: 1  1 1 1 1 0  0 0 F8
  16.   a: 1  1 1 1 1 0  0 1 F9
  17.   b: 1  0 1 0 1 0  1 1 AB

  18.   c: 1  0 0 0 0 0  1 1 83
  19.   d: 1  1 0 0 1 0  1 1 CB
  20.   e: 1  0 1 1 0 0  1 1 B3
  21.   f: 1  0 1 1 0 0  0 1 B1

  22.   g: 1  1 1 1 1 0  1 0 FA
  23.   H: 1  0 1 0 1 0  0 1 A9
  24.   I: 0  0 1 0 0 0  0 1 21
  25.   J: 0  1 0 0 1 0  1 0 4A
  26.   
  27.   K: 0  0 0 0 0 0  0 0 00
  28.   L: 0  0 1 0 0 0  1 1 23
  29.   M: 0  0 0 0 0 0  0 0 00
  30.   N: 0  0 0 0 0 0  0 0 00
  31.   
  32.   o: 1  0 0 0 1 0  1 1 8B
  33.   P: 1  1 1 1 0 0  0 1 F1
  34.   Q: 0  0 0 0 0 0  0 0 00
  35.   r: 1  0 0 0 0 0  0 1 81
  36.   
  37.   S: 1  0 1 1 1 0  1 0 BA  //和5相同
  38.   t: 1  0 1 0 0 0  1 1 A3
  39.   u: 0  0 0 0 1 0  1 1 0B
  40.   v: 0  0 0 0 0 0  0 0 00
  41.   
  42.   W: 0  0 0 0 0 0  0 0 00
  43.   X: 0  0 0 0 0 0  0 0 00
  44.   y: 1  0 1 0 1 0  1 0 AA
  45.   Z: 0  0 0 0 0 0  0 0 00
  46.   
  47.   -: 1  0 0 0 0 0  0 0 80
  48.   _: 0  0 0 0 0 0  1 0 02
  49.   [: 0  0 1 1 0 0  1 1 33
  50.   ]:0  1 0 1 1 0  1 0 5A
  51.   
  52.   ~: 0  0 0 1 0 1  0 0 14 //表示错误字符。
  53. 字符表结束*/
转换成 C语言的标准定义如下:
  1. static unsigned char code CharCode[] = {0x7B, 0x48, 0xD3, 0xDA, 0xE8, 0xBA, 0xBB, 0x58,     // 0 - 7
  2.           0xFB, 0xF8, 0xF9, 0xAB, 0x83, 0xCB, 0xB3, 0xB1,     // 8 - f
  3.           0xFA, 0xA9, 0x21, 0x4A, 0x00, 0x23, 0x00, 0x00,     // g - N
  4.           0x8B, 0xF1, 0x00, 0x81, 0xBA, 0xA3, 0x0B, 0x00,     // o - v
  5.           0x00, 0x00, 0xAA, 0x00, 0x80, 0x02, 0x33, 0x5A,     // w - z,-, _, [, ],
  6.           0x14};            
不过,在上表中,有不少是用0x00表示的,表明这个字符用数码管无法显示,因此全部灭掉,变成空白了。如果你要显示"W,M,N,K,V,X,Z ,....都无法显示的。因此在使用时,尽量避免用到以上的显示内容。但是常用的如:”Start“,"Hlt","Stop" "End" ”0-9“,”A-F“等都可以正常显示。


 楼主| 奥德赛 发表于 2015-11-16 20:57 | 显示全部楼层
在字模表定义好以后,就要显示两类信息,一类是字符串,另一类是整数数字。我们通常使用的字符串是用ASCII(American Standard Code for Information Interchange, 美国标准信息交换码)码表示的,并不是我们这里的字模。因此需要把常用的ASCII字符串,转换成所需要显示对应的字模数据,然后把字模数据再放到对应的P3端口上,就可以在数码管上显示出来了。

下面是ASCII字符到字模表的转换过程。
1. 首先定义了一个显示缓冲区,就是PC里面的显存。把要显示的内容放到显存中,然后由显示程序自动显示出来就好了。因为这个数码管只有3位,无法显示很多内容,因此这里的显存仅定义为10个字节。其中8个字节可以用来显示内容,另外2个字节用作循环时的间隔符使用。在这个基础上,最多显示的字符长度是8位ASCII码,对应于数字,则最大是99999999。超过这个范围的显示内容,会被处理掉而不予处理。
  1. #define BUFLEN          10                      //显示缓冲区, 显示起始指针和终止指针,要显示的数据的长度(1-8)。
  2. unsigned char   DispBuf[BUFLEN];        //数据长度8位,加2位隔离空格
  3. unsigned char   DISPLEN;                     //要显示的数据的长度,1-8.

2. 将单个 ASCII字符转换为LED对应的字模代码。其中CharCode[]就是前面定义的字模表。
  1. unsigned char CChar(char c)
  2. {
  3. unsigned char i;
  4. if (c >= '0' && c <= '9') i=c-'0';
  5. else if (c >='A' && c<='Z') i=c-'A'+10;
  6. else if (c >='a' && c<='z') i=c-'a'+10;
  7. else if (c == '-') i=36;
  8. else if (c == ' ') i=35;    //空格
  9. else if (c == '_') i=37;
  10. else if (c == '[') i=38;
  11. else if (c == ']') i=39;
  12. else i=40;                  //其它字符全部转换为小数点
  13. return CharCode[i];
  14. }   
 楼主| 奥德赛 发表于 2015-11-16 20:58 | 显示全部楼层
这个转换过程比较简单,就是将ASCII字符与0-9,A-Z, a-z分别比较,然后找到位置值,转换到字模表中的顺序值,最后返回字模表该位置对应的字模值即可。因此无法区分大小写,识别主要靠想象力了。
3. 显示字符串的程序是显示的一个核心部分。因为只能显示3位,因此当要显示的长度不超过3位时,靠右显示。前面显示为空白(不显示)。而对于超过3位长度的部分,则是按顺序存放在显存中,由显示程序自动显示(显示程序后面介绍)。
  1. void Disp(char *str)
  2. {
  3. unsigned char i;
  4. DISPLEN =sLen(str);
  5. if (DISPLEN==1) { //长度为1,前面2个空白,最后一个数值。
  6.   DispBuf[2]=CChar(str[0]);
  7.   DispBuf[1]=0;
  8.   DispBuf[0]=0;
  9.   DISPLEN=3;
  10. } else if (DISPLEN ==2) { //长度为2,前面1个空白,后面两个数值。
  11.   DispBuf[1]=CChar(str[0]);
  12.   DispBuf[2]=CChar(str[1]);
  13.   DispBuf[0]=0;
  14.   DISPLEN=3;
  15. }
  16. else
  17. for (i=0;i<DISPLEN;i++){
  18.   DispBuf[i]=CChar(str[i]);    //按顺序放进显存。
  19. }
  20. //显示区的最大长度是8,最后增加2个0,作为空格,隔离循环显示。
  21. for (i=DISPLEN;i<10;i++) DispBuf[i]=0;
  22. //如果dCount =0, 则立即开始刷新(Timer0的下次中断开始就刷新)。
  23. //否则等这次正常显示完成才刷新。可能会丢失部分显示内容,但是看着正常。
  24. dCount=0;
  25. }
  26. 上面用到了一个字符串长度函数sLen。因为不想使用C标准库,因此自己定义这个函数,并且限定最大长度是8。
  27. unsigned char sLen(char *str)
  28. {
  29. unsigned char i=0;
  30. while(*str != 0) {i++;str++;}
  31. if (i>8) i=8;  //获取字符串长度,不大于8。大于8时等于8.
  32. return i;
  33. }
  34. 4. 对于长整数的显示。范围 0 - 9999,9999。虽然程序内部能够处理无符号长整数(0-2(32)范围),但是显示时只处理这个较小的范围。
  35. /*--------------------------------------------------------------------------------------------
  36.   无符号长整数显示程序
  37.   限制:只能显示8位,否则显示 OFL - 表示 Overflow,溢出。
  38. ----------------------------------------------------------------------------------------------*/
  39. void DispLInt(unsigned long m)
  40. {
  41. unsigned long i;
  42. unsigned char j,k;
  43. unsigned char Res[8];
  44.   //对于超大数据的处理,显示“---”,闪烁。"OFL"
  45. if (m>99999999) {
  46.   DispBuf[0]=0x8B;   // O
  47.   DispBuf[1]=0xB1;   // F
  48.   DispBuf[2]=0x23;   // L
  49.   DISPLEN = 3;
  50.   return;
  51. }
  52. //将整数转换成十进制字符数组Res[], 如873245转换成{'8','7','3','2','4','5'}。
  53. i=m/10;
  54. j=m%10;
  55. k=0;
  56. Res[k]=j;
  57. while(i>0) {
  58.   j=i%10;
  59.   i=i/10;
  60.   k++;
  61.   Res[k]=j;
  62. }
  63. //对于仅1位数字的显示,前面填充2个空格,最后一位显示数字。
  64. if (m<10) {
  65.   DispBuf[0]=0;
  66.   DispBuf[1]=0;
  67.   DispBuf[2]=CharCode[Res[0]];
  68.   DISPLEN=3;
  69. }
  70. //对于2为数字显示,前面填1个空格,后面两位填数字。
  71. if (m >=10 && m<100) {
  72.   DispBuf[0]=0;
  73.   DispBuf[1]=CharCode[Res[1]];
  74.   DispBuf[2]=CharCode[Res[0]];
  75.   DISPLEN=3;
  76. }
  77. //对于3位及以上的数字处理。按照顺序填充在显存中。
  78. if (m>=100) {
  79.   for (j=k;j>0;j--) DispBuf[k-j]=CharCode[Res[j]];  //uchar i-- 会导致死循环,无法停下来的。
  80.   DispBuf[k]=CharCode[Res[0]];
  81.   DISPLEN=k+1;
  82. }
  83. if (k<3) k=3;
  84. //对于长度超过3位的数字,需要循环显示,并且在需要循环显示的缓冲区中增加两个空格(0)。
  85. DispBuf[k+1]=0;
  86. DispBuf[k+2]=0;
  87. //是否需要立即刷新?影响显示的美观程度。
  88. dCount = 0;
  89. }



 楼主| 奥德赛 发表于 2015-11-16 20:59 | 显示全部楼层
至此,要显示的内容存放到显示缓冲区的工作已经完成。剩下就是如何把显示缓冲区的内容放到P3端口上,让LED数码管点亮了。这里为了让程序独立的工作,使用了Timer0服务中断作为定时扫描显示使用。
5. LED的扫描频率设定。因为使用I/O口直接驱动LED的管脚进行显示,因此任何时候,都只可能在3个数码管中,仅有一个是点亮的。但是因为人眼的视觉暂留现象,我们看到多次循环扫描点亮后的数码管是一直亮着的。根据电影和电视的显示频率来看,一般每个数码管最少扫描频率在24次/秒以上时,才能感觉到一直亮着。扫描频率再低时,就会感觉到数字在闪烁。
另外,因为我们要显示的字符最多是8位,因此每3个字符显示一段时间后,必须移动一下,流水形式显示下一位,这个流水的速度不能太快,太快了一样会感到字符闪烁。因此,根据感受,这个移动的频率在1.5-2次/秒左右。这就是下面确定扫描程序的频率的依据。
为了精确确定扫描的周期,使用系统定时器Timer0作为基准。
另外,因考虑到后期还会使用Timer0复用做UART通讯时的波特率发生器,因此选择系统的主时钟在11.0592MHz或大于它的0.5倍的整倍数。这样可以较为精准的产生115200Baud的通讯速率。这里选择基准时钟为11.0592MHz(因STC15F204EA使用内部RC振荡器工作,会有0.2%以内的实际误差)。
Timer0的初始化如下:
  1. /*------------------------------------------------
  2.   定时器中断程序/用于显示
  3. ------------------------------------------------*/
  4. void Init_Timer0(void)
  5. {
  6.     TMOD |= 0x01;     //定时模式1,16位定时方式   
  7.     TH0=0xEE;      //定时器初值: 11.0592MHz晶振, 中断周期5ms
  8.     TL0=0x04;
  9.     PT0=1;          //Timer0中断优先
  10.     EA=1;           //总中断打开
  11.     ET0=1;          //定时中断打开
  12.     TR0=1;          //定时开始
  13.     cp=0;
  14.     dispPtr =0;    //显示位置指针清零
  15.     TIMER0INIT=1; //TIMER0初始化标志,其它地方用到。
  16. }
  17. /*-------------------------------------------------------------------------
  18. 显示服务中断:TIMER0_ISR
  19. 说明: LED的刷新频率在30Hz以上时,没有闪烁感。 此时中断的刷屏频率要大于90Hz。
  20.             在时钟M=11.0592MHz时,TH0=0xEC,TL0=0x04即可。
  21. --------------------------------------------------------------------------*/
  22. void Timer0_isr(void) interrupt 1
  23. {
  24. unsigned char t;
  25. unsigned char i;
  26. TH0=0xEE;  //0xFD,0x57 :32.954MHz --->2.00527KHz
  27. TL0=0x04;  //0xFA,0xB0 :32.954MHz --->1.00686KHz
  28. cp++;    //cp为刷新周期计数,每中断几次,刷新一次。如果系统主频很高,此时的刷新频率数值可以调整到更大。
  29. if (cp == LED_REFRESH_FREQ) {   //5ms * 4 = 20ms LED_REFRESH_FREQ 拖过调整显示延迟常数,
  30.   cp =0;
  31.   dispPtr++;    //显示指针指向下一个要显示的字段
  32.   if (dispPtr ==1) { //显示第一位,先关闭上一个显示位,更新要显示的数值,然后打开要显示的字段。实际显示时间等于2次中断的间隔。
  33.    DIG_3=LED_OFF;
  34.    P3=DispBuf[dispPtr-1];
  35.    DIG_1=LED_ON;
  36.    }
  37.   if (dispPtr ==2) {//显示第二位,做法同上。
  38.    DIG_1=LED_OFF;
  39.    P3=DispBuf[dispPtr-1];
  40.    DIG_2=LED_ON;
  41.    }
  42.   if (dispPtr ==3) {//显示第三位,完成后把显示指针dispPtr变成0,表示一次显示完成。
  43.    DIG_2=LED_OFF;
  44.    P3=DispBuf[dispPtr-1];
  45.    DIG_3=LED_ON;
  46.    dispPtr=0;
  47.     }
  48.    dCount++;    //是否要做流水移动的计数器。这里每刷新50次,移动一次。移动频率=(单字刷新频率*3)/50,约1.8-2.0Hz
  49.   if (dCount>50 && DISPLEN>3) { //循环次数,每个位置显示相同次数后,开始更新下一轮字符。字符移位开始。
  50.          //在两次循环中间插入段行识别2个空格或上划线? 否则首尾相连无法识别。
  51.    dCount=0; //流水移动计数器清零
  52.    t=DispBuf[0];  //保存显存中的第一位
  53.    for (i=0; i<DISPLEN+1;i++)
  54.     DispBuf[i]=DispBuf[i+1];  //循环引动第2位到DISPLEN+1位,向前移动一位
  55.    DispBuf[i]=t; //将第一位补在循环队列的尾部
  56.     }
  57. }
  58. }


 楼主| 奥德赛 发表于 2015-11-16 20:59 | 显示全部楼层
经过以上动作,数据就可以正常在LED上显示了。
6. Timer0参数设置,主频与中断频率的测量值。
对于STC15F204EA的Timer0, 其它主频下可参照调整。具体的测试数据如下(使用P1.7端口电平翻转进行测量的实际频率,非计算值):当TH0=0xEE, TL=0x11时,主频变化与P1.7的端口翻转频率的关系如下:
32.958MHz 输出:298.82Hz
   5.995MHz 输出:54.375Hz
  12.011MHz 输出:108.955Hz
  19.966MHz 输出:181.082Hz
  23.980MHz 输出:217.476Hz
  29.988MHz 输出:271.944Hz
  
  当系统的主频固定设置到33MHz(实际值32.950MHz)时,定时参数设置对输出频率的变化:  
  TH0=0xFF, TL0=0x01  :5.307KHz
  TH0=0xEF TL0=0xA0   :327.236
  TH0=0xF6 TL0=0xA0  :571.172
  TH0=0xF6 TL0=0x00   :535.521
  TH0=0xF5 TL0=0x00   :486.952   
  TH0=0xF5 TL0=0x40   :498.271
  TH0=0xF5 TL0=0x48   :499.761
  TH0=0xF5 TL0=0x4A   :500.080
  TH0=0xCA TL0=0x62   :100.006
  TH0=0xE5 TL0=0x33   :200.000
  TH0=0xEA TL0=0x90   :250.040
  TH0=0xEE TL0=0x23   :300.040
  TH0=0xF2 TL0=0x9C   :400.043
        
  在主频固定设置在M=11.0592MHz, 并且同步打开Timer1 ON(4KHz速率中断,轻负载)时,TH0,TL0与输出频率的关系如下:
  TH0,   TL0,    翻转频率
  0xF2,   0x9C,   134.267Hz
  0xEE,   0x04,   100.003Hz   LED_REFRESH_FREQ=2时,LED闪烁,LED_REFRESH_FREQ=1, 则不再闪烁。
  0xE2,   0x08,   60.016,         LED_REFRESH_FREQ=1,轻微闪烁。
  0xE8,   0x03,   75.000,         LED_REFRESH_FREQ=1.
  0xEC,   0x04,   89.904,         LED_REFRESH_FREQ=1, 此时单个字的刷新周期为29.994Hz(实际测试值)。
这些测量数据和计算值之间有一定的差距。特别是当显示的负载增大时,点亮LED和不点亮LED的中断速率是不一样的。实际使用时,如果需要准确的数据,最好用示波器测量实际值为准。
7.  LED的显示亮度问题。
对于普通的51单片机,无法直接驱动共阴极LED数码管直接显示。因此需要将端口设置为推挽输出模式。

 楼主| 奥德赛 发表于 2015-11-16 21:00 | 显示全部楼层
  1. /关闭所有显示。
  2. LED_Init();
  3. //STC单片机特殊寄存器 PxM0,PxM1设置工作状态。 M1M0=01 推挽式输出,可以直接点亮LED。但是需要增加470ohm分压电阻限流。
  4. P3M0=0xFF;
  5. P3M1=0x0;
mintspring 发表于 2015-11-16 21:03 | 显示全部楼层
系统上电后,程序完成初始化动作,然后逐步从EEPROM中读出一个动作序列执行。用户可以控制在整个动作执行多少次以后,继电器停止动作,完全处于待机状态
mintspring 发表于 2015-11-16 21:03 | 显示全部楼层
特别是当显示的负载增大时,点亮LED和不点亮LED的中断速率是不一样的。实际使用时,如果需要准确的数据,最好用示波器测量实际值为准
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

397

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部