Try   HackMD

Chapter 10 Timers and Analog Interface

tags: microcontroller

PIC18F Timers

  • PIC18F4321 有 4 個 timers ,分別為:
    1. Timer0 ( 8-bit or 16-bit )
      • 當使用 internal clock 時是一個 timer ,當使用 external clock 時變成 counter 。
    2. Timer1 ( 16-bit )
      • 這邊說明只講他只能作為 16-bit 的 timer or counter ,不能作為 8-bit 的使用。
      • 與 Timer0 一樣,當使用 internal clock 時是一個 timer ,當使用 external clock 時變成 counter 。
    3. Timer2 (8-bit)
      • 在使用 internal clock 時可以作為 8-bit timer ,但他不能當 counter 使用。
    4. and Timer3 ( 16-bit ) 。
      • 跟 Timer1 一樣,他只能作為 16-bit 的 timer or counter ,不能作為 8-bit 的使用。
  • 基本功能就是能在 rising/falling edge of a clock 時, incremented/decremented timer 的 register 。
  • 也可以作為 event counters ,像在開關被操作幾次後,會觸發什麼程式(不只是計時的功能,也能計次)。
  • Timer1, Timer2, Timer3 可作為 CCP ( Capture/Compare/Pulse Width Modulation ) operation 使用。
  • 總結來說, timer 就是一個 binary counter 用來計算,當他達到 maximum value 時,會回到 0 ,然後 overflow 的 flag 會變成 1 ,在有設定的時候還能夠觸發 interrupt 。

這邊 Timer2 比較特別,他有一個 register 叫 PR2 ,當 TMR2 = PR2 時,就會觸發 overflow ,跟其他的到達最大值不一樣。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Timer interrputs

  • 因為如果單看 TMRxIF bit 有沒有變 HIGH 的話,程式不能夠執行下去,所以才會需要 interrupt 。
  • 因為 timers 被視為 外部裝置,所以要打開 INTCON 裡面的 peripheral interrupt bit ( PEIE ) 。
  • 開啟 timer0 interrupt :
BCF INTCON, TMR0IF BSF INTCON, TMR0IE BSF INTCON, PEIE BSF INTCON, GIE
  • 當觸發 interrupt 時, PC 會寫入 0x0000008 的地址( default )。

Prescaler and Postscaler

  1. Prescaler

    • 在 clock 上面在切分,變成 n 個 clock period 才會進一個 timer period 。
    • 範例:如果 Timer0 的 prescaler 設為 4 , clock frequency 是 4 MHz ,則 Timer0 的 timer frequency 為
      Fosc4÷4=0.25
      Mhz 。
    • 每一個 Timer 好像都有 prescaler 。
  2. Postscaler

    • slow down the interrupt generation.
    • 印象中就是要 overflow 幾次才會觸發到 interrupt 。
    • 只有 Timer2 有, ppt 還講到 Timer2 的 prescaler 可以 delay 的比 postscaler 還要多。

Timer0

  • 可以作為 8-bit/16-bit timer 或 counter 。
  • 當使用 internal clock 的時候作為 timer ;當使用 external clock ( T0CK1/RA4 )時作為 counter 。

Timer0 as a timer

  1. set TMR0ON (bit 7 of T0CON register ) - let the Timer0 start.
  2. 這時候 TMR0L ( in 8-bit mode ) 或 TMR0H:TMR0L ( in 16-bit mode ),就會往上加。
  3. 直到達到 overflow 的時候, TMR0IF flag ( in INTCON ) 就會變 1 。
  4. 然後 TMR0L 就會歸 0 。

如果要停止 Timer0 只要把 TMR0ON 關掉就好了( set the bit to 0 )。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Timer0 as a counter

  1. set T0CS ( bit 5 in the T0CON ) - let Timer0 use the external clock.
  2. (選擇性)可以調整 T0Se ( bit 4 in the T0CON ),來決定是要 trigger by rising/falling edge 。
  3. 其他就等 overflow 發生之類的。

Timer0 Read/Write in 16-Bit Mode

  • TMR0H is not actual high byte of Timer0 in 16-bit mode.
  • 在執行 16-bit Timer0 操作之前一定要先把 TMR0H 歸 0 避免不必要的錯誤。
  • 實際上的 upper 8-bit value 是存在 latched register 裡面,然後在存入 TMR0H 中。
  • 當 TMR0L 的值發生改變的時候, TMR0H 的值才會更新。

Timer0 Presaler

  • 當我們寫入 Timer module 時(像 CLRF TMR0 )之類的操作時,他會自動清除 presaler count 。

Timer0 Interrupt and Timer0 Flag bits

  • 要打開 TMR0IE 來允許 Timer0 interrupt 。
  • 當 overflow 時 TMR0IF 會變成 1 來代表。
INTCONbits.TMR0IF = 0; INTCONbits.PEIE = 1; INTCONbits.TMR0IE = 1; INTCONbits.GIE = 1; T0CONbits.TMR0ON = 1;
  • 發生 interrupt 時, PC 會讀進 0x00008的地址。
  • Timer0 的 interrupt priority 是設定在 TMR0IP ( bit 2 of INTCON2 ),可設定為 high/low priority interrupt 。
  • 當為 low priority interrupt 時, PC 會讀入 0x000018 的地址。

要記得 interrupt code 裡面要把 TMR0IF 設為 0 ,不然會一直觸發 interrupt 。

  • 這邊要會算總共大概會 delay 多久,一定要記得 4次的 CPU clock 才能完成一次的 instruction ( in 8-bit device )
  • Time delay = Instruction cycle * Prescale value * Count
  • 而且除了你看到的,還會有 extra cycle ( set TMR0L to 0x00/set TMR0IF to 1 ),所以在 count 那邊除了真正會計算到的,還會再 + 1 。
  • delay 1 ms :
#include <p18f4520.h> void main(void){ OSCCON = 0x70; //8 MHz T0CON = 0x06; //initialize T0CON TMR0H = 0xFF; //Initialize TMR0H TMR0L = 0xF0; //Initialize TMR0L INTCONbits.TMR0IF = 0; //Clear Timer0 flag bit T0CONbits.TMR0ON = 1; //Start timer0 while(INTCONbits.TMR0IF == 0); //Wait for Timer0 flag bit to be 1 T0CONbits.TMR0ON = 0; //Stop Timer0 While(1); }
  • 關於 Timer interrupt 的部份去看實驗。

Timer1

  • 就只能用 16-bit ,包含 TMR1HTMR1L 來存。
  • TMRIF 在 PIR1 register 裡面,當 Timer1 overflow 時會變成 1 。
  • 在從 0xFFFF to 0x0000 時也需要 extra clycle 。
  • 可由 T1CON 控制。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Timer1 Operation

  • 可作為 timer 、 同步或非同步 counter ,可由 TMR1CS 決定:若為 0 則使用 internal clock ,若為 1 則在每一個 external clock 的 risting edge 加 1 。
  • 有一個 on-chip 的 crystal oscillator circuit 可由 T1OSCEN bit 來開啟,他的頻率是 32 kHz ,而 Timer1 可由 TMR1ON bit 開啟。

Timer1 Interrupts

  • 當 TMR1 register pair ( TMR1H:TMR1L ) overflow 時,TMR1IF 會變成 1 來代表 interrupt 發生。
  • Timer1 的 interrupt 可以由 TMR1IE ( bit 0 of PIE1 ) 來開啟。

PIR1
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

PIE1

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

注意這邊計算 delay 時要記得加 extra cycle (就是他會自己把 TMR1H:TMR1L 變成 0 ,雖然你沒有打這段程式碼,但也要算一個 instruction cycle)

  • 後面也是一些實做範例,要注意的就是前面的 config 要 OFF 一些東西,跟 Timer0 的一樣。

要記得 assemble 跟 C 的 config 寫法不一樣
assemble

config WDT = OFF;

C

#pragma config WDT = OFF

Timer2

  • 包含 8-bit timer register 和 8-bit peroid register ( TMR2 and PR2 )。
  • 是唯一一個 Timer 裡面有 postscaler 的,但 Timer2 只能作為 timer 使用。
  • 可以由 T2CON register 來控制,當 T2CON 被清 0 時也等於 Timer2 停止。

Timer2 Operation

  • PR2 register 通常會被初始化成一個特定的數字,而當 TMR2 到達那個數字的時候(當然中間會經過 prescaler and postscaler), TMR2IF bit 就會變成 1 ,並把 TMR2 歸 0 。

要注意

  1. TMR2IF bit 是在 PIR1 register 裡面。
  2. 在 interrupt code 中要記得把 TMR2IF 歸 0 。

Timer2 Interrupt

  1. Set PEIE and GIE in INTCON register to 1.
  2. Set TMR2IE bit in PIE1 register to 1.
  3. Clear TMR2IF bit in PIR1 register to 0.
  4. Clear TMR2 register to 0.
  5. Initialize PR2 and T2CON with appropriate data.
  6. 第五點中要記得包含把 Timer2 打開那個 bit ( in T2CON ) ,不然就在這步驟做。
  7. 再來就等他 interrupt , PC 裡面就會讀進 0x08 這個 address 了。

當你發現你的 prescaler and postscaler 都用到最大值還到達不了他的要求時,就要使用另一個變數來做 counter 了。

  • 後面也是一堆實做,單都是關於 delay 的,不過如果考試沒有限制的話直接用內建的 delay function 好像就可以了吧?

Timer3

  • 可以作為 16-bit 的 timer or counter (也只能作為 16-bit 使用)。
  • 透過 T3CON register 來控制,通常跟 CCP mudule 有關。

Timer3 Operation

  • 可以調整 TMR3CS bit 來決定他要用啥 mode ,有 timer/synchronous counter/asynchronous counter 可使用(但 synchronous 或 asynchronous 要自己寫,他只幫你決定 input source 是 internal 或是 external 而已)。

Timer3 Interrupt

  • 當 TMR3 register pair ( TMR3H:TMR3L ) overflow 時, TMR3IF bit ( bit 1 of PIR2 )會被設為 1 ,然後 TMR3 register pair 會被清 0 。
  • 如果要使用 interrupt 記得要開 TMR3IE bit ( bit 1 of PIE2 ) 。

PIR2


PIE2

注意,如果同一個 program 裡面用到多個 timer interrupt 時,因為他們都會跳到 0x08 這個 address ,所以在 0x08 這邊要寫一個 check 來檢查到底是哪一個 timer interrupt 了。

Analog Interface

  • 完整的Analog Interface 應該包含 A/D and D/A converter ,但 PIC18F4321 只有包含 on-chip A/D converter , D/A chip 要外接。

PIC18F on-chip ADC ( A/D Converter )

  • PIC18F 的 on-chip A/D converter 提供 8-bit or 10-bit 。
  • ADC 的 characteristics 包含以下幾項:
    1. Resolution (解析度)
      • 就看 8-bit 還是 10-bit 輸出,輸出的範圍越廣,代表在同一個區間的電壓可以被分割的越多份,解析度就越高。
      • PIC18F4520 應該就只是分割 0V ~ 5V 的電壓。
    2. Reference voltage (參考電壓)
      • 用來區分要劃分電壓的 maximum 和 minimum ,要先給一個參考的最大值與最小值,劃分才會有意義。
      • Voltage input/output 分別為 Vref+/Vref- 。
    3. ADC channels (A/D converter 通道)
      • ADC hardware module 連到一個 multiplexer 來區分 channel ,每一個 channel 都可以決定要不要連到 analog voltage 來進行 A/D convert ,像 PIC18F 有 13 個 channel ,從 AN0 ~ AN12 。
    4. Acquisition time (採樣時間)
      • 當決定一個 ADC channel 時,他需要一段時間來把裡面的一個 capacitor 充好電,這個時間就叫 acquisition time 。
      • 當達到 acquisition time 時, PIC18F 會斷開 channel 與 source 的連結,然後開始 conversion 。
    5. ADC clock
      • 就一次 A/D conversion 的週期 Tad 。
  • 每一個 channel 都可以 convert 出 8-bit or 10-bit 的 output 。

8-bit output A/D conversion

  • 有 3 個 control register ( ADCON0 ~ ADCON2 ),加上 2 個 data registers ( ADRESH, ADRESL ),全部皆為 8-bit registers 。
    1. ADCON0 register
      • 用來設定要哪一個 channel。
      • 用來啟動 ADC conversion 。
      • 用來開啟 ADC conversion 。

      注意, ADON bit 只是 enable 而已,要設定 GODONE A/D converter 才會開始動作。

    2. ADCON1 register
      • 用來設定 reference voltage 要從哪邊讀。
      • 用來設定 AN0 ~ AN12 哪一些要 analog input 哪一些要 digital I/O 。

    3. ADCON2 register
      • 用來設定 output 要 Right/Left justified ( Right 代表全部靠右, ADRESH 有 2-bit ADRESL 有 8-bit )。
      • 用來設定 ADC acquisition time 。
      • 用來設定 A/D conversion clock 。

      關於 left justified 上面寫適用於 8-bit 的 output ,因為他會只把 8-bit 的結果存入 ADRESH 中,而 ADRESL 中的結果直接捨棄掉,跟我在實驗課聽到的不一樣??

  • 不論是組合語言或 C 都可以寫。
  • 在 C 中的 ADCON0bits.GO = ADCON0bits.DONE ,兩種寫法效果同等。

A/D interrupt

  1. Set ADIE bit in PIE1 to 1 .
  2. Clear ADIF bit in PIR1 to 0 .
  3. Set PEIE bit in INTCON to 1 .
  4. Set GIE bit in INTCON to 1 .
  5. Start A/D conversion by setting GO/DONE bit in ADCON0 to 1 . (不用開 ADON 嗎?)
  • 當一次的 A/D conversion 結束時, ADIF bit in PIR1 會被設為 1 。
  • 如果想設定 A/D interrupt 是 low priority 的話可以調整 ADIP bit in PIR1

Interfacing an external D/A Converter

  • 就把讀進去的 digital 在用某個 port ( 8-bit ) 傳出去,然後再去看 external device 的 datasheet 看要怎麼設定吧?