零知开源——基于STM32F4的HC-12无线通信系统及ST7789显示应用
✔零知IDE 是一个真正属于国人自己的开源软件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧!
✔访问零知实验室,获取更多实战项目和教程资源吧!
www.lingzhilab.com
目录
一、硬件系统设计
1.1 硬件清单
1.2 接线方案
1.3 连接硬件图
1.4 接线实物图
二、软件系统设计
2.1 HC-12模块模式切换机制
2.2 ST7789显示优化技术
2.3 无线数据处理状态机
2.4 信道切换处理核心
2.5 发送端完整代码
2.6 接收端完整代码
三、数据传输展示
3.1 发送端操作
3.2 无线传输
3.3 接收端处理
3.4 视频演示
四、关键技术详解
4.1 HC-12模块工作原理
4.2 软件串口实现
五、常见问题解答
Q1: 为什么HC-12模块无法通信?
Q2: 如何增加通信距离?
六、结论
(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-12delay(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-12while (Serial.available()) {HC12.write(Serial.read());}// 按钮1处理:切换到信道01button1State = digitalRead(button1);if (button1State == HIGH && button1Pressed == LOW) {button1Pressed = HIGH;delay(20); // 按键消抖}if (button1Pressed == HIGH) {sendChannelCommand("001"); // 发送信道切换指令button1Pressed = LOW; // 重置按键状态}// 按钮2处理:切换到信道02button2State = 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-12delay(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-12while (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