[RYA2013] Giới thiệu cơ bản về sử dụng ADC của TM4C123

Discussion in 'Tài liệu hướng dẫn' started by cooliovato, Jul 31, 2013.

  1. cooliovato

    cooliovato Cố Vấn CLB Staff Member

    Bài viết mang tính sơ lược và không chuyên, nếu có sai sót mong các bạn thông cảm và các cao nhân chỉ bảo thêm :1cool_byebye::)

    Các nội dung sau đây là những phần được-cho-là-cơ-bản =)) khi làm việc với ADC của TM4C123 (hoặc LM4F120 cũ) được trích từ:
    + Datasheet, userguide: http://www.ti.com/product/tm4c1230h6pm


    1/ Sơ lược về ADC của TM4C123H6PM:
    + 2 module ADC 12 bits​
    + 12 kênh ADC input​
    + Lấy mẫu kiểu single-ended hoặc differential​
    + Tần số lấy mẫu tối đa 1MSPS (1 mega samples per second)​
    + Điện áp tham chiếu Vref = 3.3V​
    + Kích hoạt lấy mẫu bằng processor, timer, analog comparators hoặc GPIO​
    + 4 "sequence" lấy mẫu (ADC sample sequencers)​
    2/ Về ADC sample sequencers (SS):
    Sequence (tạm dịch là "chuỗi mẫu") được dùng để giúp cho việc lấy mẫu từ nhiều kênh input tiện lợi hơn, hoặc có thể dùng để lấy nhiều mẫu trên cùng một kênh input. Có 4 sequence:
    + SS3: mỗi lần lấy tối đa 1 mẫu​
    + SS1, SS2: mỗi lần lấy tối đa 4 mẫu​
    + SS0: mỗi lần lấy tối đa 8 mẫu​
    Ví dụ các bạn muốn lấy mẫu ADC từ 4 kênh (4 LED thu hồng ngoại chẳng hạn) thì có thể dùng SS1 hoặc SS2 và config để lấy mỗi lần 4 mẫu từ 4 kênh này (1 mẫu từ mỗi kênh).​
    3/ Ví dụ về config cho ADC lấy mẫu từ 4 kênh:
    Code:
    //include header files
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
     
    int main(void)
    {
      //mảng chứa giá trị mẫu mỗi lần lấy, ở đây ta cần lấy mỗi lần 4 mẫu
      //To do: đổi kích thước của mảng tùy theo số mẫu muốn lấy
      uint32_t ui32ADC0Value[4];
     
      //Set system clock
    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
     
      //Enable ADC0
      SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
     
      //Enable port E và config cho các chân PE0-PE3 thành chân ADC
      //To do: đổi sang chân GPIO theo nhu cầu (cần xem datasheet để biết các chân nào có chức năng ADC)
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
      GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
     
      /*Config cho ADC sample sequencer, ở đây ta dùng SS1, chọn kiểu kích hoạt (trigger) bằng
    poccesor, và độ ưu tiên là 0 (ưu tiên cao nhất) */
      //To do: chỉnh lại SS cần dùng, kiểu trigger hoặc độ ưu tiên (nếu dùng nhiều SS)
      ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
     
      /* Config cho 4 step của SS1 (tương ứng với 4 mẫu từ 4 kênh). Ở đây giả sử ta cần lấy mẫu từ  4 kênh
    (channel) theo thứ tự 0, 1, 2, 3 tương ứng với các chân AIN0-AIN3 hay PE3-PE0, sau khi  lấy mẫu kênh
    cuối sẽ ngừng lấy mẫu và bật cờ ngắt */
      //To do: chỉnh lại kênh (xem datasheet để biết các kênh và chân tương ứng)
      ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0);
      ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1);
      ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
      ADCSequenceStepConfigure(ADC0_BASE,1,3,ADC_CTL_CH3|ADC_CTL_IE|ADC_CTL_END);
     
      //Enable SS1
      ADCSequenceEnable(ADC0_BASE, 1);
     
      while(1)
      {
        //Xóa cờ ngắt và kích hoạt lấy mẫu
        ADCIntClear(ADC0_BASE, 1);
        ADCProcessorTrigger(ADC0_BASE, 1);
     
        //Chờ đến khi lấy mẫu xong
        while(!ADCIntStatus(ADC0_BASE, 1, false));
     
        /*Đọc data (giá trị mẫu) lưu vào mảng, thứ tự mẫu trong mảng cũng chính là thứ tự các step (hay
    channel) như đã config. Cụ thể là ui32ADC0Value[0] sẽ chứa mẫu của CH0, ui32ADC0Value[1] chứa mẫu
    của CH1,... */
        ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
      }
    }
    

     
    thuyvy3110, phuong le, 2death and 4 others like this.
  2. phucuong23192

    phucuong23192 Thành Viên PIF

    //include header files
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
    unsigned long ui32ADC0Value;
    unsigned long a;
    int main(void)
    {
    //mảng chứa giá trị mẫu mỗi lần lấy, ở đây ta cần lấy mỗi lần 4 mẫu
    //To do: đổi kích thước của mảng tùy theo số mẫu muốn lấy


    //Set system clock
    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);

    //Enable ADC0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    //Enable port E và config cho các chân PE0-PE3 thành chân ADC
    //To do: đổi sang chân GPIO theo nhu cầu (cần xem datasheet để biết các chân nào có chức năng ADC)
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1 );

    /*Config cho ADC sample sequencer, ở đây ta dùng SS1, chọn kiểu kích hoạt (trigger) bằng
    poccesor, và độ ưu tiên là 0 (ưu tiên cao nhất) */
    //To do: chỉnh lại SS cần dùng, kiểu trigger hoặc độ ưu tiên (nếu dùng nhiều SS)
    ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);

    /* Config cho 4 step của SS1 (tương ứng với 4 mẫu từ 4 kênh). Ở đây giả sử ta cần lấy mẫu từ 4 kênh
    (channel) theo thứ tự 0, 1, 2, 3 tương ứng với các chân AIN0-AIN3 hay PE3-PE0, sau khi lấy mẫu kênh
    cuối sẽ ngừng lấy mẫu và bật cờ ngắt */
    //To do: chỉnh lại kênh (xem datasheet để biết các kênh và chân tương ứng)

    ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH2|ADC_CTL_IE|ADC_CTL_END);

    //Enable SS1
    ADCSequenceEnable(ADC0_BASE, 1);

    while(1)
    {
    //Xóa cờ ngắt và kích hoạt lấy mẫu
    ADCIntClear(ADC0_BASE, 1);
    ADCProcessorTrigger(ADC0_BASE, 1);
    a=0;
    //Chờ đến khi lấy mẫu xong
    while(!ADCIntStatus(ADC0_BASE, 1, false));

    /*Đọc data (giá trị mẫu) lưu vào mảng, thứ tự mẫu trong mảng cũng chính là thứ tự các step (hay
    channel) như đã config. Cụ thể là ui32ADC0Value[0] sẽ chứa mẫu của CH0, ui32ADC0Value[1] chứa mẫu
    của CH1,... */
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value);

    a=ui32ADC0Value;
    }
    }
    mình đọc ADC zô chân PE1 sao giá trị ADC lúc cắm tín hiệu ADC vào và không cắm nó chẳng thay đổi gi.@@:-s
     
  3. cooliovato

    cooliovato Cố Vấn CLB Staff Member

    phucuong23192 : code của bạn mình nạp thử thì chạy bình thường mà.
    Khi debug bạn nhớ click vào "continuous refresh" để debugger cập nhật liên tục giá trị của biến mới thấy nó thay đổi được.
     
    2death likes this.
  4. phucuong23192

    phucuong23192 Thành Viên PIF

    ờ. tks ak. để mình xem lại. giá trị của mình khi chưa cắm tín hiệu ADC đã có giá trị rùi, mà giá trị nó chẳng ổn định chút nào. nhảy lung tug:5cool_beat_plaster:
     
  5. nguyenlkdn

    nguyenlkdn Trứng gà

    Hi PIF ! Hiện tại mình đang thắc mắc về phần cấu hình điện áp qui chiếu nội của M4F theo như mình biết thì sử dụng hàm ADCReferenceSet(...) để set nhưng mình không biết truyền giá trị như thế nào để có thể cấu hình mức điên áp qui chiếu dương là 1V và âm là 0v.
    Thân !
     
  6. honghiep

    honghiep Cố Vấn CLB Staff Member

    Bạn xem ở trang 35, DiverLib User's Guide có nói: The ADC reference is set as specified by ui32Ref . It must be one of ADC_REF_INT,
    ADC_REF_EXT_3V, or ADC_REF_EXT_1V for internal or external reference. If
    ADC_REF_INT is chosen, then an internal 3V reference is used and no external reference
    is needed. If ADC_REF_EXT_3V is chosen, then a 3V reference must be supplied to the
    AVREF pin. If ADC_REF_EXT_1V is chosen, then a 1V external reference must be supplied
    to the AVREF pin.
    Để có được áp quy chiếu 1V thì phải cấp Vref ngoài. Vref nội chỉ có 3V thôi
     
    thuyvy3110, nguyenlkdn and 2death like this.
Loading...

Share This Page