佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

查看: 9216|回复: 179

问问关于atmelAT89c51的program问题!

[复制链接]
发表于 18-2-2009 12:17 AM | 显示全部楼层 |阅读模式
我现在在做CO detection system 的 fy project, 我用了AT89c51的chip来做LCDdisplay。我burn了program进去chip了,但是就是run不了,display screen没有东西出来!有哪位大大可以帮我看看我的program有没有错。是assembly code来的。我用了JHD162A 16bits的LCDdisplay screen。也用了Octal D-type TransparentLatches74ls373。$MOD51是要用来compile成hex code用的。


$MOD51
; LCD Display Driver Demo.
; Timing code assumes 1.8MHz Clock

;LCD Registers addresses
LCD_CMD_WR    equ     0
LCD_DATA_WR    equ    1
LCD_BUSY_RD    equ    2
LCD_DATA_RD    equ    3

;LCD Commands
LCD_CLS        equ    1
LCD_HOME    equ    2
LCD_SETMODE    equ    4
LCD_SETVISIBLE    equ    8
LCD_SHIFT    equ    16
LCD_SETFUNCTION    equ    32
LCD_SETCGADDR    equ    64
LCD_SETDDADDR    equ    128

;Reset vector
    org 0000h
    jmp start


;Start of the program
    org 0100h

string1a:db ' !! D A N G E R !! '
     db 0
string1b:db '!! D A N G E R !! '
     db 0
string2:db ' CARBON MONOXIDE '
    db 0

string3:db ' IN DANGER LEVEL '
    db 0
string4:db ' OVER 100PPM '
    db 0

start:    mov A,#038h
    call wrcmd

loop:    mov A,#LCD_SETVISIBLE+6     ;Make the display & blink visible:
    call wrcmd

    mov R7,#2
loop2:
    mov DPTR,#string1a
    call wrstr

     mov DPTR,#200
     call wtms

    mov A,#LCD_CLS            ;Clear screen
    call wrcmd

    mov DPTR,#string1b
    call wrstr

     mov DPTR,#200
     call wtms

    mov A,#LCD_CLS            ;Clear screen
    call wrcmd

    djnz R7,loop2

    mov DPTR,#string1a
    call wrstr

     mov DPTR,#400
     call wtms

    mov A,#LCD_SETDDADDR+64
    call wrcmd

    mov DPTR,#string2
    call wrslow

     mov DPTR,#200
     call wtms

    mov A,#LCD_CLS            ;Clear screen
    call wrcmd

    mov DPTR,#string3
    call wrslow

        mov A,#LCD_SETDDADDR+64
    call wrcmd

    mov DPTR,#string4
    call wrslow

    mov A,#LCD_SETVISIBLE+7        ;Show the blink cursor as well.
    call wrcmd

     mov DPTR,#2000
     call wtms

    mov A,#LCD_CLS            ;Clear screen
    call wrcmd

    jmp loop


;Sub routine to write null terminated string at DPTR in program ram.
wrstr:    mov R0,#LCD_DATA_WR
wrstr1:    clr A
    movc A,@A+DPTR
    jz wrstr2
    movx @R0,A
    call wtbusy
    inc DPTR
    push DPL
    push DPH
    pop DPH
    pop DPL   
    jmp wrstr1
wrstr2:    ret

;Sub routine to write null terminated string at DPTR in program ram. Slowly
wrslow:    mov R0,#LCD_DATA_WR
wrslw1:    clr A
    movc A,@A+DPTR
    jz wrslw2
    movx @R0,A
    call wtbusy
    inc DPTR
    push DPL
    push DPH
        mov DPTR,#100
        call wtms
    pop DPH
    pop DPL   
    jmp wrslw1
wrslw2:    ret


;Sub routine to write command:
wrcmd:    mov R0,#LCD_CMD_WR
    movx @R0,A
    jmp wtbusy


;Sub routine to write character:
wrchar:    mov R0,#LCD_DATA_WR
    movx @R0,A

;Subroutine to wait for busy clear
wtbusy: mov R1,#LCD_BUSY_RD
    movx A,@r1
    jb ACC.7,wtbusy
    ret

;Wait for number of seconds in A
wtsec:    push ACC
    call wtms
    pop ACC
    dec A
    jnz wtsec
    ret

;Wait for number of milliseconds in DPTR
wtms:   xrl DPL,#0FFh            ;Can't do DEC DPTR, so do the loop by forming 2's complement
    xrl DPH,#0FFh            ;and incrementing instead.
    inc DPTR
wtms1:    mov TL0,#09Ch            ;100 ticks before overflow = 1ms at 1.2MHz Clock
    mov TH0,#0FFh   
    mov TMOD,#1            ;Timer 0 mode 1
    setb TCON.4            ;Timer 0 runs
wtms2:    jnb TCON.5,wtms2   
    clr TCON.4            ;Timer 0 stops
    clr TCON.5
    inc DPTR
    mov A,DPL
    orl A,DPH
    jnz wtms1
    ret

   
    END
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 18-2-2009 05:04 PM | 显示全部楼层
有没有哪位大大可以帮帮忙!!
回复

使用道具 举报

发表于 18-2-2009 08:43 PM | 显示全部楼层
原帖由 gabrielloy 于 18-2-2009 05:04 PM 发表
有没有哪位大大可以帮帮忙!!


不是不想帮。只是懒惰看。 有没有pseudo code还是flow chart?
schematics 呢?没有schematics很难。
回复

使用道具 举报

 楼主| 发表于 18-2-2009 10:14 PM | 显示全部楼层
请问要怎样upload图片??我harddisk里面的circuit schematic diagram.
回复

使用道具 举报

发表于 18-2-2009 11:59 PM | 显示全部楼层
原帖由 gabrielloy 于 18-2-2009 10:14 PM 发表
请问要怎样upload图片??我harddisk里面的circuit schematic diagram.


先upload 去www.photobucket.com
再link过来。
回复

使用道具 举报

 楼主| 发表于 19-2-2009 12:40 AM | 显示全部楼层
我的circuit diagram,.
其实我只是想有一个5V进其中一个input port,either pins 1~8,然后就display "CO inside car in danger level" ,没有input的时候,就display "CO inside car in safety level" 这么简单的。
那个5V的input我是connect到一个CO sensor,当sensor detect到CO above danger level,then 就会有一个5V的output,我就把它connect to AT89c51的input port。
不知我用C program来写会不会比较容易?
回复

使用道具 举报

Follow Us
发表于 19-2-2009 03:11 AM | 显示全部楼层
原帖由 gabrielloy 于 19-2-2009 12:40 AM 发表
我的circuit diagram,.
其实我只是想有一个5V进其中一个input port,either pins 1~8,然后就display "CO inside car in danger level" ,没有 ...


你不缺io pin.直接把lcd i/o 接去8051.不用latch容易。 又省ic.
我习惯用c 写,program比较readable.我也觉得比较简单。
回复

使用道具 举报

 楼主| 发表于 19-2-2009 09:16 AM | 显示全部楼层
昨晚我用C来program,我define了一个input pin,int p1.0,8个outputs,int AD0~AD7.然后我用if loop,if p1.0=1,then printf("CO inside car in danger level").else printf("CO inside car in safety level").可是有两个syntax errors,第一个就是line no.4,syntax error near'.0'就是define有问题,第二个就是line 17,syntax error near'else'.how?
#include<stdio.h>
main()
{
  int P1.0 = a;
  int AD0;
  int AD1;
  int AD2;
  int AD3;
  int AD4;
  int AD5;
  int AD6;
  int AD7;
  
  if (a = 1)
  {
    printf("CO inside car in danger level");
   else
    printf("CO inside car in safety level");
   
  }
}
我的c也很差的!!
回复

使用道具 举报


ADVERTISEMENT

发表于 19-2-2009 03:50 PM | 显示全部楼层
原帖由 gabrielloy 于 19-2-2009 09:16 AM 发表
昨晚我用C来program,我define了一个input pin,int p1.0,8个outputs,int AD0~AD7.然后我用if loop,if p1.0=1,then printf("CO inside car in danger level").else printf("CO inside car in safety level").可是有两个 ...


你用什么compiler?
你是要看a = 1 就CO inside car in danger level。 = 0 就CO inside car in safety level???
你的code 应该这样写。
我用keil c51 compiler. eval version 可以从www.keil.com拿到。
在keil c51里面, 如果要用printf,你就要overwrite putc function.
我本身有lcd code.不过不是用printf.自己写function 我的printf给serial port用。
  1. #include<stdio.h>
  2. sbit a = P1^0;
  3. int main(void)
  4. {
  5.     if (a == 1)
  6.                 printf("CO inside car in danger level";
  7.     else
  8.                 printf("CO inside car in safety level";
  9.     while (1);
  10.     return 0;
  11. }
复制代码

[ 本帖最后由 fritlizt 于 19-2-2009 06:05 PM 编辑 ]
回复

使用道具 举报

发表于 19-2-2009 06:00 PM | 显示全部楼层

回复 9# fritlizt 的帖子

应该是 if (a == 1) 吧。

但是这样的程序很奇怪,只跑一次就停了啊?

[ 本帖最后由 waiweng83 于 19-2-2009 06:03 PM 编辑 ]
回复

使用道具 举报

发表于 19-2-2009 06:07 PM | 显示全部楼层
原帖由 waiweng83 于 19-2-2009 06:00 PM 发表
应该是 if (a == 1) 吧。

但是这样的程序很奇怪,只跑一次就停了啊?


paiseh是a==1才对。
从他的program, 我是猜他跑一次而已。
回复

使用道具 举报

 楼主| 发表于 19-2-2009 11:48 PM | 显示全部楼层
原帖由 fritlizt 于 19-2-2009 03:50 PM 发表


你用什么compiler?
你是要看a = 1 就CO inside car in danger level。 = 0 就CO inside car in safety level???
你的code 应该这样写。
我用keil c51 compiler. eval version 可以从www.keil.com拿到。
在 ...

so according to ur c program,我可看到你有用while(1),不就是能让function可以一直loop吗?还有我也是用keil c51 compiler的。
如果我现在把那个74ls373拿掉,那我的circuit应该怎么接呢?是不是output ports AD0~AD7 照样接去LCD display screen 的D0~D7。那么LCD的pin 4 and 5 该怎么接?还有如果像大大的program,用了compiler,compile出来的hex code,真的可以display 在LCD吗?因为之前我用上面的assembly code,compile成hex code,然后burn进89c51里,run的时候,就是什么都不显示!!
回复

使用道具 举报

发表于 20-2-2009 02:07 AM | 显示全部楼层
原帖由 gabrielloy 于 19-2-2009 11:48 PM 发表

so according to ur c program,我可看到你有用while(1),不就是能让function可以一直loop吗?还有我也是用keil c51 compiler的。
如果我现在把那个74ls373拿掉,那我的circuit应该怎么接呢?是不是output ports AD ...


那个while(1); 是让他stuck在program 最后一行。避免program counter overflow的时候, program restart at address 0x0000.
你可以参考这个贴。 不过是用pic mcu的。

给你一个例子.
4bit mode.只需要7个i/o.如果没有check busy flag,用delay,只需要6个i/o
我的program 是要check busy flag. 用P2.0 -> P2.6
这个schematics不完整。 只是显示lcd的部分。 真正你需要crystal, reset circuit, 等之类的。
我的program 用12Mhz crystal来计算。 如果你是用其他的,delay_ms 要改。


  1. #include <at89x51.h>

  2. #define                CLR_DISP                0x01        
  3. #define                DISP_ON                        0x0C        
  4. #define                DISP_OFF                0x08        
  5. #define                CUR_HOME        0x02
  6. #define                CUR_OFF                 0x0C
  7. #define     CUR_ON_UNDER    0x0E
  8. #define     CUR_ON_BLINK    0x0F
  9. #define     CUR_LEFT        0x10
  10. #define     CUR_RIGHT       0x14
  11. #define                CUR_UP                  0x80        
  12. #define                CUR_DOWN                0xC0
  13. #define     ENTER           0xC0
  14. #define                DD_RAM_ADDR                0x80        
  15. #define                DD_RAM_ADDR2        0xC0

  16. sbit D7 = P2^6;
  17. sbit D6 = P2^5;
  18. sbit D5 = P2^4;
  19. sbit D4 = P2^3;
  20. sbit EN = P2^2;
  21. sbit RW = P2^1;
  22. sbit RS = P2^0;

  23. void system_init (void);
  24. void delay_ms (unsigned int milisec);
  25. void lcd_init (void);
  26. void lcd_write_cmd (unsigned char cmd);
  27. void lcd_write_data (unsigned char character);
  28. void lcd_print (char *string);
  29. void lcd_busy (void);

  30. int main (void)
  31. {
  32.         system_init ();
  33.         lcd_print ("fritzlizt\n@cari";
  34.         while (1);
  35.         return 0;
  36. }

  37. void system_init (void)
  38. {
  39.         P0 = 0xFF;          //port initialization
  40.         P1 = 0xAA;
  41.         P2 = 0xFF;
  42.         P3 = 0xFF;
  43.         TMOD = 0x21;        // set timer 1 to 8bit auto reload mode.
  44.         lcd_init();
  45. }

  46. void delay_ms (unsigned int milisec)
  47. {  
  48.         unsigned int i;

  49.         for (i = 1; i <= milisec; i++){
  50.                 TH0 = 0xFC;
  51.                 TL0 = 0x18;
  52.                 TR0 = 1;
  53.                
  54.                 while (!TF0);
  55.                 TF0 = 0;
  56.                 TR0 = 0;
  57.         }
  58. }

  59. void lcd_init (void)
  60. {
  61.         unsigned char i;
  62.         delay_ms (15);
  63.         RS = 0;
  64.         RW = 0;
  65.         
  66.         for (i = 0; i < 3; i++){
  67.                 EN = 1;
  68.                 D7 = 0;
  69.                 D6 = 0;
  70.                 D5 = 1;
  71.                 D4 = 1;
  72.                 EN = 0;
  73.                 delay_ms (5);
  74.         }
  75.         
  76.         EN = 1;
  77.         D7 = 0;
  78.         D6 = 0;
  79.         D5 = 1;
  80.         D4 = 0;
  81.         EN = 0;
  82.         delay_ms (5);
  83.         
  84.         lcd_write_cmd (0x28);                                   //4 bit mode
  85.         lcd_write_cmd (CUR_ON_BLINK);                //display on, curser on, curcor blink on
  86.         lcd_write_cmd (CLR_DISP);                         //Clear Display
  87.         lcd_write_cmd (0x06);                                //increment cursor position
  88. }

  89. void lcd_write_cmd (unsigned char cmd)
  90. {
  91.         lcd_busy();
  92.         RW = 0;
  93.         RS = 0;         
  94.         EN = 1;
  95.         
  96.         D7 = cmd & 0x80;
  97.         D6 = cmd & 0x40;
  98.         D5 = cmd & 0x20;
  99.         D4 = cmd & 0x10;
  100.         EN = 0;
  101.         
  102.         EN = 1;         
  103.         D7 = cmd & 0x08;
  104.         D6 = cmd & 0x04;
  105.         D5 = cmd & 0x02;
  106.         D4 = cmd & 0x01;
  107.         EN = 0;
  108. }

  109. void lcd_write_data (unsigned char character)
  110. {
  111.         lcd_busy();
  112.         RW = 0;
  113.         RS = 1;
  114.         EN = 1;
  115.         
  116.         D7 = character & 0x80;
  117.         D6 = character & 0x40;
  118.         D5 = character & 0x20;
  119.         D4 = character & 0x10;
  120.         EN = 0;
  121.         
  122.         EN = 1;                 
  123.         D7 = character & 0x08;
  124.         D6 = character & 0x04;
  125.         D5 = character & 0x02;
  126.         D4 = character & 0x01;
  127.         EN = 0;
  128. }

  129. void lcd_print (char *string)
  130. {
  131.         unsigned char temp, i = 1;
  132.         lcd_write_cmd (CLR_DISP);
  133.         for (temp = 0; string[temp]!= 0; temp++){
  134.                 if (string[temp] == '\n'){
  135.                         i++;
  136.                         if(i > 2)
  137.                                 i = 1;
  138.                         switch (i){
  139.                                 case 1:
  140.                                         lcd_write_cmd (CUR_UP);
  141.                                         break;
  142.                                 case 2:
  143.                                         lcd_write_cmd (CUR_DOWN);
  144.                                         break;        
  145.                                 default:
  146.                                         break;
  147.                         }
  148.                 }
  149.                 else
  150.                         lcd_write_data (string[temp]);
  151.         }
  152. }

  153. void lcd_busy (void)
  154. {
  155.         bit busy = 1;
  156.         RS = 0;
  157.         RW = 1;
  158.         D7 = 1;
  159.         D6 = 1;
  160.         D5 = 1;
  161.         D4 = 1;
  162.         while (busy){
  163.                 EN = 0;
  164.                 EN = 1;
  165.                 EN = 1;
  166.                 busy = D7;
  167.                 EN = 0;
  168.                 EN = 1;
  169.         }
  170.         EN = 0;
  171. }
复制代码

[ 本帖最后由 fritlizt 于 22-2-2009 12:24 AM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 20-2-2009 11:11 AM | 显示全部楼层
can i ask that how many bits LCD display screen u used,i mean the LM016L,for me one is the 16*2 LCD,JHD 162A.The crystal can connect like my diagram above,but how about the reset circuit?due to my C programming also not good, so i dont know what mean by #define                CLR_DISP                0x01        ?the 0x01?

请用中文回复。 你更改过后我再回答你。谢谢。
fritzlizt

[ 本帖最后由 fritlizt 于 20-2-2009 12:25 PM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 20-2-2009 10:03 PM | 显示全部楼层
不好意思,这是我用学校电脑时,没有换成中文。是这样的,我想问问你用的LCD是多少bits的?我用的是16*2的。我的reset circuit像你一样直接接到ground就可以了吗?如果我换了你program里的string,换成我的string,“CO inside car in danger level",program会run吗?所以我才要问你你用的是多少bits的LCD。你的program只要一个input in,就会display不是吗?如果用16*2的LCD的话,要改哪里呢?
回复

使用道具 举报

发表于 20-2-2009 10:28 PM | 显示全部楼层
原帖由 gabrielloy 于 20-2-2009 10:03 PM 发表
不好意思,这是我用学校电脑时,没有换成中文。是这样的,我想问问你用的LCD是多少bits的?我用的是16*2的。我的reset circuit像你一样直接接到ground就可以了吗?如果我换了你program里的string,换成我的string,“ ...


我想问问你用的LCD是多少bits的?我用的是16*2的。
->你用的lcd是hd44780 type.它可以有8bit 还是4 bit interface mode.看你如何configure.我的program是4bit interface的.

我的reset circuit像你一样直接接到ground就可以了吗?
-〉http://www.freewebs.com/maheshwankhede/basic.html. 我也是拿它的设计。manual reset

如果我换了你program里的string,换成我的string,“CO inside car in danger level",program会run吗?
->会

你的program只要一个input in,就会display不是吗?
->不明白。什么意思?

如果用16*2的LCD的话,要改哪里呢?
->不用改。我用的也是16*2 lcd.
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 20-2-2009 10:34 PM | 显示全部楼层
请问TH0 ,TL0 和TR0不用define吗?直接就可以在for loop里等于TH0 = 0xFC;
TL0 = 0x18;
TR0 = 1;
你的int milisec=15?
还有TMOD = 0x21;        // set timer 1 to 8bit auto reload mode.是什么意思?不是很明白,不好意思
回复

使用道具 举报

 楼主| 发表于 20-2-2009 10:40 PM | 显示全部楼层
我的意思就是input port p1.0~p1.7,随便给其中一个5V就会display了,对吗?
回复

使用道具 举报

 楼主| 发表于 20-2-2009 10:47 PM | 显示全部楼层
对对,我的LCD的pin 4,5 ,6,7,DB4,DB5,DB6和DB7都是4-bit or 8-bit interface的
回复

使用道具 举报

发表于 20-2-2009 11:17 PM | 显示全部楼层
原帖由 gabrielloy 于 20-2-2009 10:40 PM 发表
我的意思就是input port p1.0~p1.7,随便给其中一个5V就会display了,对吗?


我的program不用input.开电就有display了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 7-1-2025 08:30 AM , Processed in 0.119509 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表