版權(quán)聲明:本文為博主原創(chuàng)文章,如有需要,請注明轉(zhuǎn)載地址:http://blog.csdn.net/morixinguan。若是侵權(quán)用于商業(yè)用途,請聯(lián)系博主,否則將追究責(zé)任
ADC,就是模數(shù)轉(zhuǎn)換器,什么是模數(shù)轉(zhuǎn)換器?
模數(shù)轉(zhuǎn)換器,在電子技術(shù)中即是將模擬信號轉(zhuǎn)換成數(shù)字信號,也稱為數(shù)字量化。
當(dāng)然還有一種叫DAC,就是數(shù)模轉(zhuǎn)換,意思相反,即是將數(shù)字信號轉(zhuǎn)換成模擬信號。
在友善之臂ARM-contexA9這款開發(fā)板上的4412芯片本身就自帶了一個ADC的接口,我們來看看基本介紹:
數(shù)據(jù)手冊開篇介紹了這么多,最有用的一句話:精度10位或12位CMOS模數(shù)轉(zhuǎn)換器(ADC)包括多路模擬輸入。靈敏度為1M,一共有4路輸入,支持較低的電源模式等。
接下來我們還是跟以前一樣:
1、先看電路原理圖:
從原理圖和核心板上可以看出可調(diào)電阻的IO對應(yīng)數(shù)據(jù)手冊的是AIN[0]。
2、看數(shù)字手冊相關(guān)的寄存器
(1)ADC控制寄存器
寄存器的地址為:0x126C0000
在這里,我們要如何配置呢?
[0] 第0位:判斷A/D轉(zhuǎn)換有沒有開始
[2] 第2位:配置模式位(正常的,標(biāo)準(zhǔn)的,我們這里選擇默認(rèn)為0)
[6:13]第6~13位:這里要配置預(yù)分頻系數(shù),我們配置為49,對應(yīng)的公式就是:ADCCLK=PCLK/(49+10)=100MHZ / 50 =2MHZ
[14]第14位:選擇使能預(yù)分頻,寫1到這個位去就可以了
[15]第15位:判斷A/D轉(zhuǎn)換結(jié)束了沒有
[16]第16位:設(shè)置轉(zhuǎn)換的精度(10或者12,自己選)
(2)ADC數(shù)據(jù)寄存器
基地址:0x126C000C
[11:0] 第0~11位:ADC轉(zhuǎn)換的數(shù)據(jù)
(2)ADC通道選擇寄存器
基地址:0x12C001C
ADCMUX[0:3]:這里我們配置為0000,也就是通道0
3、寫代碼
config.h
<span style="font-size:18px;">#ifndef __CONFIG_H__
#define __CONFIG_H__
#define udelay ((void (*)(unsigned int ))0x43e25e88) //定義udelay在uboot中的地址,這樣我們就可以使用這個函數(shù)
#define print ((int (*)(const char *, ...))0x43e11434) //定義printf在uboot中的地址
typedef unsigned int u32;
typedefvolatile u32 v32;
//設(shè)置位
#define set_one(reg, bit) \
((*(v32 *)reg) |= (1<<bit))
#define set_zero(reg, bit) \
((*(v32 *)reg) &= (~(1<<bit)))
#define set_bit(reg, bit, val) \
(*(v32 *)reg = (((*(v32 *)reg) & (~(1<<bit))) | (val << bit)))
#define set_2bit(reg, bit, val) \
(*(v32 *)reg = (((*(v32 *)reg) & (~(3<<bit))) | (val << bit)))
#define set_nbit(reg, bit, n, val) \
(*(v32 *)reg = (((*(v32 *)reg) & (~( ((1<<n)-1) <<bit))) \
| (val << bit)))
#define set_val(reg, val) \
((*(v32 *)reg) = val)
#define get_bit(reg, bit) \
(((*(v32 *)reg) & (1<<bit)) >> bit)
#define get_2bit(reg, bit) \
(((*(v32 *)reg) & (3<<bit)) >> bit)
#define get_nbit(reg, bit, n) \
(((*(v32 *)reg) & (((1<<n)-1) <<bit)) >> bit)
#define get_val(reg) \
(*(v32 *)reg)
#endif</span>
<span style="font-size:18px;">#ifndef __CONFIG_H__ #define __CONFIG_H__ #define udelay ((void (*)(unsigned int ))0x43e25e88) //定義udelay在uboot中的地址,這樣我們就可以使用這個函數(shù) #define print ((int (*)(const char *, ...))0x43e11434) //定義printf在uboot中的地址 typedef unsigned int u32; typedef volatile u32 v32; //設(shè)置位 #define set_one(reg, bit) \ ((*(v32 *)reg) |= (1<<bit)) #define set_zero(reg, bit) \ ((*(v32 *)reg) &= (~(1<<bit))) #define set_bit(reg, bit, val) \ (*(v32 *)reg = (((*(v32 *)reg) & (~(1<<bit))) | (val << bit))) #define set_2bit(reg, bit, val) \ (*(v32 *)reg = (((*(v32 *)reg) & (~(3<<bit))) | (val << bit))) #define set_nbit(reg, bit, n, val) \ (*(v32 *)reg = (((*(v32 *)reg) & (~( ((1<<n)-1) <<bit))) \ | (val << bit))) #define set_val(reg, val) \ ((*(v32 *)reg) = val) #define get_bit(reg, bit) \ (((*(v32 *)reg) & (1<<bit)) >> bit) #define get_2bit(reg, bit) \ (((*(v32 *)reg) & (3<<bit)) >> bit) #define get_nbit(reg, bit, n) \ (((*(v32 *)reg) & (((1<<n)-1) <<bit)) >> bit) #define get_val(reg) \ (*(v32 *)reg) #endif</span>
adc.h
<span style="font-size:18px;">#ifndef __ADC_H__
#define __ADC_H__
#define ADCCON 0x126C0000 //ADC控制寄存器
#define ADCDAT 0x126C000C //ADC數(shù)據(jù)寄存器
#define ADCMUX 0x126C001C //ADC通道寄存器
#define CLRINTADC 0x126C0018 //清除ADC中斷
#endif</span>
<span style="font-size:18px;">#ifndef __ADC_H__ #define __ADC_H__ #define ADCCON 0x126C0000 //ADC控制寄存器 #define ADCDAT 0x126C000C //ADC數(shù)據(jù)寄存器 #define ADCMUX 0x126C001C //ADC通道寄存器 #define CLRINTADC 0x126C0018 //清除ADC中斷 #endif</span>
adc.c
<span style="font-size:18px;">#include <adc.h>
#include <config.h>
void select_mux(void)
{
set_nbit(ADCMUX, 0, 4, 0x0); //設(shè)置通道為通道0
}
void adc_init(void)
{
set_val(ADCCON, ((1<<16)|(1<<14)|(49<<6))); //按照數(shù)據(jù)手冊參數(shù)來配置adc控制寄存器的初始化部分
}
void adc_start(void)
{
set_one(ADCCON, 0); //adc轉(zhuǎn)換開始的配置,默認(rèn)參數(shù)為0
}
int adc_wait_flag(void)
{
return get_bit(ADCCON, 15);<span style="white-space:pre"> </span>//AD轉(zhuǎn)換是否成功
}
int adc_data(void)
{
return get_nbit(ADCDAT, 0, 12); //獲取ADC數(shù)據(jù)
}
void clear_adc(void)
{
set_val(CLRINTADC, 0);<span style="white-space:pre"> </span>//清ADC
}</span>
<span style="font-size:18px;">#include <adc.h> #include <config.h> void select_mux(void) { set_nbit(ADCMUX, 0, 4, 0x0); //設(shè)置通道為通道0 } void adc_init(void) { set_val(ADCCON, ((1<<16)|(1<<14)|(49<<6))); //按照數(shù)據(jù)手冊參數(shù)來配置adc控制寄存器的初始化部分 } void adc_start(void) { set_one(ADCCON, 0); //adc轉(zhuǎn)換開始的配置,默認(rèn)參數(shù)為0 } int adc_wait_flag(void) { return get_bit(ADCCON, 15);<span style="white-space:pre"> </span>//AD轉(zhuǎn)換是否成功 } int adc_data(void) { return get_nbit(ADCDAT, 0, 12); //獲取ADC數(shù)據(jù) } void clear_adc(void) { set_val(CLRINTADC, 0);<span style="white-space:pre"> </span>//清ADC }</span>
main.c
<span style="font-size:18px;">#include <config.h>
#include <adc.h>
int main(void)
{
//設(shè)置ADC通道為通道0
select_mux();
//adc初始化
adc_init();
//adc轉(zhuǎn)換開始
adc_start();
while(1)
{
//判斷是否已經(jīng)轉(zhuǎn)換
if(adc_wait_flag())
{
//打印相應(yīng)的數(shù)據(jù)
print("data = %d\n",adc_data());
//重新adc轉(zhuǎn)換開始
adc_start();
}
}
return 0;
}</span>
<span style="font-size:18px;">#include <config.h> #include <adc.h> int main(void) { //設(shè)置ADC通道為通道0 select_mux(); //adc初始化 adc_init(); //adc轉(zhuǎn)換開始 adc_start(); while(1) { //判斷是否已經(jīng)轉(zhuǎn)換 if(adc_wait_flag()) { //打印相應(yīng)的數(shù)據(jù) print("data = %d\n",adc_data()); //重新adc轉(zhuǎn)換開始 adc_start(); } } return 0; }</span>
4、makefile略
5、觀察結(jié)果
先讓uboot啟動
然后用dnw下載程序:
最后旋轉(zhuǎn)電阻觀察數(shù)據(jù)變化:
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!