一、A/D转换相关知识
1. A/D转换的技术指标
1) 分辨率,表示会触发数字量变化的最小模拟信号的变化量。分辨率又称精度,通常以数字信号的位数来表示。
2) 转换速率,指完成一次A/D转换所需的时间的倒数。积分型A/D的转换时间时毫秒级,属低速A/D;逐次比较型A/D是微秒级的,属中速A/D;全并行/串并行型A/D可达到纳秒级。
3)量化误差,指对模拟信号进行量化而产生的误差
4)偏移误差,指输入信号为零时,输出信号不为零的值。
5)满刻度误差,满刻度输出时对应的输入信号与理想输入信号值之差
2. 转换器类型
1)积分型A/D转换器
将输入电压转换成时间(脉冲宽度信号)或频率(脉冲频率),然后由定时器/计数器获得数字值。其优点是用简单电路就能获得高分辨率,但缺点是由于转换精度依赖于积分时间,因此转换速率极低。初期的单片AD转换器大多采用积分型,现在逐次比较型已逐步成为主流
2)逐次逼近型A/D
逐次逼近转换过程和用天平称物重非常相似。天平称重物过程是从最重的砝码开始试放,与被称物体进行比较,若物体重于砝码,则该砝码保留,否则移去。在加上第二个次重砝码,由物体的重量是否大于砝码的重量决定第二个砝码是否留下还是移去。以此类推,一直加到最小一个砝码为止。然后将所有留下的砝码重量相加,就得此物体的重量,按照这一思路,逐次比较型A/D转换器。,就是将输入模拟量与不同的参考电压作多次比较。使转换所得的数字量在数值上逐次逼近输入模拟量对应值。
3)全并行/串并行型A/D,原理无
3、A/D转换一般步骤
取样、保持、量化、编码
二、Exynos4412-A/D转换器
1. A/D转换器控制寄存器ADCCON,配置A/D转换器功能,如转换开始方式,工作模式,时钟频率,分辨等,还有一位只读位表示当前转换是否完成。该寄存器如下:
2. A/D转换器通路选择寄存器(ADCMUX),用来选择当前要转换的模拟量的通路。
3. A/D转换器数据寄存器(ADCDAT),存放模拟量转换为数字量的转换结果。
4. CLRINTADC,清除ADC中断寄存器
5. ADC中断号
6. 因为ADC在第10 Combiner, 所以需要了解Combiner中的中断寄存器
1)IESR2寄存器
2)IECR2寄存器
三、示例代码
//使用读启动方式
#define __READ_START_
/*
*If A/D conversion start by read
* */
//#define __READ_START_
/**********************************************************************
* @brief IRQInterrupt Service Routine program body
* @param[in] None
* @return None
**********************************************************************/
void do_irq(void )
{
unsignedint temp_adc = 0,temp_mv;
int irq_num;
irq_num = (CPU0.ICCIAR & 0x1FF);
printf("IRQinterrupt !!\n");
temp_adc = ADCDAT & 0xfff;
printf("adcdat: %0x\n", temp_adc);
//temp_mv = 1800 * temp_adc / 4095;
temp_mv = 1.8 * 1000 * temp_adc / 0xfff;
printf("adcvalue: %d mv\n", temp_mv);
//Clear SPI Pending,中断号为42, 42 / 32 = 1于10
ICDICPR.ICDICPR1 |= 0x1 << 10;
//clear ADC pending
INTADCCLR = 1;
// End of interrupt
CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;
}
/**********************************************************************
* @brief mydelay_msprogram body
* @param[in] int (ms)
* @return None
**********************************************************************/
void mydelay_ms(int time)
{
int i, j;
while(time--)
{
for (i = 0; i < 5; i++)
for (j = 0; j < 514; j++);
}
}
/*-------------------------MAINFUNCTION------------------------------*/
/**********************************************************************
* @brief Mainprogram body
* @param[in] None
* @return int
**********************************************************************/
int main(void)
{
GPX2.CON = 0x1 << 28;//GPX2CON[7]:Output drive LED
uart_init();
ADC_CFG &= ~(0x1 << 16); //Bit_16:Select ADC Mux 0:General 1:MTCADC
ADCMUX = 0x3; //0x3: 0011 = AIN3
/*
* GIC interruptcontroller:
**/
// Enables the corresponding interruptSPI10
ICDISER.ICDISER1 |= 0x1 <<10;
CPU0.ICCICR |= 0x1; //Global enablefor signaling of interrupts
CPU0.ICCPMR = 0xFF; //The prioritymask level.Priority filter. threshold
ICDDCR = 1; //Bit1: GICmonitors the peripheral interrupt signals and
// forwards pending interrupts to the CPUinterfaces2
/***** Interrupt combiner*****/
INTCOMBINER.IESR2 |= 0x1 << 19;
ICDIPTR.ICDIPTR10 = 0x01010101; //SPI8~11 interrupts are sent to processor 0
#ifdef__READ_START_
//12bit A/D conversion; enable A/Dconverter prescaler; prescaler value:255; A/D conversion start byread
ADCCON = (0x1<<16) | (0x1<<14) | (0xff<<6) |0x1<<1;
#else
//12bit A/D conversion; enableA/D converter prescaler; prescaler value:255
ADCCON = (0x1<<16) |(0x1<<14) | (0x01<<6);
#endif
#ifdef __READ_START_
temp_adc = ADCDAT & 0xfff;
#endif
printf("\n************ADC test ************\n");
while(1)
{
#ifndef __READ_START_
ADCCON |= 0x1;//start ADCconversion
#endif
//Turn on LED
GPX2.DAT |= 0x1 << 7;
mydelay_ms(1000);
//Turn off LED
GPX2.DAT &= ~(0x1 << 7);
mydelay_ms(1000);
}
return 0;
}