Merhaba arkadaslar
PIC16f877 ile 16 bit veya 24 bit frekansmetre yapmak istiyorum. CCS ile programlıcam, frekansmetre yaparken CCP modlarından hangisini(capture/PWM) kullanmam gerekir? Algoritmayı nasıl yapmam gerekir?
bir zamanlar bir yerden bulmuştum,ama yazanı bilmiyorum. umarım işine yarar...
#include "16F876.h"
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#use delay (clock=4000000)
#include "flcd.c"
//------------------------------------------------------------------------------
int durum=0;
int16 value_timer1=0x3CAF;
int sayac_tmr1=0;
int sayac0=0;
int sayac1=0;
int sayac2=0;
int sayac3=0;
int sayac4=0;
char sayac0_lcd;
char sayac1_lcd;
char sayac2_lcd;
char sayac3_lcd;
char sayac4_lcd;
//------------------------------------------------------------------------------
int kesme_tmr1(void);
int kesme_ext(void);
int duzenle(int);
//------------------------------------------------------------------------------
// 1 sn lik timer1 kesmesi
//------------------------------------------------------------------------------
#INT_TIMER1
int kesme_tmr1()
{
sayac_tmr1++;
if(sayac_tmr1==20)
{
sayac_tmr1=0;
lcd_gotoxy(9,1);
sayac0_lcd=duzenle(sayac0);
sayac1_lcd=duzenle(sayac1);
sayac2_lcd=duzenle(sayac2);
sayac3_lcd=duzenle(sayac3);
sayac4_lcd=duzenle(sayac4);
lcd_putc(sayac4_lcd);
lcd_putc(sayac3_lcd);
lcd_putc(sayac2_lcd);
lcd_putc(sayac1_lcd);
lcd_putc(sayac0_lcd);
lcd_putc("Hz");
sayac0=0;
sayac1=0;
sayac2=0;
sayac3=0;
sayac4=0;
}
set_timer1(value_timer1);
}
//------------------------------------------------------------------------------
#INT_EXT
int kesme_ext()
{
sayac0++;
if(sayac0==10)
{
sayac0=0;
sayac1++;
if(sayac1==10)
{
sayac1=0;
sayac2++;
if(sayac2==10)
{
sayac2=0;
sayac3++;
if(sayac3==10)
{
sayac3=0;
sayac4++;
if(sayac4==10)
{
sayac4=0;
}
}
}
}
}
}
//------------------------------------------------------------------------------
int duzenle(int a)
{
if(a==0)
{
return '0';
}
if(a==1)
{
return '1';
}
if(a==2)
{
return '2';
}
if(a==3)
{
return '3';
}
if(a==4)
{
return '4';
}
if(a==5)
{
return '5';
}
if(a==6)
{
return '6';
}
if(a==7)
{
return '7';
}
if(a==8)
{
return '8';
}
if(a==9)
{
return '9';
}
}
//------------------------------------------------------------------------------
int main()
{
// SET_TRIS_b(0xFF);
// output_b(0x00);
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );
set_timer1(value_timer1);
lcd_init();
lcd_putc("Frekans=");
lcd_putc("\nKORFEZ EML 12BTL");
enable_interrupts(INT_EXT);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
while(TRUE);
}
bu da flcd.c
struct lcd_pin_map { // This structure is overlayed
BOOLEAN unused; // low order up. ENABLE will
BOOLEAN rs; // access to the LCD pins.
BOOLEAN rw; // The bits are allocated from
BOOLEAN enable; // on to an I/O port to gain
int data : 4; // be pin B0.
} lcd;
#byte lcd = 0x07
#define set_tris_lcd(x) set_tris_c(x)
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// The following are used for setting
// the I/O port direction register.
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in
BYTE lcd_read_byte() {
BYTE low,high;
set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4) | low);
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
void lcd_init() {
BYTE i;
set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE address;
if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}
void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}
char lcd_getc( BYTE x, BYTE y) {
char value;
lcd_gotoxy(x,y);
while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
Alıntı yapılan: anti1990CCP modlarından hangisini(capture/PWM) kullanmam gerekir? Algoritmayı nasıl yapmam gerekir?
Arkadaşım CCP kullanırsan Capture ile pals genişliklerini ölçerek yaparsın ama benim sana tavsiyem; CCP kullanmadan, 1 saniyede gelen palsleri sayarak bu işi yapman. Genellikle bu yöntem kullanılır zaten. CCP ile yaparsan, yüksek frekanslarda pek verimli olmaz.
Bunu yaparken 2 tane Timer kullanılacak; birisi 1 saniyelik zamanı tutmak için, diğeri de gelen palsleri saymak için. Gelen palsleri sayan Timer ' in 16 bit olması daha iyi olur, bu yüzden Timer0 ' ı zamanlayıcı olarak, Timer1 ' i sayıcı olarak kullanabilirsin. Bu durumda:
Timer0 ' ı 1 saniyede kesme üretecek şekilde ayarla.
Timer1 ' i de harici clock pininden (T1CLK) gelen palsleri sayacak şekilde ayarla ve Timer1 kesmesini de aç.
Her Timer1 kesmesi gelişinde bir registeri arttır. (Ölçeceğin frekansın yüksekliğine göre, istediğin uzunlukta olabilir.(16 bit 24 bit)) (Timer1 (TMR1L TMR1H) de sayıcı registere dahildir.)
Her Timer0 kesmesi geldiğinde de sayıcı registerleri LCD ' ye yazdır ve sonraki ölçüm için sayıcı registerleri (Timer1 ile birlikte) sıfırla.
Ayrıca Picproje E-Dergi 2 de böyle bir konu vardı, oradan da faydalanabilirsin.
Kolay gelsin. :)