作为一名从事嵌入式开发多年的工程师,我最近完成了一个基于ST89C52单片机的智能水平仪系统设计。这个项目最初源于我在建筑工地看到工人们使用传统气泡水平仪时的种种不便——读数不精确、功能单一、无法记录数据。于是萌生了设计一款多功能数字水平仪的想法。
这个水平仪系统需要满足以下几个核心需求:
在确定这些需求后,我首先考虑的是系统架构的选择。经过市场调研和成本核算,决定采用单片机作为核心控制器,而非更复杂的ARM或DSP方案。这主要基于以下考虑:
在具体实现方案上,我设计了两种可行性方案进行对比:
方案一:STM32+MMA7455+DS18B20+DHT11+数码管
方案二:ST89C52+ADXL345+DHT11+LCD+蓝牙
经过深入分析,最终选择了方案二,主要基于以下考量:
实际工程中选择方案时,不能只看性能参数,更要考虑成本、易用性和市场需求。这是我多年项目经验中最重要的心得之一。
ST89C52是STC公司生产的8位单片机,基于8051内核,具有以下特点:
在本次设计中,ST89C52主要承担以下任务:
一个完整的ST89C52最小系统包括:
电路设计注意事项:
ADXL345是ADI公司的数字三轴加速度计,主要特性:
在水平仪应用中,我们主要使用其静态加速度测量功能。当传感器静止时,加速度计测量的是重力加速度在各轴的分量,通过三角函数计算可以得到倾斜角度。
角度计算公式:
θ = arctan(Ax / √(Ay² + Az²)) * (180/π)
其中:
DHT11是一款低成本数字温湿度传感器,特性如下:
电路设计要点:
选用常见的LCD1602字符型液晶模块,主要参数:
在本次设计中采用4位数据线接法,节省I/O资源。对比度调节采用10kΩ电位器。
采用有源蜂鸣器,通过NPN三极管驱动。当角度超过设定阈值时,单片机输出低电平使三极管导通,蜂鸣器发声。
电路设计注意事项:
HC-05是常用的蓝牙串口模块,工作模式:
在本系统中配置为从机模式,手机通过蓝牙串口APP接收角度和温湿度数据。
使用Keil μVision作为开发环境,配置要点:
程序下载使用STC-ISP工具,注意:
系统主程序流程如下:
c复制void main() {
// 初始化各模块
LCD_Init();
Bluetooth_Init();
DHT11_Init();
ADXL345_Init();
// 读取预设阈值
Read_Threshold();
while(1) {
// 读取传感器数据
Read_Angle();
Read_TempHum();
// 显示数据
Display_Data();
// 检查报警
Check_Alarm();
// 发送蓝牙数据
Send_Bluetooth();
// 处理按键
Key_Process();
// 延时
Delay_ms(500);
}
}
ADXL345返回的是各轴的加速度原始值,需要转换为角度:
c复制float Calculate_Angle(int16_t x, int16_t y, int16_t z) {
// 转换为g值(假设量程为±2g)
float gx = x / 256.0;
float gy = y / 256.0;
float gz = z / 256.0;
// 计算倾斜角度
float angle = atan2(gx, sqrt(gy*gy + gz*gz)) * 180.0 / PI;
return angle;
}
DHT11采用单总线协议,时序要求严格:
c复制uint8_t Read_DHT11(uint8_t *temp, uint8_t *humi) {
uint8_t buf[5];
uint8_t i, j;
// 主机拉低18ms
DHT11_IO_OUT();
DHT11_DQ_OUT(0);
Delay_ms(18);
DHT11_DQ_OUT(1);
Delay_us(30);
// 切换为输入模式
DHT11_IO_IN();
// 等待从机响应
if(DHT11_DQ_IN() != 0) return 1;
Delay_us(80);
if(DHT11_DQ_IN() != 1) return 1;
Delay_us(80);
// 读取40位数据
for(i=0; i<5; i++) {
for(j=0; j<8; j++) {
while(DHT11_DQ_IN() == 0);
Delay_us(40);
buf[i] <<= 1;
if(DHT11_DQ_IN() == 1) {
buf[i] |= 1;
while(DHT11_DQ_IN() == 1);
}
}
}
// 校验和检查
if(buf[4] != (buf[0]+buf[1]+buf[2]+buf[3]))
return 1;
*humi = buf[0];
*temp = buf[2];
return 0;
}
为简化手机端APP开发,设计简单的文本协议:
code复制格式:A:XX.X T:XX H:XX\r\n
示例:A:15.2 T:25 H:60\r\n
其中:
单片机端发送程序:
c复制void Send_Bluetooth() {
printf("A:%.1f T:%d H:%d\r\n", angle, temperature, humidity);
}
ADXL345读数不稳定
LCD显示乱码
蜂鸣器不响
使用串口调试
c复制printf("X=%d, Y=%d, Z=%d\r\n", x, y, z);
分模块测试
使用逻辑分析仪
角度滤波算法
c复制#define FILTER_NUM 5
float angle_filter_buf[FILTER_NUM];
float Moving_Average_Filter(float new_angle) {
static uint8_t index = 0;
float sum = 0;
angle_filter_buf[index++] = new_angle;
if(index >= FILTER_NUM) index = 0;
for(uint8_t i=0; i<FILTER_NUM; i++) {
sum += angle_filter_buf[i];
}
return sum / FILTER_NUM;
}
低功耗优化
经过实际测试,系统达到了设计指标:
在工地实地测试时,发现几个有趣的现象:
硬件改进
软件改进
功能扩展
这个项目从构思到实现历时3个月,期间遇到了不少挑战,但也收获了很多宝贵的经验。最大的体会是:嵌入式开发不能只关注技术实现,更要考虑最终用户的实际需求和使用场景。有时候一个简单的功能改进,比如把蜂鸣器音量调大,比增加复杂的算法更能提升用户体验。