PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Cơ bản về vi điều khiển và PIC (http://www.picvietnam.com/forum/forumdisplay.php?f=8)
-   -   Giúp tạo xung 38kHz bằng Timer (http://www.picvietnam.com/forum/showthread.php?t=4015)

nhanh0112 27-04-2009 01:46 AM

Giúp tạo xung 38kHz bằng Timer
 
Tui mới học viết Pic nên còn lơ mơ quá:
Chẳng là tui muốn làm một chiếc remote control. Nhưng khi tạo xung bằng Timer0 hay timer2 đều gặp phải vấn đề là tần số tối đa chỉ đc khoảng 14kHz (tức là on=70us, off=70us), giảm tiếp thì ko xuống đc (đã kiểm tra bằng osc scope). Bác nào có kinh nghiệm vụ này xin chỉ dẫn giùm. Thanks các bác nhiều :(
Code:

// defind crystal = 4MHz
#int_timer2
void timer2()
{
  output_toggle(PIN_A1);
}
void main()
{
  setup_timer_2(T2_DIV_BY_1,25,1);//setup_TIMER_2(mode, period, postscale);
  setup_ccp1(CCP_PWM);
  set_pwm1_duty(52); //50%duty, 38462Hz
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_TIMER2);
while(true)


namqn 27-04-2009 02:13 AM

Trích:

Nguyên văn bởi nhanh0112 (Post 25274)
Tui mới học viết Pic nên còn lơ mơ quá:
Chẳng là tui muốn làm một chiếc remote control. Nhưng khi tạo xung bằng Timer0 hay timer2 đều gặp phải vấn đề là tần số tối đa chỉ đc khoảng 14kHz (tức là on=70us, off=70us), giảm tiếp thì ko xuống đc (đã kiểm tra bằng osc scope). Bác nào có kinh nghiệm vụ này xin chỉ dẫn giùm. Thanks các bác nhiều :(
Code:

// defind crystal = 4MHz
#int_timer2
void timer2()
{
  output_toggle(PIN_A1);
}
void main()
{
  setup_timer_2(T2_DIV_BY_1,25,1);//setup_TIMER_2(mode, period, postscale);
  setup_ccp1(CCP_PWM);
  set_pwm1_duty(52); //50%duty, 38462Hz
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_TIMER2);
while(true)


Bạn chưa cho biết bạn đang dùng PIC nào.

Thân,

vietanh 27-04-2009 03:04 AM

Code:

#int_timer2
void timer2()
{
  output_toggle(PIN_A1);
}

BO CAI NAY DI KHONG CAN THIET
CHI CAN

Code:

VOID MAIN(){
  setup_timer_2(T2_DIV_BY_1,25,1);
  setup_ccp1(CCP_PWM);
  set_pwm1_duty(12);    // F== 38KHZ  T=26 us
}

xin loi dang o nha thang ban khong co unikey danh nkhong dau dd khong go duoc po tay

namqn 27-04-2009 04:05 AM

Trích:

Nguyên văn bởi vietanh (Post 25277)
...
xin loi dang o nha thang ban khong co unikey danh nkhong dau dd khong go duoc po tay

Bạn không cần dùng bất kỳ phần mềm gì để gõ tiếng Việt trên diễn đàn, vì bộ gõ của diễn đàn là một script, được đa số các trình duyệt hỗ trợ.

Thân,

nhanh0112 27-04-2009 10:56 AM

@namqn:dạ, là 12F683 ạ.
@vietanh:Em sẽ thử lại. Nhưng nếu bỏ đoạn #int_ đi thì xung ra sẽ kích vào chân nào?

namqn 27-04-2009 04:31 PM

Trích:

Nguyên văn bởi nhanh0112 (Post 25287)
@namqn:dạ, là 12F683 ạ.
@vietanh:Em sẽ thử lại. Nhưng nếu bỏ đoạn #int_ đi thì xung ra sẽ kích vào chân nào?

Vẫn còn thiếu thông tin cấu hình bộ dao động của PIC, do đó giả sử bạn dùng HFINTOSC ở tần số mặc định 4 MHz, hoặc dùng thạch anh ngoài có tần số 4 MHz.

Nếu bạn đo dạng sóng ở chân GP1 (PIC12F683 không có chân RA1) thì tần số chắc chắn không đạt 38 kHz với thiết lập phần cứng trong chương trình của bạn, vì còn overhead khi xử lý ngắt Timer 2. Tuy nhiên, nếu bạn đo dạng sóng ở chân CCP1 thì nó sẽ đúng như phần chú thích trong code, tần số khoảng 38 kHz với duty cycle bằng 50 %. Đây cũng là lý do bạn vietanh đề nghị bạn bỏ phần code xử lý ngắt Timer 2, vì không cần thiết cho bài toán của bạn.

Bạn cũng nên post code đầy đủ thông tin vào lần sau, đừng post code không đầu không đuôi như trên, vì người đọc sẽ phải đoán những thông tin mà bạn không đưa ra, hoặc phải hỏi lại bạn nhiều lần.

Thân,

nhanh0112 27-04-2009 06:36 PM

Đây là toàn bộ code (với mục đích đầu tiên là chỉ tạo xung 38kHz) đã đc sửa như chỉ dẫn. Ko biết còn thiếu xót gì ko, các bác chỉnh giùm em. Đo tại chân CCP1(chân 5) luôn là mức 1. Phần cứng đc sử dụng crystal = 4MHz lắp vào chân 2 & 3, chân 1 & 8 cấp nguồn, các chân còn lại bỏ trống.
Code:

#include <12F683.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)  // defind crystal = 4MHz

void main()
{
  setup_timer_2(T2_DIV_BY_1,25,1);//setup_TIMER_2(mode, period, postscale);
  setup_ccp1(CCP_PWM);
  set_pwm1_duty(52); //50%duty, 38462Hz
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_TIMER2);

while(TRUE);
}


namqn 28-04-2009 08:06 PM

Trích:

Nguyên văn bởi nhanh0112 (Post 25299)
Đây là toàn bộ code (với mục đích đầu tiên là chỉ tạo xung 38kHz) đã đc sửa như chỉ dẫn. Ko biết còn thiếu xót gì ko, các bác chỉnh giùm em. Đo tại chân CCP1(chân 5) luôn là mức 1. Phần cứng đc sử dụng crystal = 4MHz lắp vào chân 2 & 3, chân 1 & 8 cấp nguồn, các chân còn lại bỏ trống.
...

Tôi không dùng CCS C, và tôi cũng không thích dùng các hàm thư viện cho ngoại vi nếu không nắm được mã nguồn của chúng. Do đó, với yêu cầu tạo xung 38 kHz tại chân CCP1 của PIC12F683, từ clock 4 MHz, tôi thường viết code như sau (tôi dùng HTPIC C PRO for PIC10/PIC2/PIC16 ở Lite mode, theo link sau: http://www.microchip.com/stellent/id...cName=en535448):
Code:

#include <htc.h>
#include <pic12f683.h>

__CONFIG(FCMDIS & IESODIS & BOREN & UNPROTECT & MCLREN & PWRTEN & WDTDIS & INTIO);

void Init_CCP1(void)
{
        //Assuming 4 MHz system clock (from the internal oscillator)
        PR2 = 25;        //for 38.46 kHz PWM output at CCP1 pin
        T2CON = 0x00;        //with 1:1 prescaler, 1:1 postscaler
        TMR2IF = 0;
        CCP1CON = 0x0C;        //PWM mode, active high
        CCPR1L = 13;        //50% duty cycle (2 LSBs are '00' in CCP1CON)
        TMR2ON = 1;        //Turn on Timer 2
}

void main(void)
{
        GPIO = 0x00;
        CMCON0 = 0x07;                //Turn off comparator, GP0 .. GP2 are I/O pins
        ANSEL &= 0xF0;                //GP0 .. GP2 and GP4 are digital pins
        TRISIO = 0xFA;                //GP0 and GP2 are outputs
        Init_CCP1();
        while (1)
        {
                if (TMR2IF == 1)
                {
                        GPIO0 = GPIO0 ^ 1;;        //Toggle every Timer 2 cycle
                        TMR2IF = 0;                //Clear Timer 2 IF for next cycle
                }
        };
}

Chú ý: Tôi dùng bộ dao động nội của PIC12F683 (vì không muốn hàn thêm thạch anh vào mạch ứng dụng). Tần số tại chân GP0 sẽ bằng một nửa tần số tại chân GP2/CCP1. Code đã được thử nghiệm trên mạch thực.

Thân,

vietanh 28-04-2009 08:15 PM

Nói chung là bạn chua nắm được cơ bạn, lt pic bằng ccs . trước khi bạn muốn làm việc ,với 1 chân hay cả 1 cổng port nào đó bạn phải định nghĩa cho nó là cổng xuất hay nhập, chân đó nằm ở mức cao hay thấp.
vd set_tris_c(0x00); xuat dl
output_c(0x00); tất cả port c nằm mức thấp

nhanh0112 28-04-2009 10:37 PM

Cảm ơn các bác đã nhiệt tình giúp đỡ. Đúng là em chưa đc cơ bản lắm trong việc làm pic. Mới nhảy từ AT89 lên... chắc phải đọc thêm sách rồi. Em sẽ chú ý lời khuyên của các bác. Một lần nữa xin cảm ơn!

nhanh0112 29-04-2009 01:26 AM

Em đã tạo đc rồi các bác à! em đã tham khảo ở đây http://cblog.cari.com.my/html/32/53232-112634.html và sửa thành
set_pwm1_duty(15);
thì chạy ngon lành. Không hiểu ra làm sao nữa.

namqn 29-04-2009 01:55 AM

Trích:

Nguyên văn bởi nhanh0112 (Post 25348)
Em đã tạo đc rồi các bác à! em đã tham khảo ở đây http://cblog.cari.com.my/html/32/53232-112634.html và sửa thành
set_pwm1_duty(15);
thì chạy ngon lành. Không hiểu ra làm sao nữa.

Nếu bạn đọc tài liệu hướng dẫn của CCS C thì có thể thấy họ nói rằng các giá trị duty cycle nằm gọn trong 8-bit (giá trị 52 của bạn thỏa mãn điều này) thì nó sẽ được dịch trái 2 bit để ghi vào các thanh ghi tương ứng. Do đó, code ban đầu của bạn sẽ có giá trị 52 được đặt vào CCPR1L, dẫn đến chân CCP1 luôn luôn có giá trị '1' (vì CCPR1L > (PR2 + 1)).

Code vừa sửa của bạn sẽ tạo duty cycle = 50% nếu bạn dùng set_pwm1_duty(13).

Thân,

the_duyet 07-06-2009 02:33 AM

prescale
 
Sử dụng chức năng search trên 4r hay thật,lơ ngơ tìm đúng bài mình đang cần.hoho.Cảm ơn.Mỗi tội chưa biết cách tính timer0,1. Có ai có công thức tính timer ko,cho mình xin với. Mà cái gọi là bộ đếm gộp trước(prescaler) là gì vậy,mình vẫn chưa hiểu. Ý nghĩa và tác dụng của nó.

blackcatx87 07-06-2009 11:01 PM

cho em hỏi tí
 
Em dùng pic 16f877a viết theo chương trình các anh hướng dẫn và đã tạo ra được sóng 38khz tại chân ccp1 . Nhưng điều em muốn hỏi là làm sao để điều kiển được chân ccp1 ( vì nó cứ phát xung liên tục không ngừng ) .
VD : trong mạch em thêm 1 cái nút nhấn , khi nhấn nút thì chân ccp1 mới phát ra xung trong khoảng 1s rùi tắt thì phải làm sao ? Em dùng ccs c , lệnh #setup_ccp1 (CCP_OFF) có tác dụng gì vậy các anh ?


Múi giờ GMT. Hiện tại là 08:14 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam