学了一段时间单片机,总想着干点啥,一眼看见那个MF47,欧姆调零容易坏,
修好了没几天又坏了,扔了又可惜。突然脑袋一热,想着给它做一个不用调零的电
路板换上去就一劳永逸了。
经过不断的尝试与修改,终于有了一个满意的版本,拍个图给大家看看:
从此,我的MF47有了表棒接反报警,超量程报警等功能,灵敏度也提高了,
从20k每伏升级到了200k每伏,电流档满里程从250mV降到了100mV,
原1V档改成了5uA档,取消了2500V插孔和三极管Hfe座,其它和原表对应。
还有了数据输出功能,能接电脑,也能外接1602显示器。
万用表有两种不同的模式,一个是欧姆档测量模式,另一个是电压电流测量模
式。电压电流测量模式时,可以在1602上显示出三个数,分别对应500量程,
250量程和100量程。如果发现用户在测量电阻,则自动显示出电阻阻值,精度
和三位半数字万用表相近,但范围更宽,比如Rx1档,分辨力0.01欧,最大可显
示990.00欧,如果是在Rx10k档,则对应的最大电阻是9.9M欧。测量效果如下:
能达到这样的效果已经很满意了,从此再也不用羡慕MF10和MF63甚至MF18(MF35)。
刚开始装上去发现表针响应慢半拍,毕竟每秒10次的测量速率加上软件积分效应
导致了这样的结果,程序里增加了微分效应才使表针有了“冲”的效果,冲过去
半格后退回到稳定的位置。
虽然从无源表改成了有源表,耗电量并不大,只有580uA(3.3V),一节700mAh
铁锂电池可以连续使用1000小时,当然还有30分钟自动关机,关机后(OFF档)只有
8uA(3.3V)。外接的1602耗电1.4mA,加起来才2mA(3.3V),能跟随万用表的关闭
而自动关闭。
有时候可能无法确定万用表是不是在开机状态,我设置了五秒一次的短“嘀”声提醒。
大家还希望这款表添加什么功能呢?欢迎留言。
接下来就是上位机编程了,编一个有用户界面的上位机程序目前对我来说还是有一
定难度的,写一个控制台下的程序则容易了许多,只有“main函数”加“大循环”。
以前写的电阻并联求值小程序,只有控制台界面,算上标点符号也只有15行,贴出来
和大家一起学习最简单的电脑编程:
#include <stdio.h>
int main(void)
{
float x,y,z;
printf("\n***电阻并联求值小程序***\n\n");
while(1){
printf("============分隔线======\n");
printf("电阻1(可输入小数):");
scanf("%f",&x);
printf("\n电阻2(可输入小数):");
scanf("%f",&y);
z=(float)(x*y/(x+y));
printf("\n并联阻值=%g\n\n",z);
}
}
找一个大家喜欢的编译器编译出来就行了,运行效果如下:
电阻并联求值exe.zip
(9.93 KB, 下载次数: 0)
我这个指针万用表是通过串口连接电脑的,比如我电脑上的串口是DAP-link,
相应的驱动程序必须先安装好,然后就是电脑编程了。
经过多方查找,终于找到了一个简单的串口配置发送和接收示例程序,
此程序配置串口为57600波特率,8位字长,1位停止位,无校验,并通过COM3
发送和接收数据。源码如下,和大家一起学习:
#include <windows.h>
#include <stdio.h>
int main() {
printf("\n这是一个串口测试程序!\n\n注意串口号是否正确!\n\n");
printf("请连接串口设备的Rx和Tx,\n\n然后运行此程序\n\n");
HANDLE hSerial;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts = {0};
// 打开串口,这里改成对应的串口号
hSerial = CreateFile("\\\\.\\COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSerial == INVALID_HANDLE_VALUE) {
fprintf(stderr, "打开串口出错!\n\n请填写正确的串口号后再编译运行!\n");
getchar();
return 1;
}
// 配置串口参数
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
fprintf(stderr, "获取串口状态出错\n");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_57600;//波特率
dcbSerialParams.ByteSize = 8;//8位字长
dcbSerialParams.StopBits = ONESTOPBIT;//1位停止
dcbSerialParams.Parity = NOPARITY;//无校验
if (!SetCommState(hSerial, &dcbSerialParams)) {
fprintf(stderr, "设置串口状态出错\n");
CloseHandle(hSerial);
return 1;
}
// 设置超时
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hSerial, &timeouts)) {
fprintf(stderr, "设置超时出错\n");
CloseHandle(hSerial);
return 1;
}
// 发送数据
unsigned char sendData[] = {0xa1, 0xd2, 0xb3, 0x84, 0x35};
DWORD bytesWritten;
if (!WriteFile(hSerial, sendData, sizeof(sendData), &bytesWritten, NULL)) {
fprintf(stderr, "串口写入出错\n");
CloseHandle(hSerial);
return 1;
}
printf("发送 %lu 字节\n", bytesWritten);
// 接收数据
unsigned char receiveData[256];
DWORD bytesRead;
if (!ReadFile(hSerial, receiveData, sizeof(receiveData), &bytesRead, NULL)) {
fprintf(stderr, "串口接收出错\n");
CloseHandle(hSerial);
return 1;
}
printf("接收 %lu 字节: ", bytesRead);
for (DWORD i = 0; i < bytesRead; i++) {
printf("%02X ", receiveData[ i]);
}
printf("\n\n成功接收数据,请关闭此程序!");
// 关闭串口
CloseHandle(hSerial);
getchar();//等待用户查看结果
return 0;
}
### 代码说明
1. **打开串口**:使用`CreateFile`函数打开串口`COM3`。如果打开失败,程序会输出错误信息并退出。
2. **配置串口参数**:使用`GetCommState`获取当前串口配置,然后设置波特率、字长、停止位和校验位等参数,最后通过`SetCommState`应用这些配置。
3. **设置超时**:通过`SetCommTimeouts`设置串口的读写超时时间。
4. **发送数据**:使用`WriteFile`函数将数组`sendData`中的数据发送到串口。
5. **接收数据**:使用`ReadFile`函数从串口读取数据,并将读取到的数据存储在`receiveData`数组中。
6. **关闭串口**:使用`CloseHandle`关闭串口。
### 编译和运行
在Windows上使用C编译器(如MinGW或Visual Studio)编译该程序,并运行生成的可执行文件。
确保COM3端口已连接并配置正确。
### 注意事项
- 确保COM3端口可用且正确连接。
- 如果COM3端口被其他程序占用,程序将无法打开串口。
- 该程序假设发送和接收的数据量较小,如果需要处理大量数据,可能需要调整缓冲区大小和超时设置。
这个示例程序展示了如何使用Windows API进行基本的串口通信。
根据实际需求,可以进一步扩展和优化该程序。如果将电脑串口
的Rx和Tx连接起来,程序运行的结果是收到了自己发送的数据,
效果图如下:
经过我的几番改进,可以输入串口号和波特率,增加了数据记录到文件的功能,
控制台界面变成了如下的样子:
控制台里以文本显示接收到的文字,同时保存数据到电脑上,
程序关闭后可以用记事本打开记录到的数据。
虽然万用表的数据记录功能用处不大,但是过程中能学习到很
多的知识,不是吗?
串口到文本文件.zip
(12.13 KB, 下载次数: 0)
|