Vòng lặp chính (main loop)

Một phần của tài liệu đề tài module ethernet trên vi điều khiển pic18f67j60 và ứng dụng trong đo lường, điều khiển ( phần mềm trên mplab ) (Trang 44 - 66)

Khi chương trình được khởi tạo, ta sẽ tạo một vòng lặp vô hạn để thực hiện các nhiệm vụ của ứng dụng. Trong vòng lặp có hai hàm phải được gọi thường xuyên là StackTask() và StackApplications.

Hàm StackTask sẽ được gọi ở bất kỳ thời điểm nào khi Stack yêu cầu và sẽ điều khiển sự truyền nhận các gói dữ liệu.

Hàm StackApplications sẽ gọi những module ứng dụng được gọi. Ví dụ nếu sử dụng HTTP2 server, StackApplications sẽ tự động gọi hàm HTTPServer để thực hiện bất kỳ nhiệm vụ nào của HTTP đang được đợi.

Trong vòng lặp chính, ta có thể hỏi vòng cho bất kỳ sự thay đổi I/O nào và gọi bất kỳ một nhiệm vụ đặc biệt của ứng dụng mà bạn thực hiện. Để tránh tràn bộ đệm

trong phần cứng hoặc vi phạm sự định thời của giao thức, ta sẽ thực hiện các nhiệm vụ trong hàm callback với các trigger định thời cơ sở.

Ta sẽ phải gọi hàm StackTask mỗi khi gọi hàm StackApplications.

5.3. Các module của Stack và APIs

Microchip TCP/IP Stack bao gồm rất nhiều module. Để sử dụng được bất kì một module nào ta phải nắm rõ mục đích của nó và APIs.

5.3.1. Announce

Module này làm cho việc phát hiện ra thiết bị trở nên dễ dàng bằng việc truyền một tin nhắn UDP trên cổng 30303 bất kỳ khi nào địa chỉ IP thay đổi. Cổng được sử dụng bởi module Announce có thể được thay đổi được bằng cách sửa ở marco trong file Announce.c

#define ANNOUNCE_PORT 30303

Giao thức Announce được thiết kế để sử dụng cho phần mềm Ethernet Device Discoverer và MCHPDetect trên máy tính.

Module Announce bao gồm 2 hàm:

- AnnounceIP: AnnounceIP mở 1 socket UDP và truyền 1 gói tin đến cổng 30303. Nếu máy tính nằm trong cùng 1 subnet và tiện ích đang tìm kiếm 1 gói tin trên cổng UDP thì nó sẽ nhận gói tin này. Module này có nhiệm vụ thông báo việc thay đổi IP của mạch. Tin nhắn được hiển thị bằng phần mềm MCHPDetect.exe.

Cú pháp: void AnnounceIP();

- DiscoveryTask: Hàm này được sử dụng liên tục để lắng nghe tin nhắn trên cổng Announe. Các tin nhắn có thể gửi bằng cách sử dụng công cụ Microchip Device Discoverer.

Cú pháp: void DiscoveryTask();

Các hàm trên chỉ nên được truy cập bởi chính Stack. Ứng dụng không nên gọi các hàm trên và thay đổi các biến.

5.3.2. HTTP2 server

Module HTTP2 web server và file MPFS2 liên quan của nó cho phép mạch hoạt động như một webserver. Nó tạo ra một phương pháp đơn giản để hiển thị thông tin trạng thái và điều khiển các ứng dụng bằng cách sử dụng một trình duyệt web thông thường.

Ba thành phần chính phục vụ cho module HTTP2 web server là: web pages, phần mềm MPFS2.exe và hai file nguồn CustomHTTPApp.c và HTTPPrint.h.

Hình 25: Sơ đồ khối Web pages

Bao gồm tất cả file HTML và ảnh kèm theo, CSS Stylesheets, các file JavaScript cần thiết để hiển thị một trang web.

Phần mềm MPFS2

- Phần mềm này được cung cấp bởi Microchip, các trang web được gói lại thành một định dạng và lưu trữ trong bộ nhớ chương trình flash nội hoặc bộ nhớ ngoài. Chương trình này sẽ tìm các biến động trong các trang web và tự động cập nhật các biến này trong file HTTPPrint.h.

- Nếu bộ nhớ ngoài được sử dụng, phần mềm MPFS2 sẽ tạo ra một file BIN và có thể tải trực tiếp lên mạch. Còn nếu dữ liệu được lưu trong bộ nhớ chương trình flash thì phần mềm MPFS2 sẽ tạo ra một file đuôi .c và được chèn vào project.

- Khi các biến động được thêm vào hoặc bỏ đi, phần mềm MPFS2 sẽ cập nhật cho file HTTPPrint.h. Sau đó ta phải dịch lại project để đảm bảo các biến mới đã được thêm vào project.

Hình 26: Phần mềm MPFS2

File CustomHTTPApp.c

Thực hiện các ứng dụng của web. Nó mô tả đầu ra cho các biến động ( thông qua hàm callbacks HTTPPrint_varname), phân tích dữ liệu được gửi thông qua trang web forms.htm ( sử dụng 2 hàm HTTPExecuteGet và HTTPExecutePost) và xác nhận thông tin truy cập ( bằng hàm HTTPAuthenticate).

File HTTPPrint.h (adsbygoogle = window.adsbygoogle || []).push({});

File này được tạo tự động bởi phần mềm MPFS2. Nó định nghĩa tất cả các biến động và tạo ra một mối liên hệ giữa các biến trong trang web và hàm callbacks HTTPPrint_varname liên quan trong file CustomHTTPApp.c.

Module HTTP2 web server bao gồm các tính năng sau:

5.3.2.1. HTTP2 Dynamic Variables

Một trong những tính năng cơ bản nhất là cập nhật cái thông tin trạng thái của mạch đến người sử dụng thông qua giao diện web. Các lệnh trong mã HTML sẽ thông báo cho server thực hiện các hàm callbacks tại thời điểm đó.

Để tạo ra một biến động, chỉ cần đặt tên của biến bên trong một cặp ký tự (~) trong mã nguồn các trang web HTML (ví dụ: ~ myVariable ~). Khi ta chạy chương

trình MPFS2 để tạo ra các trang web, nó sẽ tự động định nghĩa những biến này trong file HTTPPrint.h. Ví dụ: sử dụng biến động builddate, mã HTML là:

<div class="examplebox code">~builddate~</div>

Hàm callback liên quan trong file CustomHTTPApp.c sẽ in giá trị lên trang web: void HTTPPrint_builddate(void)

{

TCPPutROMString(sktHTTP,(ROM void*)__DATE__); }

5.3.2.2. HTTP2 Form Processing

Nhiều ứng dụng cần lấy dữ liệu từ người sử dụng. Một phương pháp thông thường sử dụng web forms.htm. web forms sử dụng 2 phương pháp GET và POST và HTTP2 web server hỗ trợ cả 2 phương pháp này.

- Phương pháp GET

• Phương pháp GET sẽ gán dữ liệu vào cuối URL. Dữ liệu này sẽ đứng sau dấu chấm hỏi (?) ở trên thanh địa chỉ của trình duyệt. (Ví dụ:

http://mchpboard/form.htm?led1=0&led2=1&led3=0). Dữ liệu được gửi bằng phương pháp GET sẽ tự động được giải mã và được lưu trong biến mảng curHTTP.data. Vì dữ liệu này được lưu trong bộ nhớ, cho nên nó được giới hạn bởi kích thước của biến mảng curHTTP.data, mặc định là 100 bytes.

• Hàm callback HTTPExecuteGet sẽ xử lý dữ liệu này và thực hiện một số nhiệm vụ cần thiết. Hai hàm HTTPGetArg và HTTPGetROMArg giúp dễ dàng lấy dữ liệu cho quá trình xử lý.

- Phương pháp POST

• Phương pháp POST truyền dữ liệu sau khi các header yêu cầu đã được gửi. Dữ liệu không được hiển thị trong thanh địa chỉ của trình duyệt như phương pháp GET mà chỉ được nhìn thấy bởi một công cụ bắt gói tin. Mặc dù vậy, phương pháp này sử dụng cùng cách mã hóa URL giống phương pháp GET.

• HTTP2 server không thực hiện bất kỳ sự phân tích trước các dữ liệu này. Tất cả dữ liệu POST nằm trong bộ đệm TCP, vì vậy các ứng dụng sẽ truy cập trực tiếp vào bộ đệm TCP để lấy và giải mã nó. Các hàm HTTPReadPostName và HTTPReadPostValue sẽ thực hiện công việc này.

5.3.2.3. HTTP2 Authentication

Các giao thức HTTP cung cấp một phương pháp cho các máy chủ yêu cầu một tên người dùng và mật khẩu của khách hàng trước khi cấp quyền truy cập đến trang đó.

Chức năng xác thực này được hỗ trợ bởi hai hàm callback. Thứ nhất, là hàm HTTPNeedsAuth, xác định xem trang web hiện tại có yêu cầu sự xác thực hay không. Thứ hai, là hàm HTTPVerifyAuth, so sánh tên người dùng và mật khẩu với một danh sách được chấp nhận, nếu đúng sẽ cho phép truy cập, nếu sai sẽ bị từ chối truy cập.

- Yêu cầu xác thực

• Đầu tiên, hàm HTTPNeedsAuth sẽ được gọi để xác định xem trang có yêu cầu password hay không. Hàm này sẽ trả về giá trị để hướng dẫn HTTP server phải thực hiện như thế nào. Hàm trả về giá trị 0x80 hoặc cao hơn để cho phép truy cập vô điều kiện và trả về giá trị 0x79 hoặc thấp hơn để yêu cầu nhập lại tên người sử dụng và password. Giá trị trả lại được lưu trong curHTTP.isAuthorized để nó có thể được truy cập bởi các hàm callback trong lần tiếp theo.

• Ví dụ sau đây là trường hợp đơn giản, trong đó tất cả các tập tin yêu cầu một mật khẩu để truy cập:

BYTE HTTPNeedsAuth(BYTE* cFile) {

return 0x00; }

• Trong một số trường hợp, chỉ có một số tập tin sẽ cần phải được bảo vệ. Ví dụ thứ hai đòi hỏi một mật khẩu cho bất kỳ tập tin nằm trong thư mục /treasure:

{

// Compare to "/treasure" folder. Don't use strcmp here, because // cFile has additional path info such as "/treasure/gold.htm" (adsbygoogle = window.adsbygoogle || []).push({});

if(!memcmppgm2ram((void*)cFile, (ROM void*)"treasure", 5)) return 0x00;

return 0x80; }

- Thông tin xác thực: Hàm HTTPCheckAuth xác định xem tên và password mà người dùng cung cấp có hợp lệ để truy cập hay không. Giá trị trả lại được lưu trong curHTTP.isAuthorized để nó có thể được truy cập bởi các hàm callback trong lần tiếp theo.

5.4. Cấu hình cho Stack

5.4.1. Cấu hình cho phần cứng

Hầu như việc cấu hình phần cứng được thực hiện bằng cách thêm dấu // vào trước các dòng lệnh để làm mất tác dụng của những dòng lệnh hoặc bỏ // đi để Mplab thực hiện các dòng lệnh đó, định nghĩa một loạt các macro ở phần đầu của file HardwareProfile.h.

Trong hầu hết các trường hợp, các macro dùng để khởi tạo các mạch demo phải giống như các macro dùng để định nghĩa vi điều khiển sử dụng trong mạch. Trong file HardwareProfile.h mặc định đã bao gồm các project cho một số mạch có sẵn của Microchip, được giới hạn bằng các câu lệnh tiền xử lý. Ví dụ với Explorer 16 sẽ bắt đầu bằng macro "#elif defined (EXPLORER_16)" và tiếp tục cho đến những câu lệnh tiền xử lý cho một mạch demo khác.

5.4.1.1. Tần số

Nhiều hoạt động của TCP/IP phụ thuộc vào thời gian. Để thiết lập giá trị xung clock ta thay thế giá trị của xung clock trong macro trong file HardwareProfile.h:

#define GetSystemClock() xxxxxxxxxxxxxxx Ngoài ra còn 2 macro thiết lập xung clock khác:

• GetInstructionClock () và GetPeripheralClock () cung cấp tần số lệnh và tần số cho thiết bị ngoại vi của vi điều khiển.

5.4.1.2. Bộ nhớ ngoài

Bộ nhớ ngoài dùng để lưu trữ Web nhúng, Web ở đây định dạng http và http2. Bộ nhớ dùng để lưu trữ có thể có 3 loại: SD/MMD (Memory Card), EEPROM, Flash Serial.

Nếu muốn dùng Web nhúng, ta có thể lưu trữ vào bộ nhớ nội. Lúc ấy, cần tạo một file bộ nhớ của Web định dạng MPFS. Để tạo ra file định dạng MPFS thì Microchip đã đưa ra công cụ MPFS2 trong folder /Utilities để chuyển toàn bộ dữ liệu Web thành một file duy nhất. Web phải được đưa vào một folder, đối với trình dịch C18 thì file được xuất ra là MPFSImg2.c.

Để sử dụng Web nhúng trong bộ nhớ nội, trong file TCPIPconfig.h bỏ thiết lập dùng bộ nhớ ngoài, và #include MPFSImg2.c trong chương trình maindemo.c. Đặt lại tên mặc định của Web server là index.htm trong file TCPIPConfig.h.

Bỏ lưu trữ trong EEPROM và Flash memory: //#define MPFS_USE_EEPROM

//#define MPFS_USE_SPI_FLASH

5.4.2. Địa chỉ

5.4.2.1. Địa chỉ MAC

6 byte địa chỉ MAC cung cấp địa chỉ cho lớp giao thức Media Access Control của TCP/IP Stack. Địa chỉ MAC là địa chỉ cố định gắn liền với phần cứng.

Địa chỉ MAC được định nghĩa trong file TCPIPConfig.h. Có 6 macro được định nghĩa trong file này để thiết lập địa chỉ MAC:

#define MY_DEFAULT_MAC_BYTE1 (0x00) #define MY_DEFAULT_MAC_BYTE2 (0x04) #define MY_DEFAULT_MAC_BYTE3 (0xA3) #define MY_DEFAULT_MAC_BYTE4 (0x00) #define MY_DEFAULT_MAC_BYTE5 (0x00) #define MY_DEFAULT_MAC_BYTE6 (0x00)

Tuy nhiên, vi điều khiển PIC 18F67J60 đã được tích hợp sẵn địa chỉ MAC cho nên ta không cần phải quan tâm đến việc thiết lập địa chỉ này.

5.4.2.2. Địa chỉ IP

Địa chỉ IP dùng để định địa chỉ cho các nút mạng trên mạng giao thức Internet. Chúng ta cần cấu hình cho mạch một địa chỉ IP.

Địa chỉ subnet là một mặt nạ bit xác định phạm vi của mạng. Nếu địa chỉ IP của bạn là 192.168.5.100, và bạn chỉ định subnet mask là 255.255.255.0, Stack sẽ cho rằng địa chỉ trong phạm vi 192.168.5.x là trên cùng một subnet mà ta đang có, và các gói tin sẽ được gửi đến bất kỳ một địa chỉ trong mạng này mà không được gửi đến nơi khác.

Gateway mặc định là địa chỉ IP của nút mạng mà nó sẽ gửi gói tin đến nếu như không được định hướng đến địa chỉ IP mà ta mong muốn. Ví dụ, nếu địa chỉ IP ta đặt nằm trong mạng con 192.268.5.x, và nếu nó muốn gửi một gói tin đến địa chỉ IP 198.175.253.160 mà không biết chính xác phải gửi đến địa chỉ đó như thế nào, nó sẽ gửi đến gateway mặc định.

Có ba phương pháp để thiết lập địa chỉ IP:

- DHCP: Các module DHCP client sẽ cho phép ứng dụng tự động lấy địa chỉ IP từ máy chủ DHCP trên cùng một mạng. Việc làm này sẽ thiết lập lại địa chỉ IP, subnet mask, địa chỉ gateway, và các thông số cấu hình một số khác trong cấu trúc AppConfig. Để sử dụng DHCP ta phải nạp ba file DHCP.c; DHCPs.c ; DHCP.h và khai báo " #define STACK_USE_DHCP_CLIENT" trong TCPIPConfig.h.

- AutoIP: Module này cho phép ứng dụng chọn một địa chỉ IP và tự xác nhận địa chỉ đó. Để sử dụng AutoIP ta phải nạp hai file AutoIP.c and AutoIP.h và khai báo "#define STACK_USE_AUTO_IP" trong TCPIPConfig.h. (adsbygoogle = window.adsbygoogle || []).push({});

- Địa chỉ IP tĩnh: Việc sử dụng địa chỉ IP tĩnh chỉ hoạt động nếu server được cấu hình để hỗ trợ địa chỉ đó.

Nếu sử dụng DHCP và AutoIP đồng thời thì module AutoIP sẽ phát một địa chỉ trong subnet 169.254.x.x sau đó sẽ cấp một địa chỉ khác trong cùng subnet đến DHCP client được kết nối với board.

5.5. Demo module

Demo module chứa một số các ứng dụng thông thường:

- Web page demo: Xây dựng 1 chương trình HTTP sử dụng HTTP2 server và điều khiển 1 số đặc trưng (hiện thị nhiệt độ, điều khiển led, viết ra LCD) thông qua giao diện web.

- E-mail ( SMTP) Demo: Sử dụng e-mail client để gửi đi 1 tin nhắn khi 1 sự kiện xảy ra.

- Generic TCP Client: Xây dựng 1 ứng dụng TCP Client thông qua HTTP Client example.

- Generic TCP Server: Xây dựng ứng dụng TCP Server. - Ping (ICMP) demo: Xây dựng Ping Client.

Trong nội dung đồ án này em xin trình bày về web page demo, cụ thể là điều khiển led sáng tắt, viết ra LCD, hiện thị thông số nhiệt độ thông qua giao diện web.

Module HTTP web server và file đi kèm MPFS2 làm cho board như là một web server. Nó cho phép dễ dàng hiển thị thông tin lên LCD hoặc điều khiển sử dụng trình duyệt web.

5.5.1. Điều khiển led sáng tắt

- Gõ đường link trên trình duyệt http:/192.168.1.2/forms.htm.

- Chọn On/Off trong ô lựa chọn để đặt trạng thái cho từng led rồi ấn nút save để lưu trạng thái cho các led.

Hình 27: Điều khiển LED và viết lên LCD.

Để thực hiện được việc này ta sử dụng phương pháp GET:

- Phương pháp Get gán dữ liệu vào phần cuối của URL. Dữ liệu được gán sau dấu “?” trên thanh địa chỉ. Dữ liệu được gửi qua phương pháp GET tự động được giải mã và lưu trong biến curHTTP.data (curHTTP là biến cấu trúc để lưu trạng thái hiện tại của kết nối HTTP, một số biến trong cấu trúc curHTTP như curHTTP.byteCount, curHTTP. isAuthorized, biến mảng curHTTP.data…), biến curHTTP.data được giới hạn 100bytes. Khi biến curHTTP.data đầy thì dữ liệu sẽ được lưu vào trong bộ nhớ.

Code trong file forms.htm

Hình 28: Code trong file forms.htm

- Giả sử ta kick vào led 1 và 3. Một chuỗi sau sẽ được gửi đến server: GET /leds.htm?led1=1&led3=1 HTTP/1.1

- HTTP2 web server sẽ phân tích yêu cầu này và lưu dưới dạng một chuỗi trong biến curHTTP.data : "led1\01\0led3\01\0\0"

- Web server sẽ gọi hàm HTTPExecuteGet để xử lý đầu vào này. Mục đích của nó là phân tích những dữ liệu nhận được từ các tham số URL.

Code:

HTTP_IO_RESULT HTTPExecuteGet(void) {

BYTE *ptr;

BYTE filename[20]; // Load the file name

// Make sure BYTE filename[] above is large enough for your longest name MPFSGetFilename(curHTTP.file, filename, 20);

// If its the forms.htm page

if(!memcmppgm2ram(filename, "forms.htm", 9)) {

// Seek out each of the four LED strings, and if it exists set the LED states

ptr = HTTPGetROMArg(curHTTP.data, (ROM BYTE *)"led4"); if(ptr) (adsbygoogle = window.adsbygoogle || []).push({});

LED4_IO = (*ptr == '1');

ptr = HTTPGetROMArg(curHTTP.data, (ROM BYTE *)"led3"); if(ptr)

LED3_IO = (*ptr == '1');

ptr = HTTPGetROMArg(curHTTP.data, (ROM BYTE *)"led2"); if(ptr)

LED2_IO = (*ptr == '1');

ptr = HTTPGetROMArg(curHTTP.data, (ROM BYTE *)"led1"); if(ptr)

LED1_IO = (*ptr == '1'); }

return HTTP_IO_DONE; }

Đầu tiên, hàm MPFSGetFilename sẽ được gọi để kiểm tra trang forms.htm được truy cập. Hàm MPFSGetFilename sẽ đọc tên file truy cập hiện tại và lưu vào trong biến filename. Sau đó ta sử dụng memcmppgm2ram(filename, "forms.htm", 9) để so sánh xem biến filename có giá trị là "forms.htm" hay không. Nếu giống nhau thì hàm

Một phần của tài liệu đề tài module ethernet trên vi điều khiển pic18f67j60 và ứng dụng trong đo lường, điều khiển ( phần mềm trên mplab ) (Trang 44 - 66)