RT-Thread—STM32—enc28j60
RT-Thread—STM32—enc28j60概述本教程主要是讲解如何使用ENC28J60模块介入以太网本例程的模板使用通用模板环境搭建里面的模板RT-Thread—STM32—环境搭建示例工程请参见文末的源码仓库链接, 建议从头开始移植, 加深印象。配置打开工程目录在ENV下输入menuconfig进入图形化配置界面配置SPI2使用ENC28J60软件包使用lwIP 2.0.2使能socket使能network相关组件保存配置并且退出ENV代码修改添加drv_enc28j60.c,drv_enc28j60.h,m_udp.h,m_udp.c文件在drv_enc28j60.c文件中添加ENC28J60和SPI相关的初始化#include rtthread.h #include enc28j60.h #include drivers/pin.h #include spi_flash.h #include rtdevice.h #include drv_spi.h #include enc28j60.h #include board.h #define ENC28J60_BUS spi2 #define ENC28J60_DEVICE qspi20 #define ENC28J60_CS GET_PIN(B,8)//14 // PA0 for STM32F103RC defined in drv_gpio.c #define ENC28J60_INT GET_PIN(B,9)//15 // PA1 for STM32F103RC defined in drv_gpio.c #define ENC28J60_RESET GET_PIN(B,10)//20 // PA4 for STM32F103RC defined in drv_gpio.c /* 接线相关 * GND--------接地 * VCC--------接电源 * CS---------PB8(可自定义) * INT--------PB9(可自定义) * RST--------PB10(可自定义) * SCK--------PB13(SPI2的SCK) * MOSI(SI)---PB15(SPI2的MOSI) * MISO(SO)---PB14(SPI2的MISO) * */ void enc28j60_int_handler(void *args) { /* enter interrupt */ rt_interrupt_enter(); enc28j60_isr(); /* leave interrupt */ rt_interrupt_leave(); } /* 设备初始化 */ static int rt_hw_enc28j60_init(void) { /* Configure SPI */ rt_hw_spi_device_attach(spi2, qspi20, GPIOB, GPIO_PIN_8); /* Configure Reset */ rt_pin_mode(ENC28J60_RESET, PIN_MODE_INPUT_PULLUP); rt_pin_write(ENC28J60_RESET,0); rt_thread_delay(1); rt_pin_write(ENC28J60_RESET,1); enc28j60_attach(ENC28J60_DEVICE); /* Configure Interrupt */ rt_pin_mode(ENC28J60_INT, PIN_MODE_INPUT_PULLUP); rt_pin_attach_irq(ENC28J60_INT, PIN_IRQ_MODE_FALLING, enc28j60_int_handler, (void*)callbackargs); rt_pin_irq_enable(ENC28J60_INT, PIN_IRQ_ENABLE); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_enc28j60_init);在m_udp.c文件里面添加了通过代码实现UDP server的简单功能#include rtthread.h #include rtdevice.h #include board.h #include m_udp.h #include sys/socket.h //使用BSD socket需要包含sockets.h头文件 #include netdb.h #include string.h #include finsh.h #define BUFSZ 1024 const char send_data1[] Im a client.\n; /* 发送用到的数据 */ void thread_udp_entry(void *param) { int sock; int bytes_read; char *recv_data; socklen_t addr_len; struct sockaddr_in server_addr, client_addr; /* 分配接收用的数据缓冲 */ recv_data rt_malloc(BUFSZ); if (recv_data RT_NULL) { /* 分配内存失败返回 */ rt_kprintf(No memory\n); return; } /* 创建一个socket类型是SOCK_DGRAMUDP类型 */ if ((sock socket(AF_INET, SOCK_DGRAM, 0)) -1) { rt_kprintf(Socket error\n); /* 释放接收用的数据缓冲 */ rt_free(recv_data); return; } /* 初始化服务端地址 */ server_addr.sin_family AF_INET; server_addr.sin_port htons(5000); //设置自己的端口号 server_addr.sin_addr.s_addr INADDR_ANY; rt_memset((server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 绑定socket到服务端地址 */ if (bind(sock, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) -1) { /* 绑定地址失败 */ rt_kprintf(Bind error\n); /* 释放接收用的数据缓冲 */ rt_free(recv_data); return; } addr_len sizeof(struct sockaddr); rt_kprintf(UDPServer Waiting for client on port 5000...\n); while(1) { bytes_read recvfrom(sock, recv_data, BUFSZ - 1, 0,(struct sockaddr *)client_addr, addr_len); recv_data[bytes_read] \0; /* 输出接收的数据 */ rt_kprintf(\n(%s , %d) said : , inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); rt_kprintf(%s, recv_data); /* 发送数据 */ sendto(sock, send_data1, strlen(send_data1), 0,(struct sockaddr *)client_addr, sizeof(struct sockaddr)); rt_thread_mdelay(500); } } /* 初始化任务 */ static int m_udp_sample(void) { rt_thread_t tid_udp rt_thread_create(m_udp, thread_udp_entry, RT_NULL, 1024, 20, 5); if (tid_udp ! RT_NULL) { rt_thread_startup(tid_udp); } } INIT_APP_EXPORT(m_udp_sample);测试烧录代码连接上网线通过Xshell调试查看自己IP使用 DNS Ping 百度的服务器在同一个路由下面,模拟UDP client发数据如图如果结果和我一样就说明你已经成功了小结很多智能设备都需要接入互联网,本节就通过ENC28J60模块让单片机通过有线网接入了互联网,大家可能会问如何通过无线WIFI接入互联网,这里推荐一个乐鑫的ESP8266WIF模块.乐鑫官网源代码获取源码仓库: 码云仓库