现在的位置: 首页 > 综合 > 正文

2)51下广告灯数码管和MSP430数码管

2013年05月03日 ⁄ 综合 ⁄ 共 4782字 ⁄ 字号 评论关闭

本来只是想的实现一个开关的,但是最近自己拖拉了所以再加上点功能吧,这个功能就是广告灯的左右移动,不过我加了一个可以开关控单灯的输入。本来准备430也是一样的不过今天拿到开发板发现没有那么多LED⊙﹏⊙,所以就直接用数码管了。

#include // unsigned char i;

unsigned char temp;

 unsigned char a,b;

 sbit K1=P3^0; //开关

 sbit L1=P2^0;//小灯

void delay(void) /*延时0.2秒*/

{ unsigned char m,n,s;

for(m=20;m>0;m--)

for(n=20;n>0;n--)

for(s=248;s>0;s--);

}

void main(void)

{

while(1) {

 if(K1==0) //开关闭合

{

 L1=0; //灯亮 ---p1.0输出低电平 ,L1有电势差。

}

else

{

L1=1; //灯灭

}

}

temp=0xfe;

 P1=temp; /*P1赋值feH,这个feH是什么呢,fe就是11111110 ,效果就是P1.7为0 */

 delay();

 for(i=1;i<8;i++) /*L1到L8*/

{

a=temp<<(i); //01111111

b=temp>>(8-i);

P1=a|b; /*按位或,解释一下上面两句由于C语言的移位运算会丢失初始位,因此这个结果第一次就是01111111了*/

delay();

 }

for(i=1;i<8;i++) /*L8到L1*/ {

 a=temp>>i;

 b=temp<<(8-i);

 P1=a|b;

 delay();

}

} 会看到小灯不断变换的效果和一个开关控制了呵呵。 ############################################################## 然后是汇编的程序

ORG 00H

START1: JB P3.0,LIG ; 如果P3.0为高电平,(本例即开关闭合),则执行LIG。

 CLR P2.0

START2: MOV R2,#8

MOV A,#0FEH SETB C ;设定进位C为1

LOOP: MOV P1,A

LCALL DELAY

RLC A ;将累加器含进位C左移一位

DJNZ R2,LOOP

MOV R2,#8

LOOP1: MOV P1,A

LCALL DELAY

RRC A

DJNZ R2,LOOP1

SJMP START 1 ; 转入主程序,跳转的范围不一样,可以说是到达的远近距离不一样。存储空间占用不一样。

;AJMP 的范围是11位地址,也就是2K的空间内,占用存储空间2个字节,执行周期24个时钟周期。

;LJMP 的范围是16位地址,也就是64K的空间内,占用存储空间3个字节,执行周期24个时钟周期。

;SJMP 的范围是8位地址,也就是256BIT的空间内,占用存储空间2个字节,执行周期24个时钟周期。

;JMP一般配合DPTR使用,存储空间1个字节,执行周期24个时钟周期。一般用于多分枝选择的时候使用,比如按键处理。

LIG: SETB P2.0 ;使P2.0变为1。灯灭。

DELAY: MOV R5,#20 ;

;(延时0.2秒的开始)

D1: MOV R6,#20

D2: MOV R7,#248

DJNZ R7,$ ;$是一直执行这条指令,每执行一次R7减一,直到R7为零后,执行下一条指令.

DJNZ R6,D2

DJNZ R5,D1

RET ;(延时0.2秒的结束)

 END 这个程序可以很容易的看出一个问题就是对于移位操作来说,汇编比C语言要简洁好用的多。应为汇编不会丢失位 ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥

然后很悲剧的还是51的C代码,是驱动数码管的,我们直接忽视掉静态扫描采用动态扫描,我们51仿真用的是外接为74LS245

我们的效果是如果开关打开显示HELLO,关闭则显示12345。我手头的仿真源程序就是这么给的呵呵。

#include <AT89X51.H> //reg52.h
unsigned char code table1[]={0x06,0x5b,0x4f,0x66,0x6d}; //HELLO
unsigned char code table2[]={0x76,0x79,0x38,0x38,0x3f}; //12345
unsigned char i,j;
unsigned char a,b;
unsigned char temp; 
void main(void)
{
  while(1)
    {
      temp=0xfe; //11111110
     
      for(i=0;i<5;i++) //动态循环显示        {
          if(P1_7==1) //高电平
            {
              P0=table2[i];
            }
            else
              {
                P0=table1[i];
              }
          P2=temp; //填入com控制 ,我们只用了6个,现在就是全部是1 ~2.0到2.5 
          a=temp<<(1);
          b=temp>>(7);
          temp=a|b; //这个眼熟吧,上面那个程序里就有,就是移位,并且补充丢失位
    for(a=4;a>0;a--)
          for(b=248;b>0;b--) {}
          P2=0xff;//重置P2
        
        }
    }
}

#################################################################

有了上面广告灯的代码后这个很好理解吧,然后是汇编,汇编我就完全复制了,试着解释一下(那个括号写这个资料同志写的)

ORG 00H

START:          JB P1.7,DIR1        ;这个是开关的功能

              MOV DPTR,#TABLE1 ;将table1的内容放入数据指针寄存器

                     SJMP DIR              ;短跳转

DIR1:            MOV DPTR,#TABLE2

DIR:              MOV R0,#00H

                     MOV R1,#0FEH     ;(原文为 MOV R1,#01H ;                  R1 FEH 1111 1110

NEXT:           MOV A,R0                  ; A 中为: 00H      P0 00H

              MOVC A,@A+DPTR               ; A 中为: 76H~(A) ←((A)+(DPTR))

                     MOV P0,A                 ;                  P0 76H

              MOV A,R1                        ; A 中为: FEH

                     MOV P2,A                     ;                                           P2 FEH

                     LCALL DAY       

MOV P2,#0FFH      ; (比原文增加的,去掉变成乱码 )                      P2 FFH

              INC R0

                     RL A                          ; A 中为: FDH   累加器左循环移位

                     MOV R1,A                   ;                             R1 FDH

              CJNE R1,#0DFH,NEXT                               ;控制跳转~ 1101 1111 左移前为 1110 1111 ,所以 R1 共左移 5

                     SJMP START

DAY:             MOV R6,#4                 ; 当把 #4 改为 #255 可以明显看到 各数码管的轮流点亮

D1:                MOV R7,#248             

                  DJNZ R7,$

                     DJNZ R6,D1

                     RET

TABLE1:        DB 06H,5BH,4FH,66H,6DH     ; 显示“12345 ”字样( 共阴)

TABLE2:        DB 78H,79H,38H,38H,3FH     ; 改为 TABLE2:       DB 76H,79H,38H,38H,3FH 显示“HELLO ”字样。

                     END

¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥

发觉C现在语言真是方便啊~呵呵,下一个是MSP430的C程序

之前说一下430F449的开发板数码管是由P3口和2个锁存器一起使用的,所以可以看到下面的代码里有2个锁存器控制~这个是经过调试的了,显示12345(顺便说一下,照书抄害死人啊,书上的代码不一定都是调试过的)

#include <msp430x44x.h>
const unsigned char num[6]=
{0x14,0xcd,0x5d,0x1E,0x5b,0x00};
unsigned char led_buff[6];
unsigned char led_ctrl;
void init(void){
  char tmp;
  P3DIR = 0xff; //设置P3输出
  P3OUT = 0x00; //设置初始值0
  P4DIR |= 0x03; //设置P4.0,P4.1输出
  P4OUT &= 0xfc;//设置初始值
  led_ctrl = 0;//用于控制哪个led显示
  for(tmp=0 ; tmp<6;tmp++)//初始化缓冲区
  {
  led_buff[tmp]=tmp;
  }
}
void led_display(){
  unsigned tmp ;
  tmp =0x01;
  P3OUT = num[led_buff[led_ctrl]];//设置显示值
  P4OUT |= 0x02;//打开数据锁存
  P4OUT &= 0XFD ;//关闭
  P3OUT = ~(tmp<<led_ctrl);//设定哪个led显示
  P4OUT |= 0X01;
  P4OUT &= 0xFE;
  led_ctrl = (led_ctrl + 1)%6;//设置下一个要显示的led 
}
void main(void)
{
WDTCTL = WDTHOLD + WDTPW ;
 init();
 while(1)
 led_display();
}
######################################################################

本来这里应该是MSP430的汇编程序,不过我汇编纯属自己初学了解,尝试了一下并不是很顺利,就暂时pass吧。可以仿照上面51下的代码来做不过要注意430汇编的语句中的不同变化,还有寄存器的使用,如果是这个开发板的话那么还有控制锁存的开关问题。汇编现在的确是不流行不过我觉得了解一下对寄存器的使用很有帮助,并且以后也会遇到C和汇编混合编程的问题。不管怎么说先慢慢看着吧。真不好练习啊汇编。

抱歉!评论已关闭.