RP2040 多核基础版,带 W5100s
转发: RP2040 + W5100S Multicore Basic
项目介绍
你好!
今天,我将解释一个项目,其中我们使用安装在 W5100S-EVB-PICO 上的 RP2040 的两个内核来读取 ADC 数据并将该数据发送到连接的 TCP 客户端!
W5100S-EVB-PICO 中使用的 Raspberry Pi RP2040 有两个内核 (M0+)。
如果您使用过 W5100S-EVB-PICO,您就会知道 Wiznet 提供了基本的示例代码。
示例均是单核实现,为了更好地利用RP2040的硬件资源,使用多核实现效率更高。
然而,网上提供的许多 RP2040 多核示例都是用 MicroPython 实现的。
虽然这些示例使多核实现变得更容易,但它们与该项目的最终目标并不相符:有效地使用有限的嵌入式硬件资源。 因此,我们在这个项目中使用了C语言。
以下部分将解释运行该项目所需的硬件连接和软件设置。
硬件连接
您可以使用 RPI-PICO 和 W5100S 模块作为硬件,但我使用的是包含 RP2040 和 W5100S 的 W5100S-EVB-PICO EVB。
对于 ADC 输入,您可以使用可变电阻器,但我在未来的项目中使用了 XY 操纵杆。 我使用的 XY-Joystick 模块可以输出 X 轴和 Y 轴的 ADC 值,但该项目仅需要一个 ADC 输入。
ADC 输入馈送到 GP26 (ADC0)。
W5100S 安装在 W5100S-EVB-PICO 上,并设置为 SPI0(MOSI - GP19、MISO - GP16、SCK - SP18、CS - GP17、INT - GP21、RST - GP20)。
对于多核实现,我参考了 Rpi 提供的 PICO-SDK 文档中的 pico_multicore 部分。
对于多核实现,我参考了Rpi提供的。 以下是该项目的主要代码。
#include "hardware/adc.h"
#include "hardware/timer.h"
#include "hardware/sync.h"
#include <stdio.h>
#include "port_common.h"
#include "wizchip_conf.h"
#include "w5x00_spi.h"
#include "socket.h"
#include "pico/multicore.h"
#define TIMER_PERIOD_MS (1000)
#define PLL_SYS_KHZ (133 * 1000)
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
#define SOCKET_LOOPBACK 0
#define PORT 5000
#define ADC0_PIN 26
static wiz_NetInfo g_net_info = {
.mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56},
.ip = {192, 168, 11, 2},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 11, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_STATIC
};
static uint8_t Send_buf[ETHERNET_BUF_MAX_SIZE] = {0,};
// 기존 함수와 중복되지 않도록 함수명을 변경하였습니다.
static void init_clock_khz(void) {
set_sys_clock_khz(PLL_SYS_KHZ, true);
clock_configure(
clk_peri,
0,
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
PLL_SYS_KHZ * 1000,
PLL_SYS_KHZ * 1000
);
}
static void read_adc_core1() {
while (true) {
adc_select_input(0);
uint16_t result = adc_read();
multicore_fifo_push_blocking(result);
sleep_ms(TIMER_PERIOD_MS);
}
}
static int32_t send_adc_data_to_client(uint8_t sn, uint8_t* buf, uint16_t port) {
uint16_t adc_value = multicore_fifo_pop_blocking();
sprintf((char*)buf, "ADC data : %d\n", adc_value);
int32_t ret;
switch(getSn_SR(sn)) {
case SOCK_ESTABLISHED:
if(getSn_IR(sn) & Sn_IR_CON) {
setSn_IR(sn, Sn_IR_CON);
printf("Client connected!\n");
}
if ((ret = send(sn, buf, strlen((char*)buf))) <= 0) {
return ret;
}
break;
case SOCK_CLOSE_WAIT:
if ((ret = disconnect(sn)) != SOCK_OK) {
return ret;
}
break;
case SOCK_INIT:
if ((ret = listen(sn)) != SOCK_OK) {
return ret;
}
printf("Waiting client connection...\n");
break;
case SOCK_CLOSED:
if ((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) {
return ret;
}
break;
default:
break;
}
return 1;
}
int main() {
int retval = 0;
init_clock_khz();
stdio_init_all();
wizchip_spi_initialize();
wizchip_cris_initialize();
wizchip_reset();
wizchip_initialize();
wizchip_check();
network_initialize(g_net_info);
adc_init();
adc_gpio_init(ADC0_PIN);
multicore_launch_core1(read_adc_core1);
print_network_information(g_net_info);
printf("Port : %d\n", PORT); // 포트 번호 출력 부분 추가
while (1) {
if ((retval = send_adc_data_to_client(SOCKET_LOOPBACK, Send_buf, PORT)) < 0) {
printf(" Data sending error : %d\n", retval);
while (1);
}
}
}
主要功能流程:
系统时钟初始化:调用init_clock_khz函数。
初始化标准I/O:调用stdio_init_all函数。
Wiznet W5100S初始化:使用wizchip功能初始化W5100S。
网络设置:使用g_net_info配置网络。
ADC初始化:初始化ADC和ADC引脚。
运行 Core1:使用 read_adc_core1 函数开始读取 Core1 中的 ADC 值。
打印网络信息:显示当前网络配置信息。
无限循环:使用send_adc_data_to_client函数定期将ADC数据发送到TCP客户端。 完整的源代码发布在Github链接上,所以请参考。
这是该项目正在运行的视频。 对于 TCP 客户端,我们使用 herculas.exe
在以后的项目中,我们会以此项目为基础,探索各种多核项目。
感谢您阅读这篇长文。