[ENC28J60] Bài 3: Khởi tạo module enc28j60 – giao tiếp enc28j60 (phần 2)

ENC28j60

Trong phần trước của chuỗi bài giao tiếp enc28j60 chúng ta đã viết các hàm cơ bản để đọc ghi vào các thanh ghi. Phần này chúng ta sẽ tiếp tục hoàn thiện chức năng khởi tạo chip !

Muốn biết làm sao để khởi tạo chip thì các bạn mở datasheet mục 6 người ta có hướng dẫn từng bước 1 luôn nhé !

Các bạn chuyển tới hàm ENC29J600_ini chúng ta đã viết sẵn ngay từ đầu, đầu tiên mình sẽ reset mềm lại module bằng nhón lệnh Opcode = System Command (Soft Reset) (SC) = 0xFF

Các bạn thêm #define cho nó vào file .h nhé

Trong hàm khởi tạo

Bởi vì command thuộc nhóm reset nhận data là N/A tức là gì cũng được nên mình sẽ gửi byte 0 cho nó !

Trong datasheet trang 5 có nói, sau khi khởi tạo, nên có 1 khoảng thời gian trễ (khoảng 7500 chu kì máy) và nên kiểm tra bit CLKRDY trong ESTAT. Nếu bit này đã được set bằng 1 thì mọi thứ đã sẵn sàng. Do vậy mình sẽ thêm lệnh kiểm tra bit này nữa !

Hãy nhớ thêm định nghĩa cho các bit và thanh ghi ESTAT và file .h nhé !

Ngoài ra, do mình xài delay_ms nên chúng ta cũng cần add thêm thư viện <delay.h> mà phần mềm CodeVison AVR hỗ trợ vào file enc28j60.h

Ở đoạn chương trình trên, sau khi khởi tạo, mình delay 1 khoảng nhỏ rồi liên tục kiểm tra bit ESTAT_CLKRDY bằng vòng lặp while

Sau khi reset xong, để chắc chắn module có hoạt động, mình sẽ kiểm tra thử thanh ghi ERDPTL (ở 0x00 bank0 )trong bảng TABLE 3-2: ENC28J60 CONTROL REGISTER SUMMARY thanh ghi này luôn có giá trị là 0xFA, ta sẽ căn cứ vào nó để kiểm tra module còn hoạt động không !

thanh ghi của enc28j60

Các bạn định nghĩa thanh ghi này vào file .h nhé

// Bank 0 registers #define ERDPT (0x00|0x00)

Đến thời điểm này, hàm khởi tạo module của mình sẽ như sau:

Trước khi viết tiếp hàm khởi tạo, chúng ta thử gọi hàm này vào hàm main trước vòng lặp while(1) để test qua tí đã chứ nhỉ 🙂 viết nhiều rồi test thành quả tí đã

giao tiếp enc28j60

Chạy mô phỏng thử khi có kết nối ic ENC28J60 thì sẽ không thấy thông báo thất bại !

giao tiếp enc28j60


Còn khi xóa ic ENC28J60 đi thì dòng khởi tạo thất bại ngay lập tức được in ra !

giao tiếp enc28j60

Rồi ok ! Tiếp tục viết thêm mã khởi tạo trong phần else của hàm khởi tạo nhé !

Các bạn có thể xem mục 6 (INITIALIZATION) trong datasheet để hiểu hơn về cách khởi tạo module nhé !

Mục 6.1 datasheet yêu cầu ta phải khởi tạo cho Receive Buffer qua thanh ghi ERXST ERXND. Tương tự với Transmission Buffer cũng cần được khởi tạo tại ETXSTETXND

Thực tế, khi coi bản đó thanh ghi của chip ( TABLE 3-2: ENC28J60 CONTROL REGISTER SUMMARY ) các bạn sẽ không thay cái thanh ghi nào tên ERXST đâu, bởi nó là thanh ghi có độ dài tới 16bit, nên thằng ENC28J60 nó chia ra thành 2 thanh ghi nhỏ 8bit tên là ERXSTL ERXSTH. Có rất nhiều thanh ghi 16bit như vậy, do đó mình sẽ viết thêm 1 hàm để ghi value 16bit vào 2 cho tiện

(thêm nguyên mẫu hàm vào file .h nhé)

OK, quay trở lại hàm ENC29J600_ini chúng ta sẽ khởi tạo Receive Buffer (bộ đệm nhận) và ( Transmission Buffer ) như thế nào ?

Ethernet Buffer

Mục 3.2 datasheet

ENC28J60 có 8Kb Ram cho bộ đệm phục vụ truyền nhận các gói tin ! Chúng ta tùy ý cấu hình phần vùng cho miếng nào là nhận, miếng nào là truyền.
Địa chỉ của bộ đệm bắt đầu từ 0x00 đến 0x1FFF

bộ đệm trong chip enc28j60

Ở đây mình sẽ chia cho bộ đệm nhận 3K bộ nhớ bắt đầu từ 0x00 đến 0x0BF, còn bộ đệm truyền là 5K bắt đầu từ 0xC00 tới hết (0x1FFF)

bộ đệm trong chip enc28j60

Chúng ta #define các thông số sau vào file .h

Mình cũng #define địa chỉ của các thanh ghi ERXST ERXND ETXST ETXND
(mình gán địa chỉ của thanh ghi L cho nó)

Vì các thanh ghi này đều thuộc bank0 nên mình sẽ or thêm 0x00 ( các bạn để cạnh thanh ghi ERDPT lúc nãy đã #define cho tiện theo dõi)

Rồi, bỏ chương trình cấu hình buffer vào chỗ else của hàm ENC29J600_ini nào !

Đồng thời mình cũng reset con trỏ của bộ đệm truyền nhận về vị trí Start luôn nhé

Tiếp tục

Tiếp tục quá trình khởi tạo, ở mục 6.3 của datasheet , hắn có nói chúng ta nên cấu hình thanh ghi ERXFCON. OK thôi, xem thanh ghi này có gì nào…

giao tiếp enc28j60

Thanh ghi này có chưa các bit điều khiển chức năng lọc các gói tin, đây là chức năng nâng cao, tạm thời mình sẽ không xài đến chức năng này, mình sẽ code nhưng để comment dòng lệnh này đi, chưa cần dùng vội, sau này sẽ tính đến nó sau !

Cũng đừng quên thêm các #define cho thanh ghi này vào file .h nhé

Tiếp tục ở mục 6.4 của datasheet thì mục này chúng ta đã code ngay từ đâu lun rồi

Tiếp tục tới mục 6.5, nó có tên là MAC Initialization Settings tức là cấu hình địa chỉ MAC

Cấu hình địa chỉ MAC

Địa chỉ MAC là cái quái gì ? Nó là địa chỉ vật lí của 1 thiết bị mạng, dùng để phần biệt với các thiết bị khác trong mạng ! Nó là 1 địa chỉ cố định được gán vào vởi nhà sản xuất ( tức chúng ta )

Địa chỉ MAC là một bộ sáu cặp hai ký tự, cách nhau bằng dấu hai chấm. Ví dụ 00:1B:44:11:3A:B7 là một địa chỉ MAC

Địa chỉ MAC khác địa chỉ IP chỗ nào

Địa chỉ IP được sử dụng để truyền dữ liệu từ mạng này sang mạng khác. Địa chỉ MAC được sử dụng để phân phối dữ liệu đến đúng thiết bị trên mạng.

Địa chỉ IP giống như địa chỉ nhà, còn địa chỉ MAC là tên người nhận

ENC28J60 là 1 thiết bị mang, nó cũng cần có 1 địa chỉ MAC, và chính chúng ta là người gán địa chỉ MAC cho nó !

Các bước để cấu hình địa chỉ MAC datasheet 6.5 đã nói rất rõ, các bạn có thể tự đọc thêm nếu muốn nhé:

Đầu tiên là set các bit MARXEN TXPAUS RXPAUS PASSALL trong thanh ghi MACON1. Rồi clear thanh ghi MACON2 .

Rồi set các bit PADCFG0 TXCRCEN FRMLNEN trong thanh ghi MACON3. Rồi set giá trị 0xC12 cho thanh ghi MAIPG.

Thanh ghi MABBIPG cũng nên được set giá trị 0x12 như datasheet khuyên.

Tương tự với thanh ghi MAMXFL cũng nên được cấu hình = 1518 đổ lại

Không lan man nữa, mình sẽ đi vào code luôn, trước tiên phải thêm các #define cho các thanh ghi đã đúng không 🙂

Nếu để ý các bạn sẽ thấy các thanh ghi ở bank2 mình còn OR thêm 0x80, để làm gì lát mình sẽ nói

Điền địa chỉ MAC

Chúng ta sẽ điền địa chỉ MAC cho module vào 6 thanh ghi từ MMADR0 đến MMADR5

Tiếp tục #define 5 địa chỉ này vào file .h nhé, ngoài ra mình cũng #define thêm địa chỉ MAC của module vào

Nếu để ý các bạn sẽ thấy các thanh ghi ở bank3 mình còn OR thêm 0x80, để làm gì lát mình sẽ nói

OK, giờ mình sẽ thêm code để điền mac vào thanh ghi chứa MAC nhé

Trước hàm ENC29J600_ini mình khai bảo thêm 1 mảng macaddr[6] để lưu địa chỉ MAC mà mình thiết lập cho chip !

Tiếp tục code khởi tạo

Để chắc chắn đã ghi MAC vào đúng, mình thử đọc ra xem thế nào nhé !
Mình sẽ khởi tạo thêm mảng mymac[6] để lưu địa chỉ mac đọc ra ! Đồng thời, khởi tạo thêm mảng debug_string[60] để phục vụ việc in ra màn serial debug

Tiếp tục thêm code vô hàm khởi tạo

Sửa lại hàm ENC28J60_read_command

Chúng ta sẽ đọc địa chỉ MAC đã set bằng hàm ENC28J60_read_command, tuy nhiên hãy nhìn lại mục 4.2.1 trong datasheet

đọc data trong ecn28j60

Khi đọc các thanh ghi liên quan đến MAC và MII thì byte đầu tiên đọc ra sẽ là byte dummy (byte rác), byte thứ hai mới đúng là data ta cần. Do vậy, hàm ENC28J60_read_command mình sẽ sửa lại như sau:

Mình đã thêm vào dòng lệnh kiểm tra bit cao nhất của byte địa chỉ có được set không, nếu được set thì sẽ gọi hàm đọc nhưng không lấy kết quả vì đó là byte rác, lần đọc thứ 2 mình mới lấy ! Đó là lí do vì sao khi #define các byte địa chỉ có kiên quan đến MAC ở trên mình có OR nó thêm với 0x80

Do các byte địa chỉ chỉ xài có 5bit thấp, 2 bit tiếp dùng để xác định bank, nên bit cuối (bit cao nhất) sẽ dùng để xác định byte này có thuộc loại MAC hay MII không để tránh byte rác (không hiểu mấy ông design con chip này tính kiểu gì luôn 🙁 )

Rồi, giờ đọc địa chỉ MAC đã ghi xem có đúng với ban đầu không !

giao tiếp enc28j60

Kết quả : chúng ta đã ghi thành công địa chỉ MAC

Như vậy, qua trình khởi tạo chip cơ bản là đã xong 70% !

Trong bài tiếp, chúng ta sẽ tiếp tục viết các hàm để làm việc với các thanh ghi thuộc lớp vật lí và hoàn thành hàm khởi tạo chip !

Download

Các bạn tải source cho bài này tại đây

Bài tiếp theo ! của chuỗi bài giao tiếp enc28j60

 

Từ tác giả:

Nếu có bất kì thắc mắc nào trong bài viết, vui lòng để lại comment dưới mỗi bài ! Mình sẽ không trả lời thắc mắc của các bạn ở facebook hay email !

Nếu trong phần code bạn nhìn thấy nhưng thứ kiểu như &amp; thì đó là lỗi hiển thị, cụ thể 3 kí tự < > & bị biến đổi thành như thế
&amp; là &
&lt;  là <
&gt; là >

Giới thiệu Đào Nguyện 80 bài viết
DIY,chế cháo, viết blog chia sẽ kiến thức về lập trình,điện tử - IoT. Rất mong được giao lưu, kết bạn với các bạn cùng đam mê. Địa chỉ Facebook: https://www.facebook.com/nguyendao207

1 bình luận

  1. Em chào a ạ! Anh cho e hỏi “ENC28J60_readByte(ERDPT) != 0xFA” nếu debug chạy từng dòng lệnh thì ra đúng 0xFA còn “run” thì không ra ạ? (em dùng stm32f103cbt6)

Đã đóng bình luận.