CHƯƠNG 7: CCP – ADC

Một phần của tài liệu Bài giảng lý thuyết vi xử lý kỹ thuật vi xử lý cd rom (Trang 98 - 120)

VI. VI XỬ LÝ VÀ VI ĐIỀU KHIỂN Về cấu trúc phần cứng:

CHƯƠNG 7: CCP – ADC

- Trình bày được cấu trúc và tập lệnh của VĐK PIC và các thanh ghi lien quan đến các Modul CCP của VĐK PIC

- Trình bày được nguyên lý hoạt động và điều khiển Modul CCP ở các chế độ cơ bản của VĐK PIC. - Xây dựng mô hình, phân tích và thiết kế, vẽ lưu đồ và lập trình ứng dụng được được Modul CCP cho các ứng dụng

7.1 CCP

7.1.1. Giới thiệu Modul CCP

+ Mỗi Module Bắt giữ/So sánh/PWM (CCP -Capture/Compare/PWM) chứa một thanh ghi 16 bit mà có thể hoạt động như:

 Thanh ghi bắt giữ 16 bit.  Thanh ghi so sánh 16 bit.

+ Cả hai Module CCP1 và CCP2 là giống nhau về hoạt động. Riêng Module PWM hoạt động dựa trên Timer2.

Chế độ CCP Nguồn timer

Bắt giữ Timer 1

So sánh Timer 1

Điều rộng xung (PWM) Timer 2

+ Module CCP1: Thanh ghi bắt giữ/So sánh/Điều rộng xung (PWM) thứ 1 (CCPR1) gồm hai thanh ghi 8 bit: CCPR1L (byte thấp) và CCP1RH (byte cao). Thanh ghi CCP1CON điều khiển hoạt động của CCP1. Trigger sự kiện đặc biệt có thể được cấu hình để tạo bởi bộ khớp so sánh và sẽ reset timer 1 và bắt đầu chuyển đổi A/D (nếu môđun A/D được cho phép).

+ Tương tự, Module CCP2: Thanh ghi bắt giữ/so sánh/PWM số 2 (CCPR2) gồm có 2 thanh ghi 8 bit: CCPR2L (byte thấp) và CCPR2H (byte cao). Thanh ghi CCP2CON điều khiển hoạt động của CCP2.

98 7.1.2. Khảo sát chế độ Capture

Chế độ bắt giữ (Capture) được dùng cho chức năng lặp thời gian hay xác định độ dài của xung PWM. Khi đo thời gian xung PWM, clock TMR1 phải đủ nhanh để lấy giá trị có ý nghĩa với độ phân giải đủ cao mà có sự thể hiện chính xác của định thời.

a. Tập các thanh ghi liên quan

CCPxM3:CCPxM0: CCPx Mode Select bits trong thanh ghi CCPxCON được sử dụng:  0100 = Capture mode, every falling edge

 0101 = Capture mode, every rising edge  0110 = Capture mode, every 4th rising edge  0111 = Capture mode, every 16th rising edge

Ngoài ra, Capture sử dụng Timer1 nên tất cả các thanh ghi lien quan đến Timer1 cũng dùng cho việc thực hiện chế độ Capture.

99 b. Hoạt động nguyên lý

+ Tín hiệu capture được đưa vào chân CCPx của vđk sau khi đã chuẩn hóa tín hiệu theo mức logic-0 và logic-1. Chú ý, chân CCPx của vđk phải được cấu hình là INPUT.

+ Tùy theo cấu hình CCPx Mode Select bits, tín hiệu capture được phát hiện sau khi qua bộ chia tỉ lệ và bộ phát hiện cạnh. Timer 1 được bật chạy để đếm số lượng xung hệ thống.

+ Sau khi capture, vđk thực hiện 2 tác vụ: bật cờ báo CCPxIF và lưu giá trị Timer1 vào thanh ghi 16bit của CCPx là CCPRxH:CCPRxL. Như vậy, người lập trình cần chú trọng đến giới hạn số xung đếm của Timer1. Trong trường hợp độ rộng xung cần capture quá dài, có thể kết hợp Timer1 với bộ chia tỉ lệ trước (prescale) hoặc kết hợp với thanh ghi lưu lại số lần Timer1 đếm tràn.

+ Người lập trình dựa vào cờ báo CCPxIF hoặc dựa vào ngắt do CCP để thực hiện các bước tiếp theo (ví dụ tính toán độ rộng xung …)

100 c. Khai báo và lập trình chức năng

Ví dụ 1:

Sử dụng nút bấm tạo xung tác động vào chân RC2 (CCP1). Vđk thực hiện chức năng Capture từ chân CCP1 và đánh dấu kết quả capture được ra PORTD thông qua Led.

#define _XTAL_FREQ 4000000 #include <htc.h>

__CONFIG(0x3FFA); void main(void) {

// Configure Capture mode for Timer 1

// 0100 [every falling edge] 0101 [every rising edge] // 0110 [every 4 rising edge] 0111 [every 16 rising edge]

CCP1M3 = 0 ; CCP1M2 = 1 ; CCP1M1 = 1 ; CCP1M0 = 0 ; // Clear the flag

CCP1IF = 0 ;

// Configure Capture pin as INPUT mode TRISC2 = 1 ;

TMR1H = 0; TMR1L = 0;

101 TMR1ON = 1;

// Configure PORTD to out led TRISD = 0x00; PORTD = 0x00; while(1) { while (!CCP1IF); CCP1IF = 0; PORTD = PORTD+1; TMR1H = 0; TMR1L = 0; } }

void interrupt isr(void) // CCP2 INT Subrouting {

}

7.1.3 Khảo sát chế độ Compare

+ Chế độ so sánh (Compare) được dùng cho chức năng lặp thời gian. Chế độ so sánh thay đổi trạng thái của chân CCPx của vi điều khiển PIC khi nội dung của TMR1 khớp giá trị trong các thanh ghi CCPRxH và CCPRxL. Chế độ này được dùng kích khởi hay điều khiển phần cứng bên ngoài sau một trì hoãn cụ thể. Hoặc là dùng để kích hoạt (trigger) một sự kiện đặc biệt bên trong vi điều khiển (Timer1 và ADC).

a. Tập các thanh ghi liên quan

CCPxM3:CCPxM0: CCPx Mode Select bits trong thanh ghi CCPxCON được sử dụng:

 1000 = compare mode, when a match occurs, the RC2/CCP1 pin is driven HIGH and CCPxIF =1.  1001 = compare mode, when a match occurs, the RC2/CCP1 pin is driven LOW and CCPxIF =1.  1010 = compare mode, when a match occurs, the RC2/CCP1 pin remains unchanged, and CCPxIF

=1, and generate software interrupt.

 1011 = compare mode, when a match occurs, the RC2/CCP1 pin remains unchanged, and CCPxIF =1 and ADC convers (if ADC was enable).

Ngoài ra, Compare sử dụng Timer1 nên tất cả các thanh ghi liên quan đến Timer1 cũng dùng cho việc thực hiện chế độ Capture.

102 b. Hoạt động nguyên lý

+ Giá trị cần so sánh với Timer1 được ghi vào thanh ghi 16 bit: CCPR1H:CCPR1L. Chú ý, chân CCPx của vđk phải được cấu hình là OUTPUT. Timer 1 được bật chạy để bắt đầu so sánh.

+ Tùy theo cấu hình CCPx Mode Select bits, sau khi compare bằng nhau, vđk có thể báo hiệu thông qua thay đổi chân CCPx hoặc thông qua các sự kiện đặc biệt. Trong tất cả trường hợp, cờ CCPxIF luôn được set.

+ Người lập trình dựa vào cờ báo CCPxIF hoặc dựa vào ngắt do CCP để thực hiện các bước tiếp theo (ví dụ: thực hiện ADC, kích hoạt thiết bị khác, …)

103 Ví dụ 2:

Dùng chức năng so sánh của CCP, tạo ra xung tuần hoàn có Ton=Toff=60 ms trên 1 chân VĐK. Biết rằng, vđk thực hiện chương trình ngắt (Interrupt) khi phát hiện compare bằng nhau. #define _XTAL_FREQ 4000000

#include <htc.h> __CONFIG(0x3FFA); void main(void) {

// Configure Compare mode for Timer 1

// 1000 [CCP pin default Low, match forces High] // 1001 [CCP pin default High, match forces Low]

CCP2M3 = 1 ; CCP2M2 = 0 ; CCP2M1 = 0 ; CCP2M0 = 1 ; // Clear the flag

CCP2IF = 0 ;

// Configure Compare pin as OUTPUT mode TRISC1 = 0 ;

// Configure Compare value with Timer 1 CCPR2H = 60000/256; CCPR2L = 60000%256; // CCP2 interrupt enable CCP2IE = 1; PEIE = 1; GIE = 1;

// Configure Timer 1 as internal timer T1CON = 0x00 ;

TMR1ON = 1;

// Configure PORTD to out led TRISD = 0x00;

PORTD = 0x00; }

void interrupt isr(void) // CCP2 INT Subrouting { CCP2IF = 0; PORTD = PORTD + 1; TMR1H = 0; TMR1L = 1; }

104 7.1.4. Khảo sát chế độ PWM

+ Chế độ PWM là chế độ chiều chế độ rộng xung (Pulse Width Modulator) sử dụng Timer2. Phương pháp điều xung là phương pháp điều chỉnh điện áp ra tải, hay nói cách khác, là phương pháp điều chế dựa trên sự thay đổi độ rộng của chuỗi xung vuông, dẫn đến sự thay đổi điện áp ra. Các PWM khi biến đổi thì có cùng 1 tần số và khác nhau về độ rộng của sườn dương hay sườn âm.

+ PWM được ứng dụng nhiều trong điều khiển. Điển hình nhất mà chúng ta thường hay gặp là điều khiển động cơ và các bộ xung áp, điều áp... Sử dụng PWM điều khiển độ nhanh chậm của động cơ hay cao hơn nữa, nó còn được dùng để điều khiển sự ổn định tốc độ động cơ. + Ngoài lĩnh vực điều khiển hay ổn định tải thì PWM còn tham gia và điều chế các mạch nguồn như: boot, buck, nghịch lưu 1 pha và 3 pha... + PWM còn gặp nhiều trong thực tế ở các mạch điện điều khiển. Điều đặc biệt là PWM chuyên dùng để điều khiển các phần tử điện tử công suất có đường đặc tính là tuyến tính khi có sẵn 1 nguồn 1 chiều cố định. Như vậy PWM được ứng dụng rất nhiều trong các thiết bị điện- điện tử.

105 + CCPxM3: CCPxM0 = 11xx : dùng cho chế độ PWM. + Dạng sóng PWM ngõ ra chân CCPx:

+Chu kỳ PWM (Period): được xác định bởi độ lớn của Timer2 kết hợp với 2 bit prescale. PWM_Period = (PR2+1)*4*Tosc*Timer2_prescale_value

Thông thường, với Thạch anh 4 Mhz, ta có: PWM_period = (PR2+1)* Timer2_prescale_value (uS) + Chu kỳ nhiệm vụ (Duty Cycle) : là chu kỳ Ton của PWM, được xác định bởi 10 bit, trong đó 8bit trọng số cao là thanh ghi CCPR1L, 2bit trọng số thấp còn lại là CCP1CON<5:4>.

PWM_Duty_Cycle = (CCPR1L:CCP1CON<5:4>)*Tosc* Timer2_prescale_value Thông thường, với Thạch anh 4 Mhz, ta có:

106

PWM_Duty_Cycle = (CCPR1L:CCP1CON<5:4>)* Timer2_prescale_value/4 (uS) + Phần trăm chu kỳ nhiệm vụ: D = (Ton_của_PWM / PWM_Period)*100%

+ Độ phân giải (Resolution): là số lượng bit có thể dùng cho việc tạo ra tín hiệu PWM

b. Hoạt động nguyên lý

 Cài đặt PWM_Period bằng cách ghi giá trị tương ứng vào thanh ghi PR2

 Cài đặt PWM_Duty_Period bằng cách ghi giá trị tương ứng vào thanh ghi CCPR1L và 2 bit CCP1CON<5:4> (còn có tên gọi là <CCP1X: CCP1Y>)

 Cài đặt chân CCP1 là OUTPUT thông qua bit TRISC<2>.

 Cài đặt giá trị cho TMR2-Prescale và cho phép TMR2 đếm (TMR2ON)  Cài đặt chế độ PWM cho module CCP.

c. Khai báo và lập trình chức năng

Ví dụ 3:

Hãy tạo xung PWM trên ngõ ra CCP2, biết rằng PWM có tần số xung 5000 Hz và chu kỳ nhiệm vụ là 5% chu kỳ xung. #define _XTAL_FREQ 4000000 #include <htc.h> __CONFIG(0x3FFA); void main(void) {

//Define PWM_period and PWM_duty unsigned int PWM_freq = 5000 ;

unsigned int PWM_period = 1000000/PWM_freq ; unsigned char PWM_duty = 5 ;

unsigned int PWM_ON = (PWM_period*PWM_duty)/100 ; // Configure the CCPxCON for PWM operation

CCP2M3 = 1 ; CCP2M2 = 1 ; CCP2M1 = 1 ; CCP2M0 = 1 ; // Establish the PWM period by writing to the PR2 register // PWM period = [(PR2) + 1] • 4 • TOSC • (TMR2 prescale value)

// PWM period = [(PR2) + 1] • (TMR2 prescale value) us with 4Mhz crystal // Choose TMR2 prescale value=1:1, we have:

PR2 = (char)(PWM_period)-1 ;

107

// PWM_ON = (DCxB9:DCxB0 bits value) • Tosc • (TMR2 prescale value) // because (Tosc =1/4) and (TMR2 prescale value =1),

// PWM_ON = (DCxB9:DCxB0 bits value)/4 // CCPRxL = DCxB9:DCxB2 >> 2 = PWM_ON

// and DCxB1:DCxB0 = CCPxCON<5:4> = <CCP1X: CCP1Y> = PWM_ON % 4 ; CCPR2L=(char)PWM_ON ;

unsigned char CCPR2L_remain = (char) PWM_ON%4; switch (CCPR2L_remain)

{

case (0b00): {

CCP2X=0; // bit CCPxCON<5> CCP2Y=0; // bit CCPxCON<4> break; } case (0b01): { CCP2X=0; CCP2Y=1; break; } case (0b10): { CCP2X=1; CCP2Y=0; break; } case (0b11): { CCP2X=1; CCP2Y=1; break; } }

// Make the CCPx pin an output by clearing the appropriate TRIS bit TRISC1=0;

// Establish the TMR2 prescale value and enable Timer2 by writing to T2CON. T2CKPS1 =0 ;

T2CKPS0 =0 ; // pre-csale 1:1

TMR2ON = 1; // start Timer2 (means PWM) while(1)

{ } }

108 Ví dụ 4:

Hãy tạo xung PWM trên ngõ ra CCP2, biết rằng PWM có tần số xung 5000 Hz và chu kỳ nhiệm vụ là xx% chu kỳ xung. Với giá trị xx thay đổi được bằng 2 nút ấn trong khoãng 1% đến 99%. #define _XTAL_FREQ 4000000

#include <htc.h> __CONFIG(0x3FFA);

unsigned char read_PORTB(void); void main(void)

{

// Define PWM_period and PWM_duty unsigned int PWM_freq = 5000 ;

unsigned int PWM_period = 1000000/PWM_freq ; unsigned char PWM_duty = 5 ;

unsigned int PWM_ON = (PWM_period*PWM_duty)/100 ; // Configure the CCPxCON for PWM operation

CCP2M3 = 1 ; CCP2M2 = 1 ; CCP2M1 = 1 ; CCP2M0 = 1 ; // Establish the PWM period by writing to the PR2 register // PWM period = [(PR2) + 1] • 4 • TOSC • (TMR2 prescale value)

// PWM period = [(PR2) + 1] • (TMR2 prescale value) us with 4Mhz crystal PR2 = (char)(PWM_period)-1 ;

label_setupPWM:

// Establish the PWM_ON by writing to the DCxB9:DCxB0 bits

// PWM_ON = (DCxB9:DCxB0 bits value) • Tosc • (TMR2 prescale value) // because (Tosc =1/4) and (TMR2 prescale value =1),

// PWM_ON = (DCxB9:DCxB0 bits value)/4 // CCPRxL = DCxB9:DCxB2 >> 2 = PWM_ON

// and DCxB1:DCxB0 = CCPxCON<5:4> = <CCP1X: CCP1Y> = PWM_ON % 4 ; CCPR2L=(char)PWM_ON ;

unsigned char CCPR2L_remain = (char) PWM_ON%4; switch (CCPR2L_remain)

{

case (0b00): {

CCP2X=0; // bit CCPxCON<5> CCP2Y=0; // bit CCPxCON<4> break;

} case (0b01):

{CCP2X=0; CCP2Y=1; break;} case (0b10):

109

{CCP2X=1; CCP2Y=0; break;} case (0b11):

{CCP2X=1; CCP2Y=1; break;} }

// Make the CCPx pin an output by clearing the appropriate TRIS bit TRISC1=0;

// Establish the TMR2 prescale value and enable Timer2 by writing to T2CON. T2CKPS1 =0 ;

T2CKPS0 =0 ; // TMR2 pre-scale 1:1

TMR2ON = 1; // start Timer2 (means PWM) while(1)

{

unsigned char key =read_PORTB(); if (key ==8) { PWM_duty ++; if (PWM_duty >=99) PWM_duty=99; PWM_ON = (PWM_period*PWM_duty)/100 ; goto label_setupPWM; } else if (key ==7) { PWM_duty --; if (PWM_duty <= 1) PWM_duty=1; PWM_ON = (PWM_period*PWM_duty)/100 ; goto label_setupPWM; } } }

unsigned char read_PORTB(void) {

TRISB=0xFF; TRISD=0x00;

unsigned char key = PORTB & 0B11000000; if (key != 0B11000000)

{

__delay_ms(50);

110 if (key != 0B11000000) { switch (key) { case 0B10000000:

{PORTD = 7; return 7; break; } case 0B01000000:

{PORTD = 8; return 8; break; } default: {return 0; break; } } } else return 0; } return 0; } 7.2 ADC

7.2.1. Khảo sát chuyển đổi ADC

+ Để thực hiện đo lường analog thì ta phải cấu hình PIC16F877A thay đổi để làm cho 8 ngõ I/O số trở thành Analog INPUT từ PORT A và PORT E, để hiển thị giá trị trên led hoặc LCD ta cần cấu hình 1 PORT B hoặc PORTD là OUTPUT.

+ Độ phân giải lớn nhất của bộ ADC là 10bit. Giả sử rằng ta sử dụng Vref+ Vref- là 5V thì độ phân giải của ADC là: 4,88 mV.

7.2.2.Tập các thanh ghi liên quan

+ Để cấu hình 16F877A cho đo lường A/D, 3 thanh ghi cần được thiết lập:  ADCON0.

 ADCON1.

 ADRESH và ADRESL

+ Thanh ghi điều khiển A/D: ADCON0, địa chỉ 1FH, ADCON0 có các chức năng sau:

 Bật lên chuyển đổi A/D với ADCON0, bit 0 (ADON). Bit này bật chuyển đổi A/D khi nó được bật lên 1 và tắt A/D khi nó bị xóa về 0. Khi A/D được bật, nó có thể được để ON (bật) suốt thời gian nhưng nó lái dòng 90μA, so sánh với phần còn lại của vi điều khiển mà lái dòng 15μA.

 Ra lệnh vi điều khiển thực thi chuyển đổi bằng cách bật bit GO/DONE, bit 2. Khi bit GO/DONE=’1’ thì vi điều khiển thực hiện chuyển đổi A/D. Khi chuyển đổi hoàn thành, phần

111

cứng xóa bit GO/DONE. Bit này có thể được đọc dùng để chỉ thị kết quả chuyển đổi đã sẵn sàng để vđk lấy giá trị.

 Thiết lập kênh cụ thể (ngõ vào) để thực hiện đo lường. Điều này được thực hiện với 3 bit chọn kênh CHS0, CHS1 và CHS2, bit 3,4, và 5.

 Bit 7 và 6, ADCS1 và ADCS0: 2 bit này được kết hợp thêm với bit ADCS2 trong thanh ghi ADCON1 dùng cho việc chọn tốc độ clock chuyển đổi A/D.

+ Thanh ghi điều khiển A/D 1: ADCON1, địa chỉ 9FH. Trong ADCON1 có các chức năng sau:

 Các bit 0,1,2, và 3 được dùng cấu hình port. <PCFG0, PCFG1, PCFG2 và PCFG3> xác định chân nào của port A sẽ là ngõ vào analog và chân nào là I/O.

112

 Bit 7, ADFM : bit chọn khuôn dạng kết quả A/D. ADFM =1 kết quả chỉnh phải, 6 bit trong số cao nhất của ADRESH là đọc là ‘0’. ADFM =0 kết quả chỉnh trái, 6 bit trọng số thấp nhất của ADRESH là đọc là ‘0’.

113

+ ADRES, thanh ghi kết quả A/D. Đây là các ô nhớ mà kết quả chuyển đổi A/D được lưu trữ. Nếu nhiều đo lường yêu cầu lưu trữ thì số trong ADRES cần được chuyển tới ô nhớ người dùng trước khi nó bị đè bởi đo lường kế tiếp. PIC 16F877A có A/D 10 bit, với 8 bit cao được lưu trong ADRESH và 2 bit thấp hơn được lưu trong ADRESL. Chú ý, bit 7, ADFM trong thanh ghi ADCON1 cấu hình định dạng kết quả định trái hoặc định phải.

114 7.2.3 Khai báo và lập trình chức năng

(1) Lựa chọn xung Clock cho quá trình A/D thông qua ADCS2:ADCS1:ADCS0

(2) Cấu hình chân Analog ngõ vào: chọn chân analog INPUT và sử dụng Vref+, Vref- bên trong hay bên ngoài vđk thông qua PCFG3:PCFG0

(3) Set bit GO\DONE để kích hoạt quá trình chuyển đổi A/D (4) Đợi 1 khoãng thời gian để quá trình chuyển đổi hoàn thành (5) Đọc kết quả chuyển đổi

115 7.3 Ứng dụng của ADC

Ví dụ 5:

Giả thiết có 2 nguồn tín hiệu analog (sóng SIN) đưa vào 2 chân AN1 và AN2. Hãy dùng module ADC chuyển đổi và hiển thị giá trị mV lên LCD.

#define _XTAL_FREQ 4000000 #define uchar unsigned char #define uint unsigned int

116 #define ulong unsigned long

#define dport PORTB #define dport_in TRISB=0xFF #define dport_out TRISB=0x00 #define rs RB0

#define rw RB1 #define en RB2

void lcd1602_write_dat(uchar lcd_dat); void lcd1602_write_string(const uchar *cy); void lcd1602_write_com(uchar lcd_com); void adc_init(void);

void adc_channel(uchar channel); uint adc_converter(void); void decimal_bcd_16bit(uint cnt); uchar num_to_char[10]="0123456789"; uchar disbuf[4]; uint count=0; #include <htc.h> __CONFIG(0x3FFA); //*************** main ********************

Một phần của tài liệu Bài giảng lý thuyết vi xử lý kỹ thuật vi xử lý cd rom (Trang 98 - 120)

Tải bản đầy đủ (PDF)

(156 trang)