Hi, we connected a battery to the ADC of a AM3359 (via a resistor divider).
Where i can find a simple code source to setup the ADC and to know the voltage of the battery.
I am not using a Linux Kernel, just U-boot.
Regards
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
So, here it is:
In file pll.c
/* ADC clock enable */
__raw_writel(PRCM_MOD_EN, CM_WKUP_ADC_TSC_CLKCTRL);
while (__raw_readl(CM_WKUP_ADC_TSC_CLKCTRL) != PRCM_MOD_EN);
In myapplication.c file
/* Unprotect step registers, TSC_ADC_SS module disabled because configuration in progress */
__raw_writel(0x00000004, TSC_ADC_SS_CTRL);
while((__raw_readl(TSC_ADC_SS_CTRL) & 0x00000001) !=0);
/* No idle mode */
__raw_writel(0x00000004, TSC_ADC_SS_SYSCONFIG);
/* ADC clock 100KHz. Master clock is 24 MHz */
__raw_writel((24000000)/100000, TSC_ADC_SS_ADC_CLKDIV);
/* Enable step 1 (because it is the first one) */
__raw_writel(0x00000002, TSC_ADC_SS_STEPENABLE);
/* VREFN, AIN7, VREFP, Data in FIFO 16 samples average, SW enabled, continuous */
__raw_writel(0x01BFB011, TSC_ADC_SS_STEPCONFIG1);
/* TSC_ADC_SS module enabled */
__raw_writel(0x00000001, TSC_ADC_SS_CTRL);
while((__raw_readl(TSC_ADC_SS_CTRL) & 0x00000001)==0);
/* Wait for a value in FIFO */
tempo=5000; /* 5 msec */
while((__raw_readl(TSC_ADC_SS_FIFO0COUNT) & 0x7F)==0 && --tempo)
udelay(1);
if(tempo==0)
{printf("!!! Error: ADC stuck... in IDLE step ?\n\n");return(-1);}
/* Displays the voltage being given VREFP=1800 mV VREFN=0 */
voltage=(1800*(__raw_readl(TSC_ADC_SS_FIFO0DATA) & 0xFFF))/0xFFF;
printf("Voltage is %d mV\n",voltage);
Defines are
#define ADC_TSC (PRCM_BASE + 0xD000)
#define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP + 0xBC)/* ADC */
#define TSC_ADC_SS_SYSCONFIG (ADC_TSC + 0x010) /* SYSCONFIG */
#define TSC_ADC_SS_CTRL (ADC_TSC + 0x040) /* CTRL */
#define TSC_ADC_SS_ADC_CLKDIV (ADC_TSC + 0x04C) /* ADC_CLKDIV */
#define TSC_ADC_SS_STEPENABLE (ADC_TSC + 0x054) /* STEPENABLE */
#define TSC_ADC_SS_STEPCONFIG1 (ADC_TSC + 0x064) /* STEPCONFIG1 */
#define TSC_ADC_SS_FIFO0COUNT (ADC_TSC + 0x0E4) /* FIFO0COUNT */
#define TSC_ADC_SS_FIFO0DATA (ADC_TSC + 0x100) /* FIFO0DATA */
Critics are welcome.
Hi, there is this post with some code. It calls API from Texas Instrument.
http://e2e.ti.com/support/dsp/sitara_arm174_microprocessors/f/791/t/196266.aspx
Regards
Thanks so much for your code!
I made small changes in your code, now it can be used as a driver (of course with reduced posibilities, just read adc in oneshot mode).
I use u-boot version 3.2 (TI SDK 6), I created folder /drivers/adc/ and put there the following 3 files:
Makefile -> http://pastebin.com/GbxbTwi8
adc_am335x.h -> http://pastebin.com/zTW5WJ9X
adc_am335x.c -> http://pastebin.com/0KBXG5bn
I also changed the Makefile in srcdir, I added the following line:
...
LIBS-y += post/libpost.o
LIBS-y += test/libtest.o
LIBS-y += drivers/adc/libadc.o
...
For PLL I made the following changes:
in file arch/arm/include/asm/arch-am33xx/cpu.h I added:
/* Encapsulating core pll registers */
struct cm_wkuppll {
unsigned int wkclkstctrl; /* offset 0x00 */
...
unsigned int wkup_i2c0ctrl; /* offset 0xB8 */
unsigned int wkup_adc_tsc_ctrl; /* offset 0xBC */
unsigned int resv12[6];
unsigned int divm6dpllcore; /* offset 0xD8 */
};
In file arch/arm/cpu/armv7/am33xx/clock.c I added:
/*
* Enable the peripheral clock for required peripherals
*/
static void enable_per_clocks(void)
{
...
/* ADC clock enable */
writel(PRCM_MOD_EN, &cmwkup->wkup_adc_tsc_ctrl);
while (readl(&cmwkup->wkup_adc_tsc_ctrl) != PRCM_MOD_EN)
;
}
You can include header and use the driver in the following way:
int adc_voltage=am335x_adc_get_voltage(AIN5); if(adc_voltage<0) { puts("Error reading from ADC!\n"); return; } printf("Battery voltage: %d mV\n", adc_voltage);