赞
踩
什么是A/D 模数转换?
在工业检测系统和日常生活中许多物理量都是模拟量,比如温度、压力、位移、图像等,这些模拟量可以通过传感器变成与之对应的电压、电流等电模拟量。为实现数字系统对这些电模拟量进行检测、运算和控制,则需要一个模拟量和数字量之间相互转化的过程,即 A/D 模数转换。
什么是模拟量?
模拟量:在时间上或数值上都是连续的物理量称之为模拟量,把模拟量的信号称为模拟信号,如温度、压力、位移、图像等都是模拟量。
例如:热电偶在工作时输出的电压信号就属于模拟信号,因为在任何情况下被测温度都不可能发生突跳,所以测得的电压信号无论在时间上还是在数量上都是连续的。而且这个电压信号在连续变化过程中的任何一个取值都是具体的物理意义,即表示一个相应的温度。
什么是数字量?
数字量:在时间上或数值上都是离散的物理量称之为数字量,把数字量的信号称为数字信号。
例如:用电子电路记录从自动生产线上输出的零件数目时,每送出一个零件便给电子电路一个信号,使之记 1,而平时没有零件送出时加给电子电路的信号是 0。可见零件数目这个信号无论在时间上还是在数量上都是不连续的,因此他是一个数字信号,最小的数量单位就是 1个。
A/D转换的原理。
1、A/D 模拟数字转换主要将模拟电压成正比地转换成对应的数字量。A/D 模拟数字转换器分类和特点如下所示:
⑴并联比较型
特点:转换速度快,转换时间 10ns~1μ s,但电路比较复杂。
⑵逐次逼近型
特点:转换速度适中,转换时间几μ s~100μ s,转换精度高,在转换速度和硬件复杂度之间达到一个很好的平衡。
⑶双积分型
特点:转换速度慢,转换时间几百μ s~几ms,抗干扰能力最强。
STC15W4K 系列单片机内部集成 8 通道10 位高速电压输入逐次比较型模拟数字转换器,采样速度最高可达 300KHz(30 万次/秒),可将连续变化的模拟电压转换为相应的数字信号,常用于温度检测、电池电压检测、距离检测、按键扫描等。
以上为STC15W4K 系列单片机 A/D 模拟数字转换模块结构图。
查询法的流程图。
中断法流程图。
以下为逐次逼近型A/D转换的相关程序。
1.主函数先是对相关变量的定义,对相关IO口的初始化(设置为准双向口模式),串口1的初始化(设置分频数和计数器口以及波特率),ADC函数初始化(选择采样的引脚以及采样的周期)。然后就是while死循环,在循环里面可以选择中断法程序,每当数据刷新时即可进行输出。
int main(void) { uint16_t xdata i = 0; //定义变量i并赋值为“0” uint16_t xdata USER_ADC_Isr_Result_Backup = 256; //定义变量USER_ADC_Isr_Result并赋值为“0” MCU_GPIO_All_Init(); //MCU 所有I/O口初始化为准双向口模式函数 MCU_Uart_1_Init_Isr(0, 0, 115200); //P3.0/RxD, P3.1/TxD 12分频定时/计数器T2 115200bps MCU_Adc_Init_Isr(0, 0); //对P10采样模拟电压 90个系统时钟周期转换一次 while (1) //死循环 { /*********************测试A/D查询法模数转换******************************/ /* i = MCU_Adc_Get_Data_Check(0, 0); //对P10采样模拟电压 90个系统时钟周期转换一次 MCU_Uart_1_SendString("STC15W4K32S4 ADC测试:"); MCU_Uart_1_SendData(i % 1000 / 100 + 0x30); MCU_Uart_1_SendString("."); MCU_Uart_1_SendData(i % 100 / 10 + 0x30); MCU_Uart_1_SendData(i % 10 + 0x30); MCU_Uart_1_SendString("V\r\n"); SoftWare_Dealy_MS(500); */ /*********************测试A/D中断法模数转换******************************/ if (USER_ADC_Isr_Result_Backup != USER_ADC_Isr_Result) { USER_ADC_Isr_Result_Backup = USER_ADC_Isr_Result; MCU_Uart_1_SendString("STC15W4K32S4 ADC测试:"); MCU_Uart_1_SendData(USER_ADC_Isr_Result_Backup % 1000 / 100 + 0x30); MCU_Uart_1_SendString("."); MCU_Uart_1_SendData(USER_ADC_Isr_Result_Backup % 100 / 10 + 0x30); MCU_Uart_1_SendData(USER_ADC_Isr_Result_Backup % 10 + 0x30); MCU_Uart_1_SendString("V\r\n"); } } }
ADC初始化函数。
void MCU_Adc_Init_Isr(uint8_t MCU_ADC_Ch, uint8_t MCU_ADC_Spped) { P1ASF = _crol_(0x01, MCU_ADC_Ch); //设置P1口位0为模拟功能端口 switch (MCU_ADC_Spped) //ADC转换速度选择 { case 0: MCU_ADC_Spped = 0x00; //90个时钟周期转换一次 break; case 1: MCU_ADC_Spped = 0x20; //180个时钟周期转换一次 break; case 2: MCU_ADC_Spped = 0x40; //360个时钟周期转换一次 break; case 3: MCU_ADC_Spped = 0x60; //540个时钟周期转换一次 break; default: MCU_ADC_Spped = 0x00; //90个时钟周期转换一次 break; } ADC_CONTR = 0X00; //ADC转换控制寄存器清“0” ADC_CONTR |= MCU_ADC_Spped; //配置ADC转换速度 ADC_CONTR |= MCU_ADC_Ch; //配置ADC转换通道 ADC_CONTR |= ADC_POWER; //开启ADC转换电源 ADC_RES = 0; //清除结果寄存器 A/D转换结果高8位 ADC_RESL = 0; //清除结果寄存器 A/D转换结果低2位 SoftWare_Dealy_MS(10); //延时10毫秒等待内部模拟电源稳定 ADC_CONTR |= ADC_START; //启动ADC转换 EADC = 1; //允许ADC模数转换中断 EA = 1; //开启单片机总中断 }
ADC中断函数。
void MCU_Adc_Isr() interrupt 5
{
static uint16_t xdata ADC_Temp = 0; //定义无符号整型变量ADC_Temp,且赋值为0
static float xdata Voltage = 0; //定义单精度实型(浮点型)变量Voltage,且赋值为0
ADC_CONTR &= ~ADC_FLAG; //清除ADC结束标志
ADC_Temp = (ADC_RES << 2) | (ADC_RESL & 0X03); //读取ADC模数转换结果
Voltage = ADC_Temp * 0.00488;
USER_ADC_Isr_Result = (uint16_t)(Voltage * 100.0); //计算被测电压值
ADC_RES = 0; //清除结果寄存器 A/D转换结果高8位
ADC_RESL = 0; //清除结果寄存器 A/D转换结果低8位
ADC_CONTR |= ADC_START; //启动ADC转换
}
测试
通过自制的单片机板对程序进行测试。
当ADC引脚未接任何外设时的电压大概在3.85V左右。
当ADC引脚通过导线接入地时,如图所示,引脚电压降低至接近0V。
当ADC引脚通过导线接入VCC时,如图所示,引脚电压提升至接近5V。
测试完毕,证明改程序是可行的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。