Bài tập buổi 5: Timer 0

Manhdd

Cố Vấn CLB
Staff member
Biến kich được kiểm tra lại sau mỗi lệnh break; trong switch.
Như vậy, theo mình, trong switch bạn cần phải kiểm tra sự thay đổi của kich để gọi break;.
 

Jan

Trứng gà
Vd: kich=3 thì "switch" nhảy tới "case 3:" thực hiện mode5(). Để chạy xong mode5() thì mất 5s. Khi mode5() chạy được 2s thì nhấn nút. Hàm isr() được gọi và tăng biến kich=4. Làm thế nào để khi về lại hàm main() thì nó không chạy 3s cuối của mode5() nữa, mà thoát khỏi mode5() lập tức và chuẩn bị thực hiện lệnh khác.
Trong trình biên dịch Hitech C có hàm nào can thiệp được vậy không.
Ý anh Manhdd nói có phải là kiểm tra kich ngay bên trong hàm mode5() đúng không .... vậy phải sửa lại hàm mode() => chương trình con sẽ không tổng quát ~~.
 

Manhdd

Cố Vấn CLB
Staff member
uhm, ý mình là vậy đấy, nhất thời chưa nghĩ ra phương pháp nào hay hơn.
Trong mode() bạn có thể kiểm tra 1 "cờ" nào đó báo hiệu sự thay đổi của kich để gọi return;. Như vậy, chương trình không mất tính cấu trúc.
 

thieuhuutrung

Trứng gà
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
 
Top