硬件介绍:
这次funpack3-5活动一口气推出了3款开发板,选择困难症都犯了。最终选择了Teensy 4.1开发板。Teensy 4.1主板中的MCU来自i.MX RT1060处理器系列,采用NXP的Arm Cortex-M7内核的高级实现。它的运行速度高达600 MHz,可提供较高的CPU性能和最佳的实时响应。Teensy 4.1主板配备1024 KB RAM、7936 KB闪存和4KBEEPROM。板上有18个模拟引脚和55个数字I/O引脚,其中35个引脚支持脉宽调制,该开发板板支持CAN、I2C和SPI串行通信协议。板子上还带了以太网收发器,SD卡。
整个开发板集成度很高,板子上看不到过多的元器件,而且板子体积很小,可以很容易地和面包板一起使用。
任务选择:
这次我选择的是任务1:点灯!从板子的以太网排针处引出接口,并通过网口通信,控制板子上的LED灯。开发工具使用Vscode+platformIO,使用Arduino来进行开发。
任务实现:
Teensy 4.1开发板有集成以太网收发器,但是并没有提供网口(RJ45)的接口,应该是板子太小了,只留了2X3的排针,用来接以太网。所以第一步,先给板子做一个网络接口。
这里Teensy 4.1开发板只有6个管脚,所以是没有控制网口上边的LED灯的状态,但是这个网口,把LED灯的控制脚引出来了。
硬件改造完成,接下来就是编程了。
使用arduino最大的好处就是避免了重复造轮子。这里调用网络服务,直接使用已有的NativeEthernet类库。给Teensy 4.1开发板分配一个MAC地址(可以任意填写),这里我使用静态地址,所以给开发板分配了固定的IP。LED灯使用开发板自带的LED灯,管脚使用13管脚。端口使用浏览器默认的80端口,这样浏览器在访问时就不需要额外带端口号了。
#include <SPI.h>
#include <NativeEthernet.h>
#define LED 13
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(100, 196, 128, 12);
EthernetServer server(80);
String header; // 用于存储 HTTP 请求的变量
String LEDState = "off"; // 辅助变量存储当前输出状态
unsigned long currentTime = millis(); // 当前时间
unsigned long previousTime = 0;
const long timeoutTime = 2000; // 定义超时时间(以毫秒为单位)(示例:2000ms = 2s)
void setup()
{
Serial.begin(115200);
pinMode(LED, OUTPUT);
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true)
{
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
初始化完成后,开发板上的80端口就会处于打开状态,系统处于监听状态,等待访问。浏览器作为客户端访问该端口,开发板就返还一段html给浏览器,浏览器负责渲染html给用户。当用户在浏览器上按下关灯按键,开发板就控制LED灯关闭,否则就打开LED灯。
void loop()
{
EthernetClient client = server.available(); //监听数据
if (client) { // 如果有新客户端连接,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // 在串行端口中打印一条消息
String currentLine = ""; // 创建一个字符串来保存来自客户端的传入数据
while (client.connected() && currentTime - previousTime <= timeoutTime) { // 当客户端连接时循环
currentTime = millis();
if (client.available()) { // 如果有字节要从客户端读取,
char c = client.read(); // 读取一个字节
Serial.write(c); // 将其打印出串行监视器
header += c;
if (c == '\n') { // 如果该字节是换行符
// 如果当前行为空,则连续有两个换行符。
// 这就是客户端 HTTP 请求的结束,因此发送响应:
if (currentLine.length() == 0) {
// HTTP 标头始终以响应代码开头(例如 HTTP/1.1 200 OK)
// 一个内容类型,以便客户端知道接下来会发生什么,然后是一个空行:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// 打开和关闭 GPIO
if (header.indexOf("GET /led/on") >= 0) {
LEDState = "on";
digitalWrite(LED, HIGH);
} else if (header.indexOf("GET /led/off") >= 0) {
LEDState = "off";
digitalWrite(LED, LOW);
}
// 显示 HTML 网页
client.println("<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link rel=\"icon\" href=\"data:,\">");
// CSS 设置开/关按钮的样式
// 随意更改背景颜色和字体大小属性以满足您的喜好
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}.button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}.button2 {background-color: #555555;}</style></head>");
// 网页标题
client.println("<body><h1>Teensy4.1 Web LED</h1>");
// 显示 GPIO 26 的当前状态和 ON/OFF 按钮
client.println("<p><h2>LED State :" + LEDState + "</h2></p>");
// 如果output26状态为off,则显示ON按钮
if (LEDState=="off") {
client.println("<p><a href=\"/led/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/led/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// HTTP 响应以另一个空行结束
client.println();
// 跳出 while 循环
break;
} else { // 如果有换行符,则清除 currentLine
currentLine = "";
}
} else if (c != '\r') { // 如果除了回车符之外还有其他字符,
currentLine += c; // 将其添加到当前行的末尾
}
}
}
// 清除头变量
header = "";
// 关闭连接
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
效果展示:
点击网页上的“ON“按钮就可以控制LED灯的开了。
心得体会: 这次Funpack活动太给力啦!活动提供的三款开发板都是那么的优秀!最终到手的这块Teensy 4.1开发板性能超强,可玩性非常高!热切期望Funpack后续的活动。