Tiếp tục với hàm khởi tạo chip ở bài trước trong chuỗi bài lập trình enc28j60, ở bài này chúng ta sẽ cấu hình và khởi tạo cho các thanh ghi thuộc nhóm PHY
Thông tin về các PHY Registers nằm ở phần 3.3 datasheet
Các thanh ghi thuộc PHY đều là loại 16bit và không thể trực tiếp truy cập qua giao tiếp SPI, các truy cập vào PHY đều gián tiếp thông qua các thanh ghi được gọi là MII
READING PHY REGISTERS
Để đọc 1 thanh ghi PHY
- Ghi địa chỉ của thanh ghi đó vào thanh ghi MIREGADR
- Set bit MICMD.MIIRD để bắt đầu thao đac đọc, bit MISTAT.BUSY (bit báo bận) sẽ được set
- Đợi 10.24uS, thăm dò bit MISTAT.BUSY để chắc chắn hoạt động đọc hoàn thành
- Khi hoàn thành, bit MISTAT.BUSY sẽ tự xóa, chúng ta xóa thủ công bit MICMD.MIIRD và lấy giá trị mong muốn từ thanh ghi MIRDL và MIRDH
WRITING PHY REGISTERS
Để ghi 1 thanh PHY
- Ghi địa chỉ của thanh ghi đó vào thanh ghi MIREGADR
- Ghi giá trị 8bit thấp vào MIWRL
- Ghi giá trị 8bit cao vào MIWRH
- Ngay sau đó MISTAT.BUSY tự động được set
- Sau khoảng 10.24uS, quá trình ghi hoàn tất, bit bận sẽ tự xóa
Khá đơn giản phải không. Viết 2 hàm ghi và đọc PHY thôi nào 🙂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
static void ENC28J60_writePhy(uint8_t addres,uint16_t data) //ham ghi PHY { ENC28J60_writeByte(MIREGADR, addres); ENC28J60_writeByte16(MIWR, data); while(ENC28J60_readByte(MISTAT)&MISTAT_BUSY); //cho het ban } static uint16_t ENC28J60_readPhy(uint8_t addres) //ham doc PHY { uint16_t value; ENC28J60_writeByte(MIREGADR, addres); ENC28J60_writeByte(MICMD, MICMD_MIIRD); //set bit MICMD_MIIRD bat dau doc while(ENC28J60_readByte(MISTAT)&MISTAT_BUSY); //cho het ban ENC28J60_writeByte(MICMD,0x00); //clear bit MICMD_MIIRD value = ENC28J60_readByte(MIRDL) + ((uint16_t)ENC28J60_readByte(MIRDH)<<8) ; //doc gia tri trong 2 thanh gho MIWR return value; //tra ve gia tri } |
Đừng quên thêm nguyên mẫu hàm vào file .h và thêm cả #define cho các thanh ghi PHY và MII nhé !
1 2 3 4 5 6 7 |
//-------------------------------------------------- //MII read registers and bit #define MICMD (0x12|0x40|0x80) //thanh ghi nay thuoc bank 2 nen OR 0x40 #define MICMD_MIIRD 0x01 #define MIRDL (0x18|0x40|0x80) #define MIRDH (0x19|0x40|0x80) #define MISTAT_BUSY 0x01 |
Bây giờ cấu hình lớp vật lý PHY trong hàm khởi tạo
Quay trở lại mục 6.6 trong datasheet để xem nhưng thứ cần khởi tạo nhé !
Dưới đây là 1 số khởi tạo thanh ghi PHY theo datasheet yêu cầu, mình cũng set các bit trong thanh ghi EIE để cho phép ngắt
1 2 3 4 5 6 7 8 |
//**********Advanced Initialisations************// ENC28J60_writePhy(PHCON2,PHCON2_HDLDIS); ENC28J60_writePhy(PHLCON,PHLCON_LACFG2|PHLCON_LBCFG2|PHLCON_LBCFG1|PHLCON_LBCFG0|PHLCON_LFRQ0|PHLCON_STRCH); ENC28J60_SetBank (ECON1); ENC28J60_write_command (ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); ENC28J60_writeByte(ECOCON,0x02); delay_us(15); ENC28J60_write_command (ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); // cho phép nhan gói |
Và thêm #define địa chỉ cho các thanh ghi và bit PHY và 1 số bit trong thanh ghi EIE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#define EIE 0x1B // ENC28J60 EIE Register Bit Definitions #define EIE_INTIE 0x80 #define EIE_PKTIE 0x40 #define EIE_DMAIE 0x20 #define EIE_LINKIE 0x10 #define EIE_TXIE 0x08 #define EIE_WOLIE 0x04 #define EIE_TXERIE 0x02 #define EIE_RXERIE 0x01 #define ECOCON (0x15|0x60) //thanh ghi nay thuoc bank 3 nen OR 0x60 // PHY registers #define PHCON1 0x00 #define PHSTAT1 0x01 #define PHHID1 0x02 #define PHHID2 0x03 #define PHCON2 0x10 #define PHSTAT2 0x11 #define PHIE 0x12 #define PHIR 0x13 #define PHLCON 0x14 //-------------------------------------------------- #define PHCON2_HDLDIS 0x0100 //-------------------------------------------------- // PHLCON #define PHLCON_LACFG3 0x0800 #define PHLCON_LACFG2 0x0400 #define PHLCON_LACFG1 0x0200 #define PHLCON_LACFG0 0x0100 #define PHLCON_LBCFG3 0x0080 #define PHLCON_LBCFG2 0x0040 #define PHLCON_LBCFG1 0x0020 #define PHLCON_LBCFG0 0x0010 #define PHLCON_LFRQ1 0x0008 #define PHLCON_LFRQ0 0x0004 #define PHLCON_STRCH 0x0002 |
Đối với 2 đền LED trên cổng RJ45, nó cũng có hẳn 1 thanh ghi PHY, nhưng mình sẽ để mặc định và không cấu hình thêm
Vậy là quá trình khởi tạo cho module lúc khởi động đã hoàn tất !
Các bạn có thể tải source cho bài này tại đây
Trong bài tiếp theo – lập trình enc28j60, chúng ta sẽ làm việc với bộ đệm TX RX và viết các hàm để ghi đọc các gói tin trên bộ đệm !
Các bạn có thể xem lại các bài trước tại đây:
Cảm ơn vì bài hướng dẫn của anh, em có một vài thắc mắc mong anh giải đáp.
1. #define MICMD (0x12|0x40|0x80) //thanh ghi nay thuoc bank 2 nen OR 0x40
Anh | 0x80 có mục đích gì vậy anh?
2. #define PHLCON_STRCH 0x0002 … #define PHLCON_LACFG3 0x0800
của thanh ghi PHLCON em có xem qua datasheet nhưng không biết được địa chỉ của mấy thằng này PHLCON_STRCH, PHLCON_LACFG3… anh xem nó ở đây vậy ạ?
3. anh có thể giải thích thêm về đoạn này được không ạ
//**********Advanced Initialisations************//
cảm ơn anh!
1. Mình có giải thích rồi mà
2. Trong datasheet nó có địa chỉ LOW và HIGH của các thanh ghi đó, địa chỉ LOW đứng trước địa chỉ HIGH, mình chỉ cần lấy địa chỉ LOW là sẽ biết địa chỉ HIGH thôi. Không cần mất công định nghĩa 2 cái