Mình mới vô, đang tự học PIC kit, vô đây tìm bài tập cho TIMER0 thì thấy bài này. Mình xin phép post code mình làm ở lv 3 ( không dám gọi pro do không dám ^^). mình viết bằng mikroc nên có vài chỗ có hơi khác một chút. nó hơi dài nên mình post thành từng chương trình con cho dễ xem nhé. Mọi người xem xong cho mình ý kiến nha. cảm ơn nhiều. Ah, mình chỉ mới mô phỏng trên proteus thôi, mà nó chạy khá tốt.
Đầu tiên là các biến toàn cục mình xài:
Code:
unsigned char n,m,l,i,j,old,c500ms;
unsigned char led7seg[3]={0x40,0x79,0x24,};
cái led 7 đoạn mình ... lười nên làm 3 số 0 1 2 thôi (Anode chung => 0 là sáng)
n: chọn mod chạy module led
m: chọn số hiện ra led 7 đoạn
l: chọn đếm 1s cho led 7 đoạn
i,j: để chạy vòng for trong các mod
old: dùng để chống rung nút ( mình sẽ nói rõ hơn)
c500ms: đếm 500ms cho việc chuyển trạng thái của led module ( mình dùng timer làm delay)
Tiếp theo và cũng là quan trọng nhất, là Main
Code:
void main()
{
port_init();
timer0_init();
delay_ms(50);
n=0;
l=1;
m=0;
c500ms=1;
while(1)
{
if (test_key(PORTA.F0)==0) n++;
if (n==3) n=0;
switch(n)
{
case 0 : mod1(); break;
case 1 : mod2(); break;
case 2 : mod3(); break;
}
}
}
khúc trên chắc mọi người đều hiểu hết. có cái PORTA.F0 thì chính là chân RA0 bên mplab
kế đến là port_init(), đơn giản và dễ hiểu ^^.
Code:
void port_init()
{
ANSEL=0;
ANSELH=0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
PORTC=0X00;
TRISC=0X00;
PORTD=0Xff;
TRISD=0X00;
TRISA.F0=1; //RA0 la chan nut bam
}
Tiếp theo, timer0_init()
Code:
void timer0_init()
{
// Enable global and peripheral interrupts
INTCON = 0xC0; // Set GIE, PEIE
TMR0IE_bit = 1; // Enable TMRO interrupt
t0se_bit=0; // low to high edge
t0cs_bit=0; // using internal clock => timer
psa_bit=0; //using prescaler
ps0_bit=1;
ps1_bit=0;
ps2_bit=1; //prescaler 64
tmr0=130;
}
Lý do mình prescaler 64 và cho timer0 đếm từ 130 là để cho nó ra đúng với 1s. khi đó, tần số là 4000000/(4*64*(255-130))= 125Hz, vậy muốn đếm 1s thì cho lặp 125 lần (1-126), 500ms thì 63 (1-63). điều này sẽ giải thích cho các con số sau này.
tiếp theo, chống rung phím ( không biết có chống rung thật không vì chưa test mạch thật ^^) nhưng rất hiệu quả nếu người dùng bấm đè. khi bấm đè chương trình vẫn chạy tiếp. nguyên tắc của việc này là lấy mãu nhiều lần. có một biến old để lấy trạng thái nút bấm ở trạng thái hiện tại ( tùy thuộc vào "chỗ" mình lấy mẫu, hiệu quả nút bấm sẽ khác ^^), sau đó, trong vòng lặp for hoặc while chẳng hạn, lấy gái trị nút bấm thêm lần nữa. nếu old bằng 1 và hiện tại bằng 0 => có bấm ( nút mình thường trực bằng 1), khi đó nó sẽ tăng giá trị n, hoặc là break ra khỏi while và for => chuyển trạng thái tức thì khi bấm nút. chương trình này trả ra 0 tức là có bấm.
Code:
char test_key(char x)
{
char push;
if ((x==0)&&(old==1))
push=0;
else push=1;
return push;
}
tiếp theo, cực kì quan trọng, interrupt. mấy cái mình nói ở trên đã giải thích cho các thôgn số ở đây, nên mình không nói lại nha. cái tmr0if_bit là cờ ngắt bên mplab đó.
Code:
void interrupt(void)
{
if(tmr0if_bit)
{
tmr0if_bit=0;
tmr0=130;
l++;//dem 1s cho led7sig
c500ms++; //dem 500ms cho module led
if (l==126)
{
l=1;
m++;
}
if (m==3) m=0;
PORTD=led7seg[m];
}
}
tiếp theo, hàm delay_500ms. trong hàm này có break khỏi nếu có bấm nút.
Code:
void delay_500ms()
{
old=PORTA.F0;
c500ms=1;
while(c500ms<63)
{
if (test_key(PORTA.F0)==0) break;
}
}
và cuối cùng mình post 1 mod, đó là mod3 ( một hiệu ứng nhảm nhí mình nghĩ ra). có 2 vòng lặp for. 2 cái mod1 và mod2 nhảm lắm, khỏi post nha ^^.
Code:
void mod3()
{
unsigned char temp;
unsigned char array[9]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
PORTC=0x00;
delay_500ms();
for(i=0;i<8;i++)
{
temp=0x80;
old=PORTA.F0;
for(j=1;j<(9-i);j++)
{
PORTC=array[i] | temp;
temp=temp>>1;
if (test_key(PORTA.F0)==0) break;
delay_500ms();
}
if (test_key(PORTA.F0)==0) break;
}
}
Mong mọi người cho ý kiến, nếu vô tình còn ai vô topic này, hihi