2016年8月29日 星期一

DIY - PIC24:PIC24FJ64GA008 脈衝寬度調變(PWM) 程式(四十九)

DIY - PIC24PIC24FJ64GA008 脈衝寬度調變(PWM) 程式(四十九): 

Microchip PIC24FJ64GA008 脈衝寬度調變(Pulse Width ModulationPWM)程式是控制 OC1 Pin 58OC1/RD0)引腳輸出,當將輸出比較模組配置為 PWM 操作模式時,筆者使用了 Timer2 作時基標準,設定 OC1OC1RS OC1R 參數,最後啓動 OC1 輸出,便可以有脈衝寬度調變波形輸出。

Microchip PIC24FJ64GA008 脈衝寬度調變(PWM)顯示
脈寬調製模式(Pulse Width ModulationPWM): 
1. 通過寫選定的計時器週期寄存器(PRy)設置 PWM 週期。 
2. 通過寫 OCxRS 寄存器設置 PWM 占空比。 
3. 將初始占空比寫入 OxCR 寄存器。 
4. 如果需要的話,允許計時器和輸出比較模組的中斷。如需要使用 PWM 故障引腳,則會用到輸出比較中斷。
5. 通過寫輸出比較模式位元 OCM<2:0>OCxCON<2:0>)將輸出比較模組配置為兩種 PWM 工作模式中的一種。 
6. 設置 TMRy 預分頻值並通過設置 TONTxCON<15> = 1 使能時基。

脈衝寬度調變(PWM)輸出波形
PWM 週期 (Period)
可以通過寫 PR2 寄存器來指定 PWM 的週期。 

可以使用如下公式計算 PWM 的週期:
▼例:假設振盪頻率 8MHz ( Fosc = 8MHz)TM2 預分頻值 11 
PWM 週期 = [ PR2+1] × (1(/Fosc/2)) × TM2 預分頻值  
PR2 = (99+1) × (1/(8MHz/2)) ×
PR2 = (100) × (0.25us) ×
PR2 = 25us

Microchip PIC24FJ64GA008 計算 PWM周期
Microchip PIC24FJ64GA008 計算最大 PWM 分辨率
PWM 占空比 ( Duty Cycle) 
PWM 占空比是通過寫 OCxRS 寄存器設定的。在任何時間都可以寫入 OCxRS 寄存器,但是在 PRy TMRy 發生匹配(即週期完成)前占空比值不會被鎖存到 OCxR。這一機制為 PWM 占空比提供了雙重緩衝,對於消除 PWM 操作中產生的毛刺至關重要。在 PWM 模式中, OCxR 是唯讀寄存器。

以下是 PWM 占空比的部分重要邊界參數:
• 如果占空比寄存器 OCxR 中的值為 0000h,則 OCx 引腳將保持低電平(0% 占空比)。
• 如果 OCxR 中的值大於 PRy (計時器週期寄存器)中的值,則引腳將保持高電平(占空比為 100%)。
• 如果 OCxR 中的值等於 PRy 中的值, OCx 引腳在一個時基計數週期內為低電平,而在其餘計數週期內均為高電平。

PIC24FJ64GA008 脈衝寬度調變(Pulse Width ModulationPWM)輸出
Microchip PIC24FJ64GA008 Timer2 初始化程式:
        CloseTimer2();              // Timer2 Close
       ConfigIntTimer2(T2_INT_ON); // Timer2 Interrupt ON
        SetPriorityIntT2(1);        // Set Interrupt Priority 0~7
        OpenTimer2
        (
           T2_ON &                          // Timer2 ON
           T2_IDLE_CON &            // Idle Time Continue Run
           T2_GATE_OFF &            // Timer2 Gate Time Accumulation OFF/ON
           T2_32BIT_MODE_OFF &      // Timer2 32-bit Mode OFF/ON
           T2_PS_1_1 &              // Prescaler 1:1/8/64/256
           T2_SOURCE_INT,           // Timer2 Source Oscillator INT/EXT
            99                               // PRx=0~65535 99=25us
        );

Microchip PIC24FJ64GA008 OC1 初始化程式:
// Configure PWM OC1
// (PRx+1) * (1/(8MHz/2)) * Timer Divider
// ( 99+1) * (0.25us * 2) * 1 = 25us
// Reset PWM
OC1CON = 0x0000;    // Turn Off Output Compare 1 Module
// Set PWM Duty Cycle
OC1RS  =   60;      // Initialize Second Compare Register (Duty Cycle =Timer/RS)
OC1R   =   99;      // Initialize Compare Register        (RS/R)
// Enable PWM
OC1CON = 0x0005;    // Load the New Comapre mode to OC1CON
                                 // Mode5 DC=50% OC1R=High=Timer OC1RS=Low=Timer/2

Microchip PIC24FJ64GA008 Timer2 中斷程式
// Timer2 Interrup
void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void) {
IFS0bits.T2IF = 0;
}

Microchip PIC24FJ64GA008 OC1 主程式
while(1){
}

PIC24FJ64GA008 脈衝寬度調變(Pulse Width ModulationPWM)程式試驗
2016年 8月 29日 天氣報告
氣溫:26.6@ 20:10
相對濕度:百分之 77%
天氣:多雲

2016年8月28日 星期日

DIY - PIC24:PIC24FJ64GA008 輸出比較 / PWM 模組原理(四十八)

DIY - PIC24PIC24FJ64GA008 輸出比較 / PWM 模組原理(四十八): 

Microchip PIC24FJ64GA008 微控制器芯片內置 5個 輸出比較 / PWMPulse Width Modulation) 模組,每個模組包含一個 16 位元寄存器,它可以用作 16 位捕捉寄存器、16 位比較寄存器或 PWM /從佔空比寄存器。輸出比較模組用 OCx 代表,輸出通道由 OC1Pin 58)、OC2Pin 61)、OC3Pin 62)、OC4Pin 63)和 OC5Pin 66)組成。

Microchip PIC24FJ64GA008 5個 比較 / PWM 輸出模組
PIC24FJ64GA008 輸出比較模組能將所選時基值與一個或兩個比較寄存器的值(取決於所選的工作模式)作比較。此外,它在比較匹配事件發生時能產生單個輸出脈衝或一連串輸出脈衝。如同大多數 PIC 外設一樣,它在比較匹配事件發生時還能產生中斷。所有輸出比較通道在功能上都是相同的。引腳、寄存器或位名稱中的 “x” 表示特定的輸出比較通道。每個輸出比較通道可以使用兩個可選時基之一。使用 OCTSEL 位(OCxCON<3>)來選擇時基。各個編號的輸出比較通道一起使用的特定計時器,可用時基 Timer2 Timer3 不支援非同步模式。因此,輸出比較模組只能在同步模式下工作。

Microchip PIC24FJ64GA008 輸出比較模組原理圖
工作模式,每個輸出比較模組均有以下工作模式:
• 單比較匹配模式
• 雙比較匹配模式產生:單輸出脈衝模式、連續輸出脈衝模式
• 簡單脈寬調製(Pulse-Width Modulation PWM)模式:帶有故障保護輸入、不帶故障保護輸入

輸出比較寄存器,每個輸出比較通道均有以下寄存器:
OCxCON:輸出比較通道的控制寄存器
OCxR:輸出比較通道的資料寄存器
OCxRS:輸出比較通道的輔助資料寄存器

Microchip PIC24FJ64GA008 OCxCON 輸出比較寄存器
5 個輸出比較通道的控制寄存器被命名為 OC1CON OC5CON。所有 5 個控制寄存器具有相同的位定義,表示為以下公共寄存器定義。OCxCON 中的 “x” 表示輸出比較通道的編號。

PIC24FJ64GA008 OCxCON:輸出比較 x 控制寄存器:
bit
Description
bit 15 ~ 14
未實現:讀為 0
bit 13
OCSIDL:在空閒模式下停止輸出比較 x 控制位
1 = 輸出比較x 將在 CPU 空閒模式下停止
0 = 輸出比較x 將在 CPU 空閒模式下繼續工作
bit 12 ~ 5
OCSIDL:在空閒模式下停止輸出比較 x 控制位
1 = 輸出比較x 將在 CPU 空閒模式下停止
0 = 輸出比較x 將在 CPU 空閒模式下繼續工作
bit 4
OCFLTPWM 故障條件狀態位元
1 = 發生了 PWM 故障條件(僅可用硬體清零)
0 = 未發生 PWM 故障條件(僅當 OCM<2:0> = 111 時,才使用該位)
bit 3
OCTSEL:輸出比較 x 計時器選擇位(1)
1 = Timer3 是輸出比較 x 的時鐘源
0 = Timer2 是輸出比較 x 的時鐘源
bit 2 ~ 0
OCM<2:0>:輸出比較 x 模式選擇位元
111 = OCx 處於 PWM 模式,故障引腳使能
110 = OCx 處於 PWM 模式,故障引腳禁止
101 = 初始化 OCx 引腳為低電平,在 OCx 引腳上產生連續輸出脈衝
100 = 初始化 OCx 引腳為低電平,在 OCx 引腳上產生單個輸出脈衝
011 = 比較事件使 OCx 引腳的電平交替翻轉
010 = 初始化 OCx 引腳為高電平,比較事件強制 OCx 引腳為低電平
001 = 初始化 OCx 引腳為低電平,比較事件強制 OCx 引腳為高電平
000 = 輸出比較通道禁止

Microchip PIC24FJ64GA008 輸出比較控制寄存器
2016年 8月 28日 天氣報告
氣溫:27.4@ 20:20
相對濕度:百分之 72%
天氣:多雲

2016年8月23日 星期二

DIY - PIC24:PIC24FJ64GA008 輸入捕捉程式(四十七):

DIY - PIC24PIC24FJ64GA008 輸入捕捉(Input Capture)程式(四十七): 

Microchip PIC24FJ64GA008 輸入捕捉(Input Capture)程式是捕捉 IC1 Pin 54IC1/RTCC/RD8)引腳上輸入信號的每個上升沿,通過 Timer3 時基值,當輸入信號是上升沿,便會捕捉時基計數值,然後等到下一個上升沿,再會捕捉第二個時基計數值,然後計算出時間值,顯示在 LCD1602 上。

PIC24FJ64GA008 輸入捕捉(Input Capture)程式顯示
邊沿檢測模式:
捕捉模組可以在 ICx 引腳上輸入信號的每個上升沿和下降沿捕捉一個時基計數值。通過將 ICM<2:0> ICxCON<2:0>)位設置為 001 可以選中邊沿檢測模式。在該模式下,沒有使用預分頻捕捉計數器。

邊沿檢測模式時序圖
當輸入捕捉模組被配置為邊沿檢測模式時,該模組將:
• 在每個邊沿(上升沿和下降沿)將輸入捕捉中斷標誌位元(ICxIF)置 1
• 在該模式下,沒有使用捕捉時中斷模式位元 ICI<1:0> ICxCON<6:5>)。每個捕捉事件都將產生中斷。

與簡單捕捉事件模式相同,輸入捕捉邏輯電路根據內部相位時鐘檢測和同步捕捉引腳信號的上升沿和下降沿。如果出現了上升或下降沿,則捕捉模組邏輯電路將當前計時器計數寫到捕捉緩衝區,然後向中斷產生邏輯電路發出信號。相應的輸入捕捉中斷標誌位元 ICxIF 在捕捉緩衝寫事件發生後的兩個指令週期後被置 1。捕捉計時器計數值為在 ICx 引腳上的邊沿發生後的 1 2 TCY(指令週期)的值。

Microchip PIC24FJ64GA008 Timer3 初始化程式:
#include                                   // timer.h
#include                                   // input capture.h

void timer3init (void)
{
           TMR3 = 0;
           T3CONbits.TON = 0;
           T3CONbits.TCS = 0;    // Set Timer freq = Fcy/2
           T3CONbits.TCKPS= 0;  // prescale 1:1
           T3CONbits.TGATE = 0;
           T3CONbits.TSIDL = 0;
           T3CONbits.TON = 1;    //Timer 3 Enable
}

Microchip PIC24FJ64GA008 Capture1 初始化程式:
void capinit1(void)
{
           IC1CONbits.ICM = 3; //capture edge every rising edge
           IC1CONbits.ICI = 1; //interrupt on every second capture
           IC1CONbits.ICTMR = 0; //used tmr3
           IC1CONbits.ICSIDL = 0; // Idel Time Running
}

Microchip PIC24FJ64GA008 IC1 中斷程式
// Capture IC1 Interrup
void __attribute__((interrupt, no_auto_psv)) _IC1Interrupt(void) {

IFS0bits.IC1IF = 0;
cap1 = IC1BUF;
cap2 = IC1BUF;
}

Microchip PIC24FJ64GA008 IC1 主程式
           IPC0bits.IC1IP = 1; //level 1 priority
           IFS0bits.IC1IF = 0; //clear  the IC1 interrupt status flag
           IEC0bits.IC1IE = 1;  // Enable IC1 interrupts
          
           TRISDbits.TRISD8=1; // Make RD8/ IC1 pin 54 as an input
           TRISDbits.TRISD9=1; // Make RD9/ IC2 pin 55 as an input
          
           timer3init();
           IC1CON = 0x0000;
           capinit1();

while(1){
}


PIC24FJ64GA008 輸入捕捉(Input Capture)程式試驗
2016年 8月 23日 天氣報告
氣溫:28.0@ 20:00
相對濕度:百分之 65%
天氣:天色大致良好

2016年8月22日 星期一

DIY - PIC24:PIC24FJ64GA008 輸入捕捉介紹(四十六)

DIY - PIC24PIC24FJ64GA008 輸入捕捉(Input Capture)介紹(四十六): 

Microchip PIC24FJ 系列器件具有 5 16 位捕捉輸入(Input Capture)模組,輸入捕捉模組用於在輸入引腳上有事件發生時,捕捉來自兩個可選時基之一的計時器值。輸入捕捉功能在需要進行頻率(時間週期)和脈衝測量的應用中相當有用。

PIC24FJ64GA008 輸入捕捉框圖
輸入捕捉模組有多種工作模式,可通過 ICxCON 寄存器選擇,這些工作模式包括:
• 在 ICx 引腳輸入電平的每個下降沿捕捉計時器值
• 在 ICx 引腳輸入電平的每個上升沿捕捉計時器值
• 在 ICx 引腳輸入電平的第 4 個上升沿捕捉計時器值
• 在 ICx 引腳輸入電平的第 16 個上升沿捕捉計時器值
• 在 ICx 引腳輸入電平的每個上升沿和下降沿捕捉計時器值
CPU 休眠和空閒模式期間器件被捕捉引腳信號喚醒 
輸入捕捉模組有 4 FIFO 緩衝器。用戶可以選擇產生 CPU 中斷所需的捕捉事件數。

PIC24 系列器件上的每個捕捉通道都有以下寄存器,寄存器名稱中的 “x” 代表捕捉通道的編號:
ICxCON:輸入捕捉控制寄存器
ICxBUF:輸入捕捉緩衝寄存器

PIC24FJ64GA008 ICxCON:輸入捕捉 x 控制寄存器
PIC24FJ64GA008 ICxCON:輸入捕捉 x 控制寄存器:
bit
Description
bit 15 ~ 14
未實現:讀為0
bit 13
ICSIDL:輸入捕捉 x 在空閒時停止控制位
1 = 輸入捕捉在 CPU 空閒模式將停止
0 = 輸入捕捉在 CPU 空閒模式將繼續工作
bit 12 ~ 8
未實現:讀為 0
bit 7
ICTMR:輸入捕捉 x 計時器選擇位(1)
1 = 發生捕捉事件時捕捉 TMR2 的內容
0 = 發生捕捉事件時捕捉 TMR3 的內容
bit 6 ~ 5
ICI<1:0>:每次中斷的捕捉次數選擇位
11 = 4 次捕捉事件中斷一次
10 = 3 次捕捉事件中斷一次
01 = 2 次捕捉事件中斷一次
00 = 1 次捕捉事件中斷一次
bit 4
ICOV:輸入捕捉x 溢出狀態標誌位元(唯讀)
1 = 發生了輸入捕捉溢出
0 = 未發生輸入捕捉溢出
bit 3
ICBNE:輸入捕捉 x 緩衝器空狀態位元(唯讀)
1 = 輸入捕捉緩衝器非空,至少可以再讀一次捕捉值
0 = 輸入捕捉緩衝器為空
bit 2 ~ 0
ICM<2:0>:輸入捕捉 x 模式選擇位元
111 = 當器件處於休眠或空閒模式時,輸入捕捉僅用作中斷引腳功能(只檢測上升沿,所有其他控制位都不適用)
110 = 未使用(模組被禁止)
101 = 捕捉模式,每 16 個上升沿捕捉一次
100 = 捕捉模式,每 4 個上升沿捕捉一次
011 = 捕捉模式,每個上升沿捕捉一次
010 = 捕捉模式,每個下降沿捕捉一次
001 = 捕捉模式,每個邊沿(上升沿和下降沿)捕捉一次(ICI<1:0> 位元不控制該模式下的中斷產生)
000 = 輸入捕捉模組關閉

初始化:
當輸入捕捉模組被重定或處於 “關閉” 模式(ICM<2:0> = 000)時,輸入捕捉邏輯應:
• 將溢出條件標誌重定為邏輯 0
• 將接收捕捉 FIFO 重定為空狀態
• 復位預分頻計數 

計時器選擇:
每個 PIC24 系列器件都可能有一路或多路輸入捕捉通道。每路通道都可以選擇兩個 16 位計時器之一作為時基。可以通過 ICTMR 控制位(ICxCON<7>)實現計時器源的選擇。計時器可以被設置為使用內部時鐘源(FOSC/4)或使用在 TxCK 引腳上外接的同步外部時鐘源。

輸入捕捉事件模式:
ICx 引腳上有事件發生時,輸入捕捉模組捕捉所選的時基寄存器的 16 位值。可以被捕捉的事件分為以下 3 類: 
1)簡單捕捉事件模式
• 在 ICx 引腳輸入電平的每個下降沿捕捉計時器值
• 在 ICx 引腳輸入電平的每個上升沿捕捉計時器值 
2)在每個邊沿(上升沿和下降沿)捕捉計時器值
3)預分頻捕捉事件模式
• 在 ICx 引腳輸入電平的每 4 個上升沿捕捉計時器值
• 在 ICx 引腳輸入電平的每 16 個上升沿捕捉計時器值通過設置相應的輸入捕捉模式位元 ICM<2:0> ICxCON<2:0>)可以配置上述輸入捕捉模式。

PIC24FJ64GA008 輸入捕捉寄存器映射
2016年 8月 22日 天氣報告
氣溫:26.5@ 22:20
相對濕度:百分之 86%
天氣:天色大致良好

2016年8月19日 星期五

DIY - PIC24:PIC24FJ64GA008 Timer2 軟件時鐘程式(四十五)

DIY - PIC24PIC24FJ64GA008 Timer2 軟件時鐘程式(四十五): 

筆者利用 Microchip PIC24FJ64GA008 Timer2 B類型計時器是 16-bit Timer0 ~ 65535)製作軟件時鐘(Software Time Clock),軟件時鐘是會使用到中斷服務。軟件時鐘都是基於系統時鐘作基準,在計時器模式下,首先使用 PR2 寄存器設定的預設時間,預分頻器設置,然後啓動計時器,計時器的數值在每個指令週期都會遞增,當計時器的數值遞增至 PR2 寄存器預設數值,便會觸發中斷服務程式,中斷服務程式便會作時分秒處理,處理完成中斷服務程式,計時器便會重置,數值從新開始遞增。

PIC24FJ64GA008 Timer2 軟件時鐘顯示
PIC24FJ64GA008 Timer2 軟件時鐘比較
Timer2 配置: 
1TON 位置 1 = 1)。 
2 使用 TCKPS1:TCKPS0 位選擇計時器的預分頻比。 
3 使用 TCS TGATE 位元選擇時鐘和門控模式。 
4 TSYNC 位置 1 或清零分別配置為同步或非同步操作。 
5 將計時器的週期值裝載到 PR2 寄存器。 
6 如果需要中斷,將中斷允許位 T2IE 1。使用優先級 T2IP2:T2IP0 位設置中斷優先順序。

Microchip PIC24FJ64GA008 Timer2 初始化程式:
#include                    // timer.h
// Initialise Timer2  
timer2_isr();                                            // Interrupt Service Timer2
InitTimer2();                                           // Init Timer2

Microchip PIC24FJ64GA008 Timer2 中斷程式
// Timer2 Interrupt
void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void) {
           if(IFS0bits.T2IF == 1){ // Check the timer2 interrupt flag
                     timer2_isr();    // Jump to the timer2 interrupt funtio
IFS0bits.T2IF = 0;
}

Microchip PIC24FJ64GA008 Timer2 中斷服務程式
void timer2_isr(void){
           static int counter = 0; // A static variable is only initialized once and stays alive after the function ends.
                                             // It is like a global variable that exists only in this function.
           counter++;
           if(counter == 100){
                     counter = 0;
                     seconds++;
                     if(seconds == 60){
                                seconds = 0;
                                minutes++;
                     }
                     if(minutes == 60){
                                minutes = 0;
                                hours++;
                     }
                     if(hours == 24){
                                hours = 0;
                     }
           }
           IFS0bits.T2IF = 0; // Clear the interrupt flag.
                                                                 // If you forget this line, an interrupt wil occur again immediately
                                                                 // and your program will be stuck in the interrupt routine.
}        

PIC24FJ64GA008 Timer2 軟件時鐘程式執行
2016年 8月 19日 天氣報告
氣溫:26.8@ 20:50
相對濕度:百分之 94%
天氣:微雨