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)
-   -   Lập nhóm PIC16F877A (http://www.picvietnam.com/forum/showthread.php?t=325)

falleaf 20-03-2006 07:31 AM

Các bài viết trong luồng này rất hay, các bạn đang thảo luận về PWM, có thể nhấn thêm một bước bây giờ giả sử khi kết hợp 2 chân PWM nhưng làm xung trên 2 chân xen kẽ với nhau xem nào?

Đây có thể chỉ là một bài tập vui nhưng cũng có ứng dụng nhiều đấy.

Chúc vui.

pb1 20-03-2006 09:50 AM

hì, thế còn capture module thì sao nhỉ, có ai viết tiếp không?

ntc 20-03-2006 11:20 AM

Mình có một vài ý kiến về cách thiết kế mạch đèn giao thông của nhh như thế này: :D

Tất nhiên là chọn PORT điều khiển như thế nào cũng được, nhưng theo mình, khi thiết kế một ứng dụng, cần tìm cách để thiết kế là tối ưu.

Do PIC16F877A được tích hợp khá nhiều chức năng ngoài chức năng I/O thông thường, nên việc lựa chọn PORT điều khiển cũng nên cân nhắc. MÌnh nêu lên một số điểm như sau:

PORT C của PIC16F877A ngoài chức năng I/O là các chức năng CCP và giao tiếp nối tiếp (SPI, I2C,... ). Nếu nhh chọn PORT này làm PORT điều khiển các chân a-g của các LED thì các chức năng on-chip nêu trên sẽ không tương tác được nữa.

PORT D ngoài chức năng I/O là chức năng PSP (Parallel Slave Port). Chức năng giao tiếp này ít được sử dụng do số lượng chân cần cho giao tiếp khá lớn (8 chân PORT D và 3 chân PORT E), nhưng nhh đã sử dụng 3 chân để bật đèn giao thông. Như vậy chức năng này cũng bị mất luôn.

Có thể nói ta đã phí phạm 3 chức năng on-chip của PIC16F877A. Tất nhiên là trong ứng dụng của nhh ta chưa cần quan tâm đến vấn đề này, nhưng mình cũng muốn nêu lên để anh em cùng thảo luận.

Theo mình thì nên sửa lại như thế này:

Các chân data của Led 7 đoạn, mình sẽ đưa vào PORT D.
Các chân điều khiển đèn giao thông và quét LED sẽ đưa vào PORT B luôn.

Như vậy ta có thể tiết kiệm được các chức năng CCP và giao tiếp ở PORT C, cái mất đi chỉ là cái ít đụng tơi PSP, còn ngắt PORT B thì vẫn còn vài chân.

Trong các ứng dụng của mình có dính tới LED 7 đoạn, mình cũng bố trí các chân điều khiển như vậy.

Về chương trình cũng sẽ không có thay đổi lớn. Bạn nên "#define ..." các chân và PORT điều khiển. Như vậy khi cần thay đổi chân điều khiển, ta chỉ cần thay đổi cái phần define mà không cần phải sửa lại trong toàn bộ chương trình. Hơn nữa chương trình khi đọc cũng sẽ thân thiện và dễ hiểu hơn.

Một vài ý kiến góp vui như vậy. Anh em thấy thế nào.

:D

ntc 20-03-2006 12:06 PM

Tiếc quá nhh không làm cái Timer. Nếu làm cái Timer, bạn sẽ có thêm một kinh nghiệm sương máu và một thủ thuật kinh điển khi lập trình bằng ASM. Cái kinh nghiệm này mĩnh cũng chỉ vừa mới rút ra thôi. :D.

Nó có liên quan tới kĩ thuật bảng. :D

ngohaibac 20-03-2006 02:37 PM

Trích:

Nguyên văn bởi nhh
Để khởi động timer0,xóa bit T0CS về 0.Lúc này thanh ghi TMR0 sẽ tự động tăng lên một ứng với mỗi chu kỳ lệnh

T0CS không phải dùng để khởi động Timer0 mà T0CS dùng để chọn cho Timer0 ở chế độ timer hay counter.

Chế độ timer (T0CS = 0) thì TMR0 sẽ tăng lên 1 sau mỗi chu kì lệnh (khi prescaler = 1, nếu khác 1 thì là bộ của chu kì lệnh).

Chế độ counter thì T0CS =1 khi đó TMR0 sẽ tăng lên mỗi khi có một sườn lên hoặc sườn xuống xuất hiện trên chân T0CKI (RA4) ( chân này dạng open - drain nên bình thường nếu set dạng I/O bình thường thì phải mắc thêm trở kéo lên). Và chúng ta phải chọn sườn lên hay sườn xuống qua bít T0SE.
Trích:

Trong ứng dụng này do timer0 tràn sớm hơn 1s khi dùng thạch anh 10MHz,do vậy dùng thêm một biến đếm số lần tràn sao cho khi biến này giảm xuống 0 thì xấp xỉ 1s.

Trong 20s đầu,đèn xanh bật ON,từ giây 21 đến 30 có thêm đèn vàng ON, 20s cuối đèn đỏ ON.

Các chân từ a đến g của led 7 seg đầu nối với RC0 đến RC6, led còn lại nối RB0 đến RB6.
Mình nghĩ bạn nên làm một timer0 trễ 1ms. Sau đó tuỳ ứng dụng mình sẽ sử dụng là bội của 1ms này. Tức là dùng biến static để đếm sự kiện tràn timer0.

Lưu ý: timer0 là bộ free - auto counter sau khi thiết lập ở chế độ timer thì nó sẽ đếm mãi mà không dừng. thanh ghi OPTION ở chế độ sau reset = 0xFF nên ban đầu nó ở chế độ Counter sẽ đếm xung bên ngoài.

Mình xin ví dụ một hàm ngắt với timer0 dùng HTPIC. Với thạch anh 20MHZ thì hàm ngắt timer0 1ms -> TMR0 = 6

Code:

void interrupt inter0(void){
        static unsigned char i;
        static unsigned int counter; // bien dem su kien ngat timer0
        if(T0IF & T0IE){ // neu co ngat Timer0 xay ra
                TMR0 = 6;
                T0IF = 0 ; // xoa co ngat, cong viec khong the thieu sau ham ngat
                ++        counter;
                if (counter == a ) {
                        // do something
                };
                };
}

Trong hàm init chọn như sau: dùng pre cho timer0 với tỉ lệ 1:2
Code:

void init(void){
        // khoi tao cho các port

       
        // Khoi tao cho cac thanh ghi       
        OPTION  = 0x00; // dung prescaler cho timer0 voi ti le la 1:2

        // Khoi tao cho ngat Timer0
        GIE = 1; // cho phep ngat toan cuc
        T0IE = 1; // cho phep ngat timer0
        T0IF = 0; // xoa co ngat timer0
        TMR0 = 6; // khoi tao
}


ngohaibac 20-03-2006 02:59 PM

Chương trình đèn giao thông tại sao bạn NHN lại tốn nhiều chân để điều khiển 2 led 7 thanh thế nhỉ? Sao bạn không dùng phương pháp quét led để quét 2 led này. Khi đó dùng 7 chânPORTD (a->g) và thêm 2 chân điều khiển nữa như vậy chỉ mất có 9 chân tất cả. Như vậy tiết kiệm các chân hơn.

Thực tế đèn giao thông này là rất đơn giản. Bạn có thể phát triển thành sơ đồ đền giao thông hiện đại mới trong thực tế không? Đứng ở ngã tư một lúc xem thế nào :D. Bạn đưa ra mô hình đi mình lập trình bằng HTPIC xem thế nào. Vì làm bằng ASM đúng là mình mệt lắm:D.

chúc mọi người thành công.

nhh 20-03-2006 05:56 PM

Cảm ơn ngohaibac!

Ban đầu mình cũng nghĩ ghép chung dữ liệu cho hai led 7 seg,làm như vậy thì khi viết chương trình quét led có hơi phức tạp hơn một chút.Chương trình này mình dùng để tìm hiểu ngắt timer0 thôi chứ ko có ý định tiết kiệm chân VDK.:D

ngohaibac cứ mắc mạch như ntc:

Trích:

Theo mình thì nên sửa lại như thế này:

Các chân data của Led 7 đoạn, mình sẽ đưa vào PORT D.
Các chân điều khiển đèn giao thông và quét LED sẽ đưa vào PORT B luôn.
Bạn viết và post lên cho anh em học HTPIC tham khảo!

Chào!

nhh 20-03-2006 06:19 PM

Trích:

Nguyên văn bởi ntc
Tiếc quá nhh không làm cái Timer. Nếu làm cái Timer, bạn sẽ có thêm một kinh nghiệm sương máu và một thủ thuật kinh điển khi lập trình bằng ASM. Cái kinh nghiệm này mĩnh cũng chỉ vừa mới rút ra thôi. :D.

Nó có liên quan tới kĩ thuật bảng. :D

Tuần này tớ sẽ làm cái timer để Chính phân tích những kinh nghiệm xương máu mà mình tích lũy được.
Hy vọng sớm hoàn thành!:D

Chào!

ngohaibac 20-03-2006 06:41 PM

Mình đã viết chương trình quét 4 led 7 thanh rùi bằng HTPIC. Tại luồng này bên dientuvietnam.net. xin mời các bạn cho ý kiến về giải thuật và cấu trúc:

http://dientuvietnam.net/forums/show...6&page=1&pp=10

Mình quen về lập trình bằng C nên có vấn đề gì về các câu lệnh về C thì các bạn cứ hỏi. Còn về ASM thì chào thua. Không dám lập trình vì dài lắm, khó chữa lỗi.

chúc các bạn thành công.

ngohaibac 20-03-2006 11:52 PM

Còn về chú ý mà ntc nói thì đúng rồi. Nhưng mình hoàn toàn có thể làm được 2 công việc một lúc là vừa quét led vừa làm đầu vào Analog được. Điều này đã được nói trong App Note của bọn Microchip rồi.
Tài liệu AP557d: http://ww1.microchip.com/downloads/e...tes/00557d.pdf

Bọn này chỉ dùng có con 16C71 với 18 chân mà làm được khối việc. Anh BA đã nói đến trong bài một số kiểu tiết kiệm chân vđk rồi tại luồng
http://dientuvietnam.net/forums/showthread.php?t=5

Đây là hình vẽ minh họa:
http://i36.photobucket.com/albums/e4.../PVN_00015.gif

Các bạn thấy thế nào. Mình nghĩ là nên lập một luồng để đưa lại các App Note của bọn Microchip để mọi người cùng học tập thì chắc chắn là hay hơn nhiêu. Vì bọn nó có nhiều chú ý về các vấn đề như I/O, về display led, LCD, PID, ...

Các bạn thấy thế nào?

nhh 22-03-2006 05:44 PM

Trích:

Nguyên văn bởi falleaf
Các bài viết trong luồng này rất hay, các bạn đang thảo luận về PWM, có thể nhấn thêm một bước bây giờ giả sử khi kết hợp 2 chân PWM nhưng làm xung trên 2 chân xen kẽ với nhau xem nào?

Đây có thể chỉ là một bài tập vui nhưng cũng có ứng dụng nhiều đấy.

Chúc vui.

Mình dùng ngắt để xử lý có được không anh F!

pb1 23-03-2006 11:17 PM

Các bác cho em hỏi một tí:tại sao người ta phải sử dụng đến 10bit phân giải
CCPR1L:CCP1CON<5:4> để làm gì, mà không dùng 8 bit CCPR1L thôi?

À, còn cái này nữa. Nếu như dùng 10bit như thế thì làm thế nào để thay đổi giá trị đặt vào chúng(mục đích của em là dùng cái thằng PWM module tạo ra xung thay đổi liên tục)
Bác nào có thể giúp em tí không?

thank các bác nhiều!

pb1 24-03-2006 10:31 AM

em có đoạn chương trình này!
 
// Period of square-wave (chu kì của một sóng vuông)
/*Variables for capture and interrupt*/
static volatile bit flag=0;
static volatile unsigned int t1=0,t2=0;

void capture_setup(void)
{
CCPR1L=0; CCPR1H=0; //Clear capture registers
TMR1H=0; TMR1L=0; //Clear timer1 registers
CCP1CON = 0b00000111; //Capture every 16th rising edge on CCP1(RC2)
T1CON = 0b00100101; //Configure Timer1 module in timer mode with 1:4 prescale and start Timer1
CCP1IE=1; //Enable CCP interrupts
TMR1IE=0; //Disable Timer1 interrupts
PEIE=1;
GIE=1; //Enable global interrupts
}

static void t1func(void)
{
t1=CCPR1L;
t1+=(CCPR1H << 8);
}

static void t2func(void)
{
t2=CCPR1L;
t2+=(CCPR1H << 8);
t2-=t1;
}

static void interrupt isr(void)
{
if (CCP1IF && CCP1IE) //Clock line every 16th rising edge on CCP1IF, RC2, pin 13 on micro
{
CCP1IF=0;

if(flag==1) //Save value to t1 on every even interrupt
{
t1func();
flag = 0;
}
else //Save value to t2 on every odd interrupt
{
t2func();
flag = 1;
}
}
}
Nhà mình có bác nào dảnh thì giải thích giúp em cái này cái: :D
static volatile bit flag=0;
static volatile unsigned int t1=0,t2=0;
Khai báo biến kiểu này là kiểu gì thế?

nhh 25-03-2006 12:01 PM

To Pb1!
Bạn đang tìm hiểu về module PWM,đây là một module cùng với ADC,...được sử dụng rất nhiều.Rất hoanh nghênh bạn nhưng trong luồng này mọi người thảo luận bằng ASM.Pb1 nên mở hẳn một luồng bàn về vấn đề này nhưng phải ở mục các ngôn ngữ lập trình khác CCS C, HTPIC,..

Tớ sẽ ủng hộ cậu mở luồng mới!

nhh 25-03-2006 12:02 PM

Digital clock
 
Ý tưởng viết chương trình cho cái này như sau:

Các chân a > g của led 7 đoạn nối chung dữ liệu và nối đến PortD ,các chân cathode nối đến PortB,...

> Khởi tạo các chân I/O,ngắt TMR0 1s
> Quét 6 LED,kiểm tra có bật Switch chỉnh thời gian?Nếu có thì tắt ngắt toàn cục,chỉnh xong set cờ GIE và quay lại quét LED,chờ ngắt
Khi có ngắt
> Tăng đếm LED1 lên 1,kiểm tra xem > 9 ?Chưa thì thoát ngắt,rồi thì xóa đếm LED1 về 0,tăng đếm LED2 thêm 1
> Kiểm tra đếm LED2 >6 ?Chưa thì thoát ngắt,rồi thì xóa đếm LED2 về 0,tăng đếm LED2 thêm 1
> Tiếp cho LED3,4,5
> Kiểm tra đếm LED6 = 2 & đếm LED5 > 4 ?Chưa thì thoát ngắt,rồi thì xóa đếm LED5,6 và thoát ngắt.

Viết như thế này thì hơi rắc rối và phức tạp,vừa dài,vừa dai lại vừa dở,quá nhiều nhược điểm luôn:
1.Do call,ngắt,...nếu không cẩn thận khi vào ngắt dễ bị tràn Stack thì đi tong ngay (Ban đầu mình mô phỏng Pro thì toàn hiện 0,coi lại code mờ mắt mà không phát hiện sai ở đâu cả,nhảy sang dùng PIC Sim thì bị báo tràn Stack ầm ầm luôn!Pó tay!)
2.Ngắt TMR0 bên trên chỉ rất rất gần 1s,có thể âm thầm dùng delay bù vào ở giây 60,nhưng do làm biếng tính,mình no bù!
3.Cẩn thận với ORG dành cho dữ liệu bảng,khi chương trình dài có thể chồng dữ liệu lên vùng này thì cũng đi tong luôn
4.Khi dùng bảng tra dài hơn 255,bảng đặt ở 2 page khác nhau,...cần thay đổi cách tra,cụ thể nên xem trong tutorial Kỹ thuật bảng.

He he...!Đồng hồ thời gian thực chẳng ma nào dại mà làm như thế này cả....Chỉ mỗi cái này mà loạn cả lên thì qua mấy cái module phức tạp khác,chắc ngủm khi viết bằng ASM quá!

Trên đây là những gì mình vot được, mod Chính ý kiến thế nào?Chia sẻ kinh nghiệm cho bà con tí !

nhh 25-03-2006 12:08 PM

Code:

;========================================
;Author:                NHH
;Date:                02/03/06
;Hardware:        PIC16F877A ,Crystal 4MHz
;========================================
        PROCESSOR        PIC16f877A
        INCLUDE<P16f877A.inc>
        __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_OFF & _CPD_OFF &_LVP_OFF
;========================================
        COUNT                EQU        0x20
        COUNT1                EQU        0x21
        COUNT2                EQU        0x22
        COUNT3                EQU        0x23
        COUNT4                EQU        0x24
        COUNT5                EQU        0x25
        COUNT6                EQU        0x26
        COUNT7                EQU        0x27
       
w_temp                EQU        0x71                ; variable used for context saving
status_temp        EQU        0x72                ; variable used for context saving
pclath_temp        EQU        0x73                ; variable used for context saving                       

;=============================================================================
;CHUONG TRINH CHINH
;=============================================================================
        ORG        0x00
        GOTO        MAIN
        ORG        0004h
        GOTO        INTERRUPT

;==============================INTERRUPT PROGRAM===========================               
INTERRUPT
        movwf w_temp        ; save off current W register contents
        movf STATUS,w        ; move status register into W register
        movwf status_temp        ; save off contents of STATUS register
        movf PCLATH,w        ; move pclath register into w register
        movwf pclath_temp        ; save off contents of PCLATH register
;******************************************************************************
        DECFSZ        COUNT,F
        GOTO        CHECK
        MOVLW        d'1'
        MOVWF        COUNT       
        INCF        COUNT1,F
        GOTO        CHECK       
BACK        BCF        INTCON,TMR0IF        ;xoa co ngat TMR0
;******************************************************************************
        movf pclath_temp,w                ; retrieve copy of PCLATH register
        movwf PCLATH                ; restore pre-isr PCLATH register contents
        movf status_temp,w                ; retrieve copy of STATUS register
        movwf STATUS                ; restore pre-isr STATUS register contents
        swapf w_temp,f
        swapf w_temp,w                ; restore pre-isr W register contents
        retfie                        ; return from interrupt

CHECK       
        CALL        CHECK1
        CALL        CHECK2
        CALL        CHECK3
        CALL        CHECK4
        CALL        CHECK5
        GOTO        BACK
;==============        CHUONG TRINH CHINH===============
MAIN
        BCF        STATUS,RP1
        BSF        STATUS,RP0                ; chon BANK 1
        MOVLW        b'11111111'                ;PORTA=Input
        MOVWF        TRISA
        MOVLW        b'00000001'                ;RB0=Input
        MOVWF        TRISB
        CLRF        TRISD
;------------------------------
;Khoi tao ngat Timer0
;------------------------------
        BSF        OPTION_REG,PS0                ;TMR0 rate 1: 64
        BSF        OPTION_REG,PS1
        BCF        OPTION_REG,PS2
        BCF        OPTION_REG,PSA                ;Prescaler is assigned to the Timer0 module
        BCF        OPTION_REG,T0CS               
        BCF        STATUS,RP0                ;select BANK 0

        BSF        INTCON,GIE
        BSF        INTCON,TMR0IE
        BCF        INTCON,TMR0IF

        MOVLW        d'246'
        MOVWF        COUNT
        CLRF        COUNT1
        CLRF        COUNT2
        CLRF        COUNT3
        CLRF        COUNT4
        CLRF        COUNT5
        CLRF        COUNT6
        CLRF        COUNT7
LOOP
        CALL        DISPLAY1
        CALL        DISPLAY2
        CALL        DISPLAY3
        CALL        DISPLAY4
        CALL        DISPLAY5
        CALL        DISPLAY6
       
        BTFSC        PORTB,0
        GOTO        LOOP
        GOTO        MODIFY
MODIFY
        BCF        INTCON,GIE
       
        BTFSC        PORTA,0
        GOTO        $+2
        CALL        LED34
        BTFSC        PORTA,1
        GOTO        $+2
        CALL        LED56
        BTFSS        PORTB,0
        GOTO        MODIFY
        BSF        INTCON,GIE
        GOTO        LOOP
LED34
        INCF        COUNT3,F
        MOVLW        d'10'
        SUBWF        COUNT3,W
        BTFSS        STATUS,0
        RETURN
        CLRF        COUNT3
        INCF        COUNT4,F
        MOVLW        d'6'
        SUBWF        COUNT4,W
        BTFSS        STATUS,0
        RETURN
        CLRF        COUNT4
        RETURN
LED56
        INCF        COUNT5,F
        MOVLW        d'4'
        SUBWF        COUNT5,W
        BTFSS        STATUS,0
        RETURN
        MOVLW        d'2'
        SUBWF        COUNT6,W
        BTFSS        STATUS,0
        GOTO        LED5
        CLRF        COUNT6
        RETURN
       
LED5
        MOVLW        d'10'
        SUBWF        COUNT5,W
        BTFSS        STATUS,0
        GOTO        MODIFY
        CLRF        COUNT5
        INCF        COUNT6,F
        GOTO        MODIFY

;============CHUONG TRINH CON===
DISPLAY1
        MOVLW        b'11111101'
        MOVWF        PORTB
        MOVF        COUNT1,W
        CALL        TABLE
        MOVWF        PORTD
        CALL        DECREATE
        CLRF        PORTB
        CLRF        PORTD               
        RETURN
DISPLAY2
        MOVLW        b'11111011'
        MOVWF        PORTB
        MOVF        COUNT2,W
        CALL        TABLE
        MOVWF        PORTD
        CALL        DECREATE
        CLRF        PORTB
        CLRF        PORTD
        RETURN
DISPLAY3
        MOVLW        b'11110111'
        MOVWF        PORTB
        MOVF        COUNT3,W
        CALL        TABLE
        MOVWF        PORTD
        CALL        DECREATE
        CLRF        PORTB
        CLRF        PORTD
        RETURN
DISPLAY4
        MOVLW        b'11101111'
        MOVWF        PORTB
        MOVF        COUNT4,W
        CALL        TABLE
        MOVWF        PORTD
        CALL        DECREATE
        CLRF        PORTB
        CLRF        PORTD
        RETURN
DISPLAY5
        MOVLW        b'11011111'
        MOVWF        PORTB
        MOVF        COUNT5,W
        CALL        TABLE
        MOVWF        PORTD
        CALL        DECREATE
        CLRF        PORTB
        CLRF        PORTD
        RETURN
DISPLAY6
        MOVLW        b'10111111'
        MOVWF        PORTB
        MOVF        COUNT6,W
        CALL        TABLE
        MOVWF        PORTD
        CALL        DECREATE
        CLRF        PORTB
        CLRF        PORTD
        RETURN

DECREATE
        DECFSZ        COUNT7
        GOTO        DECREATE
        RETURN

;........................................................
CHECK1
        MOVLW        d'10'
        SUBWF        COUNT1,W
        BTFSS        STATUS,0
        GOTO        BACK
        CLRF        COUNT1
        INCF        COUNT2,F
        RETURN
CHECK2
        MOVLW        d'6'
        SUBWF        COUNT2,W
        BTFSS        STATUS,0
        GOTO        BACK
        CLRF        COUNT2
        INCF        COUNT3,F
        RETURN
CHECK3
        MOVLW        d'10'
        SUBWF        COUNT3,W
        BTFSS        STATUS,0
        GOTO        BACK
        CLRF        COUNT3
        INCF        COUNT4,F
        RETURN
CHECK4
        MOVLW        d'6'
        SUBWF        COUNT4,W
        BTFSS        STATUS,0
        GOTO        BACK       
        CLRF        COUNT4
        INCF        COUNT5,F
        RETURN
CHECK5
        MOVLW        d'10'
        SUBWF        COUNT5,W
        BTFSS        STATUS,0
        GOTO        BACK       
        CLRF        COUNT5
        INCF        COUNT6,F
        RETURN
CHECK6
        INCF        COUNT5,F
        MOVLW        d'4'
        SUBWF        COUNT5,W
        BTFSS        STATUS,0
        RETURN
        MOVLW        d'2'
        SUBWF        COUNT6,W
        BTFSS        STATUS,0
        CALL        LED_5
        CLRF        COUNT6
        RETURN
       
LED_5
        MOVLW        d'10'
        SUBWF        COUNT5,W
        BTFSS        STATUS,0
        RETURN
        CLRF        COUNT5
        INCF        COUNT6,F
        RETURN
;----------------------------------------------------------

; Bang tra ve Digital tu 0 den 9 va OFF
; Chi so dau truy cap la 0
; Bang o PAGE 0

        ORG 07F0h
TABLE
;----------------------------------------------------------
        ADDWF        PCL, F                        ; bat dau tai 0x90
        RETLW        b'00111111'                ; 0
        RETLW        b'00000110'                ; 1
        RETLW        b'01011011'                ; 2
        RETLW        b'01001111'                ; 3
        RETLW        b'01100110'                ; 4
        RETLW        b'01101101'                ; 5
        RETLW        b'01111101'                ; 6
        RETLW        b'00000111'                ; 7
        RETLW        b'01111111'                ; 8
        RETLW        b'01101111'                ; 9
        RETLW        b'00111111'                ; 0
               
        END


nhh 25-03-2006 12:09 PM

Code:

:020000040000FA
:020000001E28B8
:080008000528F1000308F200D5
:100010000A08F300A00B18280130A000A10A182834
:100020000B1173088A0072088300F10E710E09002B
:10003000A320AA20B120B820BF20102803138316C4
:10004000FF30850001308600880101148114011100
:100050008111811283128B178B160B11F630A000C1
:10006000A101A201A301A401A501A601A7016A2083
:1000700073207C2085208E20972006183728402862
:100080008B13051844284B20851847285820061C38
:1000900040288B173728A30A0A302302031C0800C4
:1000A000A301A40A06302402031C0800A4010800CE
:1000B000A50A04302502031C080002302602031C96
:1000C0006328A60108000A302502031C4028A50168
:1000D000A60A4028FD3086002108F0278800A020CD
:1000E000860188010800FB3086002208F02788007E
:1000F000A020860188010800F73086002308F02739
:100100008800A020860188010800EF3086002408BE
:10011000F0278800A020860188010800DF308600D3
:100120002508F0278800A020860188010800BF303C
:1001300086002608F0278800A02086018801080094
:10014000A70BA02808000A302102031C1028A101D7
:10015000A20A080006302202031C1028A201A30AEA
:1001600008000A302302031C1028A301A40A080077
:1001700006302402031C1028A401A50A08000A3036
:100180002502031C1028A501A60A0800A50A0430B0
:100190002502031C080002302602031CD120A60100
:1001A00008000A302502031C0800A501A60A080061
:100FE00082073F3406345B344F3466346D347D34CD
:080FF00007347F346F343F34F5
:02400E00313F40
:00000001FF

http://www.freewebtown.com/nhhao/PIC...al%20clock.gif

falleaf 25-03-2006 01:00 PM

nhh ơi, bạn gửi file .hex thì nên gửi bằng cách gửi kèm file, nhìn phía bên dưới khi bạn viết bài trả lời á, phần Chức Năng, có mục Tải file từ máy. Lúc đó bạn tải file .hex lên, hoặc tải file .zip lên, như vậy sẽ thuận tiện hơn cho người đọc.

Chúc vui.

ngohaibac 26-03-2006 12:56 AM

Trích:

Nguyên văn bởi pb1
Nhà mình có bác nào dảnh thì giải thích giúp em cái này cái: :D
static volatile bit flag=0;
static volatile unsigned int t1=0,t2=0;
Khai báo biến kiểu này là kiểu gì thế?

Theo tài liệu tại: \HT-PIC\manual\manual.pdf trang 153 . Bọn nó viết thế này: (tạm dịch)

Kiểu dữ liệu volatile được dùng để báo cho trình dịch biết rằng đối tượng được khai báo kiểu volatile có thể không cần lưu trữ lại giá trị giữa các lần truy cập liên tiếp. Điều đó làm cho chương trình có sự tối ưu hoá từ việc là những dư thừa rõ ràng đang được loại ra khi sử dụng một đối tượng có kiểu volatile bởi ví đối tượng đó có thể thay đổi tuỳ theo chương trình hoạt động như thế nào.

Tất cả các port I/O và tất cả các biến mà bị thay đổi giá trị trong trình phục vụ ngắt nên khai báo kiểu volatile.

Ví dụ:
Code:

volatile static near unsigned char PORTA @ 0xF80;
Đối tượng volatile được truy nhập theo một cách khác so với một đối tượng không có khai báo volatile. Khi gán giá trị của một đối tượng không có khai báo volatile = 1 thì đối tượng này sẽ bị xoá và địa chỉ của đối tượng sẽ tăng lên. Nhưng với biến có khai báo violatile thì cách hoạt động như sau: đầu tiên là gán giá trị của thanh ghi W = 1 và sau đó là lưu giá trị đó vào địa chỉ của ban đầu của đối tượng đó.

Kết luận: như vậy là khai báo volatile được dùng với biến phải sử dụng liên tục. Khi khai báo như thế thì tiết kiệm được địa chỉ của RAM.

Khi các bạn mở các file include ra sẽ thấy được rằng bọn nó khai báo địa chỉ cho các port đều theo kiểu này :D

pb1 26-03-2006 01:13 AM

hehe, làm ăn phải như thế chứ :D
cảm ơn bác Bắc nhé, em hiểu rùi

ntc 26-03-2006 06:02 PM

Ahahaha. Đúng như mình dự đoán. Không trật đi chỗ nào cả. :D. Không dễ chút nào đúng không.

Bây giờ nhh tính khắc phục như thế nào.

Thử nêu vài giải pháp theo suy nghĩ của nhh coi.

Bạn có thể tin là code không có gì sai. Vấn đề ở đây là một cái gì đó rất khó chịu.

Nó là cái gi??

ntc 26-03-2006 06:15 PM

Cái Timer thì thời gian chỉ cần tương đối thôi, không cần chính xác.

Về phần thiết kế phần cứng cũng ổn rồi. :D

Cái mình muốn đưa ra thảo luận trong ứng dụng này là cái chỗ bí mà nhh mắc phải.

Cái lệnh ORG, bạn có thể không cần sử dụng trước bảng tra, mà có thể để cho trình biên dịch tự sắp xếp, để tránh hiện tượng bị code đè lên. Mà trường hợp này khi biên dịch bằng MPASM thì nó có báo lỗi mà.

Stack! Bàn đầu mình cũng nghĩ vấn đề chương trình chạy không đúng là do stack. Nhưng hình như không phải. :D .

nhh 26-03-2006 06:55 PM

Trích:

Nguyên văn bởi ntc
Cái Timer thì thời gian chỉ cần tương đối thôi, không cần chính xác.

Về phần thiết kế phần cứng cũng ổn rồi. :D

Cái mình muốn đưa ra thảo luận trong ứng dụng này là cái chỗ bí mà nhh mắc phải.

Cái lệnh ORG, bạn có thể không cần sử dụng trước bảng tra, mà có thể để cho trình biên dịch tự sắp xếp, để tránh hiện tượng bị code đè lên. Mà trường hợp này khi biên dịch bằng MPASM thì nó có báo lỗi mà.

Stack! Bàn đầu mình cũng nghĩ vấn đề chương trình chạy không đúng là do stack. Nhưng hình như không phải. :D .

Kinh nghiệm của ntc vấn đề này là gì vậy? Cái bảng bị ghi đè này chăng !Chia se cho anh em với !

lamhoang 27-03-2006 11:49 AM

Cho mình hỏi chút!
 
:D Vậy dùng Timer khi khởi động thì cần lưu ý đến những chú ý gì vậy (cách thức khởi động timer).
Có gì khác nhau nhiều giữa Timer0 và các timer khác ko.
Bạn có đoạn code nào về Timer ko. Mình đang làm thử một ứng dụng đơn giản là: điều khiển led nháy với thời gian thay đổi phụ thuộc vào nút bấm nhưng mình đang gặp vấn đề về Timer (chưa cụ thể về cách điều khiển về nó). Mong bạn hướng dẫn.
Mình chỉ mới làm quen với Assembly nên các đoạn mã dùng C đọc ko hiểu mấy. Theo bạn thì mình có nên chuyển sang học C hay là thuần thục Assembly rồi mới chuyển.
Mình cũng đang mới bắt đầu với PIC nên cần học nhiều.Thank!

chuabietgi 27-03-2006 01:35 PM

Trích:

Nguyên văn bởi lamhoang
:D Vậy dùng Timer khi khởi động thì cần lưu ý đến những chú ý gì vậy (cách thức khởi động timer).
Có gì khác nhau nhiều giữa Timer0 và các timer khác ko.
Bạn có đoạn code nào về Timer ko. Mình đang làm thử một ứng dụng đơn giản là: điều khiển led nháy với thời gian thay đổi phụ thuộc vào nút bấm nhưng mình đang gặp vấn đề về Timer (chưa cụ thể về cách điều khiển về nó). Mong bạn hướng dẫn.
Mình chỉ mới làm quen với Assembly nên các đoạn mã dùng C đọc ko hiểu mấy. Theo bạn thì mình có nên chuyển sang học C hay là thuần thục Assembly rồi mới chuyển.
Mình cũng đang mới bắt đầu với PIC nên cần học nhiều.Thank!

Em xin có ý kiến thế này:
Mình có thể vừa dùng ngắt timer vừa dùng ngắt ngoài để điều chỉnh có được không á...

Bác nhh và mod ntc cho ý kiến đi !

nhh 27-03-2006 03:58 PM

Trích:

Nguyên văn bởi lamhoang
:D Vậy dùng Timer khi khởi động thì cần lưu ý đến những chú ý gì vậy (cách thức khởi động timer).
Có gì khác nhau nhiều giữa Timer0 và các timer khác ko.
Bạn có đoạn code nào về Timer ko. Mình đang làm thử một ứng dụng đơn giản là: điều khiển led nháy với thời gian thay đổi phụ thuộc vào nút bấm nhưng mình đang gặp vấn đề về Timer (chưa cụ thể về cách điều khiển về nó). Mong bạn hướng dẫn.
Mình chỉ mới làm quen với Assembly nên các đoạn mã dùng C đọc ko hiểu mấy. Theo bạn thì mình có nên chuyển sang học C hay là thuần thục Assembly rồi mới chuyển.
Mình cũng đang mới bắt đầu với PIC nên cần học nhiều.Thank!

Cách thức khởi động timer có khác nhau,timer0 bạn phải chỉ định Pre cho nó bằng lệnh:
Code:

BCF        OPTION_REG,PSA
và điều chỉnh tốc độ bằng việc khởi tạo cho 3 bit PS0,PS1 và PS2 của thanh ghi OPTION_REG.
Timer0 và timer2 là timer 8bit,timer1 là timer 16bit,ngoài chức năng định thì thì timer còn nhiều ứng dụng khác.
Cụ thể bạn xem thêm trong datasheet mấy cái thanh ghi ở phần Timer!

Theo ý nhh để điều chỉnh thời gian như bạn nói bằng nút bấm (ko biết bạn dùng mấy nút?), mình làm như sau :
Với 3 nút bấm chẳng hạn và thời gian ấn nút 1 sẽ delay 1s;nút 2 delay 500ms; nút 3 delay 100ms ,viết mấy cái lệnh kiểm tra xem cái nút nào on thì nhảy đến cái nhãn đó, ấn nút 1 -> nhảy vào Button_1 thì 500+400+100=1000ms=1s,rồi quay ngược về,hai nhãn còn lại cũng tương tự,
Trong phần main mình sẽ đặt những cái nhãn :

Code:

....
Button_1
          Call delay_500ms
Button_2
          Call delay_400ms
Button_2
          Call delay_100ms
.....

Mấy hàm delay này mình tin là bạn viết ok nếu không thì tham khảo tutorial 2 của Chính :
http://www.picvietnam.com/forum//sho...p?t=238&page=2

Ý tưởng là vậy,bạn thử viết và post lên (cả sơ đồ nguyên lí nhé!) để anh em nhà pic cùng phá luôn !

nhh 27-03-2006 04:08 PM

Về việc bắt đầu viết chương trình bằng ngôn ngữ gì ASM,CCS C,HT-PIC,...,theo mình tốt hơn vẫn nên học cơ bản bằng ASM trước sau đó đào sâu thì càng tốt không thì nhảy qua các ngôn ngữ khác cũng dễ chịu rồi !
Bạn nên đọc luồng này để tham khảo cách học của mọi người :
http://www.picvietnam.com/forum//showthread.php?t=91
Chúc bạn mau chóng tìm cho mình cách học hiệu quả nhất !

ntc 27-03-2006 10:41 PM

Dùng bao nhiêu ngắt cũng được. Cái quan trọng là ban phải phát hiện ra ngắt nào xảy ra để xử lí.

Như vậy, khi bắt đầu chương trình ngắt, bạn phải có đoạn chương trình kiểm tra xem ngắt nào xảy ra bằng cách kiểm tra các cờ ngắt. Ngắt nào xảy ra thì cờ ngắt tương ứng với ngắt đó sẽ nhảy lên mức logic 1. Kiểm tra xong thì ra lệnh cho vi điều khiển nhảy đến đoạn chương trình xử lí tương ứng.

ntc 27-03-2006 10:58 PM

PIC16F877A có tất cả 3 Timer. Mìhn không nhớ thật sự chi tiết, nhưng đại khái nó như vầy:

Timer 0 và Timer 2 là bộ đếm 8 bit.

Timer 0 có bộ chia tần số (prescaler) dùng chung với Watchdog Timer. Nghĩa là khi bộ chia tần số này được sử dụng bởi WDT, thì cái Timer 0 không được quyền xài nó và ngược lại.

Timer 2 có cả 2 bộ chia tần số phía trước và phía sau (prescaler và postscaler) cho phép ta ấn định tỉ số chia linh hoạt hơn để tạo ra khoảng thời gian thích hợp cho ứng dụng.

Timer 0 và Timer 2 tuy là bộ đếm 8 bit, nhưng tỉ số chia của các bộ chia lớn hơn Timer 1. Như vậy nó cũng cho phép tạo ra các khoảng thời gian delay với độ trễ thích hợp với các ứng dụng trong thực tế.

Timer 1 là bộ đếm 16 bit, được hỗ trợ bởi bộ chia tần số prescaler. Tuy nhiên tỉ số chia này nhỏ (1:1 đến 1:16).

Mỗi Timer có cấu tạo khác nhau, điều đó cũng có nghĩa mỗi Timer sẽ thích hợp hơn với một tình huống nào đó trong thực tế, và tùy theo cái tình huống mà lựa chọn Timer thích hợp.

Sơ lược như vậy, bạn tham khảo datasheet để biết thêm chi tiết, mình chỉ nhớ mang máng như vậy thôi, không biết có chỗ nào nhớ lộn không nữa.

Về việc tham khảo cách khởi tạo và sử dụng Timer, bạn tham khảo thêm các hướng dẫn trong tài liệu "mid-range PIC mcu reference manual" trong micro chip. Trong đó hướng dẫn rất chi tiết, bạn chỉ việc dựa trên cái sườn bài có sẵn trong cái tài liệu đó và thay đổi các thông số cài đặt cho thích hợp là ok.

:D

ntc 27-03-2006 11:10 PM

Chắc bữa nào phải sửa lại cái Timer cho đàng hoàng rồi post lên cho anh em quá. Hic, dạo này bị bác F chơi, quăng việc liên tục, mệt gần chết, cũng hết thời gian rảnh luôn.

Về cái Timer của nhh. Bạn khắc phục như thế này thử xem: cái bảng dữ liệu, bạn chuyển lên đặt ở phía trên, sao cho các lệnh của phần table nó nằm trong vùng code 256 byte đầu của bộ nhớ chương trình, không đặt nó ở cuối chương trình nữa. Nhiều khi do chương trình phía trên bạn viết dài, nên cái table bị rơi ra khỏi vùng 256 word đầu tiên của bộ nhớ chương trình. Chắc ăn là chuyển hẳn nó lên phía trên chương trình start luôn, tức là viết table xong thì tới cái label start.

Có phải cái chương trình của bạn khi viết xong, bạn không thể kiểm soát được là nó sẽ chạy theo kiểu nào đúng không. :D .

nhh hiểu ý mình không. Sửa lại rồi thông báo tình hình cho anh em như thế nào nhé!

:D .

zero_OR_one 03-04-2006 12:24 PM

em có 1 bài toán bên mục của bác Chính,nhờ mọi người chỉ cho:confused:

lamhoang 04-04-2006 07:36 PM

Trích:

Nguyên văn bởi nhh
Cách thức khởi động timer có khác nhau,timer0 bạn phải chỉ định Pre cho nó bằng lệnh:
Code:

BCF        OPTION_REG,PSA
và điều chỉnh tốc độ bằng việc khởi tạo cho 3 bit PS0,PS1 và PS2 của thanh ghi OPTION_REG.
Timer0 và timer2 là timer 8bit,timer1 là timer 16bit,ngoài chức năng định thì thì timer còn nhiều ứng dụng khác.
Cụ thể bạn xem thêm trong datasheet mấy cái thanh ghi ở phần Timer!

Theo ý nhh để điều chỉnh thời gian như bạn nói bằng nút bấm (ko biết bạn dùng mấy nút?), mình làm như sau :
Với 3 nút bấm chẳng hạn và thời gian ấn nút 1 sẽ delay 1s;nút 2 delay 500ms; nút 3 delay 100ms ,viết mấy cái lệnh kiểm tra xem cái nút nào on thì nhảy đến cái nhãn đó, ấn nút 1 -> nhảy vào Button_1 thì 500+400+100=1000ms=1s,rồi quay ngược về,hai nhãn còn lại cũng tương tự,
Trong phần main mình sẽ đặt những cái nhãn :

Code:

....
Button_1
          Call delay_500ms
Button_2
          Call delay_400ms
Button_2
          Call delay_100ms
.....

Mấy hàm delay này mình tin là bạn viết ok nếu không thì tham khảo tutorial 2 của Chính :
http://www.picvietnam.com/forum//sho...p?t=238&page=2

Ý tưởng là vậy,bạn thử viết và post lên (cả sơ đồ nguyên lí nhé!) để anh em nhà pic cùng phá luôn !

OK! Thank! như vậy là thời điểm chính thức Timer khởi động là ngay sau lệnh
BCF option_reg,PSA
Mình cũng mới viết xong nhưng do không định được thời điểm Timer khởi động nên thời gian delay ko chính xác.
Hình như các bác ở SG và HN hết thì phải . không biết có cao thủ nào ở ĐN không nhỉ. Phải phát triển phong trào sử dụng PIC ở ĐN chứ các bác nhỉ?

namqn 04-04-2006 07:54 PM

Trích:

Nguyên văn bởi lamhoang
OK! Thank! như vậy là thời điểm chính thức Timer khởi động là ngay sau lệnh
BCF option_reg,PSA

Lệnh đó dùng để chỉ định prescaler được dùng cho timer 0, thay vì cho WDT (vì WDT và timer 0 dùng chung prescaler). Với các timer khác thì thường có một bit trong thanh ghi điều khiển dùng để bật/tắt timer, với timer 0 (trong 16F877A) thì không có chuyện bật/tắt timer. Do đó, bạn phải tự đảm bảo là khi bạn gán prescaler cho timer 0 thì nó cũng bắt đầu đếm từ 0, nếu bạn muốn có thời gian delay tương đối chính xác.

Thân,

ntc 05-04-2006 11:51 AM

Timer 1 của PIC16F877A có chế độ cho phép bật tắt Timer.

:D

nhh 05-04-2006 12:50 PM

Trích:

Nguyên văn bởi ntc
Timer 1 của PIC16F877A có chế độ cho phép bật tắt Timer.

:D

Mình xin nói thêm cả timer1 và timer2 luôn, để bật timer1 và timer2 lần lượt dung lệnh:
Code:

BSF T1CON,TMR1ON    ;bat Timer1
BSF T2CON,TMR2ON    ;bat Timer2


picpicpic 16-04-2006 12:57 PM

Cũng ko có gì mới cả...
Các bác mau mau post tiếp đi chứ !

Đợi các bác lâu quá mất cả hứng ...!

newuser 19-04-2006 10:06 PM

Timer0 ở PIC6F877A vẫn là free counter, theo mình thì cấp điện vào là nó đã chạy tự do rồi, vấn đề là bạn dùng nó lúc nào thôi, về prescaler thì mình nghĩ cũng như 16F84A, nghĩa là khi đã dùng nó cho WDT thì timer0 sẽ dùng với tỉ lệ chia là 1:1

nhh 20-04-2006 11:02 AM

Tại sao lại chỉ dùng với tỉ lệ chia 1:1
Còn những tỉ lệ khác không dùng được sao, bạn xem kĩ datasheet phần timer0, nó chia đến tận tỉ lệ 1:128 lận !

ngohaibac 20-04-2006 01:38 PM

Trích:

Nguyên văn bởi nhh
Tại sao lại chỉ dùng với tỉ lệ chia 1:1
Còn những tỉ lệ khác không dùng được sao, bạn xem kĩ datasheet phần timer0, nó chia đến tận tỉ lệ 1:128 lận !

Không phải, ý bạn đó nói là Timer0 dùng chung prescaler với Watchdog cơ mà. Bit chọn lựa bộ chia trước Prescaler cho Watdog hay timer0 là bit PSA (bit 3 trong thanh ghi OPTION).

Khi PSA = 1 thì nó dùng cho WDT
PSA = 0 thì prescaler dùng cho timer0.

Và dĩ nhiên khi PSA = 1 thì timer0 chỉ có tỉ lệ chia là 1:1 tức là sẽ k bị chia trước tần số.

Chúc các bạn thành công.

pb1 21-04-2006 12:10 AM

các bác xem giúp em cái

hơ hơ.... sao không up file lên được nhỉ?

bác fall ơi, xem giúp em cái !.Em đã tải file lên rồi, tại sao không thấy file đâu?
em định tải file lên để nhờ các bác chỉ giáo tí.


Múi giờ GMT. Hiện tại là 07:33 PM.

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