实践项目6--数据采集器
一、功能说明
基于AVR单片机设计一2路模拟电压数据采集器,通过RS232与PC进行通信,利用串
口对采样参数进行控制,采样数据发送给PC。
二、具体要求
1、采集两路模拟电压(由电位器产生)。
2、采集结果精确到小数点后一位;
3、通过串口实现与PC通信,制定通信协议,由PC发送通道选择、采样间隔的设置参
数,发送开始采样命令,采样间隔设置为0.5s、0.3s和0.1s三三种。
4、利用发光二极管(LS8-LS1)对当前选择通道和采样间隔进行指示。
5、单片机收到开始采样命令后,开始一次采样过程,以设置的采样间隔从所选择的通
道进行AD转换并存储到单片机内部存储器中,采集50个样本后,停止采样,计算采集电压
的最大和最小值,并将这50个样本值以及极值通过串口发送合PC,数据间以空格为间隔,
数据格式可以为采样二进制数或转换为电压ASCII形式。
6、具有故障检测报警功能;
7、其它。可根据实际情况添加相关功能。
8、其它要求见文件最后说明。
本项目基于AVR单片机设计了一款2路模拟电压数据采集器,主要通过RS232与PC进行通信,能够实现以下功能:
采集两路模拟电压数据,并精确到小数点后一位。
通过串口与PC通信,实现采样参数(通道选择、采样间隔)的设置和控制。
采样间隔可以设置为0.5s、0.3s和0.1s三种。
使用发光二极管指示当前选择的通道和采样间隔。
支持故障检测报警功能及其他自定义功能。
AVR单片机:选择适合的AVR单片机作为主控制器,实现AD转换和串口通信功能。
模拟电路:设计电位器电路生成模拟电压作为输入信号。
串口通信:利用RS232协议与PC进行通信,实现命令和数据的传输。
主程序逻辑:采用C语言编写主程序,实现采样控制、数据处理和串口通信。
定时器中断:使用定时器中断控制采样间隔,精确触发AD转换和数据采集过程。
数据处理:采集完成后计算并存储采样数据的最大值、最小值,并通过串口发送给PC。
主程序主要负责初始化硬件设备,设置串口波特率,配置AD转换器和定时器,并处理串口接收到的命令。
cvoid main(void) {
// 主循环,处理串口接收到的命令
while (1) {
if ((UCSR1A & 0x80) != 0) { // 检查是否有数据接收
revchar = UDR1; // 读取接收到的数据
if (revchar == '5') {
// 设置采样间隔为500ms
time_tap = 50;
time1 = 0;
dijici_caiyang = 0;
Print_Str("\r\n 500MS \r\n");
PORTA |= 0x1C; // 关闭三个LED灯
PORTA &= ~0x10; // 点亮其中一个
} else if (revchar == '3') {
// 设置采样间隔为300ms
time_tap = 30;
time1 = 0;
dijici_caiyang = 0;
Print_Str("\r\n 300MS \r\n");
PORTA |= 0x1C; // 关闭三个LED灯
PORTA &= ~0x08; // 点亮其中一个
} else if (revchar == '1') {
// 设置采样间隔为100ms
time_tap = 10;
time1 = 0;
dijici_caiyang = 0;
Print_Str("\r\n 100MS \r\n");
PORTA |= 0x1C; // 关闭三个LED灯
PORTA &= ~0x04; // 点亮其中一个
} else if (revchar == 'O') {
// 开始采样
open = 1;
dijici_caiyang = 0;
Print_Str("\r\n OPEN \r\n");
} else if (revchar == 'A') {
// 选择通道A
tongdaoch = 0;
Print_Str("\r\n tongdao A \r\n");
PORTA &= ~0x01; // 打开LED1
PORTA |= 0x02; // 关闭LED2
} else if (revchar == 'B') {
// 选择通道B
tongdaoch = 1;
Print_Str("\r\n tongdao B \r\n");
PORTA &= ~0x02; // 打开LED2
PORTA |= 0x01; // 关闭LED1
}
}
}
}
定时器中断程序负责在设定的时间间隔内触发AD转换,并将采集到的数据进行处理和存储。
c// 定时器0中断服务程序
#pragma interrupt_handler TIMER0_ISR:17
void TIMER0_ISR(void) {
TCNT0 = 183; // 设置定时器初值,实现10ms定时
cnt++;
if (cnt >= 50) { // 每500ms处理一次数据
cnt = 0;
// 读取并转换ADC值
ADC_Value = ADC_read(0);
jiancev1 = convert(ADC_Value);
ADC_Value = ADC_read(1);
jiancev2 = convert(ADC_Value);
// 判断电压是否低于0.2V
if (jiancev1 < 20 || jiancev2 < 20) {
PORTA &= ~0x20; // 打开蜂鸣器
} else {
PORTA |= 0x20; // 关闭蜂鸣器
}
}
// 检查是否开始采样并处理采样数据
if (open == 1 && time_tap != 0) {
time1++;
if (time1 == time_tap) { // 到达设定的采样间隔
time1 = 0;
// 采集通道0的数据并存储
ADC_Value = ADC_read(0);
voltage = convert(ADC_Value) / 10;
ADC0BUFFER[dijici_caiyang] = voltage;
// 采集通道1的数据并存储
ADC_Value = ADC_read(1);
voltage = convert(ADC_Value) / 10;
ADC1BUFFER[dijici_caiyang] = voltage;
dijici_caiyang++; // 采样次数加1
// 打印采样次数
sprintf(buffer, "start %d\r\n", (int)dijici_caiyang);
Print_Str(buffer);
if (dijici_caiyang == 50) { // 完成50次采样
// 计算通道0的最大值和最小值
ADC0BUFFER[50] = 0;
ADC0BUFFER[51] = 50;
for (char i = 0; i < 50; i++) {
if (ADC0BUFFER[50] < ADC0BUFFER[i]) {
ADC0BUFFER[50] = ADC0BUFFER[i];
}
if (ADC0BUFFER[51] > ADC0BUFFER[i]) {
ADC0BUFFER[51] = ADC0BUFFER[i];
}
}
// 计算通道1的最大值和最小值
ADC1BUFFER[50] = 0;
ADC1BUFFER[51] = 50;
for (char i = 0; i < 50; i++) {
if (ADC1BUFFER[50] < ADC1BUFFER[i]) {
ADC1BUFFER[50] = ADC1BUFFER[i];
}
if (ADC1BUFFER[51] > ADC1BUFFER[i]) {
ADC1BUFFER[51] = ADC1BUFFER[i];
}
}
//
打印最大值和最小值
Print_Str("\r\nA通道采样50次完成\r\n");
sprintf(buffer, "0max=%d\r\n", (int)ADC0BUFFER[50]);
Print_Str(buffer);
sprintf(buffer, "0min=%d\r\n", (int)ADC0BUFFER[51]);
Print_Str(buffer);
sprintf(buffer, "1max=%d\r\n", (int)ADC1BUFFER[50]);
Print_Str(buffer);
sprintf(buffer, "1min=%d\r\n", (int)ADC1BUFFER[51]);
Print_Str(buffer);
// 停止采样
open = 0;
dijici_caiyang = 0;
}
}
}
}
通过本项目的设计与实现,成功搭建了一款功能完善的模拟电压数据采集器,实现了基本的数据采集、处理和通信功能。未来可以进一步优化硬件电路设计、增强故障检测功能,并提升数据传输效率和稳定性。
资源:
https://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?u=bdf8eeb84961492ba2b62f7bfee641ea&tab=BB08J2
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!