Mục lục:

I2C Bus cho ATtiny và ATmega: 8 bước
I2C Bus cho ATtiny và ATmega: 8 bước

Video: I2C Bus cho ATtiny và ATmega: 8 bước

Video: I2C Bus cho ATtiny và ATmega: 8 bước
Video: [Lập Trình AVR] Bài 18: Giao Tiếp I2C 2024, Tháng bảy
Anonim
I2C Bus cho ATtiny và ATmega
I2C Bus cho ATtiny và ATmega

Tôi yêu bộ vi điều khiển Atmel AVR! Kể từ khi xây dựng Hệ thống phát triển Ghetto được mô tả trong Có thể hướng dẫn này, tôi đã không còn thú vị khi thử nghiệm với AVR ATtiny2313 và ATmega168 nói riêng. Tôi thậm chí còn đi xa đến mức viết một bài Hướng dẫn sử dụng công tắc làm đầu vào và mở rộng khái niệm Hệ thống phát triển khu ổ chuột sang CPLD. Các AVR không có đủ chân I / O, vì vậy tôi phải suy nghĩ về điều gì đó. Tôi có thể đã thử một hệ thống nhập liệu phức tạp với bàn phím và màn hình, nhưng ATtiny2313 sẽ hết tài nguyên. May mắn thay, Atmel đã cung cấp một cách giải quyết vấn đề này bằng cách bao gồm một giao diện có thể liên kết với các chip bổ sung (chẳng hạn như bộ nhớ hoặc cổng I / O) với một giao diện hai dây đơn giản. Đúng vậy, bằng cách chỉ sử dụng hai chân I / O trên AVR, chúng ta có thể truy cập nhiều chân I / O bổ sung và các tài nguyên khác. Giao diện hai dây này chính thức được gọi là bus Mạch tích hợp liên kết, hay chỉ là bus I2C và được phát minh bởi NXP khi nó vẫn còn là Philips Semiconductors. Nếu bạn đang đọc Có thể hướng dẫn này thì có thể bạn đã nghe nói về bus I2C và thậm chí có thể đã sử dụng nó trên PIC hoặc vi điều khiển khác. Mặc dù về mặt khái niệm rất đơn giản và được hỗ trợ bởi tài nguyên phần cứng trên AVR, trình điều khiển phần mềm vẫn cần thiết để sử dụng bus I2C. Atmel cung cấp Ghi chú ứng dụng (xem Tài nguyên ở phần sau trong Có thể hướng dẫn này), nhưng chúng không đầy đủ và không hiển thị bất kỳ ví dụ nào ngoài việc giao tiếp với thiết bị AVR khác. AVR. Thay vào đó, tôi sẽ cung cấp các phiên bản mở rộng của trình điều khiển Atmel cho các thiết bị ATtiny2313 và ATmega168, tôi sẽ giải thích các yêu cầu và hạn chế áp dụng khi sử dụng các trình điều khiển này và tôi sẽ cho bạn thấy các ví dụ làm việc của các thiết bị I2C. Sau khi bạn làm việc thông qua Có thể hướng dẫn này, bạn sẽ có thể sử dụng thành công bus I2C trong các dự án AVR của mình. Rõ ràng, bạn có thể bỏ qua các trình điều khiển cho tiny hoặc MEGA nếu bạn chỉ quan tâm đến một trong số chúng. Đối với những người muốn tìm hiểu thêm về xe buýt I2C, tôi sẽ cung cấp các liên kết đến tài liệu thích hợp.

Bước 1: Tất cả Nội dung I2C này là gì?

Tất cả Nội dung I2C này là gì?
Tất cả Nội dung I2C này là gì?
Tất cả Nội dung I2C này là gì?
Tất cả Nội dung I2C này là gì?
Tất cả Nội dung I2C này là gì?
Tất cả Nội dung I2C này là gì?
Tất cả Nội dung I2C này là gì?
Tất cả Nội dung I2C này là gì?

I2C bus là một kết nối đơn giản, hai dây có thể liên kết nhiều thiết bị với nhau và cho phép chúng trao đổi dữ liệu. Ở dạng đơn giản nhất, có một thiết bị chính giao tiếp với nhiều thiết bị phụ. Tất cả các thiết bị được kết nối song song vào hai dây của bus I2C. Hai dây được gọi là SCL và SDA. SCL là dòng xung nhịp và được điều khiển bởi thiết bị chủ. SDA là đường dữ liệu hai chiều. Để truyền dữ liệu, master gửi một địa chỉ phụ kết hợp với cờ đọc / ghi một bit. Nếu bạn muốn ghi, cái chính sẽ tiếp tục gửi dữ liệu đến bộ phận phụ đã được định địa chỉ. Nếu yêu cầu đọc, máy chủ sẽ phản hồi bằng dữ liệu. Để điều phối các giao dịch, các đường SCL và SDA được thao tác bởi master và slave để báo hiệu một số điều kiện. Chúng bao gồm START, STOP, ACK (xác nhận) và NAK (không xác nhận). Các chi tiết của các điều kiện này được xử lý bởi các trình điều khiển. Những người đam mê thực sự trong số bạn có thể tìm hiểu tất cả các chi tiết trong các liên kết được cung cấp ở cuối Sách hướng dẫn này. Các yêu cầu về điện khá đơn giản. Chủ và các nô lệ phải sử dụng cùng một mức cho Vcc, các nền phải được kết nối, và các đường SCL và SDA phải được kéo lên đến Vcc. Giá trị của điện trở kéo lên được xác định chính xác bằng phép tính dựa trên tổng điện dung trên bus, nhưng thực tế có thể có giá trị khá lớn trong khoảng từ 1,8K đến 10K. Tôi bắt đầu với 5.1K và sử dụng các giá trị thấp hơn cho đến khi nó hoạt động. Điều này thường không phải là vấn đề trừ khi bạn có nhiều thiết bị hoặc độ dài dây dài giữa các thiết bị. Tốc độ dữ liệu danh nghĩa trên bus I2C là 100Kbits / giây. Cũng có thể có tốc độ 400Kbits / giây, 1Mbits / giây và hơn thế nữa, nhưng không được hỗ trợ bởi trình điều khiển trong Có thể hướng dẫn này. Tất cả các thiết bị I2C sẽ hoạt động ở tốc độ 100Kbits / giây. ATtiny2313 và ATmega168 mỗi thiết bị thực hiện bus I2C khác nhau. ATtiny2313 sử dụng phần cứng Giao diện Nối tiếp Đa năng (USI) - cũng có thể được sử dụng cho bus SPI. ATmega168 có phần cứng chuyên dụng cho bus I2C được gọi là Giao diện hai dây (TWI). Sau khi các trình điều khiển được viết, những khác biệt này hầu hết là minh bạch đối với người dùng. Một sự khác biệt đáng kể là trong phần mềm: Trình điều khiển ATmega168 I2C được điều khiển gián đoạn trong khi đối với ATtiny2313 thì không. Điều này có nghĩa là chương trình ATmega168 không phải đợi quá trình truyền dữ liệu I2C diễn ra, mà chỉ cần đợi trước khi bắt đầu quá trình chuyển khác hoặc cho đến khi dữ liệu đến từ một thao tác đọc. Các ví dụ và thảo luận sau đây sẽ làm rõ điều này. Địa chỉ2C dài 7 bit, vì vậy có thể lên đến 127 thiết bị trên bus nếu mỗi thiết bị có một địa chỉ duy nhất. Như trong hình, địa chỉ 7 bit này được dịch chuyển sang trái một bit và bit ít quan trọng nhất được sử dụng để gắn cờ đọc hoặc ghi thiết bị tại địa chỉ. Vì vậy, địa chỉ nô lệ hoàn chỉnh là một byte 8 bit. Địa chỉ thực tế được xác định một phần bên trong thiết bị và không thể thay đổi được (4 bit quan trọng nhất) và được xác định một phần bởi các bit có thể được kết nối với chân thiết bị (3 bit quan trọng nhất) có thể được gắn cao hoặc thấp để thiết lập một địa chỉ cụ thể. Nghe có vẻ khó hiểu, nhưng một ví dụ sẽ làm rõ điều này. Bảng dữ liệu PCA8574A cho thấy rằng bốn bit quan trọng nhất của địa chỉ I2C sẽ luôn là 0111. Ba bit tiếp theo được xác định bởi cài đặt trên các chân AD0, AD1 và AD2. Các chân này có thể được buộc vào đất hoặc với nguồn điện áp dương (5 vôn) để biểu thị 0 hoặc 1 tương ứng. Vì vậy, phạm vi địa chỉ có thể là 38 đến 3F hệ thập lục phân, như được hiển thị trong hình khác từ bảng dữ liệu PCA8574. Vì vậy, bằng cách thay đổi cài đặt bit địa chỉ, tối đa 8 PCA8574A có thể ở trên bus I2C cùng một lúc. Mỗi địa chỉ sẽ chỉ trả lời địa chỉ nô lệ cụ thể của nó. Nếu cần nhiều cổng I / O hơn nữa, PCA8574 có thể được sử dụng. Sự khác biệt duy nhất giữa PCA8574 và PCA8574A là dải địa chỉ I2C tớ của PCA8574 là 20 đến 27 hệ thập lục phân. Địa chỉ. Đọc kỹ bảng dữ liệu và ghi nhớ rằng địa chỉ phụ sẽ dài 7 bit. Bit đọc / ghi nên được xử lý riêng biệt. Một lần nữa, một ví dụ sẽ hữu ích. Bảng dữ liệu cho EEPROM 24C16 mà chúng tôi sẽ thử nghiệm cho biết bốn bit đầu tiên (quan trọng nhất) của địa chỉ phụ là 1010. Ba bit tiếp theo có thể được xác định bởi A0, A1 và A2; nhưng lưu ý rằng bảng dữ liệu cũng bao gồm 24C01 đến 24C08 là các EEPROM có kích thước nhỏ hơn. Hình từ bảng dữ liệu cho thấy cài đặt của các bit địa chỉ này bị bỏ qua khi kích thước tăng lên và hoàn toàn bị bỏ qua đối với 24C16. Đó là, ba bit cuối cùng không quan trọng và 24C16 thực sự sử dụng tất cả các địa chỉ nô lệ I2C từ 50 đến 57 hệ thập lục phân. Phạm vi địa chỉ phụ sẽ thực sự giải quyết các phần khác nhau trong 24C16. 256 byte đầu tiên ở địa chỉ 50h, 256 byte tiếp theo ở 51h, và tiếp tục lên đến 256 byte cuối cùng ở 57h - với tổng số 2K byte. Vì địa chỉ của RAM PCF8570 mà chúng tôi thử nghiệm cũng nằm trong phạm vi này nên 24C16 và PCF8570 không thể được sử dụng cùng nhau.

Bước 2: Đặt hàng một số thiết bị I2C

Bây giờ bạn đã biết một chút về I2C Bus và muốn sử dụng nó, tại sao không đặt hàng một số thiết bị I2C để thử nghiệm ngay bây giờ để chúng có thể đến với bạn trong khi bạn đang chuẩn bị phần mềm? Các thiết bị phù hợp bao gồm I / O Interface Expander (yêu thích của tôi), Ram tĩnh và EEPROM. Còn rất nhiều nữa, nhưng đây là một khởi đầu tuyệt vời. Các bộ xử lý AVR mà chúng tôi sẽ sử dụng là ATtiny2313 và Atmega168 (được sử dụng trong Arduino). Nếu bạn là người mới làm quen với những thứ này, thì hãy xem Tài liệu hướng dẫn tuyệt vời này để tìm hiểu về chúng và xây dựng Hệ thống phát triển khu ổ chuột của bạn. Sơ đồ của ATmega168 trong Bản có thể hướng dẫn hiện tại cho thấy cách triển khai Hệ thống phát triển khu ổ chuột cho bộ xử lý này. Cáp cổng song song giống như cáp của ATtiny2313. (Tôi chưa thử phiên bản USB của Hệ thống phát triển Ghetto, vì vậy tôi không chắc chắn cách truy cập bus I2C trên đó. Tương tự đối với Arduino.) Dưới đây là số bộ phận của Digikey. MỞ RỘNG 568-4236-5-NDRam: IC SRAM 256X8 W / I2C 568-1071-5-NDEEPROM: IC EEPROM SERIAL 16K CAT24C16LI-G-ND

Bước 3: Trình điều khiển I2C

Dưới đây là mô tả các chức năng của trình điều khiển cho bus I2C. Chúng được phát triển bằng Atmel Apps Notes cho người mới bắt đầu. Tôi không thể làm được điều này nếu không có chúng làm cơ sở để xây dựng. Quá trình phát triển được thực hiện bằng WinAVR và trình biên dịch gcc C. Các giới hạn về tốc độ xung nhịp được mô tả bên dưới cho từng bộ xử lý. Vì tôi không thể kiểm tra tất cả các kết hợp hương vị bộ xử lý / tốc độ xung nhịp có thể, tôi sẽ chỉ dựa vào những gì tôi thực sự có thể kiểm tra và cố gắng chỉ ra các hạn chế và hạn chế. Dưới đây là các chức năng của trình điều khiển và cách sử dụng chúng. Vui lòng xem các ví dụ để biết thêm chi tiết và để xem các chức năng được sử dụng trong các chương trình hoàn chỉnh. Nếu bạn muốn chạy ở tốc độ khác, thì bạn sẽ phải điều chỉnh các hằng số trong trình điều khiển. Gửi email cho tôi nếu bạn cần trợ giúp làm việc này. Bạn cũng có thể nhận được một số gợi ý từ ghi chú ứng dụng Atmel trong các liên kết trong Bước tài nguyên. USI_TWI_Master_Initialise () Chức năng này khởi tạo phần cứng USI cho hoạt động ở chế độ I2C. Gọi nó một lần khi bắt đầu chương trình của bạn. Nó trả về void và không có đối số. USI_TWI_Get_State_Info () Hàm này trả về thông tin lỗi I2C và được sử dụng nếu có lỗi xảy ra trong giao dịch I2C. Vì hàm này chỉ trả về mã lỗi nên tôi sử dụng hàm TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) để nhấp nháy đèn LED báo lỗi. Mã lỗi được xác định trong USI_TWI_Master.h. Đây là cách gọi nó: TWI_Act_On_Failure_In_Last_Transmission (USI_TWI_Get_State_Info ()) USI_TWI_Start_Read_Write () Hàm này được sử dụng để đọc và ghi từng byte vào thiết bị I2C. Nó cũng được sử dụng để ghi nhiều byte. Có 6 bước để sử dụng chức năng này. unsigned char messageBuf (MESSAGEBUF_SIZE); 2) Đặt Địa chỉ Slave làm byte đầu tiên trong bộ đệm. Chuyển nó sang trái một chút và HOẶC trong bit Đọc / Ghi. Lưu ý rằng bit Đọc / Ghi sẽ là 1 cho một Đọc và 0 cho một Ghi. Ví dụ này dành cho Đọc. messageBuf (0) = (TWI_targetSlaveAddress << TWI_ADR_BITS) | (TRUE << TWI_READ_BIT); 3) Khi thực hiện ghi, hãy đặt byte sẽ được ghi vào vị trí tiếp theo trong bộ đệm. 4) Gọi hàm USI_TWI_Start_Read_Write với bộ đệm thông báo và kích thước thông báo là các đối số. Giá trị trả về (tạm thời trong trường hợp này) có thể được kiểm tra để xem có lỗi xảy ra hay không. Nếu vậy, nó được xử lý như đã thảo luận ở trên. Xem ví dụ trong chương trình. 6) Nếu yêu cầu Đọc, byte đọc sẽ nằm ở vị trí thứ hai trong bộ đệm. Thiết lập bộ đệm và gọi quy trình hơi khác nhau. Byte thứ hai trong bộ đệm sẽ là địa chỉ bộ nhớ bắt đầu để ghi. Dữ liệu được ghi sẽ ở dạng byte tiếp theo. Kích thước thư sẽ là kích thước bao gồm tất cả dữ liệu hợp lệ. Vì vậy, nếu 6 byte được ghi, thì kích thước thông báo sẽ là 8 (địa chỉ phụ + địa chỉ bộ nhớ + 6 byte dữ liệu). USI_TWI_Start_Random_Read () Hàm này được sử dụng để đọc nhiều byte từ thiết bị I2C, thường thì nó chỉ có ý nghĩa đối với một ký ức của một số loại. Việc sử dụng quy trình này rất giống với quy trình trước đó, với hai ngoại lệ, việc thiết lập bit Đọc / Ghi không quan trọng. Việc gọi quy trình này sẽ luôn gây ra hoạt động Đọc. Kích thước thông báo phải là 2 cộng với số byte được đọc. Nếu không có lỗi xảy ra, dữ liệu sẽ nằm trong bộ đệm bắt đầu từ vị trí thứ hai. trình điều khiển được thiết kế cho tốc độ xung nhịp 4MHz cho ATmega168. Mã ví dụ cho thấy cách đặt tốc độ đồng hồ này. Nếu bạn muốn chạy ở tốc độ khác, thì bạn sẽ phải điều chỉnh các hằng số trong trình điều khiển. Gửi email cho tôi nếu bạn cần thực hiện việc này. TWI_Master_Initialise () Hàm này khởi tạo phần cứng TWI cho hoạt động của chế độ I2C. Gọi nó một lần khi bắt đầu chương trình của bạn. Nó trả về void và không có đối số. Đảm bảo bật ngắt bằng cách gọi swi () sau khi khởi tạo. TWI_Get_State_Info () Hàm này trả về thông tin lỗi I2C và được sử dụng nếu có lỗi xảy ra trong giao dịch I2C. Vì hàm này chỉ trả về mã lỗi nên tôi sử dụng hàm TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) để nhấp nháy đèn LED báo lỗi. Mã lỗi được xác định trong TWI_Master.h, nhưng được sửa đổi để báo hiệu trên đèn LED báo lỗi. Xem mã ví dụ để biết chi tiết. Đây là cách gọi nó: TWI_Act_On_Failure_In_Last_Transmission (TWI_Get_State_Info ()) Lưu ý rằng việc kiểm tra lỗi được thực hiện bằng cách đảm bảo rằng giao dịch I2C đã hoàn tất (chức năng được mô tả bên dưới) và sau đó kiểm tra một chút trong từ trạng thái toàn cục. TWI_Start_Read_Write () TWI_Start_Random hai chức năng hoạt động giống như các chức năng tương ứng được mô tả ở trên nhưng có một vài ngoại lệ, chúng không trả về bất kỳ giá trị lỗi nào. Dữ liệu đọc không được chuyển vào bộ đệm. Khi gọi TWI_Start_Random_Read, messageSize phải là số byte dữ liệu được yêu cầu cộng với một chứ không phải hai. Trình điều khiển I2C cho ATmega168 được điều khiển ngắt. Nghĩa là, các giao dịch I2C được bắt đầu và sau đó thực hiện độc lập trong khi quy trình chính tiếp tục chạy. Khi quy trình chính muốn có dữ liệu từ một giao dịch I2C mà nó đã bắt đầu, nó phải kiểm tra xem dữ liệu có sẵn hay không. Tình hình kiểm tra lỗi cũng vậy. Quy trình chính phải đảm bảo rằng giao dịch I2C đã hoàn tất trước khi kiểm tra lỗi. Hai hàm tiếp theo được sử dụng cho những mục đích này. TWI_Transceiver_Busy () Gọi hàm này để xem giao dịch I2C đã hoàn tất chưa trước khi kiểm tra lỗi. Các chương trình ví dụ cho thấy cách sử dụng hàm này. TWI_Read_Data_From_Buffer () Gọi hàm này để chuyển dữ liệu từ bộ đệm nhận của trình điều khiển I2C vào bộ đệm tin nhắn. Chức năng này sẽ đảm bảo giao dịch I2C hoàn tất trước khi chuyển dữ liệu. Trong khi một giá trị được trả về bởi hàm này, tôi thấy việc kiểm tra bit lỗi trực tiếp sẽ đáng tin cậy hơn. Đây là cách gọi nó. Kích thước thông báo phải lớn hơn số bit dữ liệu mong muốn. Dữ liệu sẽ có trong messageBuf bắt đầu từ vị trí thứ hai.temp = TWI_Read_Data_From_Buffer (messageBuf, messageSize);

Bước 4: Hãy xây dựng

Nào cùng xây!
Nào cùng xây!
Nào cùng xây!
Nào cùng xây!
Nào cùng xây!
Nào cùng xây!
Nào cùng xây!
Nào cùng xây!

Bắt đầu bằng cách tải xuống tệp I2C Schearies.zip. Bạn có thể muốn tạo một thư mục I2C trong khu vực làm việc của mình để chứa các sơ đồ và các tệp chương trình mẫu. Giải nén các giản đồ vào thư mục này. Bạn sẽ tìm thấy một thư mục có tên là I2C Sơ đồ. Mở tệp có tên I2C.pdf nhỏ. Sơ đồ này cho thấy Hệ thống phát triển khu ổ chuột ATtiny2313 và Bộ mở rộng cổng I / O PCA8574A (có hộp gạch ngang lớn xung quanh nó). Mạch Port Expander được xây dựng trên một breadboard. Hãy xem các bức ảnh để xem những mạch này trông như thế nào. Chúng thực sự khá đơn giản. chi tiết bổ sung. Chi tiết đó là việc bổ sung jumper (JP4, 5 và 6) có thể được loại bỏ để cho phép kết nối các đường SCL và SDA của bus I2C. Các jumper phải có sẵn để lập trình, sau đó được tháo ra để SCL và SDA có thể được kết nối. Các bức ảnh cho thấy các jumper tại chỗ và loại bỏ. Vị trí của các jumper này là tùy thuộc vào bạn, bạn chỉ cần đặt chúng vào Hệ thống Phát triển Ghetto của mình nếu bạn muốn sử dụng xe buýt I2C. Bus I2C phải được ngắt kết nối và đặt jumper vào vị trí để lập trình. Lưu ý rằng bạn chỉ thực sự cần quan tâm đến JP4 và JP6 cho bus I2C. Đặt JP5 nếu bạn nghĩ rằng bạn sẽ muốn sử dụng bus SPI. Breadboarding PCA8574A I / O Port Expander rất đơn giản. Cung cấp các kết nối Vcc (+5 volt) và Gnd (nối đất) và kết nối AD0, 1 và 2 với mặt đất (làm cho địa chỉ phụ I2C là 38 hex). Sau đó kết nối 4 đèn nháy và 4 công tắc DIP. (Nếu bạn không có công tắc DIP, bạn chỉ có thể sử dụng dây. Buộc vào đất hoặc để nổi để bật hoặc tắt tín hiệu tương ứng.) Cuối cùng, kết nối các điện trở kéo lên (R11 và 12) từ SDA và SCL với Vcc. Chúng được hiển thị dưới dạng 3,3K, nhưng bất kỳ giá trị nào từ 1,8K đến 5,1K sẽ hoạt động (có thể lên đến 10K nhưng tôi chưa thử điều đó). Khi bạn đã lập trình ATtiny2313, bạn có thể loại bỏ các jumper và kết nối SDA và SCL để thử nghiệm. Bây giờ là ATmega168. Khó khăn duy nhất ở đây là bạn có thể chưa xây dựng Hệ thống phát triển khu ổ chuột cho bộ xử lý này. Nếu đúng như vậy, thì sơ đồ tôi cung cấp (MEGA I2C.pdf) sẽ chỉ cho bạn cách thực hiện. Đây chỉ là một hoán vị của phiên bản ATtiny2313. Nếu bạn có kế hoạch trước, bạn có thể đảm bảo rằng cáp lập trình của bạn sẽ phù hợp với cả hai hệ thống. Sự khác biệt chính là việc bổ sung C2 và C3. Xem các hình ảnh để biết vị trí của chúng, chúng phải rất gần với con chip; một trong số chúng thực sự nằm dưới chip. Những điều này giúp loại bỏ tiếng ồn từ bộ chuyển đổi tương tự sang kỹ thuật số nói riêng. Bạn không cần đặt jumper trừ khi bạn định sử dụng bus SPI vì chúng không cần thiết cho bus I2C trên chip này. Lưu ý rằng breadboard PCA8754A sẽ không thay đổi. Bạn sẽ chỉ cần kết nối SDA và SCL và bạn sẽ đi! Dễ dàng, hả?

Bước 5: Hãy viết mã và kiểm tra

Hãy viết mã và thử nghiệm!
Hãy viết mã và thử nghiệm!
Hãy viết mã và thử nghiệm!
Hãy viết mã và thử nghiệm!
Hãy viết mã và thử nghiệm!
Hãy viết mã và thử nghiệm!

Đã đến lúc xây dựng các trình điều khiển và các chương trình ví dụ. Chúng ta sẽ bắt đầu với ATtiny2313 và breadboard PCA8574A mà chúng ta vừa tạo. Tải xuống tệp I2C.zip vào thư mục làm việc I2C của bạn và giải nén nó. Bạn sẽ có một thư mục mới có tên I2C. Trong đó, bạn sẽ tìm thấy USI I2C (cho ATtiny2313) và TWI I2C (cho ATmega168). Trong USI I2C, bạn sẽ tìm thấy thư mục I_O Port. Thư mục đó chứa mã cho chương trình ví dụ đầu tiên của chúng tôi và các trình điều khiển USI I2C. Sử dụng WinAVR, biên dịch và tải mã vào ATtiny2313. Hít thở sâu và bật nguồn. Đây là những gì mong đợi: Khi bật nguồn, đèn LED 1 trên cổng PD6 của ATtiny2313 nhấp nháy hai lần. Sẽ không có điều gì khác xảy ra cho đến khi bạn nhấn nút (S1). Mỗi lần nhấn nút, các công tắc sẽ được đọc và cài đặt của chúng sẽ được hiển thị trên các đèn LED được kết nối với PCA8574A. Thay đổi giá trị của các công tắc, nhấn nút và đèn LED sẽ thay đổi. Tiếp tục làm điều này cho đến khi bạn vượt qua cảm giác hồi hộp khi thấy nó hoạt động. Nếu (Chúa cấm!) Mọi thứ không hoạt động như mong đợi, hãy cẩn thận kiểm tra hệ thống dây điện của bạn. Lỗi I2C sẽ được báo hiệu bằng nhấp nháy trên LED3 (PD4) và có thể có nghĩa là bạn cần kiểm tra xem SDA và SCL đã được kết nối với đúng chân và được kéo lên chính xác chưa. Nếu mọi thứ vẫn không hoạt động, hãy đọc phần còn lại của phần này để tìm hiểu về cách gỡ lỗi. Bây giờ hãy quay lại và xem mã. Mở tệp USI_I2C_Port.c. Đây là mã cho chương trình ví dụ. (USI_TWI_Master.c và USI_TWI_Master.h chứa các trình điều khiển - bạn có thể bỏ qua chúng trừ khi bạn tò mò.) Sử dụng ví dụ để hướng dẫn các ứng dụng I2C của riêng bạn. lên địa chỉ nô lệ và phần còn lại của bộ đệm thư, và lấy dữ liệu ra khỏi đó. Bạn cũng sẽ thấy cách tôi gỡ bỏ nút và thiết lập vòng lặp while. Có một vài chi tiết của chương trình đáng nói. Lưu ý rằng dữ liệu từ các công tắc được đảo ngược trước khi nó được ghi vào các đèn LED trên Bộ mở rộng cổng. Cũng lưu ý rằng các cổng đầu vào trên Port Expander phải được viết là Cao để chúng hoạt động bình thường. Những chi tiết đó được mô tả trong bảng dữ liệu PCA8574A. Luôn đọc kỹ các bảng dữ liệu! Điều đáng quan tâm hơn là việc sử dụng gỡ lỗi có điều kiện. Gần đầu tệp chương trình là câu lệnh // # define DEBUG và rải khắp mã là câu lệnh #ifdef DEBUG. Miễn là DEBUG không được xác định (hai dấu gạch chéo làm cho dòng trở thành nhận xét và giữ cho nó không được xác định), mã trong các câu lệnh #ifdef đến #endif sẽ không được biên dịch. Nhưng nếu mọi thứ không hoạt động như bạn mong đợi, hãy biên dịch lại và tải lại mã với #define DEBUG không ghi chú. Bạn sẽ nhận được nhiều nhấp nháy hơn trên các đèn LED mà bạn có thể giải mã để theo dõi quá trình thực hiện chương trình của mình và hỗ trợ bạn trong việc tìm ra chính xác nơi xảy ra sự cố. Trên thực tế, tôi khuyên bạn nên thử điều này chỉ để xem điều gì sẽ xảy ra. Những gì bạn sẽ thấy là đèn LED 2 (trên PD5) sẽ nhấp nháy khi tiến trình thực thi thông qua chương trình. Giá trị được đọc từ các công tắc sẽ được nhấp nháy trên LED 1 (PD6) trước khi nó được hiển thị trên các đèn LED của Port Expander. Bạn sẽ có thể theo dõi chương trình khi nó chạy bằng cách sử dụng các đèn LED này. Chúng tôi sẽ làm việc với ATmega168 tiếp theo; bỏ qua phần này nếu bạn chỉ quan tâm đến ATtiny2313. Vẫn còn với tôi? Tốt. Di chuyển đến thư mục TWI_I2C, thay đổi thư mục làm việc của bạn thành IO_Port, biên dịch và tải TWI_I2C_Port.c vào ATmega168. Ngắt kết nối các đường SDA và SCL khỏi ATtiny2313 và kết nối chúng với ATmega168. Kết nối nguồn và nối đất, và khởi động nguồn. Các hoạt động phải giống nhau! Chơi cho đến khi cảm giác hồi hộp giảm bớt, sau đó hãy xem mã. Mở TWI_I2C_Port.c. Mã này gần giống nhau ngoại trừ việc xử lý lỗi và điều chỉnh các trình điều khiển điều khiển gián đoạn. Dưới đây là những điểm khác biệt: Lưu ý rằng xung nhịp phải được đặt thành 4MHz để bus I2C hoạt động bình thường. Các sei (); câu lệnh bật ngắt sau khi khởi tạo trình điều khiển I2C. Để kiểm tra lỗi, một bit trạng thái cụ thể được kiểm tra. Trong quá trình đọc, hàm TWI_Read_Data_From_Buffer phải được gọi để chuyển dữ liệu đã đọc vào bộ đệm thông báo. Trong khi ghi, phải sử dụng while (TWI_Transceiver_Busy ()) để đảm bảo quá trình chuyển hoàn tất trước khi kiểm tra lỗi. Hai chức năng cuối cùng này được mô tả ở trên trong phần mô tả của trình điều khiển. Ngoài ra, mã này khá giống với ATtiny2313. DEBUG cũng hoạt động tương tự nếu bạn muốn thử nghiệm điều đó.

Bước 6: Sử dụng bộ nhớ I2C

Sử dụng bộ nhớ I2C
Sử dụng bộ nhớ I2C
Sử dụng bộ nhớ I2C
Sử dụng bộ nhớ I2C
Sử dụng bộ nhớ I2C
Sử dụng bộ nhớ I2C
Sử dụng bộ nhớ I2C
Sử dụng bộ nhớ I2C

Bây giờ chúng ta đã học cách sử dụng bus I2C để đọc và ghi I / O Port Expander, hãy chuyển sang sử dụng bộ nhớ I2C, cả RAM và EEPROM. Sự khác biệt chính là nhiều byte có thể được đọc hoặc ghi từ các bộ nhớ bằng một lệnh I2C duy nhất. Để sẵn sàng cho những thử nghiệm này, chúng tôi cần sửa đổi một chút phần cứng và xây dựng một vài mạch mới trên breadboard. Giữ mạch Port Expander vì chúng ta sẽ sử dụng nó để hiển thị một số giá trị bộ nhớ. Tháo các công tắc DIP khỏi PCA8574A và gắn đèn nháy vào các chân đó. Nếu bạn không có đủ đèn nháy, hãy chuyển các đèn từ P4 đến P7 qua P0 đến P3. (Các giá trị được hiển thị đủ nhỏ.) Bây giờ hãy nhìn vào I2C Ram.pdf sơ đồ và kết nối PCF8570 trên breadboard. Cũng có một cái nhìn vào hình ảnh. Đảm bảo buộc chốt 7 vào Vcc. Chạy dây cho SDA và SCL từ PCA8574A. Không cần thêm điện trở kéo lên. Nếu bạn cũng quan tâm đến EEPROM, hãy xây dựng mạch đó cũng bằng I2C EEPROM.pdf cho 24C16, nhưng hãy lưu ý rằng ví dụ sử dụng ATmega168. Mạch này thực sự đơn giản. Như đã thảo luận ở trên, các bit địa chỉ nên được bỏ qua. Chỉ cần nối nguồn và nối đất. Đừng kết nối SDA và SCL vì chúng tôi chưa hoàn thành thử nghiệm với Ram. Chúng tôi sẽ bắt đầu thử nghiệm bộ nhớ của mình với ATtiny2313 được kết nối với PCA8574A Port Expander và với PCF8570 Ram. Chương trình sẽ ghi một số số vào Ram, sau đó đọc lại và hiển thị chúng trên Port Expander. Thay đổi thư mục làm việc của bạn thành RAM theo USI I2C. Sử dụng tệp tạo để biên dịch và tải xuống USI_I2C_RAM.c. Lưu ý rằng các tệp trình điều khiển I2C giống hệt với những tệp chúng tôi đã sử dụng trước đó. Kết nối nguồn và bạn sẽ thấy một nhấp nháy duy nhất trên LED 1 (PD6). Dữ liệu sẽ được ghi vào 4 byte bộ nhớ đầu tiên. Nhấn nút và hai byte sẽ được đọc lại và hiển thị. Bạn sẽ thấy một đèn LED trên Bộ mở rộng cổng (P0), hai giây tạm dừng, sau đó hai đèn LED sáng (P0 và P1). Tạm dừng hai giây nữa và đèn LED sẽ tắt. Nhấn lại nút để bắt đầu lại trình tự. Gỡ lỗi tương tự như phương pháp được mô tả ở trên. Hãy xem mã. Mở USI_I2C_RAM.c. Nó sẽ trông khá giống với mã trước đó. Sự khác biệt chính là các chi tiết của bộ nhớ đọc và ghi. Nhìn vào cách bộ đệm tin nhắn được tải trước khi cuộc gọi thực sự ghi. Byte đầu tiên là địa chỉ tớ với bit đọc / ghi được thiết lập thích hợp. Nhưng byte tiếp theo là địa chỉ bộ nhớ để bắt đầu ghi dữ liệu. Sau đó đến các byte dữ liệu thực tế sẽ được tải tuần tự vào bộ nhớ bắt đầu từ địa chỉ mà chúng tôi đã chỉ định. Chúng tôi chỉ định kích thước thông báo là 6. Vì vậy, chúng tôi bắt đầu viết tại địa chỉ 00 và ghi các giá trị 01, 03, 02 và 06 vào các vị trí bộ nhớ 00 đến 03. Để đọc dữ liệu trở lại từ bộ nhớ, chúng tôi phải sử dụng hàm USI_TWI_Start_Random_Read. Bộ đệm thông báo lấy địa chỉ nô lệ trong byte đầu tiên và địa chỉ bắt đầu trong byte thứ hai. Sau đó, gọi hàm với kích thước tin nhắn được đặt thành số byte để đọc cộng với 2. Lưu ý rằng bit đọc / ghi không quan trọng vì quá trình đọc sẽ được thực hiện bất kể. Dữ liệu trả về sẽ bắt đầu ở vị trí thứ hai trong bộ đệm tin nhắn. Khi dữ liệu được đọc vào, nó sẽ được đảo ngược để hiển thị trên Port Expander và được ghi từng byte một vào nó với khoảng dừng giữa các giá trị. Cuối cùng, đèn LED Port Expander được tắt. Việc ghi vào Port Expander giống hệt với những gì đã được thực hiện trong các ví dụ trước. Để giải trí, bạn có thể bỏ ghi chú câu lệnh #define DEBUG như trên và thấy rất nhiều đèn LED nhấp nháy. Thay đổi thư mục làm việc của bạn thành EEPROM dưới TWI I2C. Sử dụng tệp tạo để biên dịch và tải xuống TWI_I2C_EEPROM.c. Lưu ý rằng các tệp trình điều khiển I2C giống với tệp chúng tôi đã sử dụng trước đó cho PCA8574A. Để kiểm tra chương trình, hãy ngắt kết nối ATtiny2313 và kết nối ATmega168. Để bus I2C được nối với Ram và bật nguồn. Các kết quả khác nhau vì chúng tôi hiện đang viết và đọc nhiều dữ liệu hơn. Đèn LED 1 trên PD7 sẽ nhấp nháy khi khởi tạo. Nhấn nút và dữ liệu sẽ được đọc lại từ bộ nhớ và hiển thị. Các đèn LED trên PCA8574 sẽ nhấp nháy theo trình tự sau: P1, P0 & P2, (tất cả đều tắt), P0 & P1, P1 & P2. Cuối cùng, tất cả các đèn LED Cổng sẽ tắt. Nhấn nút một lần nữa để lặp lại điều này. Ồ, nhưng hãy đợi, bạn nói. Đây không phải là chương trình dành cho EEPROM? Vì chúng ta đang truy cập một thiết bị nhớ tại cùng một địa chỉ I2C, nên chương trình tương tự hoạt động cho cả Ram và EEPROM. Tắt nguồn và di chuyển SDA và SCL từ Ram sang EEPROM và chạy lại chương trình. Nó sẽ hoạt động hoàn toàn giống nhau. Lưu ý rằng EEPROM và Ram không thể được kết nối với bus I2C cùng lúc vì chúng chia sẻ cùng một địa chỉ. (Những người thông minh trong số bạn có thể xem xét thay đổi các bit địa chỉ có thể lập trình trên Ram, nhưng điều đó vẫn không hoạt động. 24C16 sử dụng toàn bộ khối địa chỉ có thể được lập trình cho Ram.) OK, hãy xem chương trình cuối cùng này. Mở TWI_I2C_EEPROM.c. Điều đầu tiên cần chú ý là tôi đã chỉ ra cách giải quyết toàn bộ EEPROM 24C16. Nó có thể được truy cập theo khối 256 byte tại 8 địa chỉ I2C slave khác nhau. Xem cách MEMORY_ADDR được xác định làm địa chỉ bắt đầu ở 50 thập lục phân; đó là lý do tại sao Ram hoạt động. Nếu bạn muốn truy cập các khối khác của 24C16, hãy sử dụng các địa chỉ khác như tôi đã chỉ ra. Hãy xem cách tôi thiết lập để ghi vào bộ nhớ. Đầu tiên, địa chỉ phụ với tập bit đọc / ghi được đưa vào bộ đệm, sau đó là địa chỉ bắt đầu của 00, sau đó là 16 byte dữ liệu. Hàm TWI_Start_Read_Write được gọi để ghi dữ liệu (như trước đây) với kích thước thông báo được đặt là 18. Khi nhấn nút, chúng ta sử dụng TWI_Start_Random_Read và TWI_Read_Data_From_Buffer để đọc lại dữ liệu. Mỗi byte thứ ba được hiển thị trên các đèn LED của Port Expander. Cuối cùng, đèn LED được tắt để chờ lần nhấn nút tiếp theo. Bạn có thể thắc mắc tại sao tôi lại chọn viết 16 byte. Nếu bạn đọc kỹ bảng dữ liệu, bạn sẽ thấy rằng 24C16 thực hiện một chu kỳ ghi bất cứ khi nào nó nhận được 16 byte ngay cả khi nhiều byte hơn đang được gửi đi. Vì vậy, đó có vẻ như là một con số đẹp để sử dụng. Nếu bạn chọn tăng mức này, bạn sẽ phải thay đổi kích thước của MESSAGEBUF_SIZE. Bạn cũng sẽ phải thay đổi giá trị TWI_BUFFER_SIZE trong TWI_Master.h. Điều này là do trình điều khiển sao chép dữ liệu từ bộ đệm thông báo để sử dụng bởi quy trình dịch vụ ngắt. Xin chúc mừng! Bây giờ bạn đã sẵn sàng sử dụng bus I2C trong các dự án của riêng mình!

Bước 7: Tài nguyên web

Dưới đây là các liên kết đến bảng dữ liệu cho các phần được sử dụng cho các thí nghiệm. Bạn chắc chắn sẽ nhận được những thứ này nếu bạn không có gì khác. (Họ thích sử dụng dấu ngoặc vuông trong URL của họ, vì vậy tôi không thể đưa chúng vào đây một cách chính xác. Xin lỗi.] Để đến khu vực I2C, hãy chọn Giao diện từ danh sách Sản phẩm. Bạn sẽ có thể truy cập trang web I2C của họ và truy cập vào tất cả các bảng dữ liệu và ghi chú ứng dụng mà họ cung cấp. Mô tả cụ thể về bus I2C và chi tiết kỹ thuật cụ thể ở đây. Lấy bảng dữ liệu ATtiny2313 và ATmega168 (sổ dữ liệu?) từ Atmel. Ghi chú ứng dụng Atmel ở đây. Nhìn vào AVR310 và AVR315. Lấy mã cũng được. Hãy xem ở đây để biết thêm nhiều nội dung I2C.

Bước 8: Ghi chú cho Geeks

Đối với những người đam mê thực sự muốn biết chi tiết, đây là một số điều cần lưu ý nếu bạn xem Atmel Apps Notes và mã trình điều khiển: - Phương pháp định địa chỉ và chỉ huy thiết bị I2C không phải là một phần của thông số kỹ thuật! Ngoài địa chỉ phụ và bit đọc / ghi, các lệnh, chế độ, v.v. không được chỉ định và dành riêng cho một thiết bị nhất định. Để làm cho điều này thật rõ ràng, hãy lưu ý rằng lược đồ được sử dụng trong ví dụ Atmel chỉ áp dụng cho ví dụ đó và không phải là tiêu chuẩn khá nhiều. - Việc triển khai USI khác với việc triển khai TWI theo một số cách quan trọng. + Với USI, tính năng đồng hồ được cung cấp bởi phần mềm; với TWI, nó được cung cấp bởi Bộ tạo tốc độ bit. + Phương pháp USI không sử dụng ngắt; TWI thì có. Điều này có ý nghĩa nhất định vì gia đình Mega (sử dụng TWI) có thể làm nhiều việc khác và không bị ảnh hưởng bởi chuyển I2C. Một phiên bản điều khiển gián đoạn cho USI chắc chắn là có thể, chỉ là nó không được triển khai trong Có thể hướng dẫn này. + Phần cứng USI không được tối ưu hóa cho I2C và chỉ có thể xử lý truyền 8 bit. Điều này có nghĩa là cần phải có hai lần chuyển để gửi bit thứ chín (NACK hoặc ACK). Phần cứng TWI tự động xử lý việc này. Điều này làm cho việc triển khai trình điều khiển USI phức tạp hơn một chút. + Phát hiện lỗi cho TWI được xử lý trong phần cứng. USI yêu cầu xử lý trong phần mềm khiến mọi thứ hơi phức tạp. + Phần cứng TWI điều khiển cấu hình của cổng trực tiếp. Phần cứng USI yêu cầu cấu hình các bit cổng trước khi cổng có thể được sử dụng. Bạn sẽ thấy điều này trong quy trình Master_Initialize cho USI.- Atmel tuyên bố rằng có thể sử dụng các cổng AVR kéo lên cho các lần kéo lên bus I2C. Tôi chưa tìm ra cách để làm cho cách tiếp cận đó hoạt động. Sử dụng hai điện trở bên ngoài có vẻ như là một kế hoạch khá đơn giản, vì vậy tôi đã không dành nhiều thời gian cho việc này.

Đề xuất: