PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Cơ bản về vi điều khiển và PIC (http://www.picvietnam.com/forum/forumdisplay.php?f=8)
-   -   Học PIC trong 1 ngày (Upd. 01/01/2006) (http://www.picvietnam.com/forum/showthread.php?t=5)

vodka1505 30-03-2008 07:26 PM

- Bác nào rảnh giải thích giúp em cái hàm Delay này cái:
Code:

Delay
        Movlw        d’250’
        Movwf        count1
D1       
        Movlw        0xc7
        Movwf        counta
        Movlw        0x01
        Movwf        countb
Delay_0
        Decfsz        counta, f
        Goto                $+2
        Decfsz        countb, f
        Goto                Delay_0
        Decfsz        count1, f
        Goto                D1
        Return

- em chưa hiểu về cái lệnh này "Goto $+2"?
- và lệnh "Goto Delay_0" với "Goto D1" thì có gì khác nhau? em thấy trong một số hàm Delay người ta chỉ dùng có lệnh "Goto Delay_0"
Em xin cảm ơn rất nhiều.

namqn 30-03-2008 07:55 PM

$ là địa chỉ lệnh hiện hành, $ + 2 là ô nhớ lệnh cách vị trí hiện hành 2 đơn vị.

Với ví dụ trên của bạn (giả sử viết cho PIC16), lệnh GOTO $ + 2 dùng để chuyển điều khiển đến lệnh GOTO Delay_0 nếu sau khi giảm biến counta kết quả vẫn khác 0 (tức là nếu sau khi giảm counta mà counta vẫn khác 0 thì bỏ qua lệnh giảm countb).

Đoạn chương trình trên dùng 3 biến đếm, do đó nếu cập nhật counta, rồi countb, thì sẽ đến lượt count1 được cập nhật. Do đó cần dùng các nhãn Delay_0 hay D1 cho các lệnh GOTO một cách thích hợp.

Thân,

vodka1505 31-03-2008 08:51 PM

- Cảm ơn anh Nam đã giúp đỡ:
em viết hàm delay như này được không? và hai cái này khác nhau ở chỗ nào?
Code:

Delay
        Movlw        d’250’
        Movwf        count1
        Movlw        0xc7
        Movwf        counta
        Movlw        0x01
        Movwf        countb
Delay_0
        Decfsz        counta
        Goto        Delay_0
        Decfsz        countb
        Goto        Delay_0
        Decfsz        count1
        Goto        Delay_0
        Return


vnchampion 13-04-2008 03:26 PM

Chài khó hiểu quá mấy bác ơi

thaile 13-04-2008 09:35 PM

PIC16 thì em không biết nhưng với PIC18F4580 thì không cần lưu lại giá trị của PCLATH :
1>Bình thường nếu không có tác động trực tiếp thì thanh ghi PCLATH sẽ không thay đổi giá trị, kể cả khi PC thay đổi từ địa chỉ 0xFF đến 0x100. Lúc đó PCL=00 và PCLATH=00. ( Kết quả có được nhờ giả lập MPLAB SIM)
2>Sau lenh RETIF hoặc RET thì chương trình đọc PC từ Stack (TOSL, TOSH, TOSU). Lúc này PC sẽ được phục hồi như ngay tại thời điểm gặp ngắt, hoặc lệnh CALL. Nhưng PCLATH vẫn không bị thay đổi nếu không có lệnh tác động trực tiếp (chẳng hạn MOVWF PCLATH)
3>Thanh ghi PCLATH chỉ có tác dụng khi ta tác động ghi lên thanh ghi PCL, chẳng hạn:
+ với PCLATH=1 thì lệnh MOVWF PCL sẽ làm cho PC=0x100 ( với WREG=0)

Nói túm lại bình thường PC không tham khảo đến thanh ghi PCLATH, chỉ khi có tác động ghi trực tiếp lên thanh ghi PCL thì PC mới tham khảo đến nó. Theo em thấy thì khi sử dụng bảng mới thực sự cần đến thanh ghi PCLATH

Em là Newbie, có sai sót gì thì nhẹ nhàng chỉ bảo em ^^

tuanlq14 14-04-2008 05:44 PM

co thể chạy chương trinh MPLAB ngay trong CCS C không
co thể vừa viết MPLAB và CCS C cung trong CCS C không

namqn 14-04-2008 08:30 PM

Trích:

Nguyên văn bởi tuanlq14 (Post 15549)
co thể chạy chương trinh MPLAB ngay trong CCS C không
co thể vừa viết MPLAB và CCS C cung trong CCS C không

MPLAB IDE là môi trường phát triển tích hợp, CCS C là một trình biên dịch. Do đó, nói ngược lại thì đúng hơn, nghĩa là có thể nhúng CCS C vào MPLAB IDE.

Bản thân CCS cũng có IDE. Tuy nhiên, IDE của CCS không hỗ trợ các trình biên dịch của Microchip (MPLAB C18, MPLAB C30, MPLAB C32).

Thân,

vodka1505 19-04-2008 04:36 PM

Code:

;==============================================================================================
;KHOI TAO VI DIEU KHIEN
                TITLE                "TUTORIAL_1"
                PROCESSOR        P16F628A
                INCLUDE                <P16F628A.INC>
                __CONFIG        _CP_OFF&_PWRTE_OFF&_WDT_ON&_HS_OSC
;==============================================================================================
;PHAN DAT BIEN
                ORG                        0x20
COUNT1        RES                        1
COUNTA        RES                        1
COUNTB        RES                        1
;==============================================================================================
                ORG                        0x0000
                GOTO                MAIN
                ORG                        0x0005
MAIN       
;                MOVLW                0x07                                ;CHUYEN 0000 0111 VAO THANH GHI W
;                MOVWF                CMCON                        ;TAT THANH GHI SO SANH

                BANKSEL        TRISB
                CLRF                TRISB

                BANKSEL                PORTB
                CLRF                PORTB
               
LOOP
                MOVLW                B'11111111'                ;W = 1111 1111
                MOVWF                PORTB                ;SANG CAC LED
                CALL                DELAY                        ;GOI HAM TAO TRE

                MOVLW                B'00000000'                ;W = 0000 0000
                MOVWF                PORTB              ; TAT LED
                CALL                DELAY                        ;GOI HAM TAO TRE

                MOVLW                B'11111111'                ;W = 1111 1111
                MOVWF                PORTB                ;
                CALL                DELAY                        ;GOI HAM TAO TRE

                MOVLW                B'00000000'                ;W = 0000 0000
                MOVWF                PORTB
                CALL                DELAY                        ;GOI HAM TAO TRE
       
                MOVLW                B'11111111'                ;W = 1111 1111
                MOVWF                PORTB                ;
                CALL                DELAY                        ;GOI HAM TAO TRE

                MOVLW                B'00000000'                ;W = 0000 0000
                MOVWF                PORTB
                CALL                DELAY                        ;GOI HAM TAO TRE

                MOVLW                B'11111111'                ;W = 1111 1111
                MOVWF                PORTB                ;
                CALL                DELAY                        ;GOI HAM TAO TRE

                MOVLW                B'10000000'
                MOVWF                PORTB
LOOP_1
                CALL                DELAY
                BCF                        STATUS, C
                RRF                        PORTB
                BTFSS                STATUS, C
                GOTO                LOOP_1

                MOVLW                B'00000001'
                MOVWF                PORTB
LOOP_2
                CALL                DELAY
                BCF                        STATUS,C
                RLF                        PORTB
                BTFSS                STATUS,C
                GOTO                LOOP_2

                MOVLW                B'11000000'
                MOVWF                PORTB
                CALL                DELAY

                MOVLW                B'11100000'
                MOVWF                PORTB
                CALL                DELAY

                MOVLW                B'11110000'
                MOVWF                PORTB
                CALL                DELAY

                MOVLW                B'11111000'
                MOVWF                PORTB
                CALL                DELAY

                MOVLW                B'11111100'
                MOVWF                PORTB
                CALL                DELAY

                MOVLW                B'11111110'
                MOVWF                PORTB
                CALL                DELAY

                MOVLW                B'11111111'
                MOVWF                PORTB
                CALL                DELAY               

                GOTO                LOOP                        ;GO BACK AND DO IT AGAIN
;==============================================================================================
;CHUONG TRINH CON
;----------------------------------------------------------------------------------------------
DELAY
                MOVLW                D'255'                        ;
                MOVWF                COUNT1                ;COUNT1 = 255
                MOVLW                d'255'                        ;
                MOVWF                COUNTA
;                MOVLW                d'51'
;                MOVWF                COUNTB
DELAY_1
                DECFSZ                COUNT1                ;COUNT1 = COUNT1 - 1
                GOTO                DELAY_1                        ;QUAY TRO LAI NHAN DELAY
;                DECFSZ                COUNTA                ;COUNTA = COUNTA - 1
;                GOTO                DELAY_1
                DECFSZ                COUNTB
                GOTO                DELAY_1       
                RETURN
GOTO        $
END

- Đoạn chương trình trên của em chạy rất tốt nếu khai báo dùng thạch anh nội của PIC, còn nếu em khai bao như trên ( dùng thạch anh ngoài) thì nó không chạy. cụ thể là các led không nháy, và chân rb4 của nó không có mức tín hiệu cao, mặc dù em đã set nó lên mức cao.
- Anh nào biết nó sai ở chỗ nào chỉ giúp em với. Mạch em dùng thạch anh 10Mhz, tụ gốm 33p.
Cảm ơn các anh nhiếu

vodka1505 21-04-2008 08:20 AM

không có ai giúp mình sao? đang cần quá.

namqn 21-04-2008 09:05 AM

Bạn đã khẳng định là chương trình chạy tốt rồi, chỉ có thay đổi thiết lập cấu hình từ bộ dao động nội sang thạch anh ngoài thôi. Như vậy có nhiều khả năng là thạch anh không dao động (đã có bạn gặp trường hợp là chân OSC2 bị hỏng, do đó chỉ dùng được cấu hình clock ngoài, không dùng được cấu hình thạch anh ngoài). Bạn cũng chú ý là bạn đang bật WDT, và trong code không hề có lệnh xóa WDT. Có khả năng là bạn tắt WDT khi chạy bằng bộ dao động nội, và bật WDT khi cấu hình lại để dùng thạch anh ngoài hay không?

Thân,

tam_pascal 22-04-2008 08:46 AM

Bang chủ làm ơn cho hỏi: địa chỉ cổng b của 18f4550 là gì ?, mình tìm mãi không thấy nó ghi ở chỗ nào cả. Xin cảm ơn !!!

namqn 22-04-2008 04:59 PM

Trích:

Nguyên văn bởi tam_pascal (Post 15701)
Bang chủ làm ơn cho hỏi: địa chỉ cổng b của 18f4550 là gì ?, mình tìm mãi không thấy nó ghi ở chỗ nào cả. Xin cảm ơn !!!

Trong datasheet của PIC18F4550, bảng 5-1, có bản đồ bộ nhớ của vùng RAM dữ liệu. Thanh ghi TRISB có địa chỉ 0xF93, còn PORTB có địa chỉ 0xF81.

Thân,

bachelor 01-08-2008 05:36 PM

góp ý với bang chủ về mẫu chương trình
 
Trích:

Nguyên văn bởi falleaf (Post 51)
Các bạn cần chú ý thêm, nếu phía trên chỗ biến ở băng 2, các bạn không đặt biến gì cả, thì các bạn cứ để nguyên như vậy, vì ngay bên dưới, các bạn đã đặt lại địa chỉ 0x0000, nó chẳng ảnh hưởng gì đến chương trình.

Cũng giống như, nếu bạn không viết gì ở đoạn ORG 0x0000 và GOTO MAIN, mà bạn để ngay dòng ORG 0x0005 thì chương trình vẫn chạy bình thường. Đơn giản là từ đoạn 0x0000 đến 0x0004, PIC sẽ không làm gì cả. Chúng tôi đang cố gắng từng bước hình thành cho bạn kết cấu chương trình viết bằng MPASM, mỗi ngày một hoàn thiện hơn, để các bạn nắm rõ lý do vì sao các chương trình được viết như vậy, và chúng ta cùng thống nhất với nhau ở điểm này khi viết chương trình. Nếu các bạn tin tưởng vào việc tạo ra một chuẩn viết chương trình MPASM cho Việt Nam, thì các bạn là người đang đặt nền móng cho nó. Tôi cũng có tham vọng này, cho nên các quy cách ký hiệu tôi cố gắng dùng một chuẩn thống nhất, và mong rằng các bạn cùng tôi làm việc này, để sau này tất cả mọi người khi làm việc cùng với nhau có thể hiểu và truyền tải ý tưởng một cách nhanh nhất.

Kể từ nay, các bạn đã biết cách đặt biến, biết cách viết phần khởi tạo, chúng ta sẽ chỉ còn bàn tới việc viết ở phần chương trình chính như thế nào nữa mà thôi.

Code:

;============================================================================
                        ORG        0x0000
                        GOTO        MAIN

                        ORG        0x0005
MAIN
                        BANKSEL        TRISB
                        CLRF                TRISB                ; đặt portb là output

                        MOVLW                D'255'
                        MOVWF                COUNT_L        ; COUNT_L là 1 byte

                        BANKSEL        PORTB
LOOP                        BSF                PORTB,        0
                        CALL                DELAY
                        BCF                PORTB,        0
                        CALL                DELAY
                        GOTO                LOOP

;=============================================================================
; Các chương trình con
;=============================================================================
DELAY                        DECFSZ                COUNT_L,        F
                        GOTO                DELAY
                        RETURN

;=============================================================================
                        GOTO                $
                        END
;=============================================================================

Các bạn vừa làm gì với đoạn chương trình trên?

Điểm thứ nhất các bạn nên chú ý, đó là việc tôi thêm phần các chương trình con vào trong phần chương trình chính. Phần cuối chương trình tôi vẫn luôn để là GOTO $ và kết thúc với lệnh END. Tạm thời các bạn cứ viết như vậy để khoá chương trình ở dòng GOTO $, khi chương trình nhảy đến đó, nó sẽ thực hiện vòng lặp vô cùng tại chỗ, còn lệnh END là lệnh bắt buộc.

Việc này giúp chúng ta phần tách rạch ròi phần chương trình con và chương trình chính để tránh nhầm lẫn. Bởi vì ở đây chúng ta mới bắt đầu các bài học cơ bản, cho nên tôi cho rằng các chương trình của các bạn viết là ngắn, nên chúng ta chưa đi xa hơn về việc phân bổ vị trí này. Các bạn chỉ đơn giản hiểu là chúng ta cần phải bỏ đoạn chương trình con ở đâu đó, và chúng ta nên tách thêm một phần nữa để dành riêng cho việc viết chương trình con. Việc làm này về sau sẽ rất có lợi, nhưng tạm thời chúng ta khoan bàn tới, và chúng ta cứ viết như vậy đã.

Phân tích về đoạn chương trình con này, chúng ta thấy chương trình con luôn bao gồm như sau:

Code:

[NHÃN]
                        các câu lệnh
                        RETURN

Lưu ý rằng ở trên, chúng ta gọi chương trình con CALL DELAY. Như vậy, việc gọi hàm được thực hiện bằng lệnh CALL [NHÃN].

Con trỏ chương trình sẽ nhảy về [NHÃN] được gọi. Nó thực hiện các lệnh nằm từ nhãn đó trở đi. Thực hiện cho đến khi gặp lệnh RETURN, nó sẽ quay trở về và thực hiện lệnh tiếp theo ngay bên dưới lệnh CALL. Ở đây, chúng ta gặp phải một vấn đề, đó là khái niệm Top of Stack. Tuy nhiên, chúng ta tạm gác nó lại cho bài học sau, còn bây giờ các bạn chỉ cần nắm được việc thực hiện lệnh CALL bao giờ cũng đi kèm với một nhãn. Con trỏ nhảy tới nhãn và thực hiện các lệnh bên trong đó, đến khi gặp lệnh RETURN thì nó nhảy trở về vị trí nằm sau lệnh CALL đó và thực hiện tiếp công việc đang làm.

Vì bỏ qua khái niệm Top of Stack, cho nên đề nghị các bạn không đặt ra câu hỏi nếu trong các lệnh thực hiện, nó lại có một lệnh CALL gọi đi chỗ khác thì làm thế nào? Chúng ta sẽ giải quyết vấn đề này ở phần sau.

Thế bên trong hàm DELAY chúng ta làm những gì?

Lưu ý rằng, ở trên chương trình chính, sau khi đã khởi tạo PORTB là ngõ output, các bạn thấy chúng ta đã ghi giá trị d'255' vào biến COUNT_L. Cách viết giá trị như sau:

b'11001010' để xác định số nhị phân
d'234' để xác định số thập phân
0xF3 để xác định số thập lục phân

Lưu ý:
Số nhị phân chỉ có các giá trị 0 và 1, và tối đa dài 8 bit. Số thập phân chỉ có thể có giá trị từ 0 đến 255, và số thập lục phân chỉ có giá trị từ 00 đến FF

Quay trở lại, biến COUNT_L đang mang giá trị 255.

Khi thực hiện hàm DELAY, các bạn thực hiện lệnh DECFSZ (DECrement File, Skip if Zero), có nghĩa là nó sẽ giảm giá trị của một thanh ghi nào đó một đơn vị. Nếu sau khi giảm xong, mà kết quả là 0, thì nó sẽ nhảy cách ra một ô nhớ trong bộ nhớ chương trình, và thực hiện lệnh tiếp theo đó. Nếu giá trị sau khi giảm một đơn vị chưa bằng 0, thì nó sẽ thực hiện lệnh liền kề với nó.

Như vậy, vòng lặp được thực hiện như sau:

Code:

COUNT_L = 255 (ở trên đã đặt)

DELAY    COUNT_L = COUNT_L - 1
if COUNT_L <> 0
        GOTO DELAY
if COUNT_L = 0
        RETURN

Code:

Lệnh DECFSZ        [File],        F/W
Nếu phía sau dấu phẩy, chúng ta để W, thì kết quả sẽ lưu vào thanh ghi W, và [File] không thay đổi giá trị gì hết. Nhưng ở đây, chúng ta muốn thực hiện như đoạn mã giả ở trên, nên chúng ta phải để là F.

COUNT_L sẽ giảm dần từ 255 đến 1, trong quá trình đó nó cứ chạy lên DELAY, rồi giảm COUNT_L một đơn vị, xong lại nhảy về DELAY, lại thực hiện việc giảm 1 đơn vị của COUNT_L

Khi COUNT_L = 1 nó lại giảm 1 đơn vị, lúc này COUNT_L = 0. Và nó không thực hiện lệnh GOTO nữa, mà thay bằng lệnh NOP, sau đó nó thực hiện lệnh RETURN, có nghĩa là quay về lại lệnh CALL ở trên.

Như vậy, các bạn đã hiểu rõ hàm DELAY rồi. Nhưng quan trọng nhất là làm sao tính toán được thời gian hao tốn của đoạn vòng lặp này kể từ khi bắt đầu thực hiện lệnh CALL, vì thực ra chúng ta muốn là muốn biết chính xác thời gian thực hiện lệnh của nó.

Thời gian thực hiện của lệnh CALL DELAY là bao lâu?

Lệnh CALL khi thực hiện tốn 2 chu kỳ máy, như vậy chúng ta ghi chú là (2) ở đây.

Lệnh DECFSZ tốn 1 chu kỳ máy khi giá trị trả về khác 0. Như vậy, trong quá trình thực hiện giảm từ 255 xuống 1, nó thực hiện 255 - 1 = 254 lần. Mỗi lần thế này nó tốn 1 chu kỳ máy, chúng ta ký hiệu (254) ở đây.

Khi thực hiện lệnh GOTO, lệnh GOTO tốn 2 chu kỳ máy, vậy nó cũng thực hiện 254 lần, chúng ta ký hiệu (254 x 2 = 506) ở đây.

Khi COUNT_L = 1, nó vẫn thực hiện lệnh DECFSZ, vậy nó tốn thêm 1 chu kỳ máy nữa (1). Sau khi thực hiện lệnh này, kết quả trả về là 0, vậy nó sẽ thực hiện một lệnh NOP (1), và sau đó thực hiện lệnh RETURN, lệnh RETURN tốn 2 chu kỳ máy (2)

Kết quả:

(2) + (254) + (508) + (1) + (1) + (2) = 768 chu kỳ máy

Nếu chúng ta dùng thạch anh 10MHz, mỗi chu kỳ máy tốn 0.4 us, có nghĩa là lệnh CALL DELAY tốn:

768 * 0.4 us tức là khoảng 1/3000 giây.

Chúng ta khoan bàn đến việc xa hơn, vậy thì chúng ta đã biết cách tính thời gian hao tốn của hàm DELAY rồi. Nhưng nếu tính như thế này thì quá mất công, chúng ta có thể chuyển nó thành công thức cụ thể như sau:

CALL = 2

DELAY (COUNT_L) = [COUNT_L - 1] * (DECFSZ + GOTO) + 1 + 1

RETURN = 2

Các bạn nên nhớ công thức này để sau này phát triển lên tính các công thức khác.

Có lẽ hôm nay chúng ta tạm dừng bài học ở đây


Các bạn lưu ý, tôi có tính sai một đoạn phía trên, vì quáng gà hay sao đó, tính từ 255 xuống 1 giảm chỉ có 253 lần. Đúng là phải 254 lần. Như từ 2 giảm xuống 1 thì chỉ có 1 lần thôi. Xin thành thật cáo lỗi với các bạn.

trong ví dụ mẫu trên theo tôi có một chỗ không hợp lý, đó là việc để các hàm con (ở ví dụ là hàm delay) nằm trên dòng lệnh goto $. ở ví dụ này sẽ không có lỗi vì bản thân vòng lặp loop là vòng lặp vô hạn nên không có vấn đề gì. nếu không phải là vòng lặp vô hạn thì chương trình sẽ được thực hiện tiếp tục và các lệnh trong hàm con sẽ được thực hiện sau đó mới đến dòng lệnh goto $ vì vậy chương trình sẽ chạy sai.
theo tôi nên đặt các hàm con nằm giữa dòng lệnh goto $ và end
mạn phép bang chủ có mấy lời góp ý :D xin mọi người cho ý kiến !

namqn 01-08-2008 07:21 PM

Trích:

Nguyên văn bởi bachelor (Post 17895)
trong ví dụ mẫu trên theo tôi có một chỗ không hợp lý, đó là việc để các hàm con (ở ví dụ là hàm delay) nằm trên dòng lệnh goto $. ở ví dụ này sẽ không có lỗi vì bản thân vòng lặp loop là vòng lặp vô hạn nên không có vấn đề gì. nếu không phải là vòng lặp vô hạn thì chương trình sẽ được thực hiện tiếp tục và các lệnh trong hàm con sẽ được thực hiện sau đó mới đến dòng lệnh goto $ vì vậy chương trình sẽ chạy sai.
theo tôi nên đặt các hàm con nằm giữa dòng lệnh goto $ và end
mạn phép bang chủ có mấy lời góp ý :D xin mọi người cho ý kiến !

PIC là một bộ xử lý nhúng, và thông thường chỉ chạy chương trình ứng dụng duy nhất (ở đây không tính đến các RTOS nhé). Do đó, luôn luôn có một vòng lặp vô tận (vòng lặp chính) trong chương trình.

Do đó, mệnh đề "nếu không phải là vòng lặp vô hạn" của bạn chỉ có giá trị true khi chương trình cho PIC được viết tồi. Và cấu trúc của chương trình mẫu không có gì bất hợp lý.

Lệnh goto $ ngay phía trước directive end của chương trình mẫu vốn là một lệnh thừa. Việc đặt các chương trình con ở đâu trong chương trình hợp ngữ vốn không quan trọng, trừ một số trường hợp liên quan đến kỹ thuật bảng.

Lập trình cho PIC có một số điểm khác biệt so với lập trình cho PC, vì sự hạn chế tài nguyên cùng cấu trúc đặc biệt của PIC so với một máy vi tính (đa dụng).

Thân,

bachelor 02-08-2008 01:11 AM

Trích:

Nguyên văn bởi namqn (Post 17898)
PIC là một bộ xử lý nhúng, và thông thường chỉ chạy chương trình ứng dụng duy nhất (ở đây không tính đến các RTOS nhé). Do đó, luôn luôn có một vòng lặp vô tận (vòng lặp chính) trong chương trình.

Do đó, mệnh đề "nếu không phải là vòng lặp vô hạn" của bạn chỉ có giá trị true khi chương trình cho PIC được viết tồi. Và cấu trúc của chương trình mẫu không có gì bất hợp lý.

Lệnh goto $ ngay phía trước directive end của chương trình mẫu vốn là một lệnh thừa. Việc đặt các chương trình con ở đâu trong chương trình hợp ngữ vốn không quan trọng, trừ một số trường hợp liên quan đến kỹ thuật bảng.

Lập trình cho PIC có một số điểm khác biệt so với lập trình cho PC, vì sự hạn chế tài nguyên cùng cấu trúc đặc biệt của PIC so với một máy vi tính (đa dụng).

Thân,

Đó, chính bản thân lệnh goto $ theo namqn đã là thừa, vậy nên phải sửa chg trình mẫu là đúng rồi :D
Tuy nhiên, theo tôi lệnh goto $ chỉ thừa trong trường hợp này thôi (trong vi dụ mẫu) còn trong một số trg hợp khác bản thân nó là một "vòng lặp vô hạn không làm gì cả " (kiểu như: while(TRUE) {}; ) thì lại không thừa. Chẳng hạn một chương trình không làm gì cả mà chỉ khởi tạo các giá trị ban đầu rồi chờ các sự kiện ngắt để phục vụ thì không thể coi đó là một chương trình tồi và lẽ đương nhiên là cần phải có một lệnh goto $ để tạo ra vòng lặp vô hạn (tất nhiên mọi người có thể nói là không cần lệnh goto $ mà dùng lệnh loop goto loop :))
Tất nhiên chương trình con thì đặt đâu mà chả được, nhưng đây là nói tới cái chương trình mẫu mà F tạo ra dành cho người mới học (như tôi chẳng hạn), cứ copy nguyên về, thay cái phần nội dung trong main và chương trình con cho phù hợp với bài toán của mình rồi biên dịch rồi chạy rồi thấy nó chạy loạn lên vì các lý do mà tôi đã đề cập ở bài trước. vì thế mới góp ý để F sửa đổi một chút chương trình mẫu để cho những người mới học khác có muốn copy về, xào xáo lại như tôi sẽ không bị nhầm lẫn nữa :D

namqn 02-08-2008 01:39 AM

Trích:

Nguyên văn bởi bachelor (Post 17901)
Đó, chính bản thân lệnh goto $ theo namqn đã là thừa, vậy nên phải sửa chg trình mẫu là đúng rồi :D
Tuy nhiên, theo tôi lệnh goto $ chỉ thừa trong trường hợp này thôi (trong vi dụ mẫu) còn trong một số trg hợp khác bản thân nó là một "vòng lặp vô hạn không làm gì cả " (kiểu như: while(TRUE) {}; ) thì lại không thừa. Chẳng hạn một chương trình không làm gì cả mà chỉ khởi tạo các giá trị ban đầu rồi chờ các sự kiện ngắt để phục vụ thì không thể coi đó là một chương trình tồi và lẽ đương nhiên là cần phải có một lệnh goto $ để tạo ra vòng lặp vô hạn (tất nhiên mọi người có thể nói là không cần lệnh goto $ mà dùng lệnh loop goto loop :))
Tất nhiên chương trình con thì đặt đâu mà chả được, nhưng đây là nói tới cái chương trình mẫu mà F tạo ra dành cho người mới học (như tôi chẳng hạn), cứ copy nguyên về, thay cái phần nội dung trong main và chương trình con cho phù hợp với bài toán của mình rồi biên dịch rồi chạy rồi thấy nó chạy loạn lên vì các lý do mà tôi đã đề cập ở bài trước. vì thế mới góp ý để F sửa đổi một chút chương trình mẫu để cho những người mới học khác có muốn copy về, xào xáo lại như tôi sẽ không bị nhầm lẫn nữa :D

Không đồng ý với bạn, vì bạn nêu lên một chi tiết không hợp lý ở post trước đó, bây giờ lại bắt sang một chi tiết (được cho là) không hợp lý khác, mà không thể hiện được cái bất hợp lý mà bạn đã nêu ở post trước.

Trong cấu trúc của chương trình mẫu, vòng lặp chính là vòng lặp giữa nhãn loop và lệnh goto loop. Nếu muốn biến nó thành while (true) {} thì không cần viết lệnh gì vào vòng lặp đó là xong. Do vậy, lệnh goto $ phía trước dẫn hướng end vẫn là thừa. Hơn nữa, viết theo kiểu loop goto loop hay goto $ đều dịch ra cùng kết quả.

Cấu trúc của chương trình mẫu là ổn, đảm bảo không có chuyện "copy nguyên về, thay cái phần nội dung trong main và chương trình con cho phù hợp với bài toán của mình rồi biên dịch rồi chạy rồi thấy nó chạy loạn lên". Đề nghị bạn post những chương trình kiểu đó lên để minh họa cho lý luận của bạn.

Về việc lệnh goto $ nằm trước dẫn hướng end: nó thừa nhưng chẳng ảnh hưởng gì đến chương trình ứng dụng (được viết đúng quy tắc) nên việc loại bỏ nó hay không vốn không phải là vấn đề.

Thân,

bachelor 02-08-2008 01:06 PM

Trích:

Nguyên văn bởi namqn (Post 17902)
Không đồng ý với bạn, vì bạn nêu lên một chi tiết không hợp lý ở post trước đó, bây giờ lại bắt sang một chi tiết (được cho là) không hợp lý khác, mà không thể hiện được cái bất hợp lý mà bạn đã nêu ở post trước.

Trong cấu trúc của chương trình mẫu, vòng lặp chính là vòng lặp giữa nhãn loop và lệnh goto loop. Nếu muốn biến nó thành while (true) {} thì không cần viết lệnh gì vào vòng lặp đó là xong. Do vậy, lệnh goto $ phía trước dẫn hướng end vẫn là thừa. Hơn nữa, viết theo kiểu loop goto loop hay goto $ đều dịch ra cùng kết quả.

Cấu trúc của chương trình mẫu là ổn, đảm bảo không có chuyện "copy nguyên về, thay cái phần nội dung trong main và chương trình con cho phù hợp với bài toán của mình rồi biên dịch rồi chạy rồi thấy nó chạy loạn lên". Đề nghị bạn post những chương trình kiểu đó lên để minh họa cho lý luận của bạn.

Về việc lệnh goto $ nằm trước dẫn hướng end: nó thừa nhưng chẳng ảnh hưởng gì đến chương trình ứng dụng (được viết đúng quy tắc) nên việc loại bỏ nó hay không vốn không phải là vấn đề.

Thân,

Theo mẫu:
Code:

;======================================
processor p16f84a
include    <p16f84a.inc>
__config  _cp_off & _wdt_off & _xt_osc
;======================================
org        0x0c
count0  res  1
count1  res  1
count2  res  1
;======================================
org        0x00
goto      main
org        0x05
;-------------------------------------------------
main
banksel  trisa
clrf        trisa
movlw    0xff
movwf    trisb
banksel  porta
clrf        porta
movlw    0x09
movwf    count0
clrw
btfsc      portb, 0
iorlw      b'00001'
btfsc      portb, 1
iorlw      b'00010'
btfsc      portb, 2
iorlw      b'00100'
btfsc      portb, 3
iorlw      b'01000'
btfsc      portb, 4
iorlw      b'10000'
addwf    count0, 1
delay0    call  delay100m
decfsz    count0,  f
goto      delay0
bsf        porta,  0
;-------------------------------------------------
delay100m
movlw    0x4e
movwf    count2
delay2
nop
nop
call        delay1278
decfsz    count2, f
goto        delay2
movlw    0xf0
movwf    count2
delay3
nop
decfsz    count2, f
goto      delay3
return
;-------------------------------------------------
delay1278
movlw    0xff
movwf    count1
delay1
nop
nop
decfsz  count1, f
goto      delay1
return
;-------------------------------------------------
goto    $
end
;======================================

thì chạy sai
nhưng chuyển các chương trình con xuống giữa 2 dòng goto $ và end thì chạy đúng
bây giờ quay trở lại chương trình mẫu: để như vậy đương nhiên vẫn chạy đúng chuyển các chương trình con xuống giữa 2 dòng goto $ và end vẫn chạy đúng
lẽ đương nhiên quẳng các chương trình con ở đâu mà chẳng được, thế nhưng với tiêu chí "học pic trong một ngày" tức là dành cho người mới học thì mẫu càng tổng quát càng tốt đúng không, vậy thì tại sao lại không chỉnh sửa một chút (chẳng sai gì và chẳng thiệt hại gì) để chương trình mẫu có thể tránh thêm một lỗi có thể gặp trong thực tế.
To Namqn: Từ đầu tôi vẫn nhất quán là chuyển chương trình con xuống thôi. còn những cái khác có thể là do cách diễn đạt làm bạn hiểu sai. Thế còn goto $ hay loop goto loop ai chả biết bản chất nó là một, ý tôi muốn nói ở đây là tôi thì thích dùng goto $ để làm vòng lặp while(TRUE); còn có thể ng khác lại thích dùng loop goto loop để làm vòng lặp while(TRUE);

namqn 02-08-2008 06:44 PM

Bạn đã phá vỡ cấu trúc của chương trình mẫu. Trong chương trình mẫu, phần code của chương trình chính bắt đầu với các lệnh khởi tạo ban đầu, sau đó đi vào vòng lặp chính, còn các chương trình con nằm dưới vòng lặp chính.

Bạn đã bỏ mất vòng lặp chính (loop ... goto loop), dẫn đến chương trình con của bạn trở thành một phần trong đoạn mã khởi tạo, và sau đó bạn mượn lệnh goto $ thừa ngay trước dẫn hướng end để làm vòng lặp while (true) của bạn. Nếu bạn vẫn giữ vòng lặp chính loop ... goto loop nhưng không viết gì vào giữa thì cấu trúc của chương trình mẫu vẫn được giữ, và bạn đạt được mục đích của mình.

Do đó, tôi xin khẳng định rằng bạn viết code không tuân theo cấu trúc của chương trình mẫu, và chương trình mẫu không có vấn đề gì cần phải sửa.

Chương trình mẫu là tổng quát, đúng cho cả trường hợp bạn thích đặt cái gì vào vòng lặp chính, hay chỉ muốn có một vòng lặp vô tận ở đó. Nếu bạn thích dùng goto $ cho vòng lặp chính, thì sau khi loại bỏ hết code giữa loop và goto loop, bạn có thể viết nó lại thành goto $ (chứ không phải xóa hẳn cái vòng lặp đó đi như bạn đã làm).

Thân,

bachelor 02-08-2008 07:49 PM

Trích:

Nguyên văn bởi namqn (Post 17908)
Bạn đã phá vỡ cấu trúc của chương trình mẫu. Trong chương trình mẫu, phần code của chương trình chính bắt đầu với các lệnh khởi tạo ban đầu, sau đó đi vào vòng lặp chính, còn các chương trình con nằm dưới vòng lặp chính.

Bạn đã bỏ mất vòng lặp chính (loop ... goto loop), dẫn đến chương trình con của bạn trở thành một phần trong đoạn mã khởi tạo, và sau đó bạn mượn lệnh goto $ thừa ngay trước dẫn hướng end để làm vòng lặp while (true) của bạn. Nếu bạn vẫn giữ vòng lặp chính loop ... goto loop nhưng không viết gì vào giữa thì cấu trúc của chương trình mẫu vẫn được giữ, và bạn đạt được mục đích của mình.

Do đó, tôi xin khẳng định rằng bạn viết code không tuân theo cấu trúc của chương trình mẫu, và chương trình mẫu không có vấn đề gì cần phải sửa.

Chương trình mẫu là tổng quát, đúng cho cả trường hợp bạn thích đặt cái gì vào vòng lặp chính, hay chỉ muốn có một vòng lặp vô tận ở đó. Nếu bạn thích dùng goto $ cho vòng lặp chính, thì sau khi loại bỏ hết code giữa loop và goto loop, bạn có thể viết nó lại thành goto $ (chứ không phải xóa hẳn cái vòng lặp đó đi như bạn đã làm).

Thân,

Có lẽ stop việc tranh luận ở đây bởi vì thực ra chẳng ai sai cả (chỉ có khác nhau ở cách nhìn nhận vấn đề, mà đó lại thuộc về suy nghĩ riêng rồi, miễn là giải quyết tốt bài toán của chính mình) mà người khác đọc vào lại chẳng tiếp nhận được thông tin gì mới
Nhân đây cũng xin hỏi namqn (và mọi người :)) : những định nghĩa trong các tệp .inc (vd p16f84a.inc) có cần thời gian không nhỉ ? (ý tôi muốn hỏi là có cần thời gian để thực hiện như các lệnh không)
mong mọi người chỉ giúp, thanks !

namqn 03-08-2008 12:35 AM

Trích:

Nguyên văn bởi bachelor (Post 17909)
Có lẽ stop việc tranh luận ở đây bởi vì thực ra chẳng ai sai cả (chỉ có khác nhau ở cách nhìn nhận vấn đề, mà đó lại thuộc về suy nghĩ riêng rồi, miễn là giải quyết tốt bài toán của chính mình) mà người khác đọc vào lại chẳng tiếp nhận được thông tin gì mới
Nhân đây cũng xin hỏi namqn (và mọi người :)) : những định nghĩa trong các tệp .inc (vd p16f84a.inc) có cần thời gian không nhỉ ? (ý tôi muốn hỏi là có cần thời gian để thực hiện như các lệnh không)
mong mọi người chỉ giúp, thanks !

Nếu không sai thì tại sao bạn lại góp ý sửa chương trình mẫu?

Bạn đã nói rằng "copy nguyên về, thay cái phần nội dung trong main và chương trình con cho phù hợp với bài toán của mình rồi biên dịch rồi chạy rồi thấy nó chạy loạn lên", nhưng cái chương trình bị "chạy loạn lên" của bạn thì lại phá vỡ cấu trúc của chương trình mẫu (xóa mất vòng lặp vô tận loop ... goto loop), và dẫn đến góp ý của bạn rằng chương trình mẫu có chỗ không hợp lý. Góp ý của bạn do đó là không hợp lý.

Vấn đề ở đây không phải ai đúng ai sai, mà là vấn đề bạn phá vỡ cấu trúc chương trình rồi đề nghị sửa lại chương trình mẫu để những người học sau đều phá vỡ cấu trúc giống như bạn. Đó là điều tôi không muốn xảy ra.

Với câu hỏi về các tập tin .inc: những định nghĩa trong đó được trình biên dịch sử dụng khi dịch ra mã máy cho PIC, và không hề liên quan đến việc thực thi chương trình trong PIC, do đó không hề tiêu tốn một chu kỳ máy nào của PIC.

Thân,

window 22-09-2008 04:17 PM

Mình đọc luồng này và rất cảm ơn các bạn rất nhiều .

window 22-09-2008 04:46 PM

Mình đang làm đồ án về con PIC 16F877 , thiết lập hệ thồng tổng đài điện thoại nội bộ :
_2 trunk
_8 Tel ra
_Giao tiếp PC
Hiện mình đang tìm tài liệu và mong các bạn hổ trợ những kiến thức kinh nghiệm trong quá trình thực hiện... .
Cảm ơn rất nhiều

NATO308 29-01-2009 10:45 PM

Cám ơn sự nhiệt tình của bang chủ và các câu hỏi của thành viên nhiều lắm . Mình học được rất nhiều từ các bạn . Cám ơn 1 lần nữa . Chúc picvietnam năm mới phát triển hơn trước và mọi người có được sức khỏe tốt để chúng ta tiếp tục tranh luận ^^

thaithien 19-02-2009 10:25 PM

Trích:

Nguyên văn bởi falleaf (Post 6)

Mình hỏi cái này hơi newbie chút nghen,trong cái hình đầu thread của anh falleaf thì làm cái mạch tạo nguồn 5V-500A ở bên dưới như thế nào vậy?Cụ thể :
-Con U3 C78l05/TO29 là con gì vậy ?
-Nguồn 9V-12V DC thì mua ở đâu ra ?Bao nhiêu ampe ?
-Liệu có trực tiếp nguồn 5V-500A mà không qua mạch trên kia không?
-Con thạch anh chọn bao nhiêu MHZ là tốt nhất ?

Hic,câu hỏi quá newbie luôn chứ không còn hơi hơi nữa,mong mọi người giúp đỡ với !!!Thanks

namqn 19-02-2009 11:24 PM

Trích:

Nguyên văn bởi thaithien (Post 22764)
Mình hỏi cái này hơi newbie chút nghen,trong cái hình đầu thread của anh falleaf thì làm cái mạch tạo nguồn 5V-500A ở bên dưới như thế nào vậy?Cụ thể :
-Con U3 C78l05/TO29 là con gì vậy ?
-Nguồn 9V-12V DC thì mua ở đâu ra ?Bao nhiêu ampe ?
-Liệu có trực tiếp nguồn 5V-500A mà không qua mạch trên kia không?
-Con thạch anh chọn bao nhiêu MHZ là tốt nhất ?

Hic,câu hỏi quá newbie luôn chứ không còn hơi hơi nữa,mong mọi người giúp đỡ với !!!Thanks

- Nguồn 5V-500 mA chứ không phải 5V-500A!

- C78L05/TO92 là vi mạch ổn áp 5 V thuộc dòng 7805 (phiên bản 78L05 chỉ có định mức 100 mA chứ không phải 500 mA như trong sơ đồ của falleaf), có kiểu vỏ TO92 (3 chân loại nhỏ, giống như các transistor C1815 hay A1015).

- Nguồn 9 - 12 VDC mua ở chợ (Ở Tp. HCM thì đến chợ Nhật Tảo), số ampe tối thiểu bằng với định mức của vi mạch ổn áp 5 V (chắc chắn có thể tìm được).

- Các thạch anh 4 MHz, 10 MHz, và 20 MHz tốt như nhau.

Thân,

thaithien 21-02-2009 12:34 AM

Như vậy là nguồn 5V-500 mA sẽ không có sẵn và mình phải làm mạch giống như trên?

namqn 21-02-2009 08:35 PM

Trích:

Nguyên văn bởi thaithien (Post 22825)
Như vậy là nguồn 5V-500 mA sẽ không có sẵn và mình phải làm mạch giống như trên?

Tôi không khẳng định như vậy, mà chỉ trả lời những câu hỏi của bạn. Tôi tin rằng bạn có thể tìm mua các adapter có điện áp ngõ ra là 5 VDC, với khả năng cấp dòng từ 500 mA trở lên. Nhưng giải pháp dùng mạch ổn áp trên mạch ứng dụng là linh hoạt hơn trong vấn đề cấp nguồn cho mạch.

Thân,

chienbinhgiuden 15-03-2009 12:53 AM

Cho tui hỏi là cái mạch ở trên đầu tiên của falleaf có thể áp dụng cho PIC 16F877a hok dzậy . Tui biết để tui ra tiệm mua linh kiện về làm liền .

thaithien 15-03-2009 06:10 AM

Trích:

Nguyên văn bởi chienbinhgiuden (Post 23571)
Cho tui hỏi là cái mạch ở trên đầu tiên của falleaf có thể áp dụng cho PIC 16F877a hok dzậy . Tui biết để tui ra tiệm mua linh kiện về làm liền .

Hình như là được.Cái đó làm mạch chạy thôi mà,chỉ gần gắn PIC đúng chân vào đó là hoạt động được

chienbinhgiuden 15-03-2009 10:00 PM

àh cho tui hỏi thêm là chân 6 của PORTA và chân 2 của PORTB có chung với nhau không , và 2 chân đó là gì vậy ( câu này có vẻ hơi ngu nhưng vì tui dở lắm nên thông cảm dùm +_+ )

Và tại sao mình phải qua 1 mạch ôn áp , mình có thể dùng PIN 5V được không


3W1 3W2 chỉ đơn thuần là tên thôi hay có ý nghĩa gì khác (tại vì tui thấy mấy nút reset chỉ cần qua 1 con điện trở tới nguồn ở trên là đủ gòi hok thấy có cái 3W)

Àh nếu được thì cho tui chương trình viết MPASM luôn nha .

chienbinhgiuden 18-03-2009 05:48 PM

T_T sao hok ai trả lời hết trơn dzậy . Kỉu này hok kịp nộp bài tập cho thầy quá

mtuankct 18-03-2009 11:32 PM

Trích:

àh cho tui hỏi thêm là chân 6 của PORTA và chân 2 của PORTB có chung với nhau không , và 2 chân đó là gì vậy ( câu này có vẻ hơi ngu nhưng vì tui dở lắm nên thông cảm dùm +_+ )
mình không hiểu bạn đang nói sơ đồ nào, nhưng mình nghĩ chẳng ai nối 2 chân này lại với nhau làm gì
Trích:

Và tại sao mình phải qua 1 mạch ôn áp , mình có thể dùng PIN 5V được không
Bạn hoàn toàn có thể dùng pin 5V để chạy vđk(nếu bạn có), cái này tùy ứng dụng thôi, nếu làm để học thì làm bộ nguồn 5V sẽ tiện dụng, kinh tế hơn việc chạy bằng pin
Trích:

3W1 3W2 chỉ đơn thuần là tên thôi hay có ý nghĩa gì khác (tại vì tui thấy mấy nút reset chỉ cần qua 1 con điện trở tới nguồn ở trên là đủ gòi hok thấy có cái 3W)
nếu bạn đang nối về cái mạch đầu tiên của anh falleaf thì mình không thấy cái nào là 3W1 và 3W2 cả chỉ có cái nút ấn và công tắc là SW1, và SW2 thôi

thaithien 21-03-2009 03:43 PM

Cái nguồn 9V-12V thì dòng điện vào là bao nhiêu vậy ?Nó có ảnh hưởng nhiều đến đầu ra 5V-500mA không?

chienbinhgiuden 21-03-2009 09:12 PM

^^ nhìn lộn , là SW chứ hok phải 3W .

Còn vụ chân số 2 của PORTB và chân số 6 của PORTA là sao vậy . Bỏ chân đó hay là sao . Àh mà tui gắn thêm PORTC , D chắc hok sao đâu ha .

thaithien 21-03-2009 10:15 PM

Cho hỏi cái này:công dụng của các con thạch anh trong mạch đầu thread là gì vậy?Nếu không có con thạch anh thì mạch có chạy không?

chienbinhgiuden 22-03-2009 07:30 PM

COn thạch anh dùng để cung cấp xung cho con PIC hoạt động . Cứ 4 nhịp động thì con PIC thực hiên 1 lệnh . Bạn hãy đọc kỹ trang 1 đi Falleaf viết rõ lắm đó

thaithien 23-03-2009 12:00 AM

Cái đó thì mình đọc rồi và cũng hiểu chút ít.Nhưng do mình lắp mạch thật ở ngoài mà chạy chưa được nên mới nghĩ vậy.Trong mạch thật mình lắp không có thạch anh.Mà trong PIC cũng đã có sẵn dao động nội rồi đúng không?

linhdien 18-05-2009 03:46 PM

Cam on fallaf, tôi đang tìm hiểu và bắt đầu học Pic. Bài viết của bạn rất hữu ích. Có kinh nghiệm nhiều bạn chỉ giáo cho tôi với nhé. Mail: anhlinhkn@gmail.com.
"Chuyển tải thông tin là bạn đã nhận được thông tin"

vocuvoba 23-09-2009 10:46 PM

hay quá các bác à
làm em mở rộng tầm mắt
:D

f85635 11-11-2009 06:35 AM

Thnaks bác Falleaf nhiều:) Bác hướngd dẫn rất cụ thể. Em mới bắt đầu học nhưng cũng hiểu so so rồi.hihi mong Bác chỉ bảo thêm


Múi giờ GMT. Hiện tại là 12:12 AM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam