✔零知IDE 是一个真正属于国人自己的开源软件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧!
✔访问零知实验室,获取更多实战项目和教程资源吧!
目录
(1)项目概述
本项目构建了一个基于STM32F407VET6微控制器的无线通信系统,通过HC-12模块实现两个零知增强板之间的长距离无线通信。发送端通过物理按键切换信道,接收端使用ST7789显示屏实时显示当前信道状态。系统实现了HC-12模块的无线通信控制、AT指令的无线传输与解析、接收端可视化界面设计、状态信息的实时更新与显示
(2)项目亮点
>提供清晰直观的UI界面
>HC-12模块支持1公里以上通信距离(空旷环境)
>功能模块分离,便于维护和扩展
>优化了通信协议,减少能耗
一、硬件系统设计
1.1 硬件清单
组件 | 数量 | 说明 |
---|---|---|
零知增强板(STM32F407VET6) | 2 | 主控制器 |
HC-12无线模块 | 2 | 433MHz无线通信 |
ST7789 TFT显示屏 | 1 | 240×320分辨率,SPI接口 |
轻触按键 | 2 | 发送端信道切换 |
杜邦线 | 若干 | 模块连接 |
1.2 接线方案
(1)发送端接线
HC-12模块 | 按键 | 零知增强板1 |
---|---|---|
VCC | 按键的一端 | 3.3V |
GND | 通过10k下拉电阻接到按键另一端 | GND |
/ | 按键1 | 4 |
/ | 按键2 | 3 |
TX | / | 10 |
RX | / | 11 |
SET | / | 6 |
(2)接收端接线
HC-12模块 | ST7789 | 零知增强板2 |
---|---|---|
VCC | VCC | 3.3V |
GND | GND | GND |
/ | SCL | 52 |
/ | SDA | 51 |
/ | RES | 47 |
/ | DC | 49 |
/ | CS | 53 |
TX | / | 10 |
RX | / | 11 |
SET | / | 6 |
1.3 连接硬件图
(1)发送端接线图
(2)接收端接线图
1.4 接线实物图
二、软件系统设计
2.1 HC-12模块模式切换机制
// 发送信道切换命令
void sendChannelCommand(String channel) {
HC12.print("AT+C" + channel); // 发送指令到另一个模块
delay(100);
// 进入AT指令模式
digitalWrite(setPin, LOW); // 设置HC-12为AT指令模式
delay(100); // 等待进入AT模式
HC12.print("AT+C" + channel); // 发送AT指令到本地HC-12
delay(200);
// 读取并显示响应
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("信道切换成功");
// 退出AT指令模式
digitalWrite(setPin, HIGH);
}
双模切换机制:
首先以透明模式发送指令到接收端(digitalWrite(setPin, HIGH))
然后进入AT模式(digitalWrite(setPin, LOW))配置本地模块
确保发送端和接收端同时切换到相同信道
2.2 ST7789显示优化技术
// 更新信道显示
void updateChannel() {
// 清除旧信道显示区域
tft.fillRect(20, 130, 200, 30, ST77XX_BLACK);
// 绘制新信道信息
tft.setCursor(20, 130);
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(3);
tft.println(currentChannel);
}
// 更新消息显示
void updateMessage() {
// 清除旧消息显示区域
tft.fillRect(20, 210, 200, 30, ST77XX_BLACK);
// 绘制新消息
tft.setCursor(20, 210);
// 根据消息类型设置颜色
if (lastMessage == "Success!") {
tft.setTextColor(ST77XX_GREEN); // 成功消息为绿色
} else {
tft.setTextColor(ST77XX_WHITE); // 普通消息为白色
}
tft.setTextSize(3);
tft.println(lastMessage);
}
局部刷新技术:
使用fillRect()仅刷新特定区域,而非整个屏幕
显著提高刷新效率(全屏刷新需300ms,局部刷新仅需20ms)
避免屏幕闪烁现象
2.3 无线数据处理状态机
void loop() {
// 接收HC-12数据并存储到缓冲区
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}
delay(100);
// 处理信道切换指令
if (readBuffer == "AT+C001") {
processChannelChange("01");
}
else if (readBuffer == "AT+C002") {
processChannelChange("02");
}
// 检查并处理AT指令
checkATCommand();
// 消息超时处理
if (millis() - messageTime > MESSAGE_TIMEOUT && lastMessage != "Waiting...") {
lastMessage = "Waiting...";
updateMessage();
}
readBuffer = ""; // 清空缓冲区
}
数据接收状态机:
使用while (HC12.available())确保完整接收数据包
delay(100)提供数据接收缓冲时间
字符串比较readBuffer == "AT+C001"实现指令识别
2.4 信道切换处理核心
void processChannelChange(String channel) {
// 进入AT指令模式
digitalWrite(setPin, LOW); // 设置HC-12为AT指令模式
delay(100);
HC12.print("AT+C" + channel); // 发送完整AT指令
delay(200);
// 读取响应
String response = "";
while (HC12.available()) {
response += char(HC12.read());
}
// 退出AT指令模式
digitalWrite(setPin, HIGH);
// 更新显示信息
currentChannel = "Channel: " + channel;
lastMessage = "Success!";
messageTime = millis(); // 重置消息计时器
// 更新显示屏
updateChannel();
updateMessage();
}
信道切换协议:
严格遵循AT指令格式"AT+C" + channel
确保与发送端指令格式完全一致
支持扩展更多信道(如"003"、"004"等)
响应处理机制:
构建response字符串收集模块响应
可用于错误检测和调试(当前版本未使用)
显示更新联动:
同时更新currentChannel和lastMessage
调用updateChannel()和updateMessage()刷新界面
重置messageTime启动超时计时器
2.5 发送端完整代码
/*
* 基于STM32F407VET6的HC-12无线通信发送端
* 功能:通过按键切换信道并发送AT指令
*/
#include <SoftwareSerial.h>
// 引脚定义
#define setPin 6 // HC-12设置引脚(PD6)
#define button1 4 // 按钮1引脚(PD4)
#define button2 3 // 按钮2引脚(PD3)
// 初始化软件串口 (RX, TX)
SoftwareSerial HC12(10, 11); // PA10(RX), PA9(TX)
// 全局变量
byte incomingByte;
String readBuffer = "";
int button1State = 0;
int button1Pressed = 0;
int button2State = 0;
int button2Pressed = 0;
void setup() {
Serial.begin(9600); // 初始化串口监视器
HC12.begin(9600); // 初始化HC-12通信
pinMode(setPin, OUTPUT); // 配置SET引脚为输出
pinMode(button1, INPUT); // 配置按键1为输入
pinMode(button2, INPUT); // 配置按键2为输入
digitalWrite(setPin, HIGH); // 设置HC-12为正常透明模式
}
void loop() {
// 接收HC-12数据并存储到缓冲区
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}
delay(100);
// 串口转发功能:将串口数据转发到HC-12
while (Serial.available()) {
HC12.write(Serial.read());
}
// 按钮1处理:切换到信道01
button1State = digitalRead(button1);
if (button1State == HIGH && button1Pressed == LOW) {
button1Pressed = HIGH;
delay(20); // 按键消抖
}
if (button1Pressed == HIGH) {
sendChannelCommand("001"); // 发送信道切换指令
button1Pressed = LOW; // 重置按键状态
}
// 按钮2处理:切换到信道02
button2State = digitalRead(button2);
if (button2State == HIGH && button2Pressed == LOW) {
button2Pressed = HIGH;
delay(100); // 按键消抖
}
if (button2Pressed == HIGH) {
sendChannelCommand("002"); // 发送信道切换指令
button2Pressed = LOW; // 重置按键状态
}
// 检查并处理AT指令
checkATCommand();
readBuffer = ""; // 清空缓冲区
}
// 发送信道切换命令
void sendChannelCommand(String channel) {
HC12.print("AT+C" + channel); // 发送指令到另一个模块
delay(100);
// 进入AT指令模式
digitalWrite(setPin, LOW); // 设置HC-12为AT指令模式
delay(100); // 等待进入AT模式
HC12.print("AT+C" + channel); // 发送AT指令到本地HC-12
delay(200);
// 读取并显示响应
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("信道切换成功");
// 退出AT指令模式
digitalWrite(setPin, HIGH);
}
// 检查并处理串口接收的AT指令
void checkATCommand() {
if (readBuffer.startsWith("AT")) {
digitalWrite(setPin, LOW); // 进入AT模式
delay(200);
HC12.print(readBuffer); // 发送AT指令
delay(200);
// 读取并显示响应
while (HC12.available()) {
Serial.write(HC12.read());
}
digitalWrite(setPin, HIGH); // 退出AT模式
}
}
2.6 接收端完整代码
/*
* 基于STM32F407VET6的HC-12无线通信接收端
* 功能:接收信道切换指令并在ST7789显示屏上显示状态
*/
#include <SoftwareSerial.h>
#include <Adafruit_GFX.h> // 核心图形库
#include <Adafruit_ST7789.h> // ST7789显示驱动
// 引脚定义
#define setPin 6 // HC-12设置引脚(PD6)
#define TFT_CS 53 // 显示屏片选(PG9)
#define TFT_DC 49 // 数据/命令选择(PG8)
#define TFT_RST 47 // 显示屏复位(PG7)
// 初始化软件串口和显示屏
SoftwareSerial HC12(10, 11); // PA10(RX), PA9(TX)
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
// 全局变量
byte incomingByte;
String readBuffer = "";
String currentChannel = "Channel: --"; // 当前信道显示
String lastMessage = "Waiting..."; // 最后消息
unsigned long messageTime = 0; // 消息时间戳
const unsigned long MESSAGE_TIMEOUT = 2000; // 消息显示超时(2秒)
void setup() {
Serial.begin(9600); // 初始化串口监视器
HC12.begin(9600); // 初始化HC-12通信
pinMode(setPin, OUTPUT); // 配置SET引脚为输出
digitalWrite(setPin, HIGH); // 设置HC-12为正常模式
// 初始化显示屏
tft.init(240, 320); // 初始化240x320显示屏
tft.setRotation(3); // 设置显示方向(0-3)
tft.invertDisplay(false); // 禁用显示反转
tft.fillScreen(ST77XX_BLACK); // 清屏
tft.setTextWrap(false); // 禁用文本换行
// 绘制静态UI元素
drawUI();
}
void loop() {
// 接收HC-12数据并存储到缓冲区
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}
delay(100);
// 串口转发功能:将串口数据转发到HC-12
while (Serial.available()) {
HC12.write(Serial.read());
}
// 处理信道切换指令
if (readBuffer == "AT+C001") {
processChannelChange("01");
}
else if (readBuffer == "AT+C002") {
processChannelChange("02");
}
// 检查并处理AT指令
checkATCommand();
// 消息超时处理
if (millis() - messageTime > MESSAGE_TIMEOUT && lastMessage != "Waiting...") {
lastMessage = "Waiting...";
updateMessage();
}
readBuffer = ""; // 清空缓冲区
}
// 处理信道切换
void processChannelChange(String channel) {
// 进入AT指令模式
digitalWrite(setPin, LOW); // 设置HC-12为AT指令模式
delay(100);
HC12.print("AT+C" + channel); // 发送完整AT指令
delay(200);
// 读取响应
String response = "";
while (HC12.available()) {
response += char(HC12.read());
}
// 退出AT指令模式
digitalWrite(setPin, HIGH);
// 更新显示信息
currentChannel = "Channel: " + channel;
lastMessage = "Success!";
messageTime = millis(); // 重置消息计时器
// 串口输出
Serial.print("Channel ");
Serial.print(channel);
Serial.println(" set successfully");
// 更新显示屏
updateChannel();
updateMessage();
}
// 检查并处理AT指令
void checkATCommand() {
if (readBuffer.startsWith("AT")) {
digitalWrite(setPin, LOW); // 进入AT模式
delay(100);
HC12.print(readBuffer); // 发送AT指令
delay(200);
// 读取并显示响应
while (HC12.available()) {
Serial.write(HC12.read());
}
digitalWrite(setPin, HIGH); // 退出AT模式
}
}
// 绘制静态UI元素
void drawUI() {
// 绘制标题
tft.setCursor(20, 20);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(3);
tft.println("HC-12 SYSTEM");
// 绘制分隔线
tft.drawFastHLine(10, 60, 220, ST77XX_BLUE);
// 绘制信道标签
tft.setCursor(20, 100);
tft.setTextColor(ST77XX_CYAN);
tft.setTextSize(2);
tft.println("Current Channel:");
// 绘制状态标签
tft.setCursor(20, 180);
tft.setTextColor(ST77XX_CYAN);
tft.setTextSize(2);
tft.println("Status:");
// 绘制边框
tft.drawRect(5, 5, 240, 235, ST77XX_WHITE);
// 初始化动态内容
updateChannel();
updateMessage();
}
// 更新信道显示
void updateChannel() {
// 清除旧信道显示区域
tft.fillRect(20, 130, 200, 30, ST77XX_BLACK);
// 绘制新信道信息
tft.setCursor(20, 130);
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(3);
tft.println(currentChannel);
}
// 更新消息显示
void updateMessage() {
// 清除旧消息显示区域
tft.fillRect(20, 210, 200, 30, ST77XX_BLACK);
// 绘制新消息
tft.setCursor(20, 210);
// 根据消息类型设置颜色
if (lastMessage == "Success!") {
tft.setTextColor(ST77XX_GREEN); // 成功消息为绿色
} else {
tft.setTextColor(ST77XX_WHITE); // 普通消息为白色
}
tft.setTextSize(3);
tft.println(lastMessage);
}
错误预防机制:
指令格式严格校验
超时管理系统
缓冲区定期清理
三、数据传输展示
系统工作时,数据传输流程如下:
3.1 发送端操作
用户按下按键1或按键2
发送端通过软件串口发送"AT+C001"或"AT+C002"指令
同时设置本地HC-12模块的信道
3.2 无线传输
两个HC-12模块通过433MHz无线频段传输数据
传输距离可达1000米(开阔地带)
3.3 接收端处理
接收端HC-12模块收到指令
解析指令内容并设置本地信道
更新ST7789显示屏上的信道信息
显示"Success!"状态信息2秒后恢复等待状态
3.4 视频演示
基于零知增强板和HC-12传输无线指令
发送端(零知增强板1)按下按键同时将接收端(零知增强板2)的信道切换成信道01和信道02
四、关键技术详解
4.1 HC-12模块工作原理
HC-12是基于Si4463射频芯片的无线串口通信模块,特点包括:
工作频率:433.4-473.0MHz
传输距离:100-1000米(取决于环境和功率设置)
支持多种波特率(1200bps-115200bps)
提供4个通信频道
AT指令关键操作:
>AT+C001:切换到信道001
>AT+RPx:设置发射功率(x=0-8,8为最大功率20dBm)
>AT+FBx:设置工作模式(x=0-2,0为FU1模式)
4.2 软件串口实现
在STM32F407VET6上使用软件串口的优势:
不占用硬件串口资源
可灵活配置任意GPIO作为TX/RX
支持多串口并发通信
SoftwareSerial库注意事项:
>波特率不宜过高(建议≤38400bps)
>避免在中断服务程序中调用
>接收缓冲区大小可调整以优化性能
五、常见问题解答
Q1: 为什么HC-12模块无法通信?
A:以下步骤进行检查:
检查电源:确保3.3V稳定供电
验证接线:TX-RX交叉连接
检查波特率:双方必须使用相同波特率
确认信道:双方必须处于相同信道
Q2: 如何增加通信距离?
A:发送端进行指令配置:
设置更高发射功率:AT+RP8(最大功率)
使用外置天线:替换模块上的弹簧天线
调整工作模式:AT+FB2(FU2模式,低速率但更远距离)
优化天线位置:避免金属屏蔽
六、结论
项目充分展示了STM32F407VET6的强大性能和HC-12模块的通信能力,为物联网应用开发提供了实用参考。系统可进一步扩展为环境监测、远程控制等多种应用场景。通过本项目的开发,我们实现了:
基于HC-12的可靠无线通信系统
ST7789显示屏的GUI界面设计与实现
硬件按键与无线指令的协同控制
实时状态反馈与显示
项目资源:
(1)所需库
ST7789显示屏: Adafruit ST7789 Library
GFX图形库: Adafruit GFX Library
软件串口库: SoftwareSerial Library
(2)技术文档
HC-12无线通信模块: HC-12用户手册
主控芯片数据手册: STM32F407VET6 Datasheet
本文详细介绍了基于STM32F407VET6零知增强板的HC-12无线通信系统设计与实现!点击了解更多零知开发教程:
https://www.lingzhilab.com/freesources.html