Nhập môn VĐK PIC với 16F877A

Thảo luận trong 'Họ PIC -> dsPIC'

Đang xem chủ đề này ( Thành viên: 0, Khách: 1)

  1. chivu

    chivu Kỹ sư

    Tham gia ngày:
    3/9/12
    Bài viết:
    57
    Đã được thích:
    194
    Điểm thành tích:
    33
    Giới tính:
    Nam
    Nơi ở:
    S11 - Việt Nam
    Trong luồng này mình sẽ hướng dẫn những kiến thức cơ bản nhất về pic thông qua dòng pic 16f877a. Đây là những kiến thức rất sơ khai nên hy vọng sẽ giúp ích phần nào cho những bạn mới nhập môn cũng như khuyến cáo với những bạn đã có kiến thức về pic không nên tìm hiểu! Trong quá trình hướng dẫn không tránh được thiếu sót, rất mong được sự đóng góp của các pro để đây là luồng thông tin hữu ích khi các bạn tìm hiểu về pic đến với codientu.org.
    Bài viết sẽ trình bày khá nhiều nên sẽ được chia làm một số phần cũng như được update liên tục vào #1
    Bạn tải tài liệu đi kèm tại đây
    pass: codientu.org (nếu có)

    PHẦN 1: TỔNG QUAN VỀ PIC VÀ CÁC TÀI LIỆU ĐI KÈM
    PIC là họ vi điều khiển mạnh, giàu tài nguyên về phần cứng và được microchip hỗ trợ nhiều tài liệu.
    Chúng ta có thể dùng ngôn ngữ C hoặc ASM để lập trình cho vi điều khiển PIC. Tuy nhiên mình khuyên bạn nên lập trình PIC bằng ngôn ngữ C. Ngôn ngữ C sẽ hỗ trợ bạn tiếp cận vi điều khiển PIC nhanh nhất, không cần tốn nhiều thời gian nghiên cứu cấu trúc PIC mà bạn vẫn lập trình cho PIC một cách dễ dàng và sẵn sàng chia sẽ code với mọi người trên mạng vì đa số họ cũng lập trình cho PIC bằng ngôn ngữ C.
    Và tất nhiên phần mềm biên dịch CCS lập trình cho họ vi điều khiển PIC bằng ngôn ngữ C. Nó là một trình biên dịch hỗ trợ ngôn ngữ C cho hầu hết các dòng vi điều khiển PIC. Bạn có thể tìm bản hướng dẫn sử dụng tại đây hoặc tài liệu đi kèm trong luồng này.
    Phần mềm mô phỏng proteus 7.10 tại đây

    PHẦN 2: CẤU TRÚC PHẦN CỨNG CỦA PIC
    Bộ nhớ chương trình (ROM) và bộ nhớ dữ liệu (RAM) của PIC khá thoải mái (các bạn nhập môn không cần quan tâm quá nhiều vào vấn đề này).
    [​IMG]


    Trong tài liệu đính kèm ở trên cấu trúc phần cứng đã được nêu khá cụ thể và chi tiết, các bạn có thể tự đọc. Trong luồng này mình sẽ nói nhiều hơn về các tập lệnh CCS sử dụng cho PIC 16f877a thông qua các ví dụ.

    PHẦN 3: TẬP LÊNH CCS C CHO PIC 16F877A
    1. Chỉ thị tiền xử lý

    1. #INCLUDE
    Cú pháp: #include<filename>
    Khai báo chỉ định đường dẫn cho trình biên dịch
    Ví dụ: #include<16f877a.h>
    hoặc #include < C:\INCLUDES\CCSC\VIDU.C >

    2.#BIT
    Cú pháp: #bit name=x.y
    Tạo biến 1bit có tên là name đặt ở byte x vị trí y. Thường dung để kiểm tra hoặc gán giá trị cho thanh ghi. Điểm khác so với dùng biến 1 bit từ khai báo int1 là: int1 tốn 1 bit bộ nhớ, còn #BIT thì không tốn thêm bộ nhớ do name chỉ danh định đại diện chi bit chỉ định ở biến x, thay đổi name (0/1) sẽ thay đổi giá trị tương ứng y -> thay đổi giá trị x.
    Ví dụ: #bit TMR1IF=0x0B.2; => tạo biến 1bit tên TMR1IF đặt ở byte có địa chỉ 0x0B ở vị trí thứ 2.

    3.#BYTE
    Cú pháp: #byte name=x
    Gán tên biến name cho địa chỉ x. name thường trùng với tên thanh ghi có địa chỉ x
    Ví dụ: #byte portB=0x06;

    4.#DEFINE
    Cú pháp: #define name text
    Dùng để khai báo một chuỗi hoặc số có tên là name
    Ví dụ: #define constan 123456;

    5.#USE:
    Cú pháp: #use delay(clock=speed)
    Dùng để khai báo tốc độ dao động của thạch anh và có chỉ thị này thì bạn mới sử dụng được các hàm trễ thời gian delay_ms hay delay_us
    Cú pháp: #use fast_io(port)
    Port là các cổng vào ra của PIC (từ A -> G)
    Có chỉ thị này thì chúng ta có thể điều chỉnh các port chỉ với 1 lệnh như output_low(), input_high()...Chú ý: trong hàm main () bạn phải dùng hàm set_tris_x() để chỉ rõ chân vào ra thì chỉ thị trên mới có hiệu lực, nếu không chương trình sẽ chạy sai!
    Ví dụ: #USE FAST_IO (A);
    Bạn có thể tìm đọc thêm một số chỉ thị #USE I2C, #USE RS232 cũng như một số tiền xử lý khác trong tài liệu CCS C bản tiếng việt của Nguyễn Xuân Trường đi kèm ở trên.

    2. Các hàm delay
    Để sử dụng các hàm delay phải khai báo tiền xử lý như đã nói ở trên​
    ví dụ: #use delay (clock=20000000);
    Hàm delay không sử dụng bất kỳ một timer nào. Có 3 hàm phục vụ:​

    1. Delay_cycles (count)
    count: hằng số từ 0 - 255, là số chu kỳ lệnh. 1 chu kỳ lệnh bằng 4 chu kỳ máy nhé!​
    ví dụ: delay_cycles (25); với tần số dao động thạch anh OSC=20MHZ thì hàm delay này 5us=5*10^-6s​

    2. Delay_us (time)
    Time là biến số thì giá trị từ 0-255, nếu là hằng số thì 0-65535.​
    ví dụ:
    int time=100;
    delay_us (time); //delay 100us
    delay_us (1000); //delay 1000us

    3. Delay_ms (time)
    Tương tự với delay_us nhưng với đơn vị là ms=10^-3s.​

    3. Các hàm vào ra trong CCS C
    Bao gồm các hàm sau:
    Output_low() Output_high()
    Output_bit() Input()
    Ouput_X() Input_X()
    Set_tris_X()

    1 / Output_low ( pin ) , Output_high (pin ) :
    Dùng để thiết lập ngõ ra mức 0 (low, 0v) hoặc mức 1 (high, 5v) cho chân PIC, pin chỉ vị trí của chân.
    Có thể xuất xung dùng set_tris_x()#use fast_io
    Ví dụ: output_high (pin_b0); //ngõ ra chân b0 là 0v
    Delay_ms (1000); //tạo trễ 1000ms=1s
    Output_low(pin_b0); //ngõ ra chân b0 là 5v

    2. Output_bit ( pin , value ):
    Pin: tên chân
    Value: giá trị 0 hoặc 1
    Hàm này cũng xuất ra chân giá trị 0 hoặc 1. Tương tự như hàm trên. Thường dùng khi giá trị ra tùy thuộc giá trị của 1 biến nào đó, hoặc muốn đảo lại giá trị ngõ ra trước đó.
    Ví dụ:

    Mã:
    while (1 )
    {
    output_bit( pin_B0 , !x ) ;
    Delay_ms(250 );
    }
    3. Input ( pin ):
    Hàm cho giá trị đang có của chân pin là 0 hoặc 1. Giá trị 1bit
    Ví dụ: m=input(pin_B1); //giá trị m bằng 0 hoặc 1

    4. Output_X ( value ) :
    Hàm xuất giá trị 1 byte (8bit) ra port x, tất cả các chân của port đều là ngõ ra
    Ví dụ:
    Mã:
    Output_B ( 212 ) ; // xuất giá trị 11010100 ra port B
    Output_A ( 10101010b ) ; // xuất giá trị 10101010 ra port A

    5. Input_X ( ) :
    Hàm trả về giá trị 8bit (1byte) là giá trị đang có của port tên X (A -> G).
    Ví dụ: m=input_A

    6. Set_tris_X ( value ) :
    Hàm này dùng để định nghĩa chân IO (vào/ra) cho 1 port là ngõ vào hay ngõ ra. Chỉ dùng được khi đã khai báo tiền xử lý #use_fast_io.
    Sử dụng #byte để tạo 1 biến chỉ đến port và thao tác trên biến này chính là thao tác trên port đó.
    Value là giá trị 8 bit. Mỗi bit đại diện cho 1 chân, bit=0 thì chân đó là ngõ ra còn bit=1 chân đó là ngõ vào
    ví dụ : Đoạn mã sau cho phép thao tác trên port b 1 cách dễ dàng:
    Mã:
    #include < 16F877.h >
    #use delay(clock=20000000)
    #use Fast_IO( B )
    #byte portB = 0x6 // 16F877 port b ở địa chỉ 6h (portB ở đây là biến chỉ thanh ghi ở địa chỉ //0x6 chứ CCS C không có từ khóa portB ở địa chỉ 0x6, ta có thể đổi portA = 0x6 vẫn ok //nhưng sẽ gây nhầm lẫn lung tung và không thống nhất với các ký hiệu của nhà sản xuất và //người sử dụng!).
    #bit B0 = portB. 0 // bit ở chân B0 có tên biến là B0
    Main()
    {
    Set_tris_b (0); // portb = 00000000b => tất cả các chân port b là ngõ ra.
    ……..
    }
    4. Hàm sử dụng trong các TIMER
    Có 3 TIMER là TIMER0, TIMER1, TIMER2. Các hàm sử dụng cho các TIMER các bạn có thể tham khỏa trong tài liệu đính kèm. Trong các ví dụ cụ thể mình sẽ cố gắng giải thích các hàm này cho các bạn dễ hình dung hơn.
    to be continued #2 :49.jpg::49.jpg::49.jpg:
     
  2. chivu

    chivu Kỹ sư

    Tham gia ngày:
    3/9/12
    Bài viết:
    57
    Đã được thích:
    194
    Điểm thành tích:
    33
    Giới tính:
    Nam
    Nơi ở:
    S11 - Việt Nam
    5. Các hàm phục vụ ngắt
    - ENABLE_INTERRUPTS( level) // khai báo ngắt
    Level: //các dạng ngắt
    +GLOBAL : cho phép ngắt toàn cục
    +INT_TIMER0 : ngắt do tràn TIMER0
    +INT_TIMER1 : ngắt do tràn Timer1
    +INT_TIMER2 : ngắt do tràn Timer2
    +INT_RB : có thay đổi 1 trong các chân RB4 _ RB7
    +INT_EXT : ngắt ngoài trên chân RB0
    Chú ý : sau khi khai báo trên thì để vào chương trình ngắt cần khai báo
    #INT_.....
    ví dụ:
    Mã:
    #INT_TIMER1
    Void ngat_Timer1( )
    {
    //chương trình ngắt viết ở đây
    }

    6. Điều chế độ rộng xung PWM

    Để giải quyết vấn đề việc điều xung PWM bằng phần mềm chiếm phần lớn thời gian hoạt động của vi điều khiển, PIC16F877A có hỗ trợ 2 kênh điều xung bằng phần cứng ở 2 chân C1(CCP2)C2(CCP1) sử dụng TIMER2. Nghĩa là, khi ta khai báo điều xung PWM ở một tần số và duty cycle nào đó thì vi điều khiển sẽ thực hiện công việc xuất xung một cách liên tục và tự động cho đến khi ta thay đổi các giá trị đã khai báo. Khi đó, ta có thể làm các công việc khác một cách dễ dàng mà không phải mất thời gian cho việc duy trì xung PWM.
    Các hàm hỗ trợ việc điều xung bằng phần cứng của CCS:
    Ghi chú: Chỉ đề cập đến các đối số của các hàm được phục vụ cho việc điều xung PWM.
    + setup_timer_2 (mode, period, postscale)
    mode: T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
    period: 0-255
    postscale: 1
    Tần số điều xung PWM:
    f = fosc / [ 4*mode*(period+1) ]


    + setup_ccp1(mode)setup_ccp2(mode)
    mode:
    CCP_PWM: chọn chế độ PWM.
    CCP_OFF: tắt chế độ PWM.

    + set_pwm1_duty(value)set_pwm2_duty(value)
    Nếu value là giá trị kiểu int 8bit:
    duty_cycle = value / ( period+1 )


    Nếu value là giá trị long int 16bit:
    duty_cycle = value&1023 / [4*( period+1 )]


    Nếu không cần điều xung quá “mịn” thì nên điều xung ở giá trị value 8bit cho đơn giản.
    Ví dụ: Ta muốn điều xung PWM với tần số 10kHz với tần số thạch anh (fosc) sử dụng là 20MHz (value 8bit).
    f=fosc/[4*mode*(period+1)]


    <=> 10000 =20000000/[ 4*mode*(period+1) ] <=> mode(period+1) = 500


    Với mode = [1,4,16] và period = 0-255 ta có thể chọn:
    mode = 4; period = 124
    mode = 16; period = 32
    Để cho việc điều xung được “mịn” (chọn được nhiều giá trị duty cycle) ta chọn mode = 4 và period = 124.
    Như vậy, để duty_cycle từ 0% đến 100% ta cho value từ 0 đến 125.
    value = 30 => duty_cycle = 30 / ( 124+1 ) = 0.32 = 32%
    value = 63 => duty_cycle = 63 / ( 124+1 ) = 0.504 = 50.4%
    value = 113 => duty_cycle = 113 / ( 124+1 ) = 0.904 = 90.4%
    ví dụ:
    Code:
    setup_timer_2(T2_DIV_BY_4,124,1);
    setup_ccp1(CCP_PWM);
    set_pwm1_duty(30);

    PHẦN 4: CÁC VÍ DỤ KÈM MÔ PHỎNG PROTEUS
    1.Xuất tín hiệu 0/1 ra các chân
    [​IMG]




    Mã:
    #INCLUDE<16F877A.h> //KHAI BAO DEVICE CHO PIC
    #FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
    /*
    XT: SU DUNG THACH ANH TAN SO THAP (=4MHZ)
    NOWDT:KHONG SU DUNG CHE DO WATCH DOG TIMER
    PUT(POWER UP TIMER): CHON CHE DO LAM VIEC CHO PIC KHI DIEN AP DA ON DINH
    NOPROTECT : KHONG CHO PHEP DOC LAI MA CHUONG TRINH TRONG CHIP
    NOBROWNOUT : KHONG RESET LAI PIC KHI BI SUT AP
    NOLVP(LOW VOLTAGE PROGRAMMING) : ??
    */
    #USE DELAY(CLOCK=4000000) //GIA TRI OSC MA BAN DUNG
    #USE FAST_IO(B)
    VOID MAIN()
    {
    SET_TRIS_B(0); //THIET LAP CAC CHAN CUA PORTA LA CAC CHAN XUAT DU LIEU
    WHILE(TRUE) //TAO VONG LAP VO TAN
    {
    OUTPUT_HIGH(PIN_B0); //XUAT GIA TRI 1 RA CHAN RB0
    DELAY_MS(500); //TAO TRE 0,5s
    OUTPUT_LOW(PIN_B0); //XUAT GIA TRI 0 RA CHAN RB0
    DELAY_MS(500);
    OUTPUT_B(255); //DUA GIA TRI 1 RA CAC CHAN CUA PORTB
    DELAY_MS(500);
    OUTPUT_B(0); //DUA GIA TRI 0 RA CAC CHAN CUA PORTB
    DELAY_MS(500);
    }
    }
    2. Giao tiếp với nút bấm
    [​IMG]


    Mã:
    #INCLUDE<16F877A.H>
    #FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
    #USE DELAY(CLOCK=4000000)
    #USE FAST_IO(B)
    #BYTE PORTB=0x06
    #BIT BUTTON=PORTB.7
    #BIT LED=PORTB.6
    VOID MAIN()
    {
    SET_TRIS_B(0b10111111); //LAP CHE CHO PIN_B6 LA XUAT CON CAC CHAN KHAC LA NHAP
    WHILE(TRUE)
    {
    IF(BUTTON==0) //KIEM TRA NUT BAM
    {
    LED=1; //BAT DEN
    DELAY_MS(1000);
    LED=0; //TAT DEN
    }
    }
    }

    3. Delay dùng vòng lặp
    Mã:
    #INCLUDE<16F877A.H>
    #FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
    #USE DELAY(CLOCK=4000000)
    #BYTE INTCON=0x0B
    #BYTE PIR1=0x0C
    #BYTE T1CON=0x10
    #BIT TMR1ON=T1CON.0 //KHOI DONG TIMER1
    #BIT TMR1IF=PIR1.0 //CO TRAN TIMER1
    #BIT INTF=INTCON.1 //CO NGAT
    VOID DELAY(INT8 TIMER)
    {
    WHILE(TIMER--)
    {
    TMR1ON=1;
    WHILE(TMR1IF==0);
    TMR1ON=0;
    TMR1IF=0;
    }
    }
    VOID MAIN()
    {
    WHILE(TRUE)
    {
    OUTPUT_HIGH(PIN_C4);
    DELAY(100);
    OUTPUT_LOW(PIN_C4);
    DELAY(100);
    }
    }
    //TUONG TU VOI CAC TIMER0 VA TIMER2 CAC BAN CO THE XEM DATASHEET DE BIET THEM VE DIA
    CHI
    // CAC THANH GHI CHUC NANG CUA CHUNG

    to be continued #3 :49.jpg::49.jpg::49.jpg:
     
  3. chivu

    chivu Kỹ sư

    Tham gia ngày:
    3/9/12
    Bài viết:
    57
    Đã được thích:
    194
    Điểm thành tích:
    33
    Giới tính:
    Nam
    Nơi ở:
    S11 - Việt Nam
    4. Delay dùng TIMER không dùng ngắt

    Mã:
    #INCLUDE<16F877A.H>
    #FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
    #USE DELAY(CLOCK=4000000)
    #BYTE INTCON=0x0B
    #BYTE PIR1=0x0C
    #BYTE T1CON=0x10
    #BYTE T2CON=0x12
    #BIT TMR1ON=T1CON.0 //KHOI DONG TIMER1
    #BIT TMR1IF=PIR1.0 //CO TRAN TIMER1
    #BIT TMR0IF=INTCON.2 //CO TRAN TIMER0
    #BIT TMR2ON=T2CON.2 //KHOI DONG TIMER2
    #BIT TMR2IF=PIR1.1 //CO TRAN TIMER2
    VOID MAIN()
    {
    SET_TRIS_E(0);
    SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_2); //SU DUNG TAN SO DAO DONG NOI VA BO CHIA
    TAN 1:2
    SET_TIMER0(0); //DAT GIA TRI THANH GHI DINH THOI TMR0=0
    SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_4); //SU DUNG TAN SO DAO DONG NOI VA BO CHIA TAN
    1:4
    SET_TIMER1(0); //DAT GIA TRI THANH GHI DINH THOI TMR1=0
    SETUP_TIMER_2(T2_DIV_BY_16,255,1); //SU DUNG TAN SO DAO DONG NOI VA BO CHIA TAN 1:16
    SET_TIMER2(0); //DAT GIA TRI THANH GHI DINH THOI TMR2=0
    TMR0IF=TMR1IF=TMR2IF=0; //XOA CAC CO TRAN
    WHILE(TRUE)
    {
    IF(TMR0IF==1) //KIEM TRA CO TRAN TIMER0
    {
    OUTPUT_HIGH(PIN_E0);
    DELAY_MS(50);
    OUTPUT_LOW(PIN_E0);
    TMR0IF=0;
    }
    ELSE IF(TMR1IF==1) //KIEM TRA CO TRAN TIMER1
    {
    OUTPUT_HIGH(PIN_E1);
    DELAY_MS(50);
    OUTPUT_LOW(PIN_E1);
    TMR1IF=0;
    }
    ELSE IF(TMR2IF==1) //KIEM TRA CO TRAN TIMER2
    {
     
    OUTPUT_HIGH(PIN_E2);
    DELAY_MS(50);
    OUTPUT_LOW(PIN_E2);
    TMR2IF=0;
    }
    }
    }

    5. Delay dùng TIMER có dùng ngắt
    Mã:
    #INCLUDE<16F877A.H>
    #FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
    #USE DELAY(CLOCK=4000000)
    #BYTE PORTB=0x06
    #BYTE PORTC=0x07
    #BYTE PORTD=0x08
    #INT_TIMER0 //CHUONG TRINH NGAT TIMER0
    VOID NGAT_TIMER0()
    {
    PORTB=0b10101010;
    DELAY_MS(200);
    PORTB=0b01010101;
    }
    #INT_TIMER1 //CHUONG TRINH NGAT TIMER1
    VOID NGAT_TIMER1()
    {
    PORTC=0b11110000;
    DELAY_MS(200);
    PORTC=0b00001111;
    }
    #INT_TIMER2 //CHUONG TRINH NGAT TIMER2
    VOID NGAT_TIMER2()
    {
    PORTD=0b11001100;
    DELAY_MS(200);
    PORTD=0b00001111;
    }
    VOID MAIN()
    {
    SET_TRIS_B(0);
    SET_TRIS_C(0);
    SET_TRIS_D(0);
    ENABLE_INTERRUPTS(GLOBAL); //CHO PHEP TAT CA CAC NGAT HOAT DONG
    ENABLE_INTERRUPTS(INT_TIMER0); //CHO PHET NGAT BANG TIMER0
    ENABLE_INTERRUPTS(INT_TIMER1); //CHO PHET NGAT BANG TIMER1
    ENABLE_INTERRUPTS(INT_TIMER2); //CHO PHET NGAT BANG TIMER2
    SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_1);
    SET_TIMER0(0);
    SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_4);
    SET_TIMER1(0);
    SETUP_TIMER_2(T2_DIV_BY_16,255,1);
    SET_TIMER2(0);
    WHILE(TRUE); //KHONG LAM GI CA CHO NGAT
    }
    
    Ngoài ra còn một số ví dụ khác về sử dụng chế độ COUNTER (chế độ đếm), chế độ điều xung PWM, ví dụ sử dụng ngắt ngoài cũng như hướng dẫn mô phỏng PROTEUS các bạn có thể đọc thêm ở trong tài liệu đính kèm ở trên! Nếu còn thắc mắc, chưa hiểu chỗ nào mình sẽ cố gắng giải thích cụ thể! những ca khó sẽ được chuyển lên tuyến trên! Chúc các bạn làm quen với PIC một cách thuận lợi nhất!
    Thân!
     
    An Hoàng Văn, ThanhNghia, thelam929 others thích bài này.
  4. The Kid

    The Kid Kỹ sư

    Tham gia ngày:
    2/8/12
    Bài viết:
    408
    Đã được thích:
    341
    Điểm thành tích:
    63
    Giới tính:
    Nam
    các bạn ơi, mình viết chương trình cho máy đếm tần trên nền asm như sau (các bít cấu hình mình đã chọn trong MPLAP)
    Mã:
    PROCESSOR 16F877A
     
    INCLUDE <P16F877A.INC>
     
    DIGIT0 EQU 0X21
     
    DIGIT1 EQU 0X22
     
    DIGIT2 EQU 0X23
     
    DIGIT3 EQU 0X24
     
    DIGIT4 EQU 0X25
     
    DIGIT5 EQU 0X26
     
    BUFF0 EQU 0X27
     
    BUFF1 EQU 0X28
     
    BUFF2 EQU 0X29
     
    BUFF3 EQU 0X31
     
    BUFF4 EQU 0X32
     
    BUFF5 EQU 0X33
     
    CNTW EQU 0X34
     
    CNT1 EQU 0X35
     
    CNT2 EQU 0X36
     
    CNT EQU 0X37
     
    WORKA EQU 0X41
     
    ; BAT DAU CHUONG TRINH
     
    ORG 0X00
     
    GOTO START
     
    START
     
    BCF STATUS,RP1
     
    BSF STATUS,RP0
     
    MOVLW 0X00
     
    MOVWF TRISB
     
    CLRF PIE1
     
    MOVLW 0X00
     
    MOVWF TRISD
     
    MOVLW 0XFF
     
    MOVWF TRISC
     
    CLRF OPTION_REG
     
    BSF OPTION_REG,7
     
    BCF STATUS,RP0
     
    MOVLW 0XC0
     
    MOVWF DIGIT0
     
    MOVWF DIGIT1
     
    MOVWF DIGIT2
     
    MOVWF DIGIT3
     
    MOVWF DIGIT4
     
    MOVWF DIGIT5
     
    CLRF BUFF0
     
    CLRF BUFF1
     
    CLRF BUFF2
     
    CLRF BUFF3
     
    CLRF BUFF4
     
    CLRF BUFF5
     
    CLRF WORKA
     
    MOVLW 0X0E
     
    MOVWF T1CON ; THIET LAP THONG SO CHO BO DEM TMR1 : CHAN DEM TU RC0, HE SO CHIA =1, DEM KO DONG BO
     
    CLRF PIR1
     
    LOOP
     
    CLRF CNT
     
    CLRF TMR1H
     
    CLRF TMR1L
     
    BCF PIR1,TMR1IF
     
    BSF T1CON,TMR1ON
     
    CALL REFRESSH ; BAT DAU DEM
     
    CALL REFRESSH
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    BCF T1CON,TMR1ON ; TAT BO DEM DE XU LY KET QUA DEM
     
    MOVF CNTW,0
     
    MOVWF CNT
     
    MOVF TMR1H,0
     
    MOVWF CNT1
     
    MOVF TMR1L,0
     
    MOVWF CNT2
     
    BTFSC PIR1,TMR1IF
     
    INCF CNT
     
    MOVLW 0X05
     
    SUBWF CNT,0
     
    BTFSC STATUS,C
     
    GOTO OVER
     
    BTFSC CNT,2
     
    GOTO CV1
     
    GOTO CV2
     
    CV1
     
    MOVLW d'2'
     
    MOVWF BUFF0
     
    MOVLW d'6'
     
    MOVWF BUFF1
     
    MOVLW d'2'
     
    MOVWF BUFF2
     
    MOVLW d'1'
     
    MOVWF BUFF3
     
    MOVLW d'4'
     
    MOVWF BUFF4
     
    MOVLW d'4'
     
    MOVWF BUFF5
     
    CV2
     
    BTFSS CNT,1
     
    GOTO CV3
     
    MOVLW d'1'
     
    MOVWF BUFF0
     
    MOVLW d'3'
     
    MOVWF BUFF1
     
    MOVLW d'1'
     
    MOVWF BUFF2
     
    MOVLW d'0'
     
    MOVWF BUFF3
     
    MOVLW d'7'
     
    MOVWF BUFF4
     
    MOVLW d'2'
     
    MOVWF BUFF5 ; 13170
     
    CV3
     
    BTFSS CNT,0
     
    GOTO CV4
     
    MOVLW d'6'
     
    ADDWF BUFF1,1
     
    MOVLW d'5'
     
    ADDWF BUFF2,1
     
    MOVLW d'5'
     
    ADDWF BUFF3,1
     
    MOVLW d'3'
     
    ADDWF BUFF4,1
     
    MOVLW d'6'
     
    ADDWF BUFF5, 1 ;65535
     
    CV4
     
    BTFSS CNT1,7
     
    GOTO CV5
     
    MOVLW d'3'
     
    ADDWF BUFF1
     
    MOVLW d'2'
     
    ADDWF BUFF2
     
    MOVLW d'7'
     
    ADDWF BUFF3
     
    MOVLW d'6'
     
    ADDWF BUFF4
     
    MOVLW d'8'
     
    ADDWF BUFF5 ;32768
     
    CV5
     
    BTFSS CNT1,6
     
    GOTO CV6
     
    MOVLW d'1'
     
    ADDWF BUFF1
     
    MOVLW d'6'
     
    ADDWF BUFF2
     
    MOVLW d'3'
     
    ADDWF BUFF3
     
    MOVLW d'8'
     
    ADDWF BUFF4
     
    MOVLW d'4'
     
    ADDWF BUFF5 ;16384
     
    CV6
     
    BTFSS CNT1,5
     
    GOTO CV7
     
    MOVLW d'8'
     
    ADDWF BUFF2
     
    MOVLW d'1'
     
    ADDWF BUFF3
     
    MOVLW d'9'
     
    ADDWF BUFF4
     
    MOVLW d'2'
     
    ADDWF BUFF5 ;8912
     
    CV7
     
    BTFSS CNT1,4
     
    GOTO CV8
     
    MOVLW d'4'
     
    ADDWF BUFF2
     
    ; MOVLW d'0'
     
    ; ADDWF BUFF3
     
    MOVLW d'9'
     
    ADDWF BUFF4
     
    MOVLW d'6'
     
    ADDWF BUFF5 ;4096
     
    CV8
     
    BTFSS CNT1,3
     
    GOTO CV9
     
    MOVLW d'2'
     
    ADDWF BUFF2
     
    ; MOVLW d'0'
     
    ; ADDWF BUFF3
     
    MOVLW d'4'
     
    ADDWF BUFF4
     
    MOVLW d'8'
     
    ADDWF BUFF5
     
    CV9
     
    BTFSS CNT1,2
     
    GOTO CV10
     
    MOVLW d'1'
     
    ADDWF BUFF2
     
    ; MOVLW d'0'
     
    ; ADDWF BUFF3
     
    MOVLW d'2'
     
    ADDWF BUFF4
     
    MOVLW d'4'
     
    ADDWF BUFF5
     
    CV10
     
    BTFSS CNT1,1
     
    GOTO CV11
     
    MOVLW d'5'
     
    ADDWF BUFF3
     
    MOVLW d'1'
     
    ADDWF BUFF4
     
    MOVLW d'2'
     
    ADDWF BUFF5
     
    CV11
     
    BTFSS CNT1,0
     
    GOTO CV12
     
    MOVLW d'2'
     
    ADDWF BUFF3
     
    MOVLW d'5'
     
    ADDWF BUFF4
     
    MOVLW d'6'
     
    ADDWF BUFF5
     
    CV12
     
    BTFSS CNT2,7
     
    GOTO CV13
     
    MOVLW d'1'
     
    ADDWF BUFF3
     
    MOVLW d'2'
     
    ADDWF BUFF4
     
    MOVLW d'8'
     
    ADDWF BUFF5
     
    CV13
     
    BTFSS CNT2,6
     
    GOTO CV14
     
    MOVLW d'6'
     
    ADDWF BUFF4
     
    MOVLW d'4'
     
    ADDWF BUFF5
     
    CV14
     
    BTFSS CNT2,5
     
    GOTO CV15
     
    MOVLW d'3'
     
    ADDWF BUFF4
     
    MOVLW d'2'
     
    ADDWF BUFF5
     
    CV15
     
    BTFSS CNT2,4
     
    GOTO CV16
     
    MOVLW d'1'
     
    ADDWF BUFF4
     
    MOVLW d'6'
     
    ADDWF BUFF5
     
    CV16
     
    BTFSS CNT2,3
     
    GOTO CV17
     
    MOVLW d'8'
     
    ADDWF BUFF5
     
    CV17
     
    BTFSS CNT2,2
     
    GOTO CV18
     
    MOVLW d'4'
     
    ADDWF BUFF5
     
    CV18
     
    BTFSS CNT2,1
     
    GOTO CV19
     
    MOVLW d'2'
     
    ADDWF BUFF5
     
    CV19
     
    BTFSS CNT2,0
     
    GOTO CVR
     
    MOVLW d'1'
     
    ADDWF BUFF5,1
     
    CVR
     
    MOVLW 0X0A
     
    SUBWF BUFF5,0
     
    BTFSS STATUS,C
     
    GOTO CR1
     
    MOVLW 0X0A
     
    SUBWF BUFF5,1
     
    INCF BUFF4
     
    GOTO CVR
     
    CR1
     
    MOVLW 0X0A
     
    SUBWF BUFF4,0
     
    BTFSS STATUS,C
     
    GOTO CR2
     
    MOVLW 0X0A
     
    SUBWF BUFF4,1
     
    INCF BUFF3
     
    GOTO CR1
     
    CR2
     
    MOVLW 0X0A
     
    SUBWF BUFF3,0
     
    BTFSS STATUS,C
     
    GOTO CR3
     
    MOVLW 0X0A
     
    SUBWF BUFF3,1
     
    INCF BUFF2,1
     
    GOTO CR2
     
    CR3
     
    MOVLW 0X0A
     
    SUBWF BUFF2,0
     
    BTFSS STATUS,C
     
    GOTO CR4
     
    MOVLW 0X0A
     
    SUBWF BUFF2,1
     
    INCF BUFF1
     
    GOTO CR3
     
    CR4
     
    MOVLW 0X0A
     
    SUBWF BUFF1,0
     
    BTFSS STATUS,C
     
    GOTO DOCKQ
     
    MOVLW 0X0A
     
    SUBWF BUFF1,1
     
    INCF BUFF0
     
    GOTO CR4
     
    DOCKQ
     
    MOVLW 0X01
     
    MOVWF PCLATH
     
    MOVF BUFF0,0
     
    CALL TABLE
     
    MOVWF DIGIT0
     
    MOVF BUFF1,0
     
    CALL TABLE
     
    MOVWF DIGIT1
     
    MOVF BUFF2,0
     
    CALL TABLE
     
    MOVWF DIGIT2
     
    MOVF BUFF3,0
     
    CALL TABLE
     
    MOVWF DIGIT3
     
    MOVF BUFF4,0
     
    CALL TABLE
     
    MOVWF DIGIT4
     
    MOVF BUFF5,0
     
    CALL TABLE
     
    MOVWF DIGIT5
     
    CLRF BUFF0
     
    CLRF BUFF1
     
    CLRF BUFF2
     
    CLRF BUFF3
     
    CLRF BUFF4
     
    CLRF BUFF5
     
    GOTO LOOP
     
    TABLE
     
    ADDWF PCL,1
     
    RETLW 0XC0
     
    RETLW 0XF9
     
    RETLW 0XA4
     
    RETLW 0XB0
     
    RETLW 0X99
     
    RETLW 0X92
     
    RETLW 0X82
     
    RETLW 0XF8
     
    RETLW 0X80
     
    RETLW 0X90
     
    REFRESSH
     
    BSF PORTB,0
     
    BCF PORTB,5
     
    MOVF DIGIT0,0
     
    MOVWF PORTD
     
    NOP
     
    CALL TMRCHK
     
    BSF PORTB,5
     
    BCF PORTB,4
     
    MOVF DIGIT1,0
     
    MOVWF PORTD
     
    BCF PORTD,7
     
    CALL TMRCHK
     
    BSF PORTB,4
     
    BCF PORTB,3
     
    MOVF DIGIT2,0
     
    MOVWF PORTD
     
    NOP
     
    CALL TMRCHK
     
    BSF PORTB,3
     
    BCF PORTB,2
     
    MOVF DIGIT3,0
     
    MOVWF PORTD
     
    NOP
     
    CALL TMRCHK
     
    BSF PORTB,2
     
    BCF PORTB,1
     
    MOVF DIGIT4,0
     
    MOVWF PORTD
     
    BCF PORTD,7
     
    CALL TMRCHK
     
    BSF PORTB,1
     
    BCF PORTB,0
     
    MOVF DIGIT5,0
     
    MOVWF PORTD
     
    NOP
     
    CALL TMRCHK
     
    RETURN
     
    TMRCHK
     
    MOVLW 0X29
     
    MOVWF WORKA
     
    nop
     
    nop
     
    KT BTFSS PIR1,TMR1IF
     
    GOTO XX1 ;3
     
    INCF CNTW
     
    BCF PIR1,TMR1IF
     
    GOTO XX2
     
    XX1
     
    NOP
     
    NOP ;5
     
    XX2
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    NOP
     
    DECFSZ WORKA
     
    GOTO KT
     
    RETURN
     
    OVER
     
    MOVLW 0XC0
     
    MOVWF DIGIT0
     
    MOVLW 0XB1
     
    MOVWF DIGIT2
     
    MOVLW 0X86
     
    MOVWF DIGIT3
     
    MOVLW 0XCE
     
    MOVWF DIGIT4
     
    MOVLW 0XFF
     
    MOVWF DIGIT1
     
    MOVWF DIGIT5
     
    goto LOOP
     
    END
     
    ;
    khi chạy trên proteus thì chạy ở tần số vào chỉ được đến 20Khz, trên nữa là mô phỏng chậm như rùa bò ấy. nó báo là " simulation is not running in real time due to excessive cpu"

    Đây là hình mình chụp khi tần số vào la 7.1 Khz



    mình lập trình để đếm tối đa đến 32 Mhz mà không thể mô phỏng được. Mong các bạn có thể giúp mình một tìm cách khắc phục điểm này nha
     
    Pakkun, LêQuốcQuânJune thích bài này.
  5. The Kid

    The Kid Kỹ sư

    Tham gia ngày:
    2/8/12
    Bài viết:
    408
    Đã được thích:
    341
    Điểm thành tích:
    63
    Giới tính:
    Nam
    Híc, làm sao để post được hình ảnh hả các bạn
     
  6. sgesvn

    sgesvn Moderator Staff Member

    Tham gia ngày:
    24/7/12
    Bài viết:
    2,236
    Đã được thích:
    3,076
    Điểm thành tích:
    113
    Giới tính:
    Nam
    • Tất các các code bạn phải đưa vào thẻ code chứ để như thế chẳng ai muốn đọc nữa
    • " simulation is not running in real time due to excessive cpu" là do khả năng tính toán thời gian trên PC của bạn nên Proteus không thể chạy với thời gian thực vì CPU sẽ quá tải. Khi chạy thật trên vi điều khiển mạch của bạn vẫn hoạt động bình thường
    • Bạn đưa code mà không đưa file mô phỏng đính kèm thì đúng là khó giúp
    Bạn nên đọc rõ các hướng dẫn sử dụng của diễn đàn:
    hướng dẫn - Đưa Ảnh Và Video Lên Diễn Đàn. Cộng đồng Cơ điện tử Việt Nam
    --------------
    Chúc vui!
     
    LêQuốcQuân, June, BuiBachTuanAnh2 others thích bài này.
  7. The Kid

    The Kid Kỹ sư

    Tham gia ngày:
    2/8/12
    Bài viết:
    408
    Đã được thích:
    341
    Điểm thành tích:
    63
    Giới tính:
    Nam
    may dem tan.

    hình trên là mình mô phỏng 7.1 Khz, còn đây là 15k, chữ số mất dần. trên nữa thì than ôi
    15k.
     
    LêQuốcQuânBolide thích bài này.
  8. BuiBachTuanAnh

    BuiBachTuanAnh Quản trị viên Staff Member

    Tham gia ngày:
    6/5/12
    Bài viết:
    1,304
    Đã được thích:
    3,783
    Điểm thành tích:
    113
    Giới tính:
    Nam
    Nghề nghiệp:
    Kinh doanh
    Nơi ở:
    http://codientu.org
    Ở đây vấn đề của bạn nói đến là thuật toán. Nếu ở tần số thấp đã chạy ok chứng tỏ thuật toán không sai. Khi bạn đưa lên tần số cao thì cái này do đáp ứng thời gian thực của PC và phần mềm mô phỏng không khớp nhau nên sẽ bị lỗi " simulation is not running in real time due to excessive cpu". Khi chạy trên mạch thật sẽ không vấn đề gì cả.
    --------------------------
    Nếu bạn đính kèm file mô phỏng thì mình có thể thử giúp bạn trên máy của mình xem sao?
    Bạn nên đọc thêm: hướng dẫn - Yêu Câu Sự Trợ Giúp Từ Thành Viên Diễn Đàn Cộng đồng Cơ điện tử Việt Nam
     
    LêQuốcQuân, ptuan12, loveboom30122 others thích bài này.
  9. nhu.ta532

    nhu.ta532 Kỹ sư

    Tham gia ngày:
    25/9/12
    Bài viết:
    213
    Đã được thích:
    106
    Điểm thành tích:
    43
    Giới tính:
    Nam
    Mã:
    #INCLUDE<16F877A.H>
     
    #FUSES XT,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
     
    #USE DELAY(CLOCK=4000000)
     
    #BYTE INTCON=0x0B // ????
     
    #BYTE PIR1=0x0C //???
     
    #BYTE T1CON=0x10 ////?????
     
    #BIT TMR1ON=T1CON.0 //KHOI DONG TIMER1
     
    #BIT TMR1IF=PIR1.0 //CO TRAN TIMER1
     
    #BIT INTF=INTCON.1 //CO NGAT
     
    VOID DELAY(INT8 TIMER)
     
    {
     
    WHILE(TIMER--)
     
    {
     
    TMR1ON=1;
     
    WHILE(TMR1IF==0);
     
    TMR1ON=0;
     
    TMR1IF=0;
     
    }
     
    }
     
    VOID MAIN()
     
    {
     
    WHILE(TRUE)
     
    {
     
    OUTPUT_HIGH(PIN_C4);
     
    DELAY(100);
     
    OUTPUT_LOW(PIN_C4);
     
    DELAY(100);
     
    }
     
    }
     
    //TUONG TU VOI CAC TIMER0 VA TIMER2 CAC BAN CO THE XEM DATASHEET DE BIET THEM VE DIA
     
    CHI
     
    // CAC THANH GHI CHUC NANG CUA CHUNG

    anh giải thích ý nghĩa mây lệnh trên giúp em vói ( chỗ dấu ? ý)
     
    LêQuốcQuân thích bài này.
  10. demon52

    demon52 Kỹ sư

    Tham gia ngày:
    17/8/12
    Bài viết:
    873
    Đã được thích:
    1,209
    Điểm thành tích:
    93
    Giới tính:
    Nam
    Nghề nghiệp:
    Director
    Nơi ở:
    Home
    Đó chỉ là các define do user đặt ra để tiện trong quá trình code thôi bạn ạ!
    VD: bạn define
    #define on 1
    thì sau này bạn viết code ở dưới chỉ cần viết:
    led1=on;
    thế là LED sẽ sáng( ko cần phải viết là LED1=1), cách viết này giúp ta quản lý code tốt hơn rất nhiều, vì sau này muốn edit code hay debug chỉ cần edit những define đầu tiên, và nếu đúng hơn bạn có thể lưu hết các define bên file main.h ( mặc định tạo ra khi sử dụng CCS-C vì code này nhìn là biết dùng CCS).
    Như vậy tương tự ở trên là khai báo các Byte tương ứng với các thanh ghi của Timer1 để sử dụng timer ko cần phải viết lại các giá trị thanh ghi, ở dưới là define các bit tương ứng với các trạng thái của Timer1.
    Regard.
     

Chia sẻ trang này