Phần 6: Demo lập trình trực tiếp ESP8266 với thư viện SDK

Wearable

Tiếp tục phần 6 của loạt bài viết tìm hiểu cách sử dụng ESP8266 trong các ứng dụng Internet Of Things. Trong bài này chúng ta sẽ thảo luận chi tiết hơn về các hàm API chính để lập trình sử dụng các module peripheral của ESP8266 như UART, GPIO, I2C, v.v… khi lập trình trực tiếp với ESP8266.

1/ Sử dụng các hàm API của Non-RTOS SDK

Như đã biết, ESP8266 hỗ trợ các module peripheral sau: GPIO, UART, I2C, SPI, TIMER, PWM. Do SPI đã được sử dụng để giao tiếp với Flash chip chứa chương trình thực thi nên chúng ta sẽ không thảo luận các API liên quan đến SPI.

Làm việc với GPIO

ESP8266 có tổng cộng 17 chân GPIO, trong đó 4 chân đã được sử dụng để giao tiếp với Flash chip trên board nên chúng ta chỉ có thể sử dụng 13 chân GPIO còn lại cho ứng dụng của mình mà thôi.

Các file code để làm việc với GPIO bao gồm:

  • C:\Espressif\ESP8266_SDK\include\driver\gpio.h
  • C:\Espressif\ESP8266_SDK\driver_lib\include\driver\gpio16.h
  • C:\Espressif\ESP8266_SDK\driver_lib\include\driver\gpio16.c

File libdriver.a là file thư viện các API để truy xuất các thanh ghi điều khiển phần cứng của ESP8266, chúng ta thêm thư viện này trong Makefile trong Eclipse khi compile chương trình. File gpio.h chính là file header khai báo các hàm API trong libdriver.a cho GPIO; còn file gpio16.h và gpio16.c là các file giúp chúng ta làm việc GPIO0 là chân đặc biệt vì liên quan đến chức năng RTC.

Trong các sample project liên quan đến GPIO khi chúng ta setup môi trường Eclipse được giới thiệu trong phần 5, chúng ta có thể thấy file gpio16.c được viết thêm để quản lý tất cả GPIO bằng cách gọi các hàm API từ gpio.h. Do đó chúng ta có thể dùng lại file gpio16.c mới này để làm việc với các chân GPIO bao gồm cả GPIO0

Ví dụ các bạn có thể tham khảo trong C:\Espressif\examples\ESP8266\gpio16_led\driver\gpio16.c và C:\Espressif\examples\ESP8266\gpio16_led\include\driver\gpio16.h

Các hàm API được cung cấp bao gồm:

  • int set_gpio_mode(unsigned pin, unsigned mode, unsigned pull)
    Chúng ta sẽ gọi hàm này để cấu hình chức năng cho chân GPIO cụ thể như input/output/interrupt và có pull up/pull down hay không. Giá trị cho “pin” là từ 0 đến 12 tương ứng cho 13 GPIO có thể sử dụng như sau:

Pin 0 = GPIO16                 Pin 1 = GPIO5                    Pin 2 = GPIO4                   Pin 3 = GPIO0
Pin 4 = GPIO2                   Pin 5 = GPIO14                  Pin 6 = GPIO12                 Pin 7 = GPIO13
Pin 8 = GPIO15                 Pin 9 = GPIO3                    Pin 10 = GPIO1                 Pin 11 = GPIO9
Pin 12 = GPIO10

  • void gpio_intr_attach(gpio_intr_handler cb)
    Dùng để đăng ký hàm callback khi có interrupt từ module GPIO
  • int gpio_intr_init(unsigned pin, GPIO_INT_TYPE type)
    Dùng để cấu hình interrupt cho chân GPIO như ngắt theo cạnh lên/xuống hay ngắt theo mức
  • int gpio_write(unsigned pin, unsigned level)
    Dùng để điều khiển chân GPIO output mức 0/1
  • int gpio_read(unsigned pin)
    Dùng để đọc giá trị 0/1 của chân GPIO

Lưu ý khi sử dụng thư viện gpio16.c này, trong hàm callback khi interrupt, chúng ta chỉ cần kiểm tra chân GPIO cần xử lý, nếu đúng là chân GPIO thì thực hiện code chương trình cho ngắt, nếu không đúng thì thoát mà không cần quan tâm xóa cờ ngắt vì code bên trong gpio16.c đã xử lý việc xóa cờ ngắt rồi.

Dễ dàng phải không nào. Chỉ cần xử dụng các hàm được cung cấp bởi gpio16.c thì chúng ta đã có thể làm việc với GPIO mà không cần quan tâm đến các thanh ghi điều khiển bên dưới rất tiện lợi và nhanh chóng

Làm việc với I2C

ESP8266 không có phần cứng cho I2C mà sử dụng các chân GPIO để tạo tín hiệu I2C để giao tiếp với các IC khác trên board. Chúng ta có thể gọi loại I2C này software I2C và thư viện I2C của ESP8266 chỉ hộ trợ chức năng của Master I2C. Software I2C trên ESP8266 có tần số tối đa là 100kHz

Các file cần để làm việc với I2C:

  • C:\Espressif\ESP8266_SDK\driver_lib\include\driver\i2c_master.h
  • C:\Espressif\ESP8266_SDK\driver_lib\driver\i2c_master.c

Các hàm API để làm việc với I2C bao gồm:

  • void i2c_master_gpio_init(void)   và   void i2c_master_init(void)
    Chúng ta sẽ gọi khi khởi động để cấu hình các chân GPIO cho I2C và điều khiển GPIO để tạo tín hiệu ban đầu trên bus I2C
  • void i2c_master_start(void)
    Điều khiển chân GPIO để tạo tín hiệu START theo chuẩn I2C
  • void i2c_master_stop(void)
    Điều khiển chân GPIO để tạo tín hiệu STOP trên bus I2C sau khi truyền nhận dữ liệu hoàn thành
  • void i2c_master_send_ack(void)   và    void i2c_master_send_nack(void)
    Điều khiển chân GPIO để gửi tín hiệu ACK hoặc NAK trên bus I2C sau khi nhận được dữ liệu từ 1 Slave I2C
  • uint8 i2c_master_getAck(void)
    Kiểm tra xem Slave I2C có gửi ACK khi nhận được dữ liệu truyền từ ESP8266
  • uint8 i2c_master_readByte(void)
    Đọc 1 byte dữ liệu trên bus I2C
  • void i2c_master_writeByte(uint8 wrdata)
    Gửi 1 byte dữ liệu trên bus I2C

Mặc định thì GPIO2 làm tín hiệu SDA và GPIO14 làm tín hiệu SCL. Chúng ta có thể sử dụng chân GPIO khác bằng cách thay đổi các macro trong file i2c_master.h

Chúng ta có thể thấy thư viện cho I2C trên ESP8266 chỉ sử dụng GPIO để tạo các tín hiệu theo chuẩn I2C và chỉ hỗ trợ vai trò Master I2C. Ngoài ra chúng ta cũng không có FIFO, DMA, ngắt phần cứng khi truyền nhận dữ liệu trên I2C cũng như việc tạo tín hiệu START/STOP/ACK/NAK đều phải thực hiện trực tiếp bằng cách gọi các hàm tương ứng; do đó có thể nói I2C trên ESP8266 có thể dùng để giao tiếp 1 cách đơn giản với các sensor I2C không yêu cầu tốc độ cao.

Làm việc với PWM

Tương tự I2C, chúng ta cũng có software PWM từ thư viện SDK của ESP8266. Software PWM của ESP8266 sử dụng hardware timer là FRC1 và NMI interrupt để tạo xung PWM tại các chân GPIO đã chọn. Thư viện cho PWM hỗ trợ tối đa 8 channels với duty cycle khác nhau nhưng cùng chung tần số xung (chúng ta không thể tạo các xung PWM với các tần số khác nhau từ các hàm API cho PWM trong SDK)

Tần số xung PWM có thể cấu hình từ 100Hz – 1kHz với độ phân giải của duty cycle là 45ns

Các file cần để làm việc với PWM bao gồm:

  • C:\Espressif\ESP8266_SDK\include\pwm.h

Các hàm API của PWM sẽ được định nghĩa trong file thư viện /lib/libdriver.a mà chúng ta sẽ add vào trong Makefile khi biên dịch code ứng dụng. Lưu ý là software PWM sử dụng hardware TIMER để hoạt động; do đó chúng ta không thể sử dụng hardware TIMER nếu đã sử dụng chức năng PWM

Các hàm API cho software PWM:

  • void pwm_init(uint32 period, uint32 *duty,uint32 pwm_channel_num,uint32 (*pin_info_list)[3])
    Khởi động module PWM với thông tin bao gồm tần số PWM, duty cycle , channel nào, và output ra chân GPIO nào
    Chúng ta có thể xác lập nhiều xung PWM ra nhiều chân GPIO bằng cách tạo các mảng *duty và mảng cho *pin_info_list ví dụ như:

uint32 io_info[][3] = { {PWM_0_OUT_IO_MUX,PWM_0_OUT_IO_FUNC,PWM_0_OUT_IO_NUM},
{PWM_1_OUT_IO_MUX,PWM_1_OUT_IO_FUNC,PWM_1_OUT_IO_NUM},
{PWM_2_OUT_IO_MUX,PWM_2_OUT_IO_FUNC,PWM_2_OUT_IO_NUM},
};
u32 duty[3] = {600,604,634};
pwm_init(1000, duty, 3, io_info);

Lưu ý period có đơn vị là us, duty được tính bằng công thức (duty cycle * 45)/(period * 1000)

  • void pwm_start(void)
    Bắt đầu chạy hardware Timer và tạo xung PWM ra chân GPIO
  • uint32 pwm_get_period(void)    và     uint32 pwm_get_duty(uint8 channel)
    Đọc lại giá trị period / duty đã cấu hình
  • void pwm_set_period(uint32 period) và void pwm_set_duty(uint32 duty, uint8 channel)
    Thay đổi tần số xung PWM và duty cycle của từng channel

Khá là đơn giản phải không nào. Chúng ta có thể dễ dàng tạo xung PWM ra các chân GPIO bằng cách gọi hàm pwm_init() và pwm_start(). Cần lưu ý các giới hạn của software PWM là không thể tạo các xung PWM với các tần số khác nhau và tần số hoạt động chỉ từ 100Hz đến 1kHz và không sử dụng được hardware TIMER nếu có sử dụng PWM.

Làm việc với UART

ESP8266 hỗ trợ 2 module UART là UART0 và UART1 với tốc độ truyền dữ liệu lên đến 4.5Mbps; tuy nhiên UART1 chỉ có chức năng Tx và thường được dùng để print debug log.

Mặc định sau khi cấp nguồn, firmware trong ROM của ESP8266 sẽ print 1 vài message từ UART0. Tốc độ baud của UARTo khi này sẽ thay đổi tùy theo giá trị thạch anh sử dụng trên board. Ví dụ như với thạch anh 40MHz thì baudrate sẽ là 115200, thạch anh 26MHz thì baudrate sẽ là 74880. Các UART module trên ESP8266 có hỗ trợ RX/TX FIFO 128bytes.

Các chân GPIO dùng cho UART bao gồm:

  • UART0: RX = GPIO03 ,  TX = GPIO01  ,  RTS = GPIO15   ,   CTS = GPIO13
  • UART1: TX = GPIO02

Các file code sử dụng cho UART:

  • C:\Espressif\ESP8266_SDK\driver_lib\include\driver\uart.h
  • C:\Espressif\ESP8266_SDK\driver_lib\include\driver\uart_register.h
  • C:\Espressif\ESP8266_SDK\driver_lib\driver\uart.c

Các hàm API:

  • void uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
    Khởi động UART0 và UART1 với baudrate tương ứng và cho phép ngắt trên 2 UART. Lưu ý là hàm uart_init() sẽ cấu hình 2 module UART theo thông số mặc định đã lưu trong ROM (8-bit dữ liệu, 1 stop bit, không parity, v.v…).
    Khi thực thi uart_init() cũng tự động đăng ký hàm interrupt callback là uart0_rx_intr_handler() để xử lý ngắt của UART0. Do đó chúng ta có thể add code trong hàm uart0_rx_intr_handler() để xử lý ngắt cần thiết cho ứng dụng của mình
  • void UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len)
    Cấu hình lại size của dữ liệu truyền trên UART nếu cần
  • void UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num)
    Cấu hình lại số lượng Stop bits nếu cần
  • void UART_SetParity(uint8 uart_no, UartParityMode Parity_mode)
    Cấu hình lại kiểu Parity nếu cần
  • void UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh)
    Cấu hình lại HW flow control sử dụng tín hiệu RTS/CTS của UART0 nếu cần
  • void uart_rx_intr_enable(uint8 uart_no)
    Cho phép ngắt trên UART tương ứng.
  • void uart_rx_intr_disable(uint8 uart_no)
    Không cho phép ngắt trên UART tương ứng
  • void UART_SetIntrEna(uint8 uart_no,uint32 ena_mask)
    Cho phép tín hiệu ngắt cụ thể trên UART tương ứng. Các tín hiệu ngắt có thể xem trong uart_register.h như UART_RXFIFO_OVF_INT_ENA, UART_TXFIFO_EMPTY_INT_ENA, v.v…
  • void UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask)
    Xóa cờ interrupt của UART tương ứng. Các cờ interrupt có thể xem trong file uart_register.h như UART_RXFIFO_OVF_INT_CLR, UART_TXFIFO_EMPTY_INT_CLR, v.v…
  • STATUS uart_tx_one_char(uint8 uart, uint8 TxChar)
    Đợi TX FIFO có byte trống và ghi 1 byte dữ liệu vào TX FIFO
  • STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar)
    Tương tự như hàm uart_tx_one_char() nhưng sẽ thoát hàm và không ghi dữ liệu nếu TX FIFO đầy
  • STATUS uart0_tx_one_char_no_wait(uint8 TxChar)
    Gọi hàm uart_tx_one_char_no_wait() cho UART0
  • void uart1_write_char(char c)
    Ghi 1 byte dữ liệu vào TX FIFO của UART1 bằng cách gọi hàm uart_tx_one_char()
  • void uart1_sendStr_no_wait(const char *str)
    Ghi dữ liệu vào TX FIFO và không đợi nếu TX FIFO đang đầy
  • void uart0_tx_buffer(uint8 *buf, uint16 len)
    Ghi nhiều bytes dữ liệu vào TX FIFO của UART0. Lưu ý là hàm này sẽ thực thi đến khi nào ghi hết dữ liệu vào FIFO
  • void uart0_sendStr(const char *str)
    Ghi các bye trong 1 string vào TX FIFO của UART0 và sẽ đợi đến khi ghi xong
  • void UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us)
    Đợi TX FIFO trống, nếu hết thời gian time_out_us thì sẽ thoát
  • void UART_ResetFifo(uint8 uart_no)
    Reset RX FIFO và TX FIFO của UART tương ứng

Làm việc với TIMER

Chúng ta có thể sử dụng các hàm API của thư viện SDK để làm việc với software timer hoặc hardware timer.

  • Software timer:

File cần sử dụng C:\Espressif\ESP8266_SDK\include\osapi.h

Các hàm API chính:

  1. void os_timer_arm (
  os_timer_t *ptimer, 
  uint32_t milliseconds, 
  bool repeat_flag
 )
    Dùng để khởi tạo 1 software tỉmer với thời gian timeout và có tự động chạy lại hay không.
  2. void os_timer_arm_us (
os_timer_t *ptimer, 
 uint32_t microseconds, 
 bool repeat_flag
)
    Tương tự như hàm os_timer_arm() nhưng thời gian sẽ tính theo đơn vị us
  3. void os_timer_disarm (os_timer_t *ptimer)
    Dùng để stop 1 software timer
  4. void os_timer_setfn(
  os_timer_t *ptimer, 
 os_timer_func_t *pfunction, 
 void *parg
)
    Dùng để đăng ký hàm callback cho 1 software timer

Ví dụ code khởi tạo software timer có thời gian tuần hoàn là 1000ms và hàm callback là timer_callback()

os_timer_t  demo_sw_timer;
os_timer_disarm(&demo_sw_timer);
os_timer_setfn(&demo_sw_timer, (os_timer_func_t *)timer_callback, (void *)0);
os_timer_arm(&demo_sw_timer, 1000, 1);

Và hàm timer_callback() có thể khai báo như sau:

LOCAL void ICACHE_FLASH_ATTR timer_callback(void *arg)
{
//…….
}

  • Hardware timer:

File cần sử dụng C:\Espressif\ESP8266_SDK\driver_lib\driver\hw_timer.c

Các hàm API chính:

  1. void ICACHE_FLASH_ATTR hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type, u8 req)
    Dùng để khởi tạo hardware timer FRC1 cho chức năng timer và khai báo ngắt dùng NMI hay ngắt của timer cũng như timer có tuần hoàn hay không
  2. void hw_timer_set_func (void (* user_hw_timer_cb_set)(void) )
    Đăng ký hàm timer callback
  3. void hw_timer_arm (uint32 val)
    Bắt đầu chạy timer với thời gian theo đơn vị us

Lưu ý là nếu PWM cũng sử dụng FRC1 timer nên chúng ta không thể dùng PWM và hardware timer cùng lúc mà phải chuyển sang dùng software timer nếu có PWM

Làm việc với Wifi, TCP/UDP 

Chúng ta đã giới thiệu các hàm API của thư viện SDK để làm việc với các module hardware của ESP8266 như GPIO, UART, I2C, v.v… Ngoài các API trên, thư viện SDK còn cung cấp đầy đủ các API để chúng ta xác lập cấu hình mạng Wifi, yêu cầu kết nối Wifi, tạo kết nối TCP/UDP để truyền dữ liệu.

Do số lượng các hàm API cho Wifi và TCP/UDP khá nhiều nên bài viết sẽ không giới thiệu ở đây. Các bạn có thể tham khảo đầy đủ trong tài liệu hướng dẫn của thư viện SDK ở đây.

Để nhanh chóng tìm hiểu các hàm API thông dụng, chúng ta có thể tham khảo các sample project sau:

C:\Espressif\examples\ESP8266\esp8266-nonos-sample-code\02Network\HTTP_Client_Demo
C:\Espressif\examples\ESP8266\wifi-sta-tcp-client
C:\Espressif\examples\ESP8266\lwip_open_demo_app
Các project này sử dụng các hàm API để demo quá trình thiết lập ESP8266 tạo kết nối Wifi và truyền nhận dữ liệu qua TCP

2/ Demo lập trình vơi thư viện SDK

Trong phần này chúng ta làm 1 ứng dụng giống như 1 demo trong Phần 4 đó là điều khiển ESP8266 ping website của google, nếu ping thành công thì sẽ blink LED. Khác với phần 4 sử dụng firmware AT command có sẵn và 1 board arduino để truyền commands cho ESP8266 để thực hiện việc giao tiếp Wifi, thực hiện ping tới Google và việc điều khiển LED cũng từ board arduino, trong lần demo này, chúng ta sẽ lập trình ESP8266 thực hiện tất cả công việc trên mà không cần board MCU bên ngoài.

Chúng ta sẽ sử dụng 1 module ESP-01 và 1 module FT232 để nạp chương trình cho ESP-01

esp-01

Về môi trường lập trình, chúng ta sẽ sử dụng môi trường trong eclipse để lập trình trên Windows như đã giới thiệu trong phần 5.

Tạo Eclipse project

Để tạo 1 eclipse project cho demo, chúng ta có thể đơn giản là copy 1 folder project có sẵn trong thư mục  C:\Espressif\examples\ESP8266\ và đặt tên lại cho ứng dụng của chúng ta

Ví dụ chúng ta sẽ copy thư mục C:\Espressif\examples\ESP8266\gpio_led và đổi tên thành thư mục C:\Espressif\examples\ESP8266\demo_phan6

Trong Eclipse, chúng sẽ import project demo1 như sau:
File -> Import -> General/Existing Projects Into Workspace  và Browse đến thư mục demo_phan6 và chọn Finish

Sau khi import, chúng ta sẽ có giao diện Eclipse như sau, chúng ta sẽ đổi tên project thành demo_phan6

Eclipse_prj

 

Chúng ta sẽ thay đổi đường dẫn để sau khi build, các file firmware sẽ sinh ra trong thư mục demo_phan6/ bằng cách thay đổi resource trong Project Properties như sau:

ChangeResource

Xóa gpio16_led và Add Resource…, sau đó chọn demo_phan6.

Thế là xong, chúng ta đã tạo 1 Eclipse project cho demo của mình

Thêm thư viện SDK vào project

Trong demo project, chúng ta thấy có 2 file code thư viện trong thư mục driver/ là gpio16.c và uart.c. Đây là các thư viện được viết bởi cộng đồng phát triển để giúp lập trình phần cứng trên ESP8266 dễ dàng hơn vì không cần phải quan tâm các thanh ghi điều khiển bên dưới.

Trong demo này, chúng ta sẽ sử dụng file thư viện gpio16.c của gpio16_led project. Đây là thư viện được viết bởi cộng đồng phát triển ESP8266 giúp điều khiển các chân GPIO rất dễ dàng như đã giới thiệu ở phần đầu của bài viết. Về file code uart.c, chúng ta sẽ không sử dụng file code này mà sử dụng trực tiếp các hàm API cho UART từ thư viện SDK của Espressif như đã giới thiệu ở phần đầu. Do đó chúng ta sẽ xóa file /demo_phan6/driver/uart.c và thay thế 2 file /demo_phan6/include/driver/uart.h, /demo_phan6/include/driver/uart_register.h bằng 2 files trong thư mục C:\Espressif\ESP8266_SDK\driver_lib\include\driver\

Do chúng ta sẽ sử dụng thư viện chuẩn SDK cho UART, chúng ta cần add file thư viện libdriver.a trong Makefile để compile cho ứng dụng. Double click vào Makefile trong Eclipse, thêm thư viện driver vào danh sách các lib như sau:

LIBS = c gcc hal phy pp net80211 lwip wpa main crypto driver

Viết code ứng dụng trong user_main.c

Chúng ta sẽ xóa hết nội dung của file user_main.c chỉ chừa lại hàm user_rf_cal_sector_set() và user_rf_pre_init() và bắt đầu viết code với hàm user_init()

  • user_init()
    Khởi tạo 1 software timer để gọi hàm app_start() sau 5s
	uart_init(115200, 115200);
	os_timer_disarm(&start_timer);
	os_timer_setfn(&start_timer, (os_timer_func_t *)app_start, (void *)0);
	os_timer_arm(&start_timer, 10000, 1);
  • app_start()
    Gọi các hàm API của Wifi để thiết lập chế độ thiết bị Wifi, thông tin mạng Wifi cần kết nối, đăng ký hàm event callback là wifi_evt_callback() và bắt đầu kết nối vào mạng Wifi
	struct station_config wifi_info;

	os_timer_disarm(&start_timer);
	os_printf("Khoi dong\n");

	//Tat Watchdog timer
	ets_wdt_enable();
	ets_wdt_disable();

	//Chon che do thiet bi Wifi
	wifi_set_opmode(STATION_MODE);

	//Stop wifi truoc khi setup
	wifi_station_disconnect();

	//Xac dinh thong tin mang wifi
	os_memset(&wifi_info,0,sizeof(wifi_info));
	os_memcpy(wifi_info.ssid, WIFI_SSID, sizeof(wifi_info.ssid));
	os_memcpy(wifi_info.password, WIFI_PASSWORD, sizeof(wifi_info.password));
	wifi_station_set_config(&wifi_info);

	//Dang ky ham callback de xu ly wifi event
	wifi_set_event_handler_cb(wifi_evt_callback);

	//Bat dau ket noi vao mang wifi
	wifi_station_connect();
  • wifi_evt_callback()
    Đợi event EVENT_STAMODE_GOT_IP sau khi module ESP01 đã kết nối thành công và gọi hàm do_ping() để tiến hành ping website google.com
	os_printf("event %x\n", evt->event);
	int res;
	switch (evt->event) {
		case EVENT_STAMODE_CONNECTED:
			os_printf("Ket noi thanh cong\n");
			break;
		case EVENT_STAMODE_DISCONNECTED:
			os_printf("Ngat ket noi\n");
			break;
		 case EVENT_STAMODE_GOT_IP:
			 os_printf("Got IP:" IPSTR ",mask:" IPSTR ",gw:" IPSTR,
						 IP2STR(&evt->event_info.got_ip.ip),
						 IP2STR(&evt->event_info.got_ip.mask),
						 IP2STR(&evt->event_info.got_ip.gw));
			 os_printf("\n");
			 do_ping();
			 break;
		 default:
			 break;
	}
  • do_ping()
    Sử dụng API dns_gethostbyname() để lấy địa chỉ IP của tên miền “google.com”; chúng ta sẽ đăng ký hàm callback wifi_dns_found_callback() để xử lý sau khi đã có địa chỉ IP
	 os_printf("Get IP of host %s\n", website);
	 err_t ret = dns_gethostbyname(website, &web_ip, wifi_dns_found_callback, 0);
	 if(ret == 0)	//ERR_OK
	 {
		 os_printf("Found ip right now:" IPSTR "\n", IP2STR(web_ip.addr));
		 ping_opt.ip = web_ip.addr;
		 ping_start(&ping_opt);

	 }
	 else
	 {
		 //nothing to do, just wait for callback to get web IP
	 }
  • wifi_dns_found_callback()
    Nhận địa chỉ IP của tên miền “google.com” và gọi hàm API ping_start() để bắt đầu quá trình ping tới địa chỉ IP đó.
    Chúng ta cũng đăng ký hàm callback ping_recv_callback() để gọi khi nhận được dữ liệu khi ping
    if(ipaddr) {
    	os_printf("Found host IP:" IPSTR "\n", IP2STR(ipaddr->addr));
    	ping_opt.ip = ipaddr->addr;
		ping_start(&ping_opt);
    }
  • ping_recv_callback()
    Nếu ping thành công, chúng ta sẽ bắt đầu chạy 1 software timer để blink LED. Trong demo này, chúng ta sẽ blink LED BLUE ngay trên board ESP01. Led Blue được điều khiển bởi chân GPIO01 và dùng cho tín hiệu TXD của UART0 nên chúng ta cần cấu hình lại để sử dụng GPIO01 cho việc blink LED của ứng dụng
        struct ping_resp *ping_resp = pdata;
	struct ping_option *ping_opt = arg;

	if (ping_resp->ping_err == -1)
		os_printf("ping host fail \r\n");
	else
	{
	    os_printf("ping recv: byte = %d, time = %d ms \r\n",ping_resp->bytes,ping_resp->resp_time);
	    //Bat dau timer de blink LED
	    os_printf("Ping thanh cong\n");
	    if(!is_led_blinking)
	    {
	    	os_printf("Start blink\n");
	    	set_gpio_mode(LED_GPIO, GPIO_OUTPUT, GPIO_PULLUP);
	    	gpio_write(LED_GPIO, 1);
	    	os_timer_disarm(&blink_timer);
	    	os_timer_setfn(&blink_timer, (os_timer_func_t *)blink_cb, (void *)0);
	    	os_timer_arm(&blink_timer, 2000, 1);
	    	is_led_blinking = true;
	    }
	}
void blink_cb(void *arg)
{
	//os_printf("Toogle LED\n");
	gpio_write(LED_GPIO, led_state);
	led_state ^=1;
}

Các bạn có thể download file user_main.c ở đây. Để chạy ứng dụng, các bạn chỉ cần thay đổi tên mạng Wifi và password tương ứng cho marco WIFI_SSID và WIFI_PASSWORD trong user_main.c

Compile và chạy ứng dụng

Sau khi compile project trong Eclipse, chúng ta sẽ thấy 2 file firmware được tạo ra trong thư mục /demo_phan6/firmware/ là eagle.flash.bin và eagle.irom0text.bin. Đây là 2 file bin để nạp trong trường hợp non-FOTA.

Mở Flash Download Tool của Espressif và thiết lập như sau:

NapPrj   load_fw

Kết nối như hình trên và bắt đầu nạp code ứng dụng xuống ESP01

 

 

 

 

 

Khởi động lại module ESP01 với chân GPIO0 không còn nối GND, mở cổng COM trong chương trình Terminal với baudrate 115200, chúng ta có thể thấy log chương trình khi chạy và LED blue trên board sẽ blink chu kỳ 2s sau khi ping thành công với tên miền “google.com”

PrjLog1

Đến đây là hết bài viết rồi. Trong bài viết này chúng ta tiếp tục chủ đề lập trình trực tiếp trên ESP8266 sử dụng thư viện SDK của Espressif trong môi trường Eclipse. Bài viết giới thiệu các hàm API chính trong thư viện SDK để làm việc với các module phần cứng trên ESP8266 như TIMER, UART, GPIO, I2C, PWM, v.v… Thông qua 1 ứng dụng demo, chúng ta cũng thảo luận cách tạo 1 Eclipse project từ 1 sample project có sẵn, cách sử dụng thư viện chuẩn SDK của Espressif (ví dụ như thêm header file của uart.h và uart_registers.h và thêm thư viện .a trong Makefile) và sử dụng thư viện được viết bởi cộng đồng phát triển của ESP8266 (ví dụ như gpio16.c) và quá trình nạp và chạy code ứng dụng. Trong bài tiếp theo, chúng ta sẽ thảo luận việc mở rộng firmware AT command có sẵn của Espressif bằng cách tạo thêm các AT command dùng cho việc điều khiển phần cứng trên ESP8266

Nguồn: htelectronics.vn