View Full Version : Giúp tạo xung 38kHz bằng Timer
nhanh0112
27-04-2009, 01:46 AM
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 :(
// 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
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 :(
// 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
#int_timer2
void timer2()
{
output_toggle(PIN_A1);
}
BO CAI NAY DI KHONG CAN THIET
CHI CAN
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
...
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
@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.
#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
Đâ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/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en535448):
#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
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
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
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 ?
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.