Thông báo

Collapse
No announcement yet.

Dùng bảng .DB và .DW như thế nào

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Dùng bảng .DB và .DW như thế nào

    Anh chị nào biết rồi chỉ em với. Để lập trình cho led 7 thanh, led matrix,..... chúng ta thường sử dụng thư viện bảng DB hay DW. Nhưng chỗ này em bị mắc vẫn chưa làm ra được. Anh chị chỉ em với. Theo em biết thì có thanh ghi Z là thanh ghi con trỏ dữ liệu và con trỏ chương trình. Và trong việc sử dụng trong bảng DB thì nó có tác dụng trỏ tới vùng địa chỉ trong bộ nhớ chương trình để lấy dữ liệu và nạp giá trị đó vào 1 trong 32 thanh ghi RF(ATMega16)
    em sử dụng lệnh

    LPM R10,Z+

    Ví dụ em có bảng DB sau
    ILOVEYOU:
    .DB $54,$32,$21,$05 ; CÁC GIÁ TRỊ NÀY CHỈ LẤY VÍ DỤ THÔI
    ret

    Bây giờ thì làm thế nào để lấy dữ liệu từ bảng DB ILOVEYOU đây hả các anh
    . Em thì đã làm qua 8051 thì nó chỉ cần dùng lệnh

    mov dptr,ILOVEYOU

    là được rồi, còn ở AVR thì em thấy có lệnh

    LDI R31, HIGH(ILOVEYOU)
    LDI R30, LOW(ILOVEYOU)

    MÀ giá trị được nập vào R31, R30 là địa chỉ hay nội dung đầu của bảng DB hả các anh. Em đang bị loạn vì kiến thức nền tảng không có nên mong anh chị nào biết thì bảo em với. Cảm ơn anh chị trươdc nha

  • #2
    Xin hướng dẫn bạn 1 chút:
    Đầu tiên là nội dung bảng LED 7 đoạn: (cái này thay đổi tùy cách nối 7 đoạn vào port)
    SevenSegTable: ; 7_seg Table
    .DB 0b00010001, 0b10110111, 0b00101001, 0b00100011
    ; 0 1 2 3
    .DB 0b10000111, 0b01000011, 0b01000001, 0b00110111
    ; 4 5 6 7
    .DB 0b00000001, 0b00000011
    ; 8 9

    Sau đó là trỏ thanh ghi chỉ số vào địa chỉ đầu tiên của bảng :
    ldi ZH, high(SevenSegTable*2)
    ldi ZL, low(SevenSegTable*2)

    Bây giờ cần tra bảng ở vị trí nào đó, hãy nạp vị trí vào thanh ghi, R17 chẳng hạn.
    Ví dụ cần tra số 5 để hiển thị, thì ldi R17, 5.
    clr R0
    add ZL, R17
    adc ZH, R0
    lpm R17, Z

    Giá trị cần tra là giá trị được nạp trở lại R17.
    R0 là 1 biến trung gian, nếu sợ trùng thì thêm lệnh push R0 ở đầu và pop R0 ở cuối của đoạn chương trình.
    Imagine all the people
    Living life in peace...

    Comment


    • #3
      Anh ơi. Cảm ơn anh nhé. Về nhà em sẽ thử.
      Nhưng em muốn hỏi thêm
      Thứ nhất là:
      ldi ZH, high(SevenSegTable*2) ; *2 ở đây là có tác dụng gì vậy
      ldi ZL, low(SevenSegTable*2)
      Thứ 2 là : Sau đó anh dùng lệnh
      add ZL, R17
      adc ZH, R0
      ; Chỗ này không bị ghi đè lên thanh ghi ZL, ZH mà đã lưu giá trị địa chỉ trong bảng hay sao, em thấy anh dùng lệnh adc mà ko dùng add thì chắc là có cái gì đó nhưng mà em ko giải thích đc

      Comment


      • #4
        Sở dĩ phải nhân 2 vì địa chỉ của bảng tính theo word, 1 word ở đây bằng 2 byte.
        Ví dụ : địa chỉ byte đầu tiên của bảng là 0x1000.
        Ta cần tra mã LED 7 đoạn của số 5, tức là cần data ở địa chỉ byte là (0x1000 * 2 +5)
        Lệnh add chính là để cộng thêm 5 vào ZL, còn lệnh adc là để cộng cờ nhớ (nếu phép cộng add gây ra nhớ) vào ZH.
        Ví dụ phép cộng thập phân cho dễ hiểu: 29 + 5 = 34
        Đầu tiên 9 + 5 cho ra 4 và nhớ 1.
        Sau đó 2 cộng "nhớ 1" bằng 3.
        Imagine all the people
        Living life in peace...

        Comment


        • #5
          Nguyên văn bởi GS_Nobita Xem bài viết
          Anh chị nào biết rồi chỉ em với. Để lập trình cho led 7 thanh, led matrix,..... chúng ta thường sử dụng thư viện bảng DB hay DW. Nhưng chỗ này em bị mắc vẫn chưa làm ra được. Anh chị chỉ em với. Theo em biết thì có thanh ghi Z là thanh ghi con trỏ dữ liệu và con trỏ chương trình. Và trong việc sử dụng trong bảng DB thì nó có tác dụng trỏ tới vùng địa chỉ trong bộ nhớ chương trình để lấy dữ liệu và nạp giá trị đó vào 1 trong 32 thanh ghi RF(ATMega16)
          em sử dụng lệnh

          LPM R10,Z+

          Ví dụ em có bảng DB sau
          ILOVEYOU:
          .DB $54,$32,$21,$05 ; CÁC GIÁ TRỊ NÀY CHỈ LẤY VÍ DỤ THÔI
          ret

          Bây giờ thì làm thế nào để lấy dữ liệu từ bảng DB ILOVEYOU đây hả các anh
          . Em thì đã làm qua 8051 thì nó chỉ cần dùng lệnh

          mov dptr,ILOVEYOU

          là được rồi, còn ở AVR thì em thấy có lệnh

          LDI R31, HIGH(ILOVEYOU)
          LDI R30, LOW(ILOVEYOU)

          MÀ giá trị được nập vào R31, R30 là địa chỉ hay nội dung đầu của bảng DB hả các anh. Em đang bị loạn vì kiến thức nền tảng không có nên mong anh chị nào biết thì bảo em với. Cảm ơn anh chị trươdc nha
          toàn sử dụng ngôn ngữ C,ASM bó tay luôn,sao bạn không sử dụng C cho đơn giản hơn nhỉ.

          Comment


          • #6
            Chứng tỏ bạn chưa học Asm rồi, càng học sẽ càng thấy hay, càng viết càng thấy thích...
            C giúp thực hiện các đề tài một cách đơn giản hơn, nhưng để hiểu rõ cấu trúc cũng như hoạt động của VDK. Hãy lập trình bằng ASM để thấy cái thú của nó.!

            Comment


            • #7
              Nguyên văn bởi mrcuongcon Xem bài viết
              Chứng tỏ bạn chưa học Asm rồi, càng học sẽ càng thấy hay, càng viết càng thấy thích...
              C giúp thực hiện các đề tài một cách đơn giản hơn, nhưng để hiểu rõ cấu trúc cũng như hoạt động của VDK. Hãy lập trình bằng ASM để thấy cái thú của nó.!
              hehe,bác nhầm rùi,mình có học asm chứ.ban đầu mình học asm với 89,khi nắm rõ rùi mới qua C chơi cho vui.hồi học avr táng luôn bằng thằng C,ngồi cầy avr bằng asm cũng mệt và mất thời gian hơn thằng C.Học asm để hiểu đc phần gốc của nó thì là đúng rồi.nhưng học C luôn cũng không thiệt là bao đâu

              Comment


              • #8
                Cảm ơn anh nha. Em đã làm được rùi.mất mấy hôm chỉ vì cái bảng DB. bây giờ em đang tập dùng Timer và ngắt. Sao em đọc không thấy có ví dụ nào cụ thể về cái này nhỉ. Đọc sách của thầy Tập thấy lung tung quá.không có ví dụ đến cách dùng của cái này gì cả. Nếu em muốn dùng Timer thay cho Delay thì phải làm gì hả anh chị. Anh, chị nào biết chỉ em với nhé.

                Comment


                • #9
                  À ! Em đã có xem lại về cái bảng DB này và về vùng bộ nhớ chương trình. Cách mà nó trỏ tới địa chỉ của một lệnh nào đó đã nạp vào khác với cách mà nó trỏ tới vùng nhớ chương trình của bảng DB có đúng ko nhỉ ?
                  Khi nó trỏ tới 1 địa chỉ của một lệnh nào đó trong vùng này thì nó là vùng bộ nhớ chương trình dường như đc sắp xếp theo địa chỉ 16 bit.
                  Còn nếu khi trỏ tới bảng DB thì việc tổ chức dữ liệu lại đc sắp xếp theo kiểu 8 bit có phải ko nữa . Đại khái là nó như vậy. Em cũng chẳng biết giải thích cái chỗ này ra sao nữa. Anh chị nào biết chỉ dùm em với nha. Thanks anh chị nhiều.

                  Comment


                  • #10
                    Bác Vinhsnooker cho mình hỏi là : Bạn thấy học học lập trình C cho 89 rồi chuyển sang lập trình C cho AVR có gì khác nhiều lắm ko. Mình cũng đang định chuyển sang C để phất triển ứng dụng nhưng mà mình phải sài thằng ASM này cho tươm tươm đã. Có gì bạn chỉ mình về lập trình C với nha

                    Comment


                    • #11
                      Nguyên văn bởi mrcuongcon Xem bài viết
                      Chứng tỏ bạn chưa học Asm rồi, càng học sẽ càng thấy hay, càng viết càng thấy thích...
                      C giúp thực hiện các đề tài một cách đơn giản hơn, nhưng để hiểu rõ cấu trúc cũng như hoạt động của VDK. Hãy lập trình bằng ASM để thấy cái thú của nó.!
                      Lúc mới học VDK mình cũng xài toàn là ASM ko hè,viết chương trình càng nhiều thì càng hiểu hơn về cấu trúc của nó,tuy nhiên để lập trình cho những cái lớn thì vất vả lắm đấy,theo mình thì mới học nên chọn ASM, thấy ổn rồi thì chuyển qua C, khi đó các bạn sẽ thấy dc sự khác biệt rõ rệt => C khỏe hơn nhiều,mình viết chương trình quang báo bằng C thấy sướng quá trời luôn,lúc trước viết bằng ASM mệt bỏ mẹ

                      Comment


                      • #12
                        .include"m8def.inc"
                        ;===================NAME OF RESISTER========================
                        .def TEMP=R17
                        .def TEMP1=R18
                        .def TEMP2=R19
                        .def DK=R16
                        .def VALUE=R20





                        .ORG 0X00
                        RJMP RESET

                        DELAY:
                        LDI R27,5
                        D0:
                        LDI R25,200
                        D1:
                        LDI R26,200
                        D2:
                        DEC R26
                        BRNE D2
                        DEC R25
                        BRNE D1
                        DEC R27
                        BRNE D0
                        RET



                        RESET:

                        ;================PUT POINTER DATA TO MYDATA=============
                        LDI ZH,HIGH(MYDATA*2)
                        LDI ZL,LOW (MYDATA*2)
                        ;========================PORT DATA OUT===================
                        LDI TEMP,0XFF
                        OUT DDRB,TEMP

                        LDI TEMP,0X00
                        OUT PORTB,TEMP

                        LDI TEMP,0XFF
                        OUT DDRD,TEMP

                        LDI TEMP,0X00
                        OUT PORTD,TEMP
                        ;======================MAIN PROGRAM====================

                        LDI VALUE,0X00
                        LDI TEMP1,0x00

                        LOOP1:


                        ADD ZL,TEMP1
                        ADC ZH,VALUE

                        LPM TEMP2,Z
                        OUT PORTB,TEMP2

                        LDI DK,0X00
                        OUT PORTD,DK

                        RCALL DELAY
                        INC TEMP1

                        RJMP LOOP1



                        MYDATA:
                        .DB 0x08,0X01,0X04,0XAB,0X03,0X07,0X01,0X00


                        mình đã làm như các bạn nói nhưng khi mình cho chạy vòng lặp để tăng con trỏ lên
                        ở đây là thanh ghi TEMP1
                        nhưng nó không chạy
                        mà cứ đứng ở giá trị đầu của bảng (cụ thể là 0x08)
                        có bạn nào giải thích dùm mình với
                        chân thành cảm ơn!!!!!!!!!!!!!!!!!!!!!!!!

                        Comment


                        • #13
                          Nguyên văn bởi GS_Nobita Xem bài viết
                          Bác Vinhsnooker cho mình hỏi là : Bạn thấy học học lập trình C cho 89 rồi chuyển sang lập trình C cho AVR có gì khác nhiều lắm ko. Mình cũng đang định chuyển sang C để phất triển ứng dụng nhưng mà mình phải sài thằng ASM này cho tươm tươm đã. Có gì bạn chỉ mình về lập trình C với nha
                          89 và avr thì tất nhiên là phải khác nhau rồi,đấy là điều đương nhiên thôi đúng không,còn ngôn ngữ c mà để sử dụng cho chúng thì không có gì là khác nhau cả.

                          Comment


                          • #14
                            hic, nghe mấy bác nói về biến con trỏ Z mà em thấy buồn.
                            bộ nhớ của AVR phân ra bao gồm bộ nhớ data(ram) epprom và bộ nhớ chương trình (program).
                            để đọc được dữ liệu từ bộ nhớ chương trình thì có lệnh LPM. và nó có 3 cách sử dụng, các bạn có thể đọc rõ hơn trong phần help của AVRstudio
                            ở đây bạn cần load dữ liệu từ một khung nên bạn sử dụng lệnh như thế này:
                            LPM Rd,Z+
                            dữ liệu sẽ được load vào Rd và biến con trỏ sẽ tự động được tăng lên.
                            vòng lặp của bạn ngocpro tui sửa tí nhé:
                            LDI ZH,HIGH(MYDATA*2)
                            LDI ZL,LOW (MYDATA*2)
                            .
                            .
                            .
                            .
                            .
                            LOOP1:

                            LPM TEMP2,Z+
                            OUT PORTB,TEMP2

                            LDI DK,0X00
                            OUT PORTD,DK

                            RCALL DELAY

                            RJMP LOOP1
                            mục đích ở đoạn mã này của bạn là xuất dữ liệu ra portb phải không
                            LDI ZH,HIGH(MYDATA*2)
                            LDI ZL,LOW (MYDATA*2)
                            hai lệnh này load địa chỉ của dữ liệu về Z. tại mỗi địa chỉ của bộ nhớ chương trình thì có 16 bit, mà trong khi đó lệnh LPM sẽ lấy dữ liệu về Rd:chỉ có 8 bit, vậy mỗi lần load dữ liệu nó chỉ lấy được 8 bit. vì vậy, ở biến Z sẽ sử dụng 15 bỉt đầu để trỏ tới địa chỉ, và bít 0 để trỏ tới byte cao hoặc byte thấp trong địa chỉ đó.
                            đây là lí do tại sao lại có thêm *2 trong dòng lệnh, kí hiệu này thay cho lệnh nhân 2 và cũng là lệnh dịch dữ liệu sang trái một bít.
                            LPM TEMP2,Z+
                            dòng lệnh này thì load dữ liệu vào temp2 và sau đó tăng Z lên 1, nghĩa là sẽ tuần tự đọc byte thấp, byte cao rồi tăng địa chỉ lên.. byte thấp, byte cao...
                            tui chỉ biết đến vậy có ji mọi người chỉ giáo thêm...

                            Comment


                            • #15
                              Nguyên văn bởi GS_Nobita Xem bài viết
                              Cảm ơn anh nha. Em đã làm được rùi.mất mấy hôm chỉ vì cái bảng DB. bây giờ em đang tập dùng Timer và ngắt. Sao em đọc không thấy có ví dụ nào cụ thể về cái này nhỉ. Đọc sách của thầy Tập thấy lung tung quá.không có ví dụ đến cách dùng của cái này gì cả. Nếu em muốn dùng Timer thay cho Delay thì phải làm gì hả anh chị. Anh, chị nào biết chỉ em với nhé.
                              Sách của TS Tập là cuốn sách viết về VDK dở nhất trong các sách viết về VDK

                              Comment

                              Về tác giả

                              Collapse

                              GS_Nobita Tìm hiểu thêm về GS_Nobita

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X