单片机与ADC0809的接口连接电路和8位转换结果显示电路。编程控制ADC0809进行模数转化,并使用8个LED灯显示转化结果。 分别运行程序记录读入的数字量,并列表格,计算转换值与真实值的误差。 编程核心内容 1、选择通道,启动AD转换 2、判断AD转换是否结束 3、读取AD转换结果 4、显示AD转换结果 采用中断方式读取转换结果
时间: 2024-03-12 15:49:05 浏览: 123
以下是基于8051单片机的ADC0809模数转换程序,其中使用P0口作为数据口,P1.0口作为ADC0809的SC引脚,P1.1口作为ADC0809的CLK引脚,P1.2口作为ADC0809的IN引脚,P1.3口作为ADC0809的CS引脚。8个LED灯分别连接到P2口的8个IO口上,使用了中断方式读取转换结果。
```
#include <reg51.h>
#define FREQ_OSC 12000000UL
#define BAUDRATE 9600
// ADC0809控制信号
sbit CS = P1^3; // Chip Select
sbit CLK = P1^1; // Clock
sbit IN = P1^2; // Input
sbit SC = P1^0; // Start Conversion
// 8个LED灯
sbit LED1 = P2^0;
sbit LED2 = P2^1;
sbit LED3 = P2^2;
sbit LED4 = P2^3;
sbit LED5 = P2^4;
sbit LED6 = P2^5;
sbit LED7 = P2^6;
sbit LED8 = P2^7;
void delay(unsigned int n)
{
unsigned int i;
for(i = 0; i < n; i++);
}
void initUART()
{
TMOD = 0x20; // 8-bit auto-reload timer1
TH1 = 0xFD; // BAUDRATE = 9600
SCON = 0x50; // Mode 1, 8-bit UART
TR1 = 1; // start timer1
}
void sendChar(char c)
{
SBUF = c;
while(TI == 0);
TI = 0;
}
void sendString(char* str)
{
while(*str != '\0')
{
sendChar(*str++);
}
}
void initADC()
{
CS = 1; // 设置ADC0809的CS引脚为高电平
}
unsigned char readADC(unsigned char ch)
{
unsigned char result;
CS = 0; // 低电平使能ADC0809
IN = ch & 0x01; // 设置ADC0809的IN引脚
CLK = 0; // 向ADC0809发送时钟信号
SC = 1; // 启动ADC0809的模数转换
delay(1);
SC = 0;
while(IN == 1); // 等待模数转换完成
CLK = 1; // 读取8位转换结果
result = P0;
CLK = 0;
CS = 1; // 高电平禁用ADC0809
return result;
}
void main()
{
unsigned char ch = 0, result;
unsigned int i, val;
float voltage, error;
initUART();
initADC();
while(1)
{
result = readADC(ch); // 读取ADC0809的转换结果
for(i = 0; i < 8; i++) // 显示转换结果
{
if((result & (1 << i)) == (1 << i))
{
switch(i)
{
case 0: LED1 = 1; break;
case 1: LED2 = 1; break;
case 2: LED3 = 1; break;
case 3: LED4 = 1; break;
case 4: LED5 = 1; break;
case 5: LED6 = 1; break;
case 6: LED7 = 1; break;
case 7: LED8 = 1; break;
}
}
else
{
switch(i)
{
case 0: LED1 = 0; break;
case 1: LED2 = 0; break;
case 2: LED3 = 0; break;
case 3: LED4 = 0; break;
case 4: LED5 = 0; break;
case 5: LED6 = 0; break;
case 6: LED7 = 0; break;
case 7: LED8 = 0; break;
}
}
}
val = result; // 记录数字量
voltage = ((float)val / 255) * 5; // 计算电压值
error = voltage - 1.5; // 计算误差
sendString("Channel: ");
sendChar(ch + '0');
sendString(" Value: ");
sendChar(val / 100 + '0');
sendChar((val % 100) / 10 + '0');
sendChar(val % 10 + '0');
sendString(" Voltage: ");
sendChar((int)voltage + '0');
sendChar('.');
sendChar(((int)(voltage * 10)) % 10 + '0');
sendString("V Error: ");
if(error >= 0)
{
sendChar('+');
}
else
{
sendChar('-');
error = -error;
}
sendChar((int)error + '0');
sendChar('.');
sendChar(((int)(error * 10)) % 10 + '0');
sendString("V\r\n");
ch = (ch + 1) % 8; // 切换通道
delay(500);
}
}
```
在程序中,我们先定义了一些常量和变量,包括系统频率、波特率、ADC0809控制信号和8个LED灯。然后定义了一些辅助函数,如延时函数、串口初始化函数、串口发送字符函数和串口发送字符串函数。接着定义了初始化ADC0809的函数和读取ADC0809转换结果的函数,其中需要注意的是每次读取转换结果时需要先启动模数转换并等待转换完成。
在主函数中,我们不断切换通道、读取转换结果、显示转换结果和计算误差,并通过串口输出相关信息。其中,切换通道使用了取模运算符,可以循环切换通道;而显示转换结果则需要根据转换结果的每一位控制对应的LED灯亮起或熄灭。
最后,我们可以通过调整ADC0809的ADJ3来模拟输入不同的电压值,并记录转换结果和误差,可以得到一个转换表格,以便评估ADC0809的精度和稳定性。
阅读全文