单片机
返回首页

mini2440裸机试炼之--A/D模拟信号转换

2020-07-06 来源:eefocus

实现功能

        通过开发板上的滑动变阻器控制的模拟信号经过A/D转换器

        转换为数字信号用uart_printf()打印在串口上。 并且滑动

        变阻器同时控制指示灯led的闪烁速度(时长)。


S3C2440ADC的主要特性如下:


    ●分辨率:10位


    ●最大转换速率:500KSPS


    ●微分线性度误差:±1.0 LSB


    ●积分线性度误差:±2.0 LSB


    ●供电电压:3.3V


    ●模拟输入电压范围:0~3.3V


    ●模拟输出数值范围:0~1023


ADC原理

ADC是一种将模拟信号转化为数字信号的方法,一般要经过采样、保持、量化、编码4个步骤。在实际电路中,有些过程是合并进行的,如采样和保持,量化和编码在转换过程中时同时实现的。由奈奎特采样定理可知,当采样频率大于模拟信号中最高频率的2倍时,采样值才能不失真地反映原来模拟信号。

从图1可以看出,ADC共有8路模拟输入,其中XP、XM、YP和YM是触摸屏使用的4路,剩下的4路模拟输入A[3:0]可以用于一般的ADC输入通道(AIN0、AIN1、AIN2和AIN3)。当触摸屏引脚(YM、YP、XM和XP)为禁止时,这些端口可以被用于ADC的模拟输入端口(AIN4、AIN5、AIN6和AIN7)


对于S3C2440处理器,ADC输入时钟是由PCLK分频得到的,如图2所示

ADC寄存器

ADCCON部分

图3


根据图3,ADCCON控制寄存器


ECFLG 是转换结束标志位,当转换结束时,ECFLG值为1,进入转换状态为0;


PRSCEN是使能预分频控制位 ;


PRSCVL 是预分频值放置位;0~255


■当PRSCEN为1时,设置PRSCVL的值将会决定AD转换的时间。ADC使用的时钟是系统的PCLK,由于main函数设置mpll为400MHZ,所以PCLK = 50MHz,设置PRSCVL的值为49,那么:


A/D 转换的频率 = 50MHz / (49+1) = 1 MHz


A/D 转换的时间 = 1 /(1MHz / 5cycles)=5 uS


由此可知当PRSCVL的值越小,A/D 转换的时间越短,A/D 转换的频率也就越大。


注意:当从待机模式中变换到正常工作模式时,ADC的预分频器必须在最后的3个ADC时钟前使能????


SEL_MUX是模拟输入通道选择控制器


READ_START要使能A/D转换启动,就必须禁止READ_ START


ENABLE_START 使能A/D转换控制位


ADCDAT0

由于只是通过AIN0模拟信号输入。并没使用触摸屏功能,所以,ADCDAT0只考虑普通ADC转换数值(模拟信号转换的数字数值存于XPDATA)

W1可调电位器

mini2440上有一个可调电位器,如下图所示。电位器的中间抽头部分接在ADC输入通道AIN0上,当电位器滑动头位于最下端时,AIN0引脚电压为0V;当电位器滑动头位于最上端时,AIN0引脚电压为3.3V;当电位器上、下滑动时,AIN0引脚的电压值会在0~3.3V之间变换。由此可知,W1是通过AIN0模拟输入通道间模拟信号传给ADC,再进行转换的。

代码部分

#include'2440addr.h'     //引脚宏定义

#include'def.h'          // U8 U32宏定义

#include'2440lib.h'      //使用Uart_Printf,Dalay声明,Uart_Printf定义在2440lib.c文件

 

/*

当PRSCEN为1时,设置PRSCVL的值将会决定AD转换的时间。ADC使用的时钟是系统的PCLK

,由于main函数设置mpll为400MHZ,所以PCLK = 50MHz,设置PRSCVL的值为49,那么:

 

A/D 转换的频率 = 50MHz / (49+1) = 1 MHz

 

A/D 转换的时间 = 1 /(1MHz / 5cycles)=5 uS

*/

/********ADC********/

#definePRSC_EN     0x1           //允许预分频

#define PRSCVL      0x19          //预分频值

#defineSEL_MUX     ~0x7          //模拟通道选择AIN0通道

#define STDBM       0x0           //正常工作模式

#defineREAD_START  0x0           //读数时不进行A/D转换

#defineADC_STAR    0x1           //ADC开启

 

/********LED*********/

#defineLED1_out  (1<<(5*2))

#defineLED2_out  (1<<(6*2))

#defineLED3_out  (1<<(7*2))

#defineLED4_out  (1<<(8*2))

#defineLED4_ON   (0x0E<<8)       //LED1+LED2+LED3+LED4 ON

#defineLED_OFF   (0x0F<<5)

 

void ADC_display(){

    Uart_Printf('n');

    Uart_Printf('n');

    Uart_Printf('n');

              Uart_Printf('---------HELLOADCn');

              Uart_Printf('PRSC_EN:  %5x  允许预分频n',PRSC_EN);

              Uart_Printf('PRSCVL:   %5x  预分频值n',PRSCVL);

              Uart_Printf('SEL_MUX:   ~0x7  模拟通道选择AIN0通道n',SEL_MUX);

    Uart_Printf('STDBM:    %5x  正常工作模式n',STDBM);

              Uart_Printf('READ_START:%4x  读数时不进行A/D转换n',READ_START);

              Uart_Printf('ADC_STAR:  %4x ADC开启n',ADC_STAR);

              Uart_Printf('变阻器控制的模拟信号经过A/D转换器转换为n');      

    Uart_Printf('数字信号用串口显示,并且滑动变阻器同时控n');

    Uart_Printf('制指示灯led的闪烁速度(时长)n');              

   Uart_Printf('#########################################nn');               

}

//初始化AD控制寄存器

void ADC_INIT(){

  rADCCON&=(~((0x1<<14)|(0xff<<6)|(0x7<<3)|(0x1<<2)|(0x1<<1)|(0x1<<0)));

  rADCCON=(PRSC_EN<<14)|(PRSCVL<<6)|(SEL_MUX<<3)|(STDBM<<2)|(READ_START<<1);

   rADCCON|=(ADC_STAR<<0);          //开启ADC(开启ADC后,此位会自动清零)

 

}

 

//初始化LED,四个LED输出

voidLED_INIT(){                   

   rGPBCON=LED1_out|LED2_out|LED3_out|LED4_out;

}

 

//LED函数

void W1_LED(intget_data0){        

    rGPBDAT= LED4_ON;     //点亮四个LED

    Delay(get_data0);     //ADC后十位时延函数

    rGPBDAT= LED_OFF;     //熄灭LED

}

 

//串口打印变阻器模拟信号数值

void W1_ADC(int*read_xpdata){

              ADC_INIT(); //初始化AD控制寄存器

    /*****串口打印ADC数据函数****/

    while(rADCCON & 0x1);                //因为成功启动A/D转换后,该位会

                                          //自动清零,因此在这里检查ADC是否真正启动

    while(!(rADCCON & (1<<15)));            //使用查询方式等待ADC转换结束

   *read_xpdata=(int)(rADCDAT0&0x3ff);  //读取ADCDAT0后十位

    Uart_Printf('n HELLO ADC# W1值为: %04d ',*read_xpdata);//串口输出ADCDAT0后十位值

    Delay(500);

              }

 

//子main函数

voidADC_read_W1(){                    

  

    int read_xpdata0;

    ADC_display(); 

    LED_INIT(); //初始化LED

  

    while(1)

    {

     /*串口打印变阻器模拟信号数值*/

     W1_ADC( &read_xpdata0 );//传递read_xpdata0地址,改变read_xpdata0的值来给W1_LED函数使用

   

     /*****LED点亮函数*****/

     W1_LED(read_xpdata0);                 //LED函数

    

    }

 

}

 

◆串口输出截图

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • 开关电源的基本组成及工作原理

  • 带有短路保护系统的5V直流稳压电源电路图

  • 如何构建一个触摸传感器电路

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

    相关电子头条文章