查看: 4182|回复: 1

SAM4N ADC的使用

[复制链接]
  • TA的每日心情
    奋斗
    2015-1-22 18:04
  • 签到天数: 189 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2013-12-3 19:49:37 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 nongxiaoming 于 2013-12-4 10:04 编辑

    SAM4N有两种ADC,一种是12bit的,一种是10bit的。两种ADC的配置基本是一样的。因为板子上引出的ADC10和ADC11都是10bit的,所以凑合着用了,ADC的通道16读出的值就是MCU内部的温度传感器ADC值,所以这次的驱动只驱动ADC10,ADC11和ADC16,代码如下:
    1. void ADC_Init(uint16_t adc_clk,uint8_t tracktim)
    2. {
    3.            uint8_t prescal,startup,shtim;
    4.     /*计算ADC CLK分频值*/
    5.          prescal=SystemCoreClock/(adc_clk*2)-1;
    6.         /*禁止外设管理控制寄存器(PMC)写保护*/
    7.   PMC->PMC_WPMR = 0x504D4300;
    8.   /*使能ADC和PIOC时钟*/        
    9.   PMC->PMC_PCER0 = ((1UL << ID_PIOC) |   
    10.                     (1UL << ID_ADC) );  
    11.         /*使能外设管理控制寄存器(PMC)写保护*/
    12.   PMC->PMC_WPMR = 0x504D4301;  
    13.    /*配置PC13为ADC10,PC15为ADC11*/        
    14.         PIOC->PIO_IDR=(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
    15.         PIOC->PIO_PUDR=(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
    16.         PIOC->PIO_ABCDSR[0]&=~(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
    17.         PIOC->PIO_ABCDSR[1]&=~(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
    18.         PIOC->PIO_PDR=(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
    19.         /*软件复位ADC*/
    20.         ADC->ADC_CR=ADC_CR_SWRST;
    21.         /*配置ADC模式*/
    22.         ADC->ADC_MR=ADC_MR_TRGEN_DIS|     //禁止硬件触发,即使用软件控制
    23.                     ADC_MR_TRGSEL_ADC_TRIG0| //使用定时器通道0的TIOA输出
    24.                     ADC_MR_LOWRES_BITS_10|   //设置为10Bit模式
    25.                     ADC_MR_SLEEP_NORMAL|  //设置为普通模式
    26.                                                         ADC_MR_PRESCAL(prescal)| //设置adc clk分频值
    27.                                                         ADC_MR_STARTUP_SUT8|     //设置启动时间为8个adc_clk时钟周期
    28.                                                         ADC_MR_TRACKTIM(tracktim)|
    29.                                                         ADC_MR_TRANSFER(2);       //这个必须为2,数据手册已注明
    30.                 /*使能通道10,通道11和通道16*/                                       
    31.          ADC->ADC_CHER=ADC_CHER_CH10|ADC_CHER_CH11|ADC_CHER_CH16;  
    32.    /*使能内部温度传感器*/
    33.    ADC->ADC_TEMPMR=ADC_TEMPMR_TEMPON;         
    34.                  /*开始ADC转换*/
    35.         ADC->ADC_CR=ADC_CR_START;
    36. }
    37. void ADC_StartConvert(void)
    38. {
    39.          /*开始ADC转换*/
    40.         ADC->ADC_CR=ADC_CR_START;
    41. }
    42. void ADC_EnableChannel(uint8_t channel)
    43. {
    44.   if(channel>16)
    45.                 return;
    46.         ADC->ADC_CHER=(0x01<<channel);
    47. }
    48. void ADC_DisableChannel(uint8_t channel)
    49. {
    50.   if(channel>16)
    51.                 return;
    52.         ADC->ADC_CHDR=(0x01<<channel);
    53. }
    54. uint16_t ADC_GetConvertedData(uint8_t channel)
    55. {
    56.     unsigned int data=0;
    57.     if(channel<17){
    58.     data = ADC->ADC_CDR[channel]&0x3ff;
    59.                 }
    60.     return data;   
    61. }
    复制代码
    对于温度来说,读出的只是一个10bit的值,需要进行转换才得到温度值。这换算公式手册并没有给出,只有官方例程提供了换算方法,如下:
    1. /** Reference voltage for ADC,in mv. */
    2. #define VOLT_REF        (3300)
    3. /** The maximal digital value */
    4. #define MAX_DIGITAL     (1023UL)
    5. int16_t ADC_GetTempTemperature(void)
    6. {
    7. uint16_t adc_value;
    8.         int16_t temp=0;
    9.         adc_value=ADC_GetConvertedData(16);
    10.         adc_value=adc_value* VOLT_REF / MAX_DIGITAL;
    11.         temp = (adc_value - 1440)  * 100 / 470 + 27;
    12.         return temp;
    13. }
    复制代码
    下面是一个读取ADC值的例子:
    1. int main(void)
    2. {
    3. systick_hw_init();
    4. led_hw_init();
    5. UART0_Init(115200);
    6. printf("this is a adc demo!\r\n");
    7. ADC_Init(4000000UL,8);         //初始化adc,clk为4Mhz
    8. while(1){
    9. uint16_t adc10_value,adc11_value;
    10. int16_t temp=0;
    11. ADC_StartConvert();
    12.           delay_ms(100);
    13. adc10_value=ADC_GetConvertedData(10);
    14. adc11_value=ADC_GetConvertedData(11);
    15. temp=ADC_GetTempTemperature();
    16. printf("ADC10:%d,ADC11:%d,Temp:%d\r\n",adc10_value,adc11_value,temp);
    17. PIOB->PIO_CODR=(0x01<<LED0_PIN);
    18. delay_ms(300);
    19. PIOB->PIO_SODR=(0x01<<LED0_PIN);
    20. delay_ms(300);
    21. }

    22. }
    23. 运行输出如下:
    24. <img src="https://www.cirmall.com/bbs/forum.php?mod=image&aid=69227&size=300x300&key=373c946ffa4cdd0dcb28c9fbf5616ac4&nocache=yes&type=fixnone" aid="attachimg_69227" alt="" border="0"> 11.adc.rar (1.07 MB, 下载次数: 10)
    复制代码
    QQ图片20131028164543.jpg
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2015-1-22 18:04
  • 签到天数: 189 天

    连续签到: 1 天

    [LV.7]常住居民III

     楼主| 发表于 2013-12-4 10:05:18 | 显示全部楼层
    补上了图片和代码~~昨天太急了
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-20 01:32 , Processed in 0.130280 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.