PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Các ngôn ngữ lập trình khác (CCS C, HT PIC,...) (http://www.picvietnam.com/forum/forumdisplay.php?f=12)
-   -   CCS C for PIC16F877A (http://www.picvietnam.com/forum/showthread.php?t=357)

thaithienanh 22-05-2007 08:52 PM

Úi code của bạn sai rồi nếu muốn sử dụng được ngắt thì trong hàm main bạn phải thực hiện cho phép ngắt timer_0 và ngắt toàn cục (global) hoạt động, định xung nhịp cho timer, và hàm ngắt() phải được đặt ngay bên dưới chỉ thị #int_timer0 để trình dịch có thể hiểu được đây là hàm phục vụ ngắt, hàm ngắt() này bạn không thể gọi đến giống như một hàm thông thường đuợc mà nó chỉ được máy gọi đến khi có xuất hiện cờ tràn timer_0, mà khi đã sử dụng ngắt timer (tức ngắt định thời) thì bạn không nên dùng delay trong nó (rất dở),vì ngắt timer được tạo ra để thay thế hoàn hảo cho delay, code của bạn mình sửa như sau :
#include<18F4450.h>
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=4000000)
int16 count=0;
int8 a=1;

#int_timer0
void ngat(){
++count;
if(count==2000) {count=0;a=a<<1;} // dich trai a 1bit
if(a==256) {a=1;count=0; }}

void main(){
enable_interrupts(global);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); //xung timer = xung máy/2
while(true) {
output_b(a);
}}

như vậy ở hàm trên ta sẽ thấy sau mỗi lần tràn ngắt timer_0 (sau hai xung máy) biến đếm count sẽ tăng lên 1 đơn vị và cứ thế cho đến khi đạt giá trị 2000 (đây là giá trị mà bạn cần phải tính để chọn đúng thời gian cần làm làm trễ) khi đó biến a sẽ đuợc dịch bit sang trái,....rồi tiếp tục... chắc khúc này bạn hiểu rồi há.

An Hiep 23-05-2007 11:37 AM

Giải thích như bạn thaithienanh là đúng đấy. Bạn phải khai báo thủ tục ngắt cho đúng và trong chương trình chính phải cho phép ngắt (hoặc không) đúng ý đồ thuật toán.
Tiện đây các bạn cho hỏi có cách nào đo được biên độ điện áp của xung vuông có độ rộng xung (thời gian tồn tại mức) nhỏ cỡ 0.4us không? Tôi định dùng ADC thông thường với xung clock nội (thạch anh 20MHz) và dùng thêm các chân phát hiện mức (sườn lên) của xung rồi cho phép lấy ADC nhưng không biết với độ rộng xung hẹp như vậy có khả thi không? Anh em nào biết phương pháp thì giúp tôi với.
Thanks!
-----------------------------------------------------------------------
An Hiệp

suongrong17 23-05-2007 04:38 PM

Pic18f4450
 
Trích:

Nguyên văn bởi thaithienanh (Post 8833)
Úi code của bạn sai rồi nếu muốn sử dụng được ngắt thì trong hàm main bạn phải thực hiện cho phép ngắt timer_0 và ngắt toàn cục (global) hoạt động, định xung nhịp cho timer, và hàm ngắt() phải được đặt ngay bên dưới chỉ thị #int_timer0 để trình dịch có thể hiểu được đây là hàm phục vụ ngắt, hàm ngắt() này bạn không thể gọi đến giống như một hàm thông thường đuợc mà nó chỉ được máy gọi đến khi có xuất hiện cờ tràn timer_0, mà khi đã sử dụng ngắt timer (tức ngắt định thời) thì bạn không nên dùng delay trong nó (rất dở),vì ngắt timer được tạo ra để thay thế hoàn hảo cho delay, code của bạn mình sửa như sau :
#include<18F4450.h>
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=4000000)
int16 count=0;
int8 a=1;

#int_timer0
void ngat(){
++count;
if(count==2000) {count=0;a=a<<1;} // dich trai a 1bit
if(a==256) {a=1;count=0; }}

void main(){
enable_interrupts(global);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); //xung timer = xung máy/2
while(true) {
output_b(a);
}}

như vậy ở hàm trên ta sẽ thấy sau mỗi lần tràn ngắt timer_0 (sau hai xung máy) biến đếm count sẽ tăng lên 1 đơn vị và cứ thế cho đến khi đạt giá trị 2000 (đây là giá trị mà bạn cần phải tính để chọn đúng thời gian cần làm làm trễ) khi đó biến a sẽ đuợc dịch bit sang trái,....rồi tiếp tục... chắc khúc này bạn hiểu rồi há.

Thật sự cảm ơn sự chỉ giáo của thaithienanh. Mình cũng đang tập tành chơi với PIC thôi. Trước giờ cũng chưa từng đụng đến các loại vi xử lý thành ra không nắm rõ, khi đọc tài liệu cũng cảm thấy khó hiểu ở phần ngắt. Mình đang dự định dùng con PIC này để làm thành Keyboard USB, viết cả driver cho nó. Nhưng bây giờ cơ bản cũng còn chưa biết, chỉ có ý tửong7 thôi. Nhờ bạn chỉ them cho mình với nhé. Thế nhưng khi đưa trình ngắt này cho chạy thử thì vẫn thấy bặt vô âm tín, không hiểu bị sao nữa.

tranvanthuong 23-05-2007 09:23 PM

cho em hỏi, em đang làm thí nghiệm pic16f84a, làm led chớp tắt theo ý muốn nhưng em muốn dùng 1 biến trở để chỉnh tốc độ delay thì phải làm sao? nhờ các anh chỉ giáo! và em muốn dùng time 0 được không?
(xin lỗi mấy anh, mục này mà em hỏi F84a)

namqn 23-05-2007 11:07 PM

Trích:

Nguyên văn bởi tranvanthuong (Post 8845)
cho em hỏi, em đang làm thí nghiệm pic16f84a, làm led chớp tắt theo ý muốn nhưng em muốn dùng 1 biến trở để chỉnh tốc độ delay thì phải làm sao? nhờ các anh chỉ giáo! và em muốn dùng time 0 được không?
(xin lỗi mấy anh, mục này mà em hỏi F84a)

Người ta thường dùng bộ ADC trong PIC (tất nhiên đang nói đến những chip có module ADC) để đọc giá trị của biến trở rồi điều chỉnh thời gian/tốc độ chớp tắt. Với PIC16F84A (không có module ADC), bạn vẫn có thể làm được điều đó, nhưng dùng một cách khác, được đề cập đến trong app. note 863 của Microchip. Bạn tìm đọc app. note đó trên web site của Microchip.

Thân,

suongrong17 24-05-2007 07:15 PM

quét led 7 segment.
 
Cảm ơn anh thaithienanh nhiều, mình đã làm được rồi.Đã OK phần ngắt. Chiều nay mới quét và hiển thị 2x7 segment leds. Cho nó đếm, đã dần hiểu đựoc7 lập trình vi điầu khiển. Mong đựoc7 các bác chỉ giáo nhiều hơn nữa.

đây là chưong7 trình mà mình mới viết, mai sẽ sử dụng ngắt và timer để làm lại.

Code:

#include<18F4550.h>
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=10000000)
#use fast_io(b)
#use fast_io(a)
#byte portb=0x6

BYTE CONST LED_MAP[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x58,0x00,0x10};
int8 a,i,j;

void ngat()
{

a++;
  if(a>=100)
  a=0;
  }
void main()
{set_tris_a(0);
 a=0;
set_tris_b(0);
while(true)
{  i=0;while(i<=200)
 {i++;
 output_b(led_map[a/10]);
 output_high(PIN_B7);
  output_low(PIN_A0);
  delay_ms(3);
  output_high(PIN_A0);
  output_b(led_map[a%10]);
    output_low(PIN_A1);
    delay_ms(3);
  output_high(PIN_A1);
  } 
 ngat();
}
return;
}


phamthaihoa 24-05-2007 10:28 PM

Trích:

Nguyên văn bởi tranvanthuong (Post 8845)
cho em hỏi, em đang làm thí nghiệm pic16f84a, làm led chớp tắt theo ý muốn nhưng em muốn dùng 1 biến trở để chỉnh tốc độ delay thì phải làm sao? nhờ các anh chỉ giáo! và em muốn dùng time 0 được không?
(xin lỗi mấy anh, mục này mà em hỏi F84a)

Làm như anh namqn là ok roài, nhưng con 16F84A không có comparator nên bạn sẽ phải thêm một con comparator ngoài, ví dụ LM393

hawinter 29-05-2007 06:38 PM

Em làm mạch đo nhiệt độ sử dụng LM335Z để hiển thị LCD .
Code:

#include <16F877A.h>
#include <DEFS_16F877A.h>
#device*=16 adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define RS RB3
#define RW RB4
#define E RB5
#byte lcd_data = PORTD  // Dia chi PORTD
int8 hight,low,i;
float value;
void convert_bcd(int8 a){
  low=a%10;
  hight=a/10;
  low+=0x30;//doi ra ma ASCII de hien thi LCD
  hight+=0x30;
}

byte lcd_read_byte()
{
  byte read_byte;
  set_tris_D(0xFF);      // PORTD = input
  RW = 1;
  delay_cycles(1);
  E  = 1;
  delay_cycles(1);
  read_byte = lcd_data;
  E  = 0;
  set_tris_D(0x00);      // PORTD = output
  return(read_byte);
}
/* Goi 1byte den LCD */
void lcd_send_byte( byte address, byte n )
{
  RS = 0;
  while ( bit_test(lcd_read_byte(),7) ) ;
  RS = address;
  delay_cycles(1);
  RW = 0;
  delay_cycles(1);
  E  = 0;
  lcd_data = n;
  delay_cycles(1);
  E = 1;
  delay_us(2);
  E = 0;
}

/* Khoi tao ban dau cho LCD */
void lcd_init()
{
    byte const lcd_init_string[4] = {0x38, 0x0C, 1 , 6};
    byte i;
    set_tris_D(0x00);
    RS = 0;
    RW = 0;
    E  = 0;
    delay_ms(15);
    for(i=1;i<=3;++i)
      {
        lcd_data = 3;
        delay_cycles(1);
        E = 1;
        delay_us(2);
        E = 0;
        delay_ms(5);
      }
    lcd_data = 2;
    delay_cycles(1);
    E = 1;
    delay_us(2);
    E = 0;
    delay_ms(5);
    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=0x40;
  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;
  }
}
main()
{
  set_tris_B(0);
  set_tris_D(0);
  set_tris_A(0xFF);
  lcd_init();
  delay_ms(100);
  lcd_gotoxy(3,1);
  lcd_putc("hello");
  lcd_gotoxy(1,2);
  lcd_putc("Welcom Everybody");
  delay_ms(2000);
  lcd_send_byte(0,1);//xoa LCD
  lcd_send_byte(0,6);
  setup_adc(ADC_CLOCK_INTERNAL);
  setup_adc_ports(AN0);
  set_adc_channel(0);
  delay_ms(100);
  value=(float)read_adc();
  value=(value-558.5)/2.048;
  convert_bcd((int8)value);
  delay_us(20);
  lcd_putc("nhiet do:");
  while(1)
  {
      value=(float)read_adc();
      value=(value-558.5)/2.048;
      convert_bcd((int8)value);
      delay_ms(1000);
      lcd_gotoxy(2,4);
      lcd_putc(hight);
      lcd_putc(low);
      lcd_putc(" do C");
      //delay_ms(1000);
  }
 }

Chương trình có tham khảo từ các bài viết trên Picvietnam và dientuvietnam.
khi chay chương trình thì giá trị nhiệt độ hiển thị chỉ quanh các giá trị 50,52,54,56,48,58 em cũng không biết tại sao .Xin các bậc tiền bối giải đáp hộ .

hawinter 29-05-2007 10:18 PM

Các sư huynh dúp em với đau đầu quá mà vẫn chưa tìm ra nguyên nhân ???
Cho em hỏi thêm là trong CCS để truy cập đến các thanh ghi thì làm thế nào nhỉ .

huybo02 30-05-2007 09:28 PM

Bạn kiểm tra lại Vref trên LM335 thử xem. Chương trình trên ứng với Vref = 5V. Nếu Vref có giá trị khác bạn phải tính lại các số cho biểu thức
" value=(value-558.5)/2.048;"
Với 5V thì:
5V = 1024 muc (ADC 10bit 2^10 = 1024) => 10mV tuong ung voi 2.048 muc ADC
0oC = 273oK => 0oC ung voi muc dien the 2.73V ung voi 559 muc ADC
Nhiet do = dien the Analog/10 - 273
Tuong ung
Nhiet do = (adc -559)/2.024

Còn truy cập thanh ghi thì có lẽ giống như khai báo địa chỉ port I/O lúc đầu
VD: #byte portb = 0x06;
Lúc này ta có thể gán giá trị vào portb:
portb = 0xFF;
hay đọc giá trị từ portb ra ngoài:
data = portb;
Đối với các thanh ghi khác chắc cũng như vậy. Đặt tên thanh ghi, định nghĩa địa chỉ và truy xuất
Bạn thử xem <<< chưa thử :D

LeDuc 08-06-2007 06:31 PM

cho em hoi trong ccs co ho tro vong lap " for" ko vay cac bac .. sao em lam hoai ma ko duoc vay .. bien dich van dung ma chay thi ko duoc...
--------------------------------
Code:

#include<16F877.h>
#device *=16 ADC=8
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=10000000)
#use fast_io(b)
#byte p3=0x06
#byte porta=0x05

void main()

  int8 const led[]={1,2,4,8,16,32,64,128},a;
  set_tris_b(0);
  set_tris_a(0);
  set_tris_c(0);
  set_tris_d(0);
 
  while(true)
    {
      for( a=0;a<8;a++)
      p3=led[a];
      delay_ms(100);
    }

}


namqn 08-06-2007 07:56 PM

Như thế nào là chạy không được?

Theo code của bạn, trong vòng while quá trình sau sẽ được thực hiện, nếu a là biến:
1. Xuất 8 lần dữ liệu ra p3 (địa chỉ 0x06)
2. Làm trễ 100 ms
3. Quay lại bước 1

Tôi không dùng CCS C nên bạn phải kiểm tra lại xem khai báo như bạn đã làm thì a là biến hay là hằng.

Thân,

LeDuc 10-06-2007 12:21 AM

Em biet no sai o dau roi. Sau moi lan gia tri a tang len 1 . phai delay mot khoan thoi gian, neu ko no se chay den gia tri cuoi cung roi xuat ra portb , vay p3=led[7]=128; nhu vay xem nhu vong lap ko co tac dung(co vay thoi cugn so y thiet(~_~).. Vay doan code dung la :( 8 con led se chay duoi nhau hoai (^_^)..)
-----------------------------
Code:

#include<16F877.h>
#device *=16 ADC=8
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=10000000)
#use fast_io(b)
#byte p3=0x06

void main()

  int8 const led[]={1,2,4,8,16,32,64,128},a;
  set_tris_b(0);
  while(true)
    {
      for(a=0;a<8;a++)
      {
      p3=led[a];
      delay_ms(20);
      }
    }
}

namqn: bạn nên đặt phần code của bạn giữa hai tag [ code] và [ /code] để định dạng cho phần code (hai tag không có khoảng trắng nào hết chứ không phải như được hiển thị ở đây).

LeDuc 11-06-2007 03:08 PM

Timer ! Help !
 
Các bác có thể chỉ rõ hơn về timer ko? ví dụ như khi nào timer sẽ tràn( reset ) . giống như 8051( la TF =0)
Và muốn định khỏan thời gian đếm cho timer phải làm sao?
Ví dụ như : tạo một xung vuông với tần số 1Hx, cách tính thời gian set timer như thế nào ? giá trị nạp cho timer là bao nhiêu ?
Còn timer 16 bit .. sau khi reset có cần phải nạp lại gia trị ban đầu ko?( giống như 8051 vậy ..).. Ai có the so sanh giữa 8051 va 16f877 kô?
Mong các bác giúp đỡ sớm để em mau biết rõ hơn ...
Cam ơn các bác !

nguyen.geo 21-06-2007 06:53 PM

Trích:

Nguyên văn bởi LeDuc (Post 9309)
Các bác có thể chỉ rõ hơn về timer ko? ví dụ như khi nào timer sẽ tràn( reset ) . giống như 8051( la TF =0)
Và muốn định khỏan thời gian đếm cho timer phải làm sao?
Ví dụ như : tạo một xung vuông với tần số 1Hx, cách tính thời gian set timer như thế nào ? giá trị nạp cho timer là bao nhiêu ?
Còn timer 16 bit .. sau khi reset có cần phải nạp lại gia trị ban đầu ko?( giống như 8051 vậy ..).. Ai có the so sanh giữa 8051 va 16f877 kô?
Mong các bác giúp đỡ sớm để em mau biết rõ hơn ...
Cam ơn các bác !

Theo mình thì bạn cần xem lại datasheet của 16F877A Từ Trang 47-60.
Mỉnh thấy nó nói khá rõ mà.

An Hiep 26-06-2007 11:54 AM

To LeDuc:
Bạn nên sử dụng ngắt sẽ rất dễ dàng.
1. Nạp cho Timer giá trị cần tạo ra
2. Cho phép ngắt Timer(Ví dụ Timer0(8bit) hoặc Timer1(16bit))
3. Xử lý ngắt(Không cho phép ngắt để lấy giá trị và tính toán)
4. Cho phép ngắt
Giá trị nạp cho Timer được tính tương tự như đối với 8051.

Chúc bạn thành công!

An Hiệp

An Hiep 26-06-2007 12:01 PM

Bạn chú ý đối với từng Timer thì việc nạp giá trị là khác nhau.
Ví dụ Timer0: 8bit = 256 giá trị
Nếu bạn sử dụng lệnh set_timer0(10); thì thời gian bạn thu được là 256-10 = 246 giá trị. Còn set_timer1(10); thì thời gian bạn thu được là 65536-10 =65526 giá trị.

Chúc bạn thành công!


An Hiệp

dvnccbmacbt 27-06-2007 10:32 AM

Hỏi về ngắt trên chân RB4-RB7!!
 
Em viết chương trình như sau: chương trình dùng để chạy led thuận trên portD, khi có ngắt trên RB7 thì chạy led ngược lại.
Code:

/#include <16F877A.h>
#device *=16
#fuses NOWDT,HS,NOPROTECT
#use delay(clock=20000000)
#use fast_io(b)
#use fast_io(c)
#use fast_io(a)
#use fast_io(d)
#use fast_io(e)

#byte intcon=0x000B
#bit RBIF=intcon.0

int8 const led[]={1,2,4,8,16,32,64,128};
int8 a=0,j=0,i=0;
int16 dem=0;
//========ham ngat timer0==========//
#int_rb
void ngat_rb()
 {
  for(j=8;j>0;j--)
    {
    output_d(led[j-1]);
    delay_ms(10);
    }output_d(0);RBIF=0;
 }
//===========ham chinh=============//
void main()
{set_tris_d(0);
 set_tris_b(0xff);
 enable_interrupts(global);
 enable_interrupts(int_rb);
ext_int_edge(L_TO_H );
 while(1)
 {  for(i=0;i<8;i++)
    {
    output_d(led[i]);
    delay_ms(10);
    }output_d(0);
 }
}

còn đây là sơ đồ mạch:

http://img225.imageshack.us/img225/9474/untitledgq0.jpg

đầu tiên nó chạy thuận thì đúng rồii. khi bấm nut thì nó chạy ngược lại cũng đúng nhưng sau đó thì nó cứ chạy ngược mãi mà không chạy thuận lại. Em nghĩ khi nó chạy xong chương trình ngắt rồi thì nó sẽ thực hiện chương trình chính chứ. Ở đây hàm delay có gây ra lỗi ko?

Cho em Hỏi thêm 1 ý nữa: Ngắt sẽ xảy ra khi có chuyển trạng thái trên chân RB4-Rb7. vây nếu trong chương trinh ta thiêt lập là output và cho chuyển trạng thái bằng lệnh thì có xảy ra ngắt ko? Sự khác nhau giữa ngắt ngoài trên chân RBO và ngắt trên RB4->RB7 là gì?

anh_gioi 27-06-2007 11:34 AM

Trích:

Nguyên văn bởi ngoalongdochanh (Post 2153)
Cám ơn nhh đã trả lời cho mình, do lần trước mình khai báo chưa đúng cách giữa 16f877A và *=16 đúng ra phải viết liền như bạn minh lại viết cách ra như thế này "16f877A *=16". Nhân tiện cho mình hỏi luôn ý nghĩa của việc khai báo "#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT"

sao mình khai báo #device 16F877*=16 ADC=8 mà nó vẫn báo:
"can not change device type this far into the code"
thanhk!

anh_gioi 27-06-2007 05:29 PM

Trích:

Nguyên văn bởi nhh (Post 2260)
Chào cả nhà !

Sao không thấy bác nào post bài vào luồng này vậy kà !Trầm quá...!Trầm quá...!Hay cái CCS C này không hấp dẫn mọi người chăng!
Không ai viết gì, tớ vẫn post cho nó đỡ trầm....!

Đã ví dụ về ngắt Timer, sau đây là 2 ví dụ về ngắt ngoài trên chân RB0 và trên các chân RB4 đến RB7:

Chương trình sau dùng ngắt ngoài trên RB0 đếm số lần cái button được nhấn xuống, hiển thị lên led 7 đoạn (common cathode).Nếu số lần nhấn vượt quá 9, chương trình sẽ quay về hiển thị lên led từ số 1.
Code:

//*****************************************************************************
// Author  : nhh
// Date    : 03/04/06
// Hardware: PIC16F877A
//*****************************************************************************
#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)
#use fast_io(d)
#byte portb=0x06
#byte portd=0x08
const unsigned char digital[]={0b00000110, 0b01011011, 0b01001111, 0b01100110,\
                                                0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111};
                  // ma hoa digital duoi dang mang
// Chuong trinh ngat
#int_ext
void ngat_RB0()
{
int i;
  if(i<9)
      {
      portd=digital[i];
      ++i;
      }
  if(i==9)
      {
      i=0;
      }
}
// Chuong trinh chinh
main()
{
set_tris_b(0b00000001);
set_tris_d(0);
enable_interrupts(global);
enable_interrupts(int_ext);
ext_int_edge(H_to_L);
portd=0b00111111;
while(true)
  {
  // chi doi ngat nen vong lap nay ko co gi ca !
  }
}

http://www.freewebtown.com/nhhao/PIC...gngatngoai.gif

sao bai nay chỉ sủ dụng RB0 là chân vào thôi vậy.còn các chân khác sao lại không dc.
thank!

picpicpic 27-06-2007 06:02 PM

Bác nhh này biến đi đâu lâu quá ko thấy xuất hiện, ko biết làm mod kiểu gì đây ???

To dvnccbmacbt: mô phỏng bằng proteus, bạn ko cần mắc thạch anh vào đâu.

To anh_gioi: thì chương trình đó chỉ viết cho ngắt RB0 mà bạn.

LeDuc 27-06-2007 06:39 PM

Code:

#include <16F877A.h>
#device *=16 ADC=8
#fuses NOWDT,HS,NOPROTECT

#use delay(clock=20000000)
#use fast_io(b)
#use fast_io(c)
#use fast_io(a)
#use fast_io(d)
#use fast_io(e)

#byte intcon=0x000B
#byte portb=0x6

#bit RB7 =portb.7
#bit RBIF=intcon.0
#bit RBIE=intcon.3
//-----------------------------
int8 const led[]={1,2,4,8,16,32,64,128};
int8 j=0,i=0;

//========ham ngat tren RB ==========//
#int_rb
void ngat_rb()
{
  if(rb7==0)
  for(j=8;j>0;j--)
  {
      output_d(led[j-1]);
      delay_ms(10);
  }
}
//===========ham chinh=============//
void main()
{
  set_tris_d(0);
  set_tris_b(0xff);
  enable_interrupts(global);
  enable_interrupts(int_rb);
  ext_int_edge(L_TO_H );
  while(true)
  {
      for(i=0;i<8;i++)
      {
          output_d(led[i]);
          delay_ms(10);
      }
  }
}

Mình đã sửa lại đoạn code của bạn rồi ..thay đổi một chút thôi.
Mình đã kiểm tra và chạy ok rồi... Nhưng có lẽ dùng delay trong hàm ngắt là ko nên . Nên tìm 1 giải thuật khác , dịch bit chẳng hạn ...
Còn sự khác biệt giữa các ngắt :" bạn xem lại phía trên các anh có chỉ dẫn đó ...
hy vọng mọi người sẽ cùng nhau tìm hiểu nhiều hơn...có sai nhiều .. có sửa nhiều ..--->> tiến bộ nhiều (^_^)!!!
Rất cảm ơn vì đã gởi thắc mắc lên đây.. qua bài trên mình đã tìm hiểu thêm được nhiều điều mới..

dvnccbmacbt 28-06-2007 12:03 AM

Em đã làm thử một bài tập về RB4-Rb7. Có phải chỉ khi nào các chân từ RB4-Rb7 là chân input thì mới có thể tạo ra ngắt được đựoc không? Nếu là output thì dù có chuyển trạng thái cũng không tạo ra ngắt, đúng không? Nếu vậy tại sao các chân này không gọi là ngắt ngoài nhỉ? Các bác giải thích giùm em với. Nếu có 1 đoạn code mẫu thì càng tốt. Cảm ơn các bác nhiều.

picpicpic 28-06-2007 12:14 AM

Trích:

Nguyên văn bởi dvnccbmacbt (Post 9649)
Em đã làm thử một bài tập về RB4-Rb7. Có phải chỉ khi nào các chân từ RB4-Rb7 là chân input thì mới có thể tạo ra ngắt được đựoc không? Nếu là output thì dù có chuyển trạng thái cũng không tạo ra ngắt, đúng không? Nếu vậy tại sao các chân này không gọi là ngắt ngoài nhỉ? Các bác giải thích giùm em với. Nếu có 1 đoạn code mẫu thì càng tốt. Cảm ơn các bác nhiều.

Tất nhiên, đã là ngắt RB4-RB7 thì nó phải là các ngõ input, ngắt RB0 cũng vậy. Ngắt RB0 đã gọi là ngắt ngoài rồi, chả lẽ lại gọi trùng tên, nên tiên sư microchip nó đặt là ngắt RB.
http://www.picvietnam.com/forum/show...p?t=357&page=2

dvnccbmacbt 28-06-2007 01:10 AM

Các bác giúp em một câu nữa nhé. Em thắc mác chỗ TIMER1. Chế độ đếm đồng bộ là sao và không đồng bộ là sao? Em thấy trong các tài liệu và HELP giải thích dơn giản quá chẳng hiểu gì cả. Các bác cho em xin một ví dụ và ứng dụng của món này với. Cảm ơn các bác nhiều.

HL2 28-06-2007 01:54 PM

Tuyệt vời, cảm ơn các bác nhiều lắm. Cảm ơn bác nhh đã khởi xướng ra chuyên mục này để anh em có cơ hội trao đổi kinh nghiệm, học hỏi.

anh_gioi 28-06-2007 07:58 PM

thay dổi tốc độ LED ngoài
 
Trích:

Nguyên văn bởi nhh (Post 2261)
Còn đây là ứng dụng ngắt ngoài trên RB4 đến RB7 để thay đổi kiểu cũng như tốc độ chớp nháy mấy con led chỉ để....ngắm cho vui mắt !

Ấn sw1, led1 nhấp nháy với delay 250ms
Ấn sw2, led1,2 nhấp nháy với delay 200ms
Ấn sw3, led1,2,3 nhấp nháy với delay 150ms
Ấn sw4, led1,2,3,4 nhấp nháy với delay 100ms
[code]//************************************************** ***************************
// Author : nhh
// Date : 03/04/06
// Hardware: PIC16F877A
//************************************************** ***************************
#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)
#byte portb=0x06
#byte intcon=0x000B
#bit RB4=portb.4
#bit RB5=portb.5
#bit RB6=portb.6
#bit RB7=portb.7
#bit RBIF=intcon.0 //dinh nghia co ngat RB
#bit RBIE=intcon.3 //dinh nghia bit cho phep ngat RB
int led=0,speed;
// Chuong trinh ngat
#int_RB
void ngat_RB()
{
if((RBIF)&&(RBIE))
{
//Kiem tra sw1
{
if(RB4==0)
{
led=0b00000001; //led1 sang
speed=250;
}
}
//Kiem tra sw2
{
if(RB5==0)
{
led=0b00000011; //led1,2 sang
speed=200;
}
}
//Kiem tra sw3
{
if(RB6==0)
{
led=0b00000111; //led1,2,3 sang
speed=150;
}
}
//Kiem tra sw4
{
if(RB7==0)
{
led=0b00001111; //led1,2,3,4 sang
speed=100;
}
}
RBIF=0; //Xoa co ngat RB
}
}
// Chuong trinh chinh
main()
{
set_tris_b(0b11110000);
portb=0b00001111;
enable_interrupts(global);
enable_interrupts(int_RB);
ext_int_edge(H_to_L);
while(true)
{
portb=led;
delay_ms(speed);
portb=0;
delay_ms(speed);
}
}

http://www.freewebtown.com/nhhao/PIC...gngatngoai.gif

các bác ơi kiểm tra hộ em nhé.
em viết lại bài này ,thông báo không có lỗi gì,nhưng khi mô phỏng proteus thì không nhấp nháy dc.các bác kiểm tra hộ em phát


//thay doi toc do nhap nhay LED theo cac bit vao RB4-RB7
//RB0-RB3 bit ra

//khai bao cong vao ra
#use fast_io(b)
#byte portb = 0x06
#byte intcon = 0x000B
#bit RB4 = portB.4
#bit RB5 = portB.5
#bit RB6 = portB.6
#bit RB7 = portB.7
#bit RBIF = intcon.0 //dinh nghia ham ngat RB
#bit RBIE = intcon.3 //dinh nghia bit ngat RB
int LED = 0,speed;

//tao ham ngat
#int_ext
void ngat_RB(){
IF((RBIE)&&(RBIF)){
if(RB4==0){
LED = 0x01;//den 1 sang
speed = 500;
}
if(RB5==0){
LED = 0x03;//den 1 va 2 sang
speed = 300;
}
if(RB6==0){
LED = 0x07;//den 1 2 3 sang
speed = 200;
}
if(RB7 ==0){
LED = 0x0f;
speed = 50;
}
RBIF = 0;
}
}

//ham chinh

void main(){

set_tris_b(0b11110000); //dinh nghia cong vao ra
portb = 0x00; //bit cao thap
enable_interrupts(int_ext);
ext_int_edge(H_to_L);
enable_interrupts(global);
while(true){
portB = LED;
delay_ms(speed);
portB = 0;
delay_ms(speed);
}
}

NBC 28-06-2007 09:16 PM

Ghi và đọc bộ nhớ ngoài
 
1 Attachment(s)
Đây là đoạn chương trình có chức năng đọc giá trị ADC, sau đó ghi vào RAM ngoài, rồi đọc từ RAM ngoài để xử lí.
Có một vấn đề là khi tôi xóa dòng
output_high( PIN_D7 );
ở cuối hàm if thì các hàm này không thực thi được. Bác nào biết xin chỉ giúp tại sao.

anh_gioi 28-06-2007 10:16 PM

Trích:

Nguyên văn bởi nhh (Post 2386)
Mạch quét 16 phím, hiện kết quả lên led 7 đoạn.
Code:

//*****************************************************************************
// Author  : nhh
// Date    : 03/04/06
// Hardware: PIC16F877A
//*****************************************************************************
#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)
#use fast_io(c)
#byte portb = 0x06
#byte portc = 0x07
#bit RB0 = 0x06.0
#bit RB1 = 0x06.1
#bit RB2 = 0x06.2
#bit RB3 = 0x06.3
#bit RB4 = 0x06.4
#bit RB5 = 0x06.5
#bit RB6 = 0x06.6
#bit RB7 = 0x06.7
#bit RBIF=intcon.0 //dinh nghia co ngat RB
#bit RBIE=intcon.3 //dinh nghia bit cho phep ngat RB
int a;
const unsigned char dig[]={0b00111111,0b00000110, 0b01011011,0b01001111,\
0b01100110,0b01101101,0b01111101,0b00000111,0b01111111,0b01101111,0b01110111,\
0b01111100,0b00111001,0b01011110,0b11111001,0b11110001};
                  // ma hoa digital duoi dang mang
// Chuong trinh ngat
#int_RB
void ngat_RB()
{
if((RBIF)&&(RBIE))
  {
        {
        if(RB4&&RB0)
        a=dig[0];
        }
        {
        if(RB4&&RB1)
        a=dig[4];
        }
        {
        if(RB4&&RB2)
        a=dig[8];
        }
        {
        if(RB4&&RB3)
        a=dig[12];
        }
//.......
        {
        if(RB5&&RB0)
        a=dig[1];
        }
        {
        if(RB5&&RB1)
        a=dig[5];
        }
        {
        if(RB5&&RB2)
        a=dig[9];
        }
        {
        if(RB5&&RB3)
        a=dig[13];
        }
//........
          {
        if(RB6&&RB0)
        a=dig[2];
        }
        {
        if(RB6&&RB1)
        a=dig[6];
        }
        {
        if(RB6&&RB2)
        a=dig[10];
        }
        {
        if(RB6&&RB3)
        a=dig[14];
        }
//........
          {
        if(RB7&&RB0)
        a=dig[3];
        }
        {
        if(RB7&&RB1)
        a=dig[7];
        }
        {
        if(RB7&&RB2)
        a=dig[11];
        }
        {
        if(RB7&&RB3)
        a=dig[15];
        }
  RBIF=0; //Xoa co ngat RB
  }
}
// Chuong trinh chinh
main()
{
set_tris_b(0b11110000);
set_tris_c(0);
enable_interrupts(global);
enable_interrupts(int_RB);
ext_int_edge(H_to_L);
portb=0;
portc=0;
while(true)
  {
  portb=1;
  portb=2;
  portb=4;
  portb=8;
  portc=a;
  }
}

http://www.freewebtown.com/nhhao/PIC/Giaimabanphim.gif

portb=1;
portb=2;
portb=4;
portb=8;
portc=a;
lệnh gán này không biết có ý nghĩa gì nhỉ?
thank!

anh_gioi 28-06-2007 11:53 PM

mình đánh lại chương trình trên ,CCS thông báo không có lỗi gì nhưng khi mô phỏng không chạy được.
mong mọi người tìm ra chỗ sai hộ mình!
thank!

Code:

#include "C:\Documents and Settings\Administrator\Desktop\thu\giai ma ban phim\giai ma ban phim.h"

#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=4000000)
//giai ma ban phim
#use fast_io(b)
#use fast_io(c)
#byte portb = 0x06
#byte portc = 0x07
#byte intcon = 0x000B
#bit RB0 = portB.0
#bit RB1 = portB.1
#bit RB2 = portB.2
#bit RB3 = portB.3
#bit RB4 = portB.4
#bit RB5 = portB.5
#bit RB6 = portB.6
#bit RB7 = portB.7
#bit RBIF = intcon.0 //dinh nghia ham ngat cong RB
#bit RBIE = intcon.3 //dinh nghia bit ngat RB
int a;
const unsigned char digital[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f\
                                0x77,0x7c,0x39,0x5e,0x79,0x71};
     
//tao ham ngat
#int_ext
void ngat_RB(){
                    IF((RBIF)&&(RBIE)){
                                            if(RB4&&RB0)
                                            { a = digital[0];}
                                           
                                            if(RB5&&RB0) 
                                            {a = digital[1];}
                                           
                                            if(RB6&&RB0)
                                            { a = digital[2];}
                                           
                                            if(RB7&&RB0)
                                            {a = digital[3];}
                                            ////
                                            if(RB4&&RB1)
                                            { a = digital[4];}
                                             
                                            if(RB5&&RB1) 
                                            {a = digital[5];}
                                           
                                            if(RB6&&RB1) 
                                            {a = digital[6];}
                                           
                                            if(RB7&&RB1)
                                            {a = digital[7];}
                                            ////
                                            if(RB4&&RB2)
                                            {a = digital[8];}
                                           
                                            if(RB5&&RB2) 
                                            {a = digital[9];}
                                           
                                            if(RB6&&RB2)
                                            {a = digital[10];}
                                           
                                            if(RB7&&RB2)
                                            {a = digital[11];}
                                            RBIF =0; //xoa co ngat                                         
}
}
                                                                     
                   
                   
  //tao ham chinh
  void main(){
                    set_tris_b(0xf0);
                    set_tris_c(0x00);
                    portb = 0;
                    portc = 0;
                    enable_interrupts(int_ext); //ngat toan bo
                    ext_int_edge(H_to_L);
                    enable_interrupts(global);
                    while(true){
                              portb = 1;
                              portb = 2;
                              portb = 4;
                              portb = 8;
                              portc = a;
                    }
                        }


namqn 29-06-2007 03:46 AM

Trích:

Nguyên văn bởi anh_gioi (Post 9666)
portb=1;
portb=2;
portb=4;
portb=8;
portc=a;
lệnh gán này không biết có ý nghĩa gì nhỉ?
thank!

Lần lượt cấp điện cho từng cột bàn phím, nếu có cột nào có phím nhấn thì nó sẽ tạo ngắt. Quét xong các cột bàn phím thì xuất giá trị của a ra LED 7 đoạn 1 lần, sau đó tiếp tục vòng lặp (cấp điện từng cột bàn phím, rồi xuất ra LED).

Thân,

nhh 29-06-2007 11:55 AM

Trích:

Nguyên văn bởi anh_gioi (Post 9669)
mình đánh lại chương trình trên ,CCS thông báo không có lỗi gì nhưng khi mô phỏng không chạy được.
mong mọi người tìm ra chỗ sai hộ mình!
thank!

#include "C:\Documents and Settings\Administrator\Desktop\thu\giai ma ban phim\giai ma ban phim.h"

#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=4000000)
...

Ở đây có cả giải thuật và code, đã test trên mạch thật. Bạn tham khảo thêm:
http://www.picvietnam.com/forum/showthread.php?t=839

anh_gioi 29-06-2007 12:43 PM

cam on anh rất nhiều !

anh_gioi 29-06-2007 01:49 PM

Trích:

Nguyên văn bởi namqn (Post 9671)
Lần lượt cấp điện cho từng cột bàn phím, nếu có cột nào có phím nhấn thì nó sẽ tạo ngắt. Quét xong các cột bàn phím thì xuất giá trị của a ra LED 7 đoạn 1 lần, sau đó tiếp tục vòng lặp (cấp điện từng cột bàn phím, rồi xuất ra LED).

Thân,

anh có thể nói rõ hơn được không a? số: 1,2,4,6,8 nó mặc định cho cổng đấy a?

anh_gioi 30-06-2007 01:44 AM

dịch
 
tui dốt tiếng anh quá, mọi người có thể dịch những từ dưới ra tiếng việt được ko? thanhk!
#FUSES NOWDT
#FUSES XT
#FUSES NOPUT
#FUSES NOPROTECT
#FUSES BROWNOUT
#FUSES LVP
#FUSES NOCPD
#FUSES NOWRT
#FUSES NODEBUG

namqn 30-06-2007 02:01 AM

Trích:

Nguyên văn bởi anh_gioi (Post 9680)
anh có thể nói rõ hơn được không a? số: 1,2,4,6,8 nó mặc định cho cổng đấy a?

- Xuất 1 ra PORTA thì chỉ có bit 0 (tức là chân RA0) ở mức 1, các bit (chân) khác là 0.
- Xuất 2 ra PORTA thì chỉ có bit 1 (tức là chân RA1) ở mức 1, các bit (chân) khác là 0.
- Xuất 4 ra PORTA thì chỉ có bit 2 (tức là chân RA2) ở mức 1, các bit (chân) khác là 0.
- Xuất 8 ra PORTA thì chỉ có bit 3 (tức là chân RA3) ở mức 1, các bit (chân) khác là 0.

Bạn nhìn vào sơ đồ mạch của nhh sẽ thấy các chân RA0 .. RA3 nối với các cột của bàn phím.

Thân,

anh_gioi 30-06-2007 02:13 AM

cám ơn anh lần nữa nha
anh có thể dịch cho em masy nghĩa của từ trên kia được ko ạ.

namqn 30-06-2007 02:14 AM

Trích:

Nguyên văn bởi anh_gioi (Post 9693)
tui dốt tiếng anh quá, mọi người có thể dịch những từ dưới ra tiếng việt được ko? thanhk!
#FUSES NOWDT
#FUSES XT
#FUSES NOPUT
#FUSES NOPROTECT
#FUSES BROWNOUT
#FUSES LVP
#FUSES NOCPD
#FUSES NOWRT
#FUSES NODEBUG

Đây là những tên viết tắt đã được định nghĩa sẵn bởi trình biên dịch (thường thông qua tập tin include .h). Tôi không dịch (vì những từ đó là viết tắt) mà sẽ giải thích:

NOWDT - Không dùng watchdog timer (cái này không nên dịch ra)
XT - Dùng mức XT (mức công suất trung bình) cho bộ dao động với thạch anh ngoài
NOPUT - Không dùng power up timer (làm trễ khi bật nguồn)
NOPROTECT - Không bảo vệ code (không cấm đọc nội dung flash)
BROWNOUT - Dùng chức năng bảo vệ chống thấp áp
LVP - Cho phép chế độ nạp chương trình ở điện áp thấp
NOCPD - Không bảo vệ EEPROM dữ liệu (không cấm đọc nội dung EEPROM)
NOWRT - Không cấm ghi vào flash
NODEBUG - Không dành riêng các chân RB6 và RB7 cho debug

Thân,

dvnccbmacbt 30-06-2007 11:50 AM

Hỏi về ADC!
 
Đây là chưong trinh :
Code:

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#device 16F877*=16 ADC=8
#use delay(clock=10000000)
#use fast_io(b)
int8 adc;
main()
{set_tris_b(0);
setup_adc(adc_clock_internal);
setup_adc_ports(AN0);
set_adc_channel(0);
delay_ms(10);
while(true)
{
adc=read_adc();
output_B(adc);
}
}

Còn đây là mạch :
http://img412.imageshack.us/img412/3863/up001lm7.jpg

sau khi chạy thì tất cả các led đều sáng.Em không hiểu tại sao. Do sai ở mạch hay do chương trình.
http://img412.imageshack.us/img412/4703/up002qa2.jpg

Có bác nào giúp em với

nhh 30-06-2007 05:04 PM

http://i82.photobucket.com/albums/j257/nhhao/ADC.gif
Giữa biến trở và tụ C5 của bạn cần kéo xuống đất, nếu ko ngõ ra biến trở luôn ở mức cao 5V nên portB của bạn 8 đèn luôn sáng.

Thành thật cáo lỗi vì nhầm lẫn ngớ ngẩn này!


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

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