AT91SAM7S: Использование АЦП

AT91SAM7S: Использование АЦП.

Микроконтроллеры семейства AT91SAM7S имеют в своем составе «на борту» аппаратный АЦП. АЦП — По английски это  Analog-to-Digital-Converter (ADC).

АЦП служит для измерения напряжения, т.е. преобразования аналоговой информации в цифру. Амплитудам в диапазоне Vn + deltaV ставится в соответствие число n. Одной из характеристик АЦП является его разрядность, т.е. количество дискретных значений напряжения, на которые может делиться весь рабочий диапазон входных (анализируемых) напряжений. (http://nuclphys.sinp.msu.ru/electronics/adc.htm)

Для преобразования аналогового сигнала в цифровой как раз и  предназначены АЦП. Принцип работы заключается в том, что входной аналоговый сигнал преобразуется в цифровой код, который потом можно использовать в микроконтроллере по своему усмотрению. Для наглядности, рассмотрим один из возможных примеров АЦП.

АЦП (картинка взята с http://www.gaw.ru/html.cgi/txt/doc/adc/adc_3_3.htm)

А теперь нам нужно реализовать АЦП на базе микроконтроллера AT91SAM7S. Для этого нужно воспользоваться интегрированным АЦП в микроконтроллер.

В данном случае рассмотрим простую программу, по использованию АЦП.

В данном примере используется вход АЦП.

 

 

Пример взят от сюда – http://www.yeralan.org/agen/code/adc.c

// Simple program that runs ADC channel 7 and displays the
// most-significant four bits of the result by the LEDs
#define  TRUE                   1
#define  FALSE                  0
typedef  unsigned char       BOOL;
typedef  unsigned char       BYTE;
#define  PORT_LED0             11
#define  PORT_LED1             27
#define  PORT_LED2             29
#define  PORT_LED3             31
#define  CHANNEL                7
#define  PORT_MASK(nBit) (1<<nBit)
#include "AT91SAM7S64.h"
// ------------------------------------------------------------
// Init() initializes the Flash, the watchdog timer, the Power
// Management Controller (PMC), and the PIO port.
// See the steps outlined in the section titled "Programming
// Sequence" of the Atmel AT91SAM7S data sheet (Section 26.7 )
// to program the PMC.
// ------------------------------------------------------------
void Init(void){
AT91PS_PMC   pPMC;
AT91PS_PIO   pPIO;
unsigned int u;
// --- set flash memory parameters ---
// MCK will be set to 47.92 MHz (approximately 48MHz) below
// so set FMCN=48.  Add minimal wait states since we are above 40 MHz.
 AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(48 <<16)) | AT91C_MC_FWS_1FWS ;
// --- disable the watchdog timer ---
 AT91C_BASE_WDTC->WDTC_WDMR=AT91C_WDTC_WDDIS;
// --- program the Power Management Controller (PMC) ---
// steps are as given in Section 26.7 "Programming Sequence"
 pPMC=AT91C_BASE_PMC;
// 1. start the "main oscillator" (Section 25.3.3)
// slow clock frequency = 32.768 KHz
// slow clock period = 30.5176 microseconds
// Start up time = 8*7*30.5176 = 1708.984375 microseconds or 1.709 milliseconds
 pPMC->PMC_MOR = (AT91C_CKGR_OSCOUNT & (0x07 <<8)) | AT91C_CKGR_MOSCEN;
// 2. check the main oscillator frequency (optional)
// skipped
// wait the master clock to settle
 while(!(pPMC->PMC_SR & AT91C_PMC_MOSCS));
// 3. set the PLL and the divider
// main clock or (crystal) frequency = 18.432MHz)
// use: USBDIV=1, DIV=5, MUL=25, and OUT=0, which yields,
// (18.432/5)*(25+1)=95,8464MHz
// for a LOCK time of 1000 microseconds (1 milliseconds),
// set PLLCOUNT to 1000/30.5176=33
 pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 5) | (AT91C_CKGR_PLLCOUNT & (33<<8)) |
                     (AT91C_CKGR_MUL & (25<<16)) | (AT91C_CKGR_USBDIV & (1<<28)) );
// wait for the PLL to stabalize
 while(!(pPMC->PMC_SR&AT91C_PMC_LOCK));
// wait for the "master clock ready" flag
 while(!(pPMC->PMC_SR&AT91C_PMC_MCKRDY));
// 4. select the master clock source and the prescalar
// source    = the PLL clock
// prescalar = 2
 pPMC->PMC_MCKR=AT91C_PMC_CSS_PLL_CLK|AT91C_PMC_PRES_CLK_2;
 while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
// 5. select programmable clocks
// (programmable clocks are not used in this application)
// 6. enable the peripheral clock used by PIOA and ADC
 pPMC->PMC_PCER=(1<<AT91C_ID_PIOA)|(1<<AT91C_ID_ADC);
// initializ the port defined as PORT_LED as an output port.
//configure the PIO register used by the LED
 pPIO=AT91C_BASE_PIOA;
 u=PORT_MASK(PORT_LED3)|PORT_MASK(PORT_LED2)|PORT_MASK(PORT_LED1)|PORT_MASK(PORT_LED0);
 pPIO->PIO_PER  = u;   // enable LED ports
 pPIO->PIO_OER  = u;   // configure LED ports as an outputs
 pPIO->PIO_SODR = u;   // setting the output ports turn off the LEDs
}
// ------------------------------------------------------------
BOOL GetPort(BYTE bPort){
AT91PS_PIO pPio;
 pPio=AT91C_BASE_PIOA;
 return((pPio->PIO_PDSR & PORT_MASK(bPort))?TRUE:FALSE);  // return BOOL
}
// ------------------------------------------------------------
void SetPort(BYTE bPort, BOOL bState){
AT91PS_PIO pPio;
 pPio=AT91C_BASE_PIOA;
 if(bState) pPio->PIO_SODR = PORT_MASK(bPort);
    else pPio->PIO_CODR = PORT_MASK(bPort);
}
// ------------------------------------------------------------
void LedMeter(unsigned int uData){
 uData=uData;
 SetPort(PORT_LED0, !(uData&1));
 SetPort(PORT_LED1, !(uData&2));
 SetPort(PORT_LED2, !(uData&4));
 SetPort(PORT_LED3, !(uData&8));
}
// ------------------------------------------------------------
int main(void){
AT91PS_ADC   pADC;
volatile int n, nADC;

// perform initialization tasks
 Init();

// initialize the ADC
// track-an-hold : 600 nS   --> SHTIM   =  2
// start up time :  20 uS   --> STARTUP = 12
// 10-bit adc clk:   5 MHz  --> PRESCAL =  3
 pADC=AT91C_BASE_ADC;
 pADC->ADC_MR=0x020C0300;      // SHTIM:STARTUP:PRESCAL:00
 pADC->ADC_CHER=(1<<CHANNEL);  // enable adc channel
 pADC->ADC_CR=2;               // start ADC
// endless loop blinks the LED
 nADC=0;
 while(TRUE)
  {
   for(n=0; n<0x10000; n++);        // delay
   if((pADC->ADC_SR)&(1<<CHANNEL))  // check if adc channel is ready
    {
     nADC=pADC->ADC_LCDR;           // read conversion value
     pADC->ADC_CR=2;                // start ADC
    }
   LedMeter((nADC>>6)&0xFF);
   }
}
// -------------------------------------------------------------
// end of module main
// -------------------------------------------------------------
Makefile
# GNU make file for project_02
CC      = arm-none-eabi-gcc
AS      = arm-none-eabi-as
LD      = arm-none-eabi-ld
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
CFLAGS = -g -O6 -c -I. -mthumb -mthumb-interwork

# project and modules names
PRJNAME= adc_00
MEMMAP = map_rom
A_SRCS = startup.asm
C_SRCS = main.c
A_OBJS = $(A_SRCS:%.asm=%.obj)
A_LSTS = $(A_SRCS:%.asm=%.lst)
C_OBJS = $(C_SRCS:%.c=%.obj)
OBJS   = $(A_OBJS) $(C_OBJS)
#KEEPALL= TRUE

all: report build clean_intermediate
	@echo Done...

build: $(PRJNAME).bin $(PRJNAME).dmp

ifdef KEEPALL
clean_intermediate:
	@echo keeping intermediate files ...
else
clean_intermediate:
	@echo deleting intermediate files ...
	-del *.obj
	-del *.lst
	-del *.out
endif

$(PRJNAME).bin: $(PRJNAME).out
	@$(OBJCOPY) -O ihex -S -g $(PRJNAME).out $(PRJNAME).hex

	@echo generate the binary image "$(PRJNAME).bin" ...
	@$(OBJCOPY) -O binary -S -g $(PRJNAME).out $(PRJNAME).bin

$(PRJNAME).dmp: $(PRJNAME).out
	@echo generate the dump file "$(PRJNAME).dmp" ...
	@$(OBJDUMP) -h -S -C $(PRJNAME).out > $(PRJNAME).dmp

$(PRJNAME).out: $(OBJS)
#	@$(CC) -g -O6 -S -I. -mthumb -mthumb-interwork main.c -o main.src
#	@$(LD) --verbose > verbose.txt

	@echo link the object files {$(OBJS)} to generate "$(PRJNAME).out"
#	@$(LD) -e 0 -static -M $(MEMMAP).ld -o $(PRJNAME).out $(OBJS) >out.map
#	@$(LD) -e 0 $(MEMMAP).ld -o $(PRJNAME).out $(OBJS) -lgcc -LW:\Tools\SourceryG++\lib\gcc\arm-none-eabi\4.1.0\thumb
	@$(LD) -e 0 $(MEMMAP).ld -o $(PRJNAME).out $(OBJS) -lgcc

%.obj: %.c
	@echo compile "$< " to generate "$@" ...
	@$(CC) $(CFLAGS) $< -o $@

%.obj : %.asm
	@echo assemble "$<" to generate "$*.lst" and "$@" ...
	@$(AS) -a=$*.lst -o $@ $<

report:
	@echo ------------------------------------------------------------------------------------
	@echo project      : $(PRJNAME)
	@echo asm sources  : $(A_SRCS)
	@echo c sources    : $(C_SRCS)
	@echo c objects    : $(C_OBJS)
	@echo asm objects  : $(A_OBJS)
	@echo all objects  : $(OBJS)
	@echo link         : $(MEMMAP).ld
	@echo output       : $(PRJNAME).out
	@echo dump         : $(PRJNAME).dmp
	@echo binary image : $(PRJNAME).bin
	@echo ------------------------------------------------------------------------------------

.PHONY: clean
clean:
	-del *.obj
	-del *.lst
	-del *.out
	-del *.dmp
	-del *.bin
	-del *.src
	-del *.map
	-del *.hex
startup.asm
@ --- this is a comment ---
.extern main

.text
.section .init
.code	 32
reset:
    b     start            @ reset and other vectors
    b     error
    b     error
    b     error
    b     error
    b     error
    b     error
    b     error

start:
    ldr   sp, =0x00203FF8  @ stack starts at top of RAM

@ enter the C code
    ldr   r3, =main
    ldr   lr, =error       @ adr lr, error
    bx    r3               @ call main()

error:
    b     error

 

Добавить комментарий