Thông báo

Collapse
No announcement yet.

Bàn về ngắt và CCS compiler

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

  • Bàn về ngắt và CCS compiler

    Ngắt

    Là cơ cấu cho phép VĐK đáp một số sự kiện ngay thời điểm mà sự kiện đó xảy ra bất chấp VĐK đang làm gì!Đây là phần quan trọng của VĐK giúp VĐK giao tiếp với môi trường xung quanh..Khi xảy ra ngắt thì VĐK thực hiện chương trình ngắt,thực hiện xong chương trình ngắt,rồi lại quay lại chương trình chính.
    16F84 có 4 ngắt
    1.Hoàn thành việc viết vào EEPROM
    2. Ngắt Timer 0 // Bạn tưởng tượng TMR0 như một cái đồng hồ.Nó cứ đếm,cứ đếm nếu vượt qua một giá trị nào đó thì ngắt xảy ra(ff-->00).
    3. Ngắt RB-4,5,6,7 //có thay đổi trạng thái trên các chân này thì ngắt xảy ra
    4.Ngắt ngoài RB0/INT trên chân RB0. // có xung thì ngắt xảy ra

    Hình vẽ mô tả một cơ cấu ngắt.<chèn hình vẽ>



    VD: Về ngắt TMR0 nội dung chương trình
    Chương trình chính sẽ thực hiện Nháy Led đỏ tại chân RA1- chu kì 100ms/ 50 lần
    Chương trình ngắt thực hiện Nháy Led xanh tại chân RB1- chu kì 1s/5 lần
    Ví dụ đơn giản để các bạn kiểm tra khi nào chương trình chạy chương trình chính
    khi nào chạy chương trình ngắt.


    Chương trình như sau:
    [code:1]
    //CHUONG TRINH NGAT TIMER 0
    //author:noisepic@gmail.com
    //status:OK test !
    //date: 29/07/2005
    //***********************************************
    #include<16f84A.h>
    #include<def_84.h>
    #fuses NOWDT,PUT,NOPROTECT,HS
    #use delay(clock=4000000)
    #INT_TIMER0
    led()
    {
    unsigned int i;

    for(i=0;i<50;i++)
    {
    PORTA=0x00;// LED PORTA tat
    output_high(PIN_B4);
    delay_ms(100);
    output_low(PIN_B4);
    delay_ms(100);
    }
    }
    void main()
    {
    unsigned int i;
    TRISB=0x00;// PORTA,PORTB output
    TRISA=0x00;
    while(TRUE)
    {
    disable_interrupts(GLOBAL);
    for(i=0;i<5;i++)
    {
    PORTB=0x00;// led PORTB tat
    PORTA=0x00;
    delay_ms(1000);
    PORTA=0xff;// led sang o PORTA
    delay_ms(1000);
    }
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_TIMER0);
    setup_timer_0(RTCC_INTERNAL);
    set_timer0(100);
    while(toif==0)
    {
    }

    }
    }

    [/code:1]
    Trong đó phần khai báo ban đầu ...chưa vội quan tâm .Khi nào học sâu quan tâm chưa muộn!
    [code:1]
    #include<16f84A.h>
    #include<def_84.h>
    #fuses NOWDT,PUT,NOPROTECT,HS
    #use delay(clock=4000000)
    [/code:1]
    Khai báo phần cứng cho chương trình dịch biết dùng PIC nào? thạch anh bao nhiêu MHZ,...


    Việc khai báo và nội dung chương trình ngắt
    [code:1]
    #INT_TIMER0
    ham()
    {
    }
    [/code:1]
    Chương trình chính

    main()
    {

    }
    [code:1]
    TRISB=0x00;
    TRISA=0x00;// output
    [/code:1]
    Cấu hình I/O cho PORTA,PORTB
    Trong chương trình chính bạn phải đảm bảo(GIE=0).Cái này được thực hiện bằng hàm
    [code:1]
    disable_interrupts(GLOBAL);[/code:1]
    Sau đó lại GIE=1. sử dụng hàm enable_interrupts(GLOBAL)
    Sử dụng ngắt TMR0
    [code:1]enable_interrupts(INT_TIMER0);[/code:1]
    [code:1]
    setup_timer_0(RTCC_INTERNAL); [/code:1]chọn nguồn ngắt là xung đồng hồ bên trong PIC
    [code:1] set_timer0(100); [/code:1]đặt giá trị ban đầu cho TMR0..và đợi nó đếm đến 256 =0xff và xảy ra tràn
    // đợi nó đếm!
    [code:1]
    while(toif==0)
    {
    }
    [/code:1]

    -------------------------------------------------------------------------------------
    Hi vọng bài viết này giúp các bạn mới làm quen với PIC sẽ dễ hiểu hơn,noisepic rất mong nhậnđược góp ý của mọi người để noisepic rút kinh nghiệm và POST tiếp!
    -------------------------------------------------------------------------------------
    Learn more...

  • #2
    Bài viết của bác noisePic rất cơ bản. Anh em đọc xong có thể làm ngay, đúng là dùng CCS học PIC cực nhanh.
    Tui có mấy ý kiến nho nhỏ:
    +Có thể bác dùng 16F628A thay cho 16F84, con 16F628a = giá con 84 nhưng hiện đại hơn, thậm chí ko cần dung thach anh. Bât cứ chương trình nào viết cho 84 thì nạp vào 628a đều chạy.
    +Bác nên hạn chế dùng hàm delay trong ngắt. Thay vì việc đó, nêu dùng timer 0/1, bác dùng prescale để giảm Clock. Nạp thời gian là 100ms chả sướng hơn. Nêu thời gian 1s(dài quá), thì bác dùng thêm 1 biến đếm trong ngắt, mỗi lần ngắt, thì biến này tăng lên 1. Và khi 100*Value=1s thì value =0.
    -------------------

    Comment


    • #3
      Ngắt change on RB4-RB7

      Chương trình mô tả sử dụng ngắt trên chân RB4-RB7.PIC làm như sau: so sánh giá trị
      tại chân RB4-RB7 với giá trị trước đó.Nếu có sự khác biệt--> chạy chương trình ngắt.
      Để ngắt trên chân RB4-RB7 ta phải làm một số việc sau:
      - RB4-RB7 là Input
      -Set bit GIE=1
      -Set bit RBIE=1
      -Khi có ngắt xảy ra thì RBIF(cờ ngắt)=1
      - Sau khi thực hiện chương trình ngắt ta phải xóa cờ này.

      Code
      [code:1]
      // CHUONG TRINH DUNG NGAT RB4-RB7
      //date:30/07/2005
      //author:noisepic@gmail.com
      //status:
      //**************************************
      #include<16f84a.h>
      #fuses NOWDT,PUT,HS,NOPROTECT
      #use delay(clock=4000000)
      #include<def_84.h>
      main()
      {
      unsigned int j;
      TRISA=0x00;
      TRISB=0xf0; // đặt RB4-RB7 là Input
      output_low(PIN_A2);
      enable_interrupts(GLOBAL); //GIE=1
      enable_interrupts(INT_RB); //RBIE=1
      while(TRUE)
      {
      output_low(PIN_B3);
      output_high(PIN_A2);
      delay_ms(100);
      output_low(PIN_A2);
      delay_ms(100);
      }
      }

      //***************************************
      // chương trình ngắt
      #INT_RB
      flash()
      {
      unsigned int i;
      for(i=0;i<10;i++)
      {
      output_low(PIN_A2);
      output_low(PIN_B3);
      delay_ms(100);
      output_high(PIN_B3);
      delay_ms(100);
      }

      }
      //*****************************************
      [/code:1]
      Chương trình chính chạy thì led ở chân A2 sẽ nhấp nháy,chân B3 tắt
      Chương trình ngắt chạy thì LED ở chân A2 tắt,Chân B3 sẽ nhấp nháy.

      Một số chú ý khi làm với ngắt này:
      - Chân RB4-RB7 là input do vậy ta nên để giá trị cho nó là 0 hay 1(Dùng điện trở
      kéo lên nguồn).Nếu để mức trôi nổi "float" thì sẽ chạy sai!! ban đầu noisepic viết
      không biết làm sao sai...
      - Trong chương trình ngắt khi thoát khỏi chương trình bit RBIF tự động xóa!! --> sướng
      không phải làm!!
      Learn more...

      Comment


      • #4
        Nếu chibang không bảo có lẽ noisepic cũng không biết! Có gì cậu gửi code lên đây để mọi người xem.
        chúc vui!
        Learn more...

        Comment


        • #5
          Đây la đoạn code đơn giản về ngắt onchange.
          RBIF phải được xóa sau mỗi ngắt onchange.
          void interrupt MyInt(void)
          if((RBIF)&&(RBIE))
          {
          if(RB7==0)
          {
          //Mot phim duoc an', xư lý....
          }
          RBIF=0;//Xoa' co ngat' onchange
          }

          Còn sau đây là ngắt timer 1
          void interrupt MyInt(void)
          if (TMR1IF)
          {
          TMR1ON=0;
          TMR1H=-(Load_timer_1/256);
          TMR1L=-(Load_timer_1%256);
          TMR1ON=1;
          TMR1IF=0;

          if(clk++==20)
          {
          clk1=0;
          //Viết mã để xử lý... ở đây
          }

          }

          Các ví dụ trên đều sơ sài, nhưng để đáp ứng yêu cầu của đại hiệp noisePIC thì tạm đủ.
          -------------------

          Comment


          • #6
            if((RBIF)&&(RBIE))
            Lệnh này anh có thể giải thích giúp em.
            Có lúc nào các anh gặp 2 ngắt :ngắt bàn phím và TIMER1 gặp nhau ở cùng 1 thời điểm ?
            Trường hợp xử dụng nhiều ngắt có cách nào xếp đặt mức độ ưu tiên như họ 8051 để các ngắt không đụng nhau.
            Mong các anh giúp đở.

            Comment


            • #7
              Hình như bác Chi Bang viết nhầm
              Nó là :
              if(RBIF &&(RBIE))
              {
              ...
              }

              Cấu trúc ngăt của PIC16 và 89 khác nhau rõ rệt.
              -89 chia thành nhiều địa chỉ ngắt, mỗi nguồn ngắt thì nhảy tới các địa chỉ ngắt khác nhau. Và nó có 2 kiểu ưu tiên:
              +Ngắt ưu tiên ngang hàng(nếu nhiều ngắt đồng thời xảy ra: thì nó ưu tiên ngắt đứng trước trong bảng địa chỉ ngắt)
              +Kiểu ngắt trong ngắt (khi đang trong ngắt, nó có thể nhảy vào ngắt khác có cấp ưu tiên cao hơn), nó có 2 cấp ưu tiên.

              -Về PIC16:
              +Ưu tiên ngắt = phần mềm, tất cả các ngắt xảy ra---> nó đều nhảy về cùng 1 địa chỉ. Tại địa chỉ này, mình phải viết lệnh lân lượt hỏi các cờ ngắt để xác định nguyên nhân ngắt xuất phát từ nguồn ngắt nào.
              +Trong việc hỏi các cờ ngắt, thì cờ ngắt được hỏi trước sẽ có mức ưu tiên cao hơn.
              Ví dụ:
              //Địa chỉ ngắt từ đây
              if(cờ ngắt Timer1)
              {
              }
              //Ngắt timer1 có mức cao nhất: mưc1
              if(cờ ngắt ngoài)
              {
              }
              //Ngắt ngoài có mức ưu tiên 2
              if()...
              //Mức 3
              }
              Khi vào ngắt, cờ cho phép ngắt toàn cục GIE tự động bị xóa = 0;
              Khi thoát khỏi ngắt cờ được set = 1;//cho phép ngắt

              Bởi thế ko thể thiết kế ngắt trong ngắt, bởi GIE=0; Nếu thiết kế ngắt trong ngắt thì trong hàm ngắt, buộc phải đặt = tay: GIE=1, nhưng chú ý kẻo tràn stack

              Đến dòng PIC18F thì có ngắt trong ngắt.Có 2 cấp ưu tiên.

              Comment


              • #8
                Bạn tham khảo thêm bào viết của tôi tại:
                http://www.dientuvietnam.net/board/s...0&page=2&pp=10
                http://www.dientuvietnam.net/board/s...0&page=3&pp=10
                để biết thêm thông tin. Ngắt của PSoC và của PIC khá giống nhau, tuy cũng có khác chút ít.

                Comment


                • #9
                  Chào các bạn. Mình mới tham gia diễn đàn. Mình đang nghiên cứu lập trình PIC trên MPLAB 6.0. Tuy nhiên còn nhiều lúng túng, với lại mình chưa có mạch nạp từ MPLAB. Bạn nào có kinh nghiệm chỉ dùm mình với.
                  Co cong mai sat co ngay nen kim !

                  Comment


                  • #10
                    #include<16f84a.h>
                    #fuses NOWDT,PUT,HS,NOPROTECT
                    #use delay(clock=4000000)
                    #include<def_84.h>
                    main()
                    {
                    //unsigned int j;
                    TRISA=0x00;
                    TRISB=0xf0;

                    //output_low(PIN_A2);
                    enable_interrupts(GLOBAL); //GIE=1
                    enable_interrupts(INT_RB); //RBIE=1
                    while(TRUE)
                    {
                    output_low(PIN_B3);
                    output_high(PIN_A2);
                    delay_ms(100);
                    output_low(PIN_A2);
                    delay_ms(100);
                    }
                    }

                    //***************************************
                    // chuong trình ng?t
                    #INT_RB
                    flash()
                    {
                    int i;
                    for(i=0;i<100;i++)
                    {
                    output_low(PIN_A2);
                    output_high(PIN_B3);
                    delay_ms(100);
                    output_low(PIN_B3);
                    delay_ms(100);
                    }
                    bác kiểm tra gium sao chương trình trên không chạy
                    Khi tôi bấm phím cho chân số 4 xuống mass như sơ đồ trên của bác thì không xay ra ngắt,có nghĩa là LED B3 không nhấp nháy. Mục đích của tôi là khi nhấn phím thì LED trên chân B3 sẽ nháy.CÒn không nhấn phím thì LED trên chân A2 sẽ nhấp nháy.Nhưng không hiểu hiểu sai chổ nào.Bác NoisePic kiểm tra giùm cái nha
                    Cám ơn bác
                    Ai nên khôn mà chẳng dại đôi lần.

                    Comment


                    • #11
                      Ngắt???

                      Nguyên văn bởi BinhAnh
                      -Về PIC16:
                      +Ưu tiên ngắt = phần mềm, tất cả các ngắt xảy ra---> nó đều nhảy về cùng 1 địa chỉ. Tại địa chỉ này, mình phải viết lệnh lân lượt hỏi các cờ ngắt để xác định nguyên nhân ngắt xuất phát từ nguồn ngắt nào.
                      +Trong việc hỏi các cờ ngắt, thì cờ ngắt được hỏi trước sẽ có mức ưu tiên cao hơn.
                      Ví dụ:
                      //Địa chỉ ngắt từ đây
                      if(cờ ngắt Timer1)
                      {
                      }
                      //Ngắt timer1 có mức cao nhất: mưc1
                      if(cờ ngắt ngoài)
                      {
                      }
                      //Ngắt ngoài có mức ưu tiên 2
                      if()...
                      //Mức 3
                      }
                      Khi vào ngắt, cờ cho phép ngắt toàn cục GIE tự động bị xóa = 0;
                      Khi thoát khỏi ngắt cờ được set = 1;//cho phép ngắt

                      Bởi thế ko thể thiết kế ngắt trong ngắt, bởi GIE=0; Nếu thiết kế ngắt trong ngắt thì trong hàm ngắt, buộc phải đặt = tay: GIE=1, nhưng chú ý kẻo tràn stack

                      Đến dòng PIC18F thì có ngắt trong ngắt.Có 2 cấp ưu tiên.
                      Xin hỏi bác BinhAnh:
                      - Nếu ko thể có ngắt trong ngắt thì các ngắt xẩy ra vào thời điểm isr đang thực hiện có được lưu lại để xử lý ko? hay bị bỏ qua.

                      Comment


                      • #12
                        Nguyên văn bởi tuancdc
                        Xin hỏi bác BinhAnh:
                        - Nếu ko thể có ngắt trong ngắt thì các ngắt xẩy ra vào thời điểm isr đang thực hiện có được lưu lại để xử lý ko? hay bị bỏ qua.
                        Theo tui biết ,với PIC 16F877A(các dòng khác thì không biết ) khi thực hiện ngắt ,thì bit GIE tự động Reset ,ngăn cấm ngắt khác xảy ra ,sau khi thực hiện xong rồi thì GIE =1 ,khi đó ngắt khác được kiểm tra để thực hiện !
                        Và anh biết là khi bên em, anh sẽ vượt qua tất cả

                        Comment


                        • #13
                          Nguyên văn bởi tuancdc
                          Xin hỏi bác BinhAnh:
                          - Nếu ko thể có ngắt trong ngắt thì các ngắt xẩy ra vào thời điểm isr đang thực hiện có được lưu lại để xử lý ko? hay bị bỏ qua.
                          OK, nó vẫn được lưu lại và xử lý khi thoát khỏi ngắt.

                          Comment


                          • #14
                            Re: Ngắt???

                            Xin hỏi với VDK PIC thì thời gian thực hiện ISR có giới hạn không(mặc dù tôi biết có khuyến cáo ISR càng nhanh càng tốt)?

                            Comment


                            • #15
                              Nguyên văn bởi tuancdc
                              Xin hỏi với VDK PIC thì thời gian thực hiện ISR có giới hạn không(mặc dù tôi biết có khuyến cáo ISR càng nhanh càng tốt)?
                              Tùy vào từng loại...mỗi con có giới hạn cho ISR (hay là Program counter).
                              Như dòng 16F hay dùng là 16F877A thì là 20MHz...chia ra thì có 5 triệu lệnh trên giây.
                              Dòng 18Fxx thì chắc cũng thế.
                              Thấy bảo dòng DSPIC còn nhanh hơn 30 triệu lệnh trên giây.
                              sở thích: Ngắm gái
                              Em xinh thế , em đi @

                              Comment

                              Về tác giả

                              Collapse

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

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

                              Collapse

                              Đang tải...
                              X