Thông báo

Collapse
No announcement yet.

Help chút vấn đề về đếm xung

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

  • Help chút vấn đề về đếm xung

    chào mọi người, mình viết một cái code đơn giản thế này thôi. mình cho xung vào chân T1 của atmega16, khi có xung vào chân T1 thì một biến sẽ tăng dần giá trị,
    mình sử dụng ngắt tràn ở timer1 để cứ 1s thì sẽ in ra giá trị đó ra lcd,
    nhưng kô hiểu sao nó chạy linh tinh kinh khủng
    PHP Code:
    /****************************************************
    Chip type           : ATmega16
    Program type        : Application
    Clock frequency     : 12.000000 MHz
    Memory model        : Small
    External RAM size   : 0
    Data Stack size     : 256
    *****************************************************/

    #include <mega16.h>

    // Alphanumeric LCD Module functions
    #asm
       
    .equ __lcd_port=0x1B ;PORTA
    #endasm
    #include <lcd.h>
    #include <stdio.h>
    unsigned long ulSo_xung=0;
    unsigned char tick 0;
    char buff[33];

    // Timer 1 overflow interrupt service routine
    interrupt [TIM1_OVFvoid timer1_ovf_isr(void)
    {
    // Place your code here
     //dat gia tri cho timer1
     
    TCNT1H 0xD239>>8;//timer1 se bat dau dem tu gia tri
     
    TCNT1L 0xD239&0xFF ;
      
    tick++;
        if(
    tick >= 1)
        {
            
    #asm("cli");
            
    tick 0;
            
    lcd_clear();
            
    lcd_gotoxy(0,0);
            
    lcd_putsf(" Tan So La:"); 
            
    lcd_gotoxy(0,1);
            
    sprintf(buff," %d%d%d%d",ulSo_xung/1000,(ulSo_xung%1000)/100,(ulSo_xung%100)/10,ulSo_xung%10);
            
    lcd_puts(buff);
            
    ulSo_xung 0;
            
    #asm("sei");
        
    }
    }

    // Declare your global variables here

    void main(void)
    {
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 11.719 kHz
    // Mode: Normal top=FFFFh
    // OC1A output: Discon.
    // OC1B output: Discon.
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer 1 Overflow Interrupt: On
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A=0x00;
    TCCR1B=0x05;
    TCNT1H=0xD2;
    TCNT1L=0x39;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;

    /

    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x04;

    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;

    // LCD module initialization
    lcd_init(16);

    // Global enable interrupts
    #asm("sei")

    while (1)
          {
    // doạn chương trình này để nhận dạng một xung đầu vào
          // Place your code here
           
    if (PINB.1 ==1) {
            while(
    PINB.1 == 0)
           
    ulSo_xung++; 
     }
          };

    mọi người xem giúp mình với nhé
    thank
    ĐỪNG KHÓC CHO NHỮNG GÌ ĐÃ QUA, MÀ HÃY CƯỜI CHO NHỮNG ĐIỀU SẮP TỚI!

  • #2
    Bạn vướng vấn đề khá phổ biến trong việc lập trình.
    Việc hiển thị LCD là việc có độ ưu tiên (priority) thấp trong khi việc bắt xung là việc lại có yêu cầu chính xác cao.
    Nhưng việc bắt xung bạn lại để cho nó hoạt động ở luồng main có độ ưu tiên thấp hơn so với timer nên khi vào timer để hiển thị lcd thì xung nào cũng mất.

    Giải quyết có thể dùng giải pháp dùng các phần counter với external clock của timer tích hợp với việc đếm chống tràn.
    Còn hiển thị với tần số 1hz (1s 1 lần) thì đưa xuống main chẳng là vấn đề gì.

    Sông dài, Thuyền lớn, Biển rộng bao la.
    Tháo neo ngôn ngữ, lèo lái con thuyền kiến thức nhân loại.

    Comment


    • #3
      cảm ơn. ý bạn nói mình hiểu một phần, nhưng bạn nói là:
      Code:
      Giải quyết có thể dùng giải pháp dùng các phần counter với external clock của timer tích hợp với việc đếm chống tràn.
      bạn có thể nói rõ là như thế nào kô?
      thank
      ĐỪNG KHÓC CHO NHỮNG GÌ ĐÃ QUA, MÀ HÃY CƯỜI CHO NHỮNG ĐIỀU SẮP TỚI!

      Comment


      • #4
        Nguyên văn bởi quocdat_dtvt Xem bài viết
        cảm ơn. ý bạn nói mình hiểu một phần, nhưng bạn nói là:
        Code:
        Giải quyết có thể dùng giải pháp dùng các phần counter với external clock của timer tích hợp với việc đếm chống tràn.
        bạn có thể nói rõ là như thế nào kô?
        thank
        Các timer tích hợp bên trong các MCU thường có chức năng hoạt động như 1 thanh ghi đếm xung ở các cạnh nên nếu bạn muốn giảm tải cho hệ thống thay vì dùng ngắt ngoài để đếm thì có thể dùng idea này, mình chỉ đề cập đến 1 idea nhỏ cho vấn đề đếm xung thôi còn ý tưởng chính vẫn là priority trong thiết kế chương trình.

        Sông dài, Thuyền lớn, Biển rộng bao la.
        Tháo neo ngôn ngữ, lèo lái con thuyền kiến thức nhân loại.

        Comment


        • #5
          Post nhầm, sorry
          Đẹp từng kilomét

          Comment


          • #6
            Rốt cuộc lại bạn lấy xung đếm từ đâu? Input Capture hay biến ulSo_xung? Nếu là Input Capture thì ISR phải lấy xung trong thanh ghi ra hiển thị LCD, còn nếu lấy từ biến ulSo_xung thì đoạn code bạn viết trong hàm main coi bộ hơi rối. Cái vụ while(PINB.1==0) bien++; làm cái biến không chạy lung tung mới lạ
            Thử sửa thành
            Code:
            while(PINB.1==1)
               ;
            bien++;
            while(PINB.1==0)
              ;
            gọn hơn và dễ nhìn hơn. Thử xem
            Đẹp từng kilomét

            Comment


            • #7
              Xung đưa vào chân T1 rồi thì bạn cứ set cho Timer1 ở chế độ counter là nó tự đếm thôi. Dùng thêm Timer0 tạo ngắt (1ms chẳng hạn), rồi đọc giá trị TCNT1 và in ra. Đoạn code tăng giá trị biến đếm ở vòng lặp while có vẻ sai rồi.

              Comment


              • #8
                như bác quoc_thaibk đã nói, bạn nên thực hiện ý tưởng theo hướng dùng chức năng counter của bộ timer để đếm số xung, bạn chỉ việc set các thông số cho timer chạy ở chế độ này (nên dùng timer 1 vì nó đếm được 16 bit), đó là bạn cho nó chạy ở chế độ nomal và nguồn xung clock là nguồn xung từ bên ngoài, chứ ko dùng xung của hệ thống. sau đó dùng thêm một timer khác nữa để đặt thời gian đếm, sau thời gian đó bạn sẽ update giá trị lên lcd, cần chú ý để bộ đếm của bạn ko bị tràn, vì nếu tần số xung đếm khá cao, mà thời gian delay đếm xung lại lớn thì sẽ gây tràn bộ đếm( nếu ko có biện pháp phát hiện tràn thì số đếm về sẽ bị sai),

                thêm chỗ nữa là ở dòng này...
                Code:
                        sprintf(buff," %d%d%d%d",ulSo_xung/1000,(ulSo_xung%1000)/100,(ulSo_xung%100);
                bạn chỉ cần viết thế này là đủ,
                Code:
                        sprintf(buff," %d",ulSo_xung);

                Comment


                • #9
                  Trước đây mình hay dùng ngắt ngoài cùng với một biến chạy tốt và không lo chàn nhiều vì mình có thể quy định kiểu biến nhưng kiểu này thường làm gián đoạn chương trình chính.
                  Tốt nhất là dùng counter của một time nào đó và dùng time khác quy định thời gian hiển thị chỉ có điều cách này bạn phải thiết kế mạch chống dội ngoài (nếu mạch tạo xung có dội).
                  Thiết kế chế tạo các loại máy xoáy nắp, chiết rót định lượng dùng trong dược phẩm và thực phẩm.

                  Comment

                  Về tác giả

                  Collapse

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

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

                  Collapse

                  Đang tải...
                  X