Thông báo

Collapse
No announcement yet.

PIC_16f887 từ dễ đến khó_ Dành cho người mơi bắt đầu

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

  • PIC_16f887 từ dễ đến khó_ Dành cho người mơi bắt đầu

    Em xin phép lập luồng này để dành cho các thành viên mới sử dụng PIC như em ^^, cùng vơi luồng này, các bạn có thể xem thêm luồng " các câu hỏi thông dụng về lập trình CCS" nữa nhé
    - các bài mình hoặc các bạn khác post lên đây chú ý nên giải thích từng dòng lệnh và nên chỉ rõ tài liệu tham khảo để có thể hiểu rõ được vấn đề này. chúc các bạn học tốt
    Be quan. Plz contact through email:

  • #2
    bài đầu tiên: sử dụng Timer0 đếm xung ngoại ( từ chân RA4 ) nhé

    #include "C:\Users\Cocacola\Desktop\Lap trinh CCS\timer0-demxung\DEMXUNG_TMR0.h"

    // CAC BYTE THANH GHI TU DINH NGHIA
    #byte PORTA =0x05
    #byte PORTB =0x06
    #byte PORTC =0x07
    #byte PORTD =0x08
    #byte PORTE =0x09
    #byte ANSEL =0X188
    #byte ANSELH =0X189
    #byte TRISA =0x85
    #byte TRISB =0x86
    #byte TRISC =0x87
    #byte TRISD =0x88
    #byte TRISE =0X89


    // DINH NGHIA CAC THANH GHI SU DUNG LIEN QUAN DEN TIMER0
    #byte OPTION_REG = 0X81
    #byte TMR0 = 0X01 // thanh ghi luu gia tri cua counter0
    #bit RBPU = OPTION_REG.7 // bit lua chon co su dung dien tro keo len hay khong
    #bit INTEDG= OPTION_REG.6 // bit lua chon
    #bit T0SC = OPTION_REG.5 // bit lua chon nguon cung cung cap cho che do counter ( nguon xung o chan RA4 hay Fosc/4)
    #bit T0SE = OPTION_REG.4 // bit
    #bit PSA = OPTION_REG.3 // bit gan bo chia cho timer hay watgodtimer
    #bit PS2 = OPTION_REG.2 // 3 bit cuoi cung gan so chia cua bo chia, vi o day ta dem xung nen ta gan bo chia cho wgt, ta khong can quan tam den 3 bit nay
    #bit PS1 = OPTION_REG.1
    #bit PS0 = OPTION_REG.0

    // khai bao bien su dung trong chuong trinh
    int8 chuc,donvi,value;

    // chuong trinh con giaima 7 doan
    int giaima(int8 a)
    { int8 b;
    switch(a){

    case 0 : b = 0xc0;
    break;
    case 1 : b = 0xF9;
    break;
    case 2 : b = 0xA4;
    break;
    case 3 : b = 0xB0;
    break;
    case 4 : b = 0x99;
    break;
    case 5 : b = 0x92;
    break;
    case 6 : b = 0x82;
    break;
    case 7 : b = 0xF8;
    break;
    case 8 : b = 0x80;
    break;
    default : b = 0x90;
    break;
    }
    return b;
    }

    void main()
    {
    setup_adc_ports(NO_ANALOGS|VSS_VDD); // KHONG SU DUNG TIN HIEU ANALOG
    setup_adc(ADC_OFF); // NGAT BO CHUYEN DOI ADC
    setup_spi(FALSE); // KHONG GIAO TIEP SPI
    setup_timer_1(T1_DISABLED); // KHONG SU DUNG TIMER1
    setup_timer_2(T2_DISABLED,0,1); // KHONG SU DUNG TIMER2
    setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard // KHONG SU DUNG BO SO SANH
    setup_oscillator(osc_8mhz);



    // TODO: USER CODE!!
    TRISA = 0XFF; // PORT A LA NGO VAO
    TRISB = TRISC = TRISD = 0X00;
    ANSEL = ANSELH = 0X00;


    // chuong trinh dem xung ngoai su dung counter
    RBPU = 0;
    INTEDG = 0;
    PSA = 1; // GAN BO CHIA CHO WDT ( NHU VAY TA CO THE KHONG CAN LUU TAM DEN 3 BIT THIET LAP CHO BO CHIA LA PS2, PS1, PS0
    T0SC = 1;
    PS2 = 0;
    PS1 = 1;
    PS0 = 1;
    T0SE = 1; // THIET LAP TIMER 0 O CHE DO COUNTER

    chuc = donvi = value = 0;
    TMR0 = 0;

    while(1){
    value = TMR0;
    if(value ==99)
    TMR0 = 0;
    else {
    chuc = value/10;
    donvi = value - 10*chuc;
    portd = giaima(chuc);
    portc = giaima(donvi);
    }
    }
    }

    để hiểu được bài này có những chú ý sau:

    - tôi định nghĩa lại các port và thanh ghi thông dụng ( ví dụ như #BYTE PORTA = 0X50 - SAU ĐÓ TÔI SỬ DỤNG LỆNH PORTA = ....TÔI LÀM NHƯ VẬY ĐỂ GẦN VỚI PHẦN CỨNG HƠN). LÝ DO TÔI LÀM NHƯ VẬY: CCS khai báo I/o lung tung quá, làm như thế này dễ quản lý hơn từng chân, từng port
    - các bạn nên đọc về timer0 cũng như các thanh ghi liên quan đến hoạt động của timer0 nhé, dễ mà)
    Be quan. Plz contact through email:

    Comment


    • #3
      Chưa có thời gian để tìm hiểu về PIC nhưng mình cũng thích dòng vi điều khiển này vì nó rất đa dạng. Luồn này mình nghĩ chắc chắn sẽ rất hay đây. Cảm ơn nhiều!

      Comment


      • #4
        Nguyên văn bởi Lenh Ho Xem bài viết
        bài đầu tiên: sử dụng Timer0 đếm xung ngoại ( từ chân RA4 ) nhé

        #include "C:\Users\Cocacola\Desktop\Lap trinh CCS\timer0-demxung\DEMXUNG_TMR0.h"

        // CAC BYTE THANH GHI TU DINH NGHIA
        #byte PORTA =0x05
        #byte PORTB =0x06
        #byte PORTC =0x07
        #byte PORTD =0x08
        #byte PORTE =0x09
        #byte ANSEL =0X188
        #byte ANSELH =0X189
        #byte TRISA =0x85
        #byte TRISB =0x86
        #byte TRISC =0x87
        #byte TRISD =0x88
        #byte TRISE =0X89


        // DINH NGHIA CAC THANH GHI SU DUNG LIEN QUAN DEN TIMER0
        #byte OPTION_REG = 0X81
        #byte TMR0 = 0X01 // thanh ghi luu gia tri cua counter0
        #bit RBPU = OPTION_REG.7 // bit lua chon co su dung dien tro keo len hay khong
        #bit INTEDG= OPTION_REG.6 // bit lua chon
        #bit T0SC = OPTION_REG.5 // bit lua chon nguon cung cung cap cho che do counter ( nguon xung o chan RA4 hay Fosc/4)
        #bit T0SE = OPTION_REG.4 // bit
        #bit PSA = OPTION_REG.3 // bit gan bo chia cho timer hay watgodtimer
        #bit PS2 = OPTION_REG.2 // 3 bit cuoi cung gan so chia cua bo chia, vi o day ta dem xung nen ta gan bo chia cho wgt, ta khong can quan tam den 3 bit nay
        #bit PS1 = OPTION_REG.1
        #bit PS0 = OPTION_REG.0

        // khai bao bien su dung trong chuong trinh
        int8 chuc,donvi,value;

        // chuong trinh con giaima 7 doan
        int giaima(int8 a)
        { int8 b;
        switch(a){

        case 0 : b = 0xc0;
        break;
        case 1 : b = 0xF9;
        break;
        case 2 : b = 0xA4;
        break;
        case 3 : b = 0xB0;
        break;
        case 4 : b = 0x99;
        break;
        case 5 : b = 0x92;
        break;
        case 6 : b = 0x82;
        break;
        case 7 : b = 0xF8;
        break;
        case 8 : b = 0x80;
        break;
        default : b = 0x90;
        break;
        }
        return b;
        }

        void main()
        {
        setup_adc_ports(NO_ANALOGS|VSS_VDD); // KHONG SU DUNG TIN HIEU ANALOG
        setup_adc(ADC_OFF); // NGAT BO CHUYEN DOI ADC
        setup_spi(FALSE); // KHONG GIAO TIEP SPI
        setup_timer_1(T1_DISABLED); // KHONG SU DUNG TIMER1
        setup_timer_2(T2_DISABLED,0,1); // KHONG SU DUNG TIMER2
        setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard // KHONG SU DUNG BO SO SANH
        setup_oscillator(osc_8mhz);



        // TODO: USER CODE!!
        TRISA = 0XFF; // PORT A LA NGO VAO
        TRISB = TRISC = TRISD = 0X00;
        ANSEL = ANSELH = 0X00;


        // chuong trinh dem xung ngoai su dung counter
        RBPU = 0;
        INTEDG = 0;
        PSA = 1; // GAN BO CHIA CHO WDT ( NHU VAY TA CO THE KHONG CAN LUU TAM DEN 3 BIT THIET LAP CHO BO CHIA LA PS2, PS1, PS0
        T0SC = 1;
        PS2 = 0;
        PS1 = 1;
        PS0 = 1;
        T0SE = 1; // THIET LAP TIMER 0 O CHE DO COUNTER

        chuc = donvi = value = 0;
        TMR0 = 0;

        while(1){
        value = TMR0;
        if(value ==99)
        TMR0 = 0;
        else {
        chuc = value/10;
        donvi = value - 10*chuc;
        portd = giaima(chuc);
        portc = giaima(donvi);
        }
        }
        }

        để hiểu được bài này có những chú ý sau:

        - tôi định nghĩa lại các port và thanh ghi thông dụng ( ví dụ như #BYTE PORTA = 0X50 - SAU ĐÓ TÔI SỬ DỤNG LỆNH PORTA = ....TÔI LÀM NHƯ VẬY ĐỂ GẦN VỚI PHẦN CỨNG HƠN). LÝ DO TÔI LÀM NHƯ VẬY: CCS khai báo I/o lung tung quá, làm như thế này dễ quản lý hơn từng chân, từng port
        - các bạn nên đọc về timer0 cũng như các thanh ghi liên quan đến hoạt động của timer0 nhé, dễ mà)
        Hi,
        Đối với PIC thì mỗi loại nó lại có địa chỉ thanh ghi khác nhau ví dụ Port A của con này là 0x05 nhưng Port A của con khác thì lại khác. Vì thế khai báo #byte PORTA = 0x05 sẽ bất tiện khi phải giỡ datasheet ra tra lại địa chỉ thanh ghi. Tuy nhiên CCS hỗ trợ một cách làm dễ hơn giúp người dùng không cần quan tâm đến thanh ghi đó ở địa chỉ bao nhiêu bằng cách khai báo: #byte Port_A = getenv("SFR:PORTA"). Tương tự đối với #bit, #word... cũng thế. Các bác xem thêm về getenv trong phần Help của CCS. Lưu ý khi dùng khai báo #byte... thì các bác phải set chiều cho cổng trên PIC, nếu không dùng các khai báo này thì các hàm input/output đã tự động set chiều in/out rồi. CCS định nghĩa một file .h rất tiện dụng cho người dùng với nhiều hàm, hằng để config PIC và lập trình vì vậy các bác nên làm quen với cách viết code này. Viết theo cách của CCS thì người đọc dễ hiểu code hơn và nhìn vào chương trình nó không phức tạp. Không nên lệ thuộc vào thói quen làm với 8051 là phải chỉ rõ tên từng thanh ghi mới làm việc được.
        Xin comment thêm một chút về phần giải mã led7 ở trên, viết kiểu đó thì chương trình chạy tốt nhưng chạy chậm và chiếm nhiều bộ nhớ chương trình. Nên viết cách giải mã led7 bằng cách tra bảng. Các bác chỉ cần khai báo một mảng chứa các mã led7 của các số, ví dụ tên mảng là led7[]. Khi cần giải mã led7 của số 0 các bác chỉ cần led7[0], số 1 --> led7[1] vv... ví dụ muốn đưa mã led7 của số 5 ra port A, chỉ cần output_a(led7[5]); là xong không cần phải chạy qua 1 chương trình con để lấy mã led7 của số 5 rồi mới đưa ra cổng.
        Chúc các bác sớm thành thạo CCS.
        Thân ái.
        Đường đến những ngày vinh quang không còn xa
        Con đường chúng ta... chúng ta đã chọn.

        Comment


        • #5
          cảm ơn bác rất nhiều, em post những bài này lên để hướng tới các bạn mới học, em sẽ thực hiện hướng dẫn của bác và post lên biến thể của bài trên ( tuy nhiên em vẫn cho là cách định nghĩa Byte vẫn có ý nghĩa, nó giúp mình hiểu cấu trúc phần cứng hơn và quản lý chặt chẽ hơn).

          -
          Be quan. Plz contact through email:

          Comment


          • #6
            Hình như mới tiếp cận với PIC hay rắc rối ở chỗ mấy thanh ghi. Thế trong CCS ko hỗ trợ sẵng việc định nghĩ các thanh ghi thành các từ gợi nhớ sao, include<> gì đó ????

            Comment


            • #7
              Cũng có bạn ạ khi biên dịch bạn xổ file.h ra để xem các định nghĩa trong đó, tuy nhiên theo mình nó là khó quản lý vì rất dễ lẫn lộn . mỗi lệnh trong C thực ra là một macro , bạn sử dụng lệnh đó tương ứng với sử dụng một đoạn lệnh asm khác. tùy theo mỗi cách viết và quen thuộc của từng người nhưng theo mình thì khi thiết lập nên bỏ thời gian ra viết một header riêng để quen. việc này rất ý nghĩa, bạn có thể sử dụng một cách chắc chắn các thanh ghi. theo mình thì viết chưong trình nửa asm và nửa c là tốt nhất

              Mình làm thế này:

              mình viết một đoạn code bằng notepad như sau:

              #byte INDF =0x00
              #byte TMR0 =0x01
              #byte PCL =0x02
              #byte STATUS =0x03
              #byte FSR =0x04
              #byte PORTA =0x05
              #byte PORTB =0x06
              #byte PORTC =0x07
              #byte PORTD =0x08
              #byte PORTE =0x09

              #byte EEDATA =0x10C
              #byte EEADR =0x10D
              #byte EEDATH =0x10E
              #byte EEADRH =0x10F
              #byte ADCON0 =0x1F
              #byte ADCON1 =0x9F
              #byte ADRESH =0x9F
              #byte ADSESL =0x9F

              #byte PCLATH =0x0a
              #byte INTCON =0x0b
              #byte PIR1 =0x0c
              #byte PIR2 =0x0d
              #byte PIE1 =0x8c
              #byte PIE2 =0x8d

              #byte OPTION_REG =0x81
              #byte TRISA =0x85
              #byte TRISB =0x86
              #byte TRISC =0x87
              #byte TRISD =0x88
              #byte TRISE =0x89

              #byte EECON1 =0x18C
              #byte EECON2 =0x18D

              //DINH NGHIA BIT
              #bit ra5 =0x05.5
              #bit ra4 =0x05.4
              #bit ra3 =0x05.3
              #bit ra2 =0x05.2
              #bit ra1 =0x05.1
              #bit ra0 =0x05.0

              #bit rb7 =0x06.7
              #bit rb6 =0x06.6
              #bit rb5 =0x06.5
              #bit rb4 =0x06.4
              #bit rb3 =0x06.3
              #bit rb2 =0x06.2
              #bit rb1 =0x06.1
              #bit rb0 =0x06.0

              #bit rC7 =0x07.7
              #bit rC6 =0x07.6
              #bit rC5 =0x07.5
              #bit rC4 =0x07.4
              #bit rC3 =0x07.3
              #bit rC2 =0x07.2
              #bit rC1 =0x07.1
              #bit rC0 =0x07.0

              #bit rD7 =0x08.7
              #bit rD6 =0x08.6
              #bit rD5 =0x08.5
              #bit rD4 =0x08.4
              #bit rD3 =0x08.3
              #bit rD2 =0x08.2
              #bit rD1 =0x08.1
              #bit rD0 =0x08.0

              #bit rE2 =0x09.2
              #bit rE1 =0x09.1
              #bit rE0 =0x09.0


              #bit trisa5 =0x85.5
              #bit trisa4 =0x85.4
              #bit trisa3 =0x85.3
              #bit trisa2 =0x85.2
              #bit trisa1 =0x85.1
              #bit trisa0 =0x85.0

              #bit trisb7 =0x86.7
              #bit trisb6 =0x86.6
              #bit trisb5 =0x86.5
              #bit trisb4 =0x86.4
              #bit trisb3 =0x86.3
              #bit trisb2 =0x86.2
              #bit trisb1 =0x86.1
              #bit trisb0 =0x86.0

              #bit trisc7 =0x87.7
              #bit trisc6 =0x87.6
              #bit trisc5 =0x87.5
              #bit trisc4 =0x87.4
              #bit trisc3 =0x87.3
              #bit trisc2 =0x87.2
              #bit trisc1 =0x87.1
              #bit trisc0 =0x87.0

              #bit trisd7 =0x88.7
              #bit trisd6 =0x88.6
              #bit trisd5 =0x88.5
              #bit trisd4 =0x88.4
              #bit trisd3 =0x88.3
              #bit trisd2 =0x88.2
              #bit trisd1 =0x88.1
              #bit trisd0 =0x88.0

              #bit trise2 =0x89.2
              #bit trise1 =0x89.1
              #bit trise0 =0x89.0

              // INTCON Bits for C
              #bit gie = 0x0b.7
              #bit peie = 0x0b.6
              #bit tmr0ie = 0x0b.5
              #bit int0ie = 0x0b.4
              #bit rbie = 0x0b.3
              #bit tmr0if = 0x0b.2
              #bit int0if = 0x0b.1
              #bit rbif = 0x0b.0

              // PIR1 for C
              #bit pspif = 0x0c.7
              #bit adif = 0x0c.6
              #bit rcif = 0x0c.5
              #bit txif = 0x0c.4
              #bit sspif = 0x0c.3
              #bit ccp1if = 0x0c.2
              #bit tmr2if = 0x0c.1
              #bit tmr1if = 0x0c.0

              //PIR2 for C
              #bit cmif = 0x0d.6
              #bit eeif = 0x0d.4
              #bit bclif = 0x0d.3
              #bit ccp2if = 0x0d.0

              // PIE1 for C
              #bit adie = 0x8c.6
              #bit rcie = 0x8c.5
              #bit txie = 0x8c.4
              #bit sspie = 0x8c.3
              #bit ccp1ie = 0x8c.2
              #bit tmr2ie = 0x8c.1
              #bit tmr1ie = 0x8c.0

              //PIE2 for C
              #bit osfie = 0x8d.7
              #bit cmie = 0x8d.6
              #bit eeie = 0x8d.4

              // OPTION Bits
              #bit not_rbpu = 0x81.7
              #bit intedg = 0x81.6
              #bit t0cs = 0x81.5
              #bit t0se = 0x81.4
              #bit psa = 0x81.3
              #bit ps2 = 0x81.2
              #bit ps1 = 0x81.1
              #bit ps0 = 0x81.0

              // EECON1 Bits
              #bit eepgd = 0x18c.7
              #bit free = 0x18C.4
              #bit wrerr = 0x18C.3
              #bit wren = 0x18C.2
              #bit wr = 0x18C.1
              #bit rd = 0x18C.0

              //ADCON0
              #bit CHS0 =0x1F.3
              #bit CHS1 =0x1F.4
              #bit CHS2 =0x1F.5


              sau đó mình lưu lại dưới tên THANHGHI_BIT.h, sau đó bạn chép vào mục device trong ổ C của PIC C, khi sử dụng bạn chỉ cần khai báo #include "THANHGHI.h" và có thể sử dụng sự định nghĩa của mình rồi, lúc này thay vì : output_a(0xff) ( xuất các chân porta ra mức cao ) thì bạn chỉ cần PORTA = 0xff;

              có phải dễ dàng hơn nhiều không nào .

              Mong mọi người bổ sưng và cho ý kiến nhé.
              Be quan. Plz contact through email:

              Comment


              • #8
                Hi,
                Bác lại tìm đường khó mà đi rồi, mục đích của các từ khóa #byte, #bit là để cho người dùng gán một biến vào một cổng (port) hay một chân (pin) nào đó của VDK, Ví dụ để kết nối LCD với port_b của VDK ta khai báo:
                Code:
                struct LCD_Interface
                {
                	int Unused:1;	// used for external interrupt
                	int RS:1;
                	int RW:1;
                	int E:1;
                	int Data:4;
                };
                struct LCD_Interface LCD;
                #byte LCD = getenv("SFR:PORTB")
                Lúc này cổng B được kết nối với LCD, để truy cập LCD ta chỉ cần:
                LCD.RS = 1; // Pin B1 được set
                vv...
                Đó là mục đích chính của các từ khóa #byte, #bit...
                Còn việc truy cập các thanh ghi thì các hàm dựng sẵn đã tự động thao tác rồi. Nếu bác muốn định nghĩa thêm thì nên định nghĩa các hằng (constant) thay vì bỏ thời gian ra định nghĩa lại thanh ghi và bit.
                Ví dụ:
                #define BIT0 0x01
                #define BIT1 0x02
                ...
                #define BIT8 0x80
                Đây là các hằng dùng để làm mặt nạ (mask) khi cần kiểm tra bit nào đó hoặc set/clear bit nào đó.
                Thân ái.
                Đường đến những ngày vinh quang không còn xa
                Con đường chúng ta... chúng ta đã chọn.

                Comment


                • #9
                  Nguyên văn bởi nquoccdt Xem bài viết
                  Hình như mới tiếp cận với PIC hay rắc rối ở chỗ mấy thanh ghi. Thế trong CCS ko hỗ trợ sẵng việc định nghĩ các thanh ghi thành các từ gợi nhớ sao, include<> gì đó ????
                  Trong CCS ở phần View / Special Register nó sẽ liệt kê địa chỉ các thanh ghi với mỗi dòng PIC. Có thể copy các dòng địa chỉ cần thiết trực tiếp vào Main Source hoặc có thể make 1 file Registers và include vào Main Source.
                  Ví dụ như hình dưới.
                  Attached Files

                  Comment


                  • #10
                    Nguyên văn bởi duong_act Xem bài viết
                    Trong CCS ở phần View / Special Register nó sẽ liệt kê địa chỉ các thanh ghi với mỗi dòng PIC. Có thể copy các dòng địa chỉ cần thiết trực tiếp vào Main Source hoặc có thể make 1 file Registers và include vào Main Source.
                    Ví dụ như hình dưới.
                    Em đã làm theo hứong dẫn của anh, nhưng trong file.h em thực hiện thì bất cứ thanh ghi nào cũng có MCU_ ở đầu tiên, làm thế nào mà nó không có tiền tố này trong việc định nghĩa thanh ghi hả anh,
                    thêm chút nữa anh nhé
                    nếu em add nó vào chương trình, ví có nhiều thanh ghi mình định nghĩa mà không sử dụng tới, liệu có tốn thêm bộ nhớ không anh ( theo em hiểu thì không vì mình đang định nghĩa các thanh ghi đặc biệt có sẵn trên ROM mà) . em hiểu có đúng không ạ. mong anh chỉ thêm. cảm ơn anh nhiều.
                    Be quan. Plz contact through email:

                    Comment


                    • #11
                      Nguyên văn bởi Hard Xem bài viết
                      Hi,
                      Bác lại tìm đường khó mà đi rồi, mục đích của các từ khóa #byte, #bit là để cho người dùng gán một biến vào một cổng (port) hay một chân (pin) nào đó của VDK, Ví dụ để kết nối LCD với port_b của VDK ta khai báo:
                      Code:
                      struct LCD_Interface
                      {
                      	int Unused:1;	// used for external interrupt
                      	int RS:1;
                      	int RW:1;
                      	int E:1;
                      	int Data:4;
                      };
                      struct LCD_Interface LCD;
                      #byte LCD = getenv("SFR:PORTB")
                      Lúc này cổng B được kết nối với LCD, để truy cập LCD ta chỉ cần:
                      LCD.RS = 1; // Pin B1 được set
                      vv...
                      Đó là mục đích chính của các từ khóa #byte, #bit...
                      Còn việc truy cập các thanh ghi thì các hàm dựng sẵn đã tự động thao tác rồi. Nếu bác muốn định nghĩa thêm thì nên định nghĩa các hằng (constant) thay vì bỏ thời gian ra định nghĩa lại thanh ghi và bit.
                      Ví dụ:
                      #define BIT0 0x01
                      #define BIT1 0x02
                      ...
                      #define BIT8 0x80
                      Đây là các hằng dùng để làm mặt nạ (mask) khi cần kiểm tra bit nào đó hoặc set/clear bit nào đó.
                      Thân ái.
                      em cản ơn bác rất nhiều, em cũng hiểu được ý nghĩa sơ sơ của nó rồi. nhưng em hỏi thêm bác nữa nhé: khi em định nghĩa #byte LCD = getenv("SFR:PORTB") có nghĩa là em gán các thành phần tương ứng của biến LCD vào PORTB phải không ạ, trong geten(...) thì dấu 3 chấm nhất định phải là "SFR:xxx" trong đó xxx là tên các thanh ghi đặc biệt được công nhận trong chip phải không ạ. em xin cảm ơn

                      Em mong bác tích cực tham gia luồng này giúp em nhé, các bài bác phản biện cực kỳ hay và hữu ích. em hy vọng luồng này sẽ phát triển cùng với sự giúp đỡ của các bác.
                      Be quan. Plz contact through email:

                      Comment


                      • #12
                        Nguyên văn bởi Lenh Ho Xem bài viết
                        Em đã làm theo hứong dẫn của anh, nhưng trong file.h em thực hiện thì bất cứ thanh ghi nào cũng có MCU_ ở đầu tiên, làm thế nào mà nó không có tiền tố này trong việc định nghĩa thanh ghi hả anh,
                        thêm chút nữa anh nhé
                        nếu em add nó vào chương trình, ví có nhiều thanh ghi mình định nghĩa mà không sử dụng tới, liệu có tốn thêm bộ nhớ không anh ( theo em hiểu thì không vì mình đang định nghĩa các thanh ghi đặc biệt có sẵn trên ROM mà) . em hiểu có đúng không ạ. mong anh chỉ thêm. cảm ơn anh nhiều.
                        Nó không tốn thêm bộ nhớ đâu.

                        Trong file .h có cấu trúc MCU_ ở đầu vì khi Creat file .h bạn để mặc định.
                        Để mất MCU_ ở đầu thì khi Creat ở trong bảng Generate Register Defines bạn chú ý có 2 ô text là Byte PrefixBit Prefix có giá trị mặc định là MCU_. Chính cái mặc định này đã tạo MCU_ trong file .h. Bạn có thể xóa trắng để được như bình thường hoặc có thể ghi nó là ABC.. gì đó nếu thích và khi đó trong file .h cũng có ABC... ở đầu.

                        Comment


                        • #13
                          em đã làm được như bác duong_act chỉ, em xin hỏi thêm ( đừng cho là em hỏi nhiều quá nha), em mới học mà:
                          - giải thích dùm em tại sao trong file 16f887.h có dòng này:
                          #define PIN_A0 40

                          đây là một định nghĩ, theo như em hiểu thì nó định nghĩa chân A0 của porta, nhưng như vậy thì có khác gì với khi em sử dụng #bit PIN_A0 = 0x05 không ạ. em chỉ hay gặp định nghĩa một hàm nào đó . ví dụ : #define hi(x) (x<<4)

                          a = hi(x) // tuong duong voi a = a << 4;
                          còn định nghĩa #define này kia trong 16f887 khó hiểu quá

                          em lấy thêm ví dụ nữa:

                          trong 16f887.h có dòng:
                          // Constants used for SETUP_ADC() are:
                          #define ADC_OFF 0 // ADC Off
                          #define ADC_CLOCK_DIV_2 0x100
                          #define ADC_CLOCK_DIV_8 0x40
                          #define ADC_CLOCK_DIV_32 0x80
                          #define ADC_CLOCK_INTERNAL 0xc0 // Internal 2-6us

                          ai giải thích được dùm em một dòng trong số này không? nó là các giá trị khi em sử dụng chế độ adc đựoc sử dụng cho lệnh adc_setup(...), bên trên nó nói contants used for setup_adc() nghĩa là sao ạ. em khó hiểu về mấy thằng hằng số này quá, tại sao lại định nghĩa adc_off là 0...mong các bác trả lời em nhé
                          Be quan. Plz contact through email:

                          Comment


                          • #14
                            Theo mình đó là giá trị các thanh ghi tương ứng để điều khiển các chế độ tương ứng.

                            Ví dụ như trên giả sử thanh ghi quy định clock của ADC là thanh ghi ADC( ví dụ thế) thì :
                            Nếu giá trị của nó là 0x40 thì sẽ là clock_div_8
                            _________________0x80________________32

                            Comment


                            • #15
                              Rõ hơn nữa được không anh?
                              Be quan. Plz contact through email:

                              Comment

                              Về tác giả

                              Collapse

                              Lenh Ho Tìm hiểu thêm về Lenh Ho

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

                              Collapse

                              Đang tải...
                              X