|
Tài trợ cho PIC Vietnam |
Giao tiếp USB, CAN, I2C, SPI, USART... Những giao tiếp được tích hợp trên PIC |
|
Ðiều Chỉnh | Xếp Bài |
07-09-2006, 11:54 PM | #1 |
PIC Bang chủ
|
Giao tiếp I2C
Bài báo cáo này do Nguyễn Chí Linh thực hiện trong thời gian làm mod của picvietnam, nhưng không hiểu sao vẫn chưa được đăng. Hôm nay thấy bên dientuvietnam thảo luận về vấn đề này, cho nên mới tìm lại bài báo cáo này và gửi lên.
Chúc vui
__________________
Công ty TNHH Thương mại và Giao nhận R&P store.hn@rpc.vn - store.hcm@rpc.vn Học PIC như thế nào? |
08-09-2006, 06:19 PM | #2 |
...Damned...
Tham gia ngày: Apr 2006
Nơi Cư Ngụ: Hồ Chí Minh
Bài gửi: 522
: |
Em post 1 bài ngoài vấn để kỹ thuật nhé. Chữ I2C đọc là gì nhỉ? Nguyên gốc của nó là IIC hoặc viết I2C nhưng số 2 viết nhỏ phía trên giống số mũ. Có người đọc là "Ai chu xi" (I 2 C đánh vần tiếng Anh ), em nghĩ đúng phải đọc là "Double I C", tương tự như IEEE đọc là (I triple E).
Nhưng em thích đọc là I 2 C (đánh vần tiếng Việt ). Không biết mọi người đọc như thế nào nhỉ? |
08-09-2006, 07:14 PM | #3 | |
Trưởng lão PIC bang
|
Trích:
Thân,
__________________
Biển học mênh mông, sức người có hạn. Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau: http://www.picvietnam.com/forum/showthread.php?t=1263 |
|
09-09-2006, 01:22 PM | #4 | |
PIC Bang chủ
|
Trích:
Còn "Eye Triple E" là cách đọc được ghi chú trực tiếp trên trang ieee.org. Ở Pháp thì nó lại đọc (anh viết tiếng Việt) "Y troa dsơ" Cũng đồng nghĩa với I và 3 chữ E. Do vậy, từ nay về sau, thống nhất trên PICVietnam, chúng ta đọc I2C là "Eye two See", chứ không đọc "Eye Square See" (đề phòng trường hợp cần voice chat, sẽ có một ngày đại hội picvietnam online), còn khi viết thì viết I2C cho nhanh, chứ không nên viết rất mất công viết công thức Latex. Chúc vui.
__________________
Công ty TNHH Thương mại và Giao nhận R&P store.hn@rpc.vn - store.hcm@rpc.vn Học PIC như thế nào? |
|
11-09-2006, 10:51 AM | #5 |
Nhập môn đệ tử
|
Mình dùng lệnh I2C trong CCS có hiệu quả ko ?!
Vì mình đang viết thử I2C. Thấy chương trình mẫu(EX_Slave) trong CCS C mô phỏng bộ nhớ ngoài 24xx chuẩn, nên nạp chạy thử thấy: viết từ Master (Ctr Mater lấy ví dụ: EX_EXTEE) ít nhất là 4 lần mới được, còn đọc thì lại ko được. Xem tài liệu thì thấy có rất nhiều bit bẫy tình huống I2C, nhưng các lệnh về I2C trong CCS thì đơn giản và ít. Vậy, có vấn đề gì không.
Code:
#include <16F876A.h> #fuses XT,NOWDT,NOPROTECT,NOLVP #use delay(clock=4000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12 #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0) typedef enum {NOTHING, CONTROL_READ, ADDRESS_READ, READ_COMMAND_READ} I2C_STATE; I2C_STATE fState; BYTE address, buffer[0x10]; #INT_SSP void ssp_interupt () { BYTE incoming; if (i2c_poll() == FALSE) { if (fState == ADDRESS_READ) { //i2c_poll() returns false on the i2c_write (buffer[address]);//interupt receiving the second fState = NOTHING; //command byte for random read operation } } else { incoming = i2c_read(); if (fState == NOTHING){ fState = CONTROL_READ; } else if (fState == CONTROL_READ) { address = incoming; fState = ADDRESS_READ; } else if (fState == ADDRESS_READ) { buffer[address] = incoming; fState = NOTHING; } } } void main () { int i; fState = NOTHING; address = 0x00; for (i=0;i<0x10;i++) buffer[i] = 0x00; enable_interrupts(GLOBAL); enable_interrupts(INT_SSP); while (TRUE) {} } thay đổi nội dung bởi: falleaf, 13-09-2006 lúc 04:49 PM. |
12-09-2006, 11:25 AM | #6 |
Nhập môn đệ tử
|
Có ai quan tâm vấn đề I2C trong CCS, cho Hà hỏi 1 chút:
i2c_isr_state() hình như không có trong V 3.227. Version này chỉ có các lệnh I2C cho 16F877A là: i2c_start(), i2c_stop(), i2c_read(),i2c_write(), i2c_poll(). Có phải vậy không. Nếu vậy, mình phải tự tạo i2c_irs_state(). Có phải vậy ko?!. Vì trong Help V4.0,có nói đến i2c_isr_state(), còn Help V3.227 Hà đang dùng thì ko thấy nói đến. Có ai rành I2C, chỉ giáo giùm chút ít kinh nghiệm.Xin rất cảm ơn!! |
12-09-2006, 12:52 PM | #7 |
Đệ tử 3 túi
Tham gia ngày: Jun 2006
Bài gửi: 51
: |
Chào Hà.
Tui cũng đang mò làm I2C trên CCS đây. Hà nói là phiên bản 3.227 kô có i2c_irs_state(). Vậy sao Hà kô tải V3.249 về làm. Mình hi vọng tui cả Hà sẽ cùng nghiên cúu vấn đề này. Chào hoanf |
12-09-2006, 01:00 PM | #8 |
Nhập môn đệ tử
|
Hà đang tìm đường link để tải Version khác cao hơn: V3.242 thì sáng tới giờ ko thấy gì. Vậy, mình tìm thử V3.249 xem sao.
Bạn biết link V3.249 thì hướng dẫn Hà với !! Rất cảm ơn !!! Thanhha |
12-09-2006, 02:52 PM | #9 |
Đệ tử 3 túi
Tham gia ngày: Jun 2006
Bài gửi: 51
: |
|
13-09-2006, 01:59 PM | #10 |
Nhập môn đệ tử
|
Hà vừa thử chtr I2c: Master 16F877A, Slave 16F876A, cùng giao tiếp PC để kiểm tra dữ liệu đọc và viết của Master và Slave> Thấy rất tốt ! I2C hay thiệt! Nhiêm vụ bây giờ mình chỉ tạo giao thức dữ liệu, còn chtr service plug&play slave thì thấy hơi khó! Nhưng mònh cố gắn viết thử. Cảm ơn Hoanf, mọi người rất nhiều !!
Code:
********************************************** Chtr Master, mình thay đổi chút ít từ chtr mẫu EX_EXTEE. 1.chỉ liên kết 2401.c (thay vì địa chỉ mặc đinh là 0xa0, mình thay là 0x10). 2. Vẫn truyền lệnh từ PC ********************************************** #include <16F877A.h> #fuses XT,NOWDT,NOPROTECT,NOLVP #use delay(clock=4000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) #include <input.c> #include <2401.c> void main() { BYTE value, cmd; EEPROM_ADDRESS address; init_ext_eeprom(); do { do { printf("\r\nRead or Write: "); cmd=getc(); cmd=toupper(cmd); putc(cmd); } while ( (cmd!='R') && (cmd!='W') ); printf("\n\rLocation: "); address = gethex1(); if(cmd=='R') printf("\r\nValue: %X\r\n",READ_EXT_EEPROM( address ) ); if(cmd=='W') { printf("\r\nNew value: "); value = gethex(); printf("\n\r"); WRITE_EXT_EEPROM( address, value ); } } while (TRUE); } Code:
********************************************** Chtr Slave, thì có thay đổi chút ít từ chtr mẫu EX_Slave: 1. giám sát 3 ô nhớ trên PC 2. khai báo địa chỉ la 0x10. ********************************************** #include <16F876A.h> #fuses XT,NOWDT,NOPROTECT,NOLVP #use delay(clock=4000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10) BYTE address, buffer[0x10]; #INT_SSP void ssp_interupt () { BYTE incoming, state; state = i2c_isr_state(); if(state < 0x80) //Master is sending data { incoming = i2c_read(); if(state == 1) //First received byte is address address = incoming; if(state == 2) //Second received byte is data buffer[address] = incoming; } if(state == 0x80) //Master is requesting data { i2c_write(buffer[address]); } } void main () { enable_interrupts(GLOBAL); enable_interrupts(INT_SSP); while (TRUE) { printf("\r\nValue0: %X\r\n",buffer[0]); delay_ms(1000); printf("\r\nValue1: %X\r\n",buffer[1]); delay_ms(1000); printf("\r\nValue2: %X\r\n",buffer[2]); delay_ms(1000); printf("\r\nValue3: %X\r\n",buffer[3]); delay_ms(1000); } } Phần mạch điện có File đính kèm : thay đổi nội dung bởi: thanhha, 14-09-2006 lúc 05:53 PM. Lý do: thêm mạch |
13-09-2006, 04:48 PM | #11 |
PIC Bang chủ
|
Anh đề nghị em post thêm sơ đồ mạch nguyên lý đi kèm. Thực ra không có gì phức tạp cả, chỉ vì bài viết mà chỉ có code không thôi thì nó không sinh động. Hơn nữa, người sau đọc vào không có hình ảnh đi kèm, nhiều khi người ta không hiểu nổi và ngại đọc. Chỉ cần có một cái hình vào, thì bài viết sẽ sinh động hơn nhiều.
Chúc vui.
__________________
Công ty TNHH Thương mại và Giao nhận R&P store.hn@rpc.vn - store.hcm@rpc.vn Học PIC như thế nào? |
13-09-2006, 05:24 PM | #12 |
Đệ tử 3 túi
Tham gia ngày: Jun 2006
Bài gửi: 51
: |
:d
Chào các bạn và Hà.
Mình mới viết được chương trình giao tiếp I2C đơn giản dùng các hàm của CCS. Mời các bạn xem và cho nhận xét Master: truyền dữ liệu cho Slave. Mỗi lần truyền 1 byte. Code:
#include <16F877A.H> #fuses XT,NOWDT,NOPROTECT,NOLVP #use Delay(Clock=4000000) #define SLAVE_ADDRESS 0x10 #use i2c(master, sda=PIN_C4, scl=PIN_C3) void write_I2C(int8 a) { i2c_start(); i2c_write(SLAVE_ADDRESS); i2c_write(a); i2c_stop(); } void main() { int8 value; value = 0; while(1){ write_I2C(value); value++; delay_ms(100); } } Slave thì chỉ tiến hành kiểm tra có phải Master truyền hay kô. Nếu truyền thì nhận byte dữ liệu và hiển thị lên port_B: Code:
#include <16F877A.H> #fuses XT,NOWDT,NOPROTECT,NOLVP #use delay(Clock=4000000) #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10) int8 value; #INT_SSP void i2c_isr() { int8 state; int8 address; state = i2c_isr_state(); if(state == 0) address = i2c_read(); else if(state < 0x80) value = i2c_read(); } void main() { enable_interrupts(GLOBAL); enable_interrupts(INT_SSP); set_tris_b(0x00); while(1){ output_b(value); } } hoanf thay đổi nội dung bởi: hoanf, 15-09-2006 lúc 10:00 AM. |
14-09-2006, 12:34 PM | #13 |
Đệ tử 3 túi
Tham gia ngày: Jun 2006
Bài gửi: 51
: |
Alo
Chào các bạn!!
Mình gặp trục trặc khi đọc dữ liệu từ Slave về. Đây là đoạn code sử dụng cho 2 con PIC 18F877A. Master: Yêu cầu Slave nhận dữ liệu liên tục (cách nhau 500ms) và nó sẽ hiển thị giá trị nhận được lên Port_b. Dùng leds để quan sát. Code:
#include <16F877A.H> #fuses XT,NOWDT,NOPROTECT,NOLVP #use Delay(Clock=4000000) #define SLAVE_ADDRESS 0x10 #use i2c(master, sda=PIN_C4, scl=PIN_C3) int8 read_I2C() { int8 value; i2c_start(); i2c_write(SLAVE_ADDRESS + 1); value = i2c_read(); i2c_stop(); return value; } void main() { int8 value; set_tris_b(0x00); while(1){ value = read_I2C(); output_b(value); delay_ms(500); } } Code:
#include <16F877A.H> #fuses XT,NOWDT,NOPROTECT,NOLVP #use delay(Clock=4000000) #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10) int8 value = 0x01; #INT_SSP void i2c_isr() { int8 state; int8 address; state = i2c_isr_state(); if(state >= 0x80){ i2c_write(value); value++; } } void main() { enable_interrupts(GLOBAL); enable_interrupts(INT_SSP); set_tris_b(0x00); while(1){ output_b(value); } } thay đổi nội dung bởi: hoanf, 15-09-2006 lúc 12:40 PM. |
14-09-2006, 04:24 PM | #14 |
Nhập môn đệ tử
|
Theo Hà nghĩ, ở Master, khi mình đọc cũng phải chờ xung ACK từ Slave thì chtr ko bị rối.
Bạn thử thêm một chtr con chờ Bus trong <2401.c>: Code:
//**************code thêm vào********************* BOOLEAN ext_eeprom_ready() { int1 ack; i2c_start(); ack = i2c_write(SLAVE_ADDRESS); i2c_stop(); return !ack; } //********************************************** int8 read_I2C() { int8 value; while(!ext_eeprom_ready()); // code thêm vào i2c_start(); i2c_write(SLAVE_ADDRESS + 1); value = i2c_read(); i2c_stop(); return (value); } void main() { int8 value; value = 0x00; set_tris_b(0x00); while(1){ value = read_I2C(); output_b(value); delay_ms(500); } } Thân mến !! thay đổi nội dung bởi: thanhha, 14-09-2006 lúc 06:11 PM. Lý do: Canh lề |
14-09-2006, 04:49 PM | #15 |
PIC Bang chủ
|
Các em nhớ đặt chương trình trong thẻ [code]...[/code ] (nhớ viết liền lại)
Như vậy thì mọi người sẽ đọc dễ hơn, và nếu code dài quá thì nó cũng thu gọn lại trong một khung cố định. Ngoài ra, code cũng có thụt ra thụt vào rõ ràng như trong đoạn code mà tụi em copy. Chú ý điều này khi viết bài. Chúc vui. Hoanf, và ThanhHa, như anh nói, giúp anh post một cái hình mạch nguyên lý giao tiếp đúng như trong cái đề tài mà tụi em đang thảo luận, để mọi người dễ theo dõi. Thanks muchie.
__________________
Công ty TNHH Thương mại và Giao nhận R&P store.hn@rpc.vn - store.hcm@rpc.vn Học PIC như thế nào? |