We're no longer updating This wiki!!

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
en:xu3_hardware_adc [2016/01/21 11:50]
john1117 [Using mmap]
en:xu3_hardware_adc [2016/12/19 16:03] (current)
charles.park [Using mmap]
Line 8: Line 8:
 | 23         | ADC_0.AIN3 ​  | XADC0AIN_3 ​        | | 23         | ADC_0.AIN3 ​  | XADC0AIN_3 ​        |
  
-==== Using sysfs ====+===== Using sysfs =====
  
 Read raw data.(ADC Channel 0) Read raw data.(ADC Channel 0)
Line 19: Line 19:
 **Input voltage range is 0~1.8Volt. Otherwise your ODROID will be damaged permanently.** **Input voltage range is 0~1.8Volt. Otherwise your ODROID will be damaged permanently.**
  
-==== Using mmap ====+===== Using mmap =====
  
-Example ​source code+Example ​source code to access the ADC.
 <file c mmap_adc.c>​ <file c mmap_adc.c>​
 #include <​stdio.h>​ #include <​stdio.h>​
Line 27: Line 27:
 #include <​sys/​mman.h>​ #include <​sys/​mman.h>​
 #include <​stdint.h>​ #include <​stdint.h>​
- +  
-/* EXYNOS4412/​5250 ​ADC_V1 registers definitions */+/* EXYNOS ​ADC_V1 registers definitions */
 #define ADC_V1_DATAX 0x0C #define ADC_V1_DATAX 0x0C
 + 
 /* Future ADC_V2 registers definitions */ /* Future ADC_V2 registers definitions */
 #define ADC_V2_CON1 0x00 #define ADC_V2_CON1 0x00
 #define ADC_V2_CON2 0x04 #define ADC_V2_CON2 0x04
-#​define ​ADC_V2_INT_EN 0x10 +#​define ​ADC_V2_STAT 0x08 
-#define ADC_V2_INT_ST 0x14 + 
 /* Bit definitions for ADC_V2 */ /* Bit definitions for ADC_V2 */
 #define ADC_V2_CON1_SOFT_RESET (1u << 2) #define ADC_V2_CON1_SOFT_RESET (1u << 2)
 + 
 #define ADC_V2_CON2_OSEL (1u << 10) #define ADC_V2_CON2_OSEL (1u << 10)
 #define ADC_V2_CON2_ESEL (1u << 9) #define ADC_V2_CON2_ESEL (1u << 9)
Line 46: Line 45:
 #define ADC_V2_CON2_ACH_SEL(x) (((x) & 0xF) << 0) #define ADC_V2_CON2_ACH_SEL(x) (((x) & 0xF) << 0)
 #define ADC_V2_CON2_ACH_MASK 0xF #define ADC_V2_CON2_ACH_MASK 0xF
 + 
 /* Bit definitions common for ADC_V1 and ADC_V2 */ /* Bit definitions common for ADC_V1 and ADC_V2 */
 #define ADC_CON_EN_START ​       (1u << 0) #define ADC_CON_EN_START ​       (1u << 0)
Line 52: Line 51:
  
 static volatile uint32_t *adc; static volatile uint32_t *adc;
 +static unsigned char channel;
 static uint32_t con1, con2; static uint32_t con1, con2;
 +static int val0;
 +static int val3;
 +
 void exynos_read_raw(unsigned char channel); void exynos_read_raw(unsigned char channel);
-void exynos_adc_isr();​ 
-static int val; 
  
 int main(int argc, char **argv) int main(int argc, char **argv)
 { {
  int fd;  int fd;
 + 
  if ((fd = open("/​dev/​mem",​ O_RDWR | O_SYNC)) < 0) {  if ((fd = open("/​dev/​mem",​ O_RDWR | O_SYNC)) < 0) {
  printf("​Unable to open /​dev/​mem\n"​);​  printf("​Unable to open /​dev/​mem\n"​);​
  return -1;  return -1;
  }  }
 + 
  adc = mmap(0, getpagesize(),​ PROT_READ | PROT_WRITE,  adc = mmap(0, getpagesize(),​ PROT_READ | PROT_WRITE,
  MAP_SHARED,​ fd, 0x12D10000);​  MAP_SHARED,​ fd, 0x12D10000);​
Line 72: Line 73:
  return -1;  return -1;
  }  }
 + 
  // exynos_adc_hw_init  // exynos_adc_hw_init
  con1 = ADC_V2_CON1_SOFT_RESET;​  con1 = ADC_V2_CON1_SOFT_RESET;​
Line 79: Line 80:
  ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);​  ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);​
  *(adc + (ADC_V2_CON2 >> 2)) |= con2;  *(adc + (ADC_V2_CON2 >> 2)) |= con2;
- + 
- // Enable interrupts +
- *(adc + (ADC_V2_INT_EN >> 2)) |= 1;+
  while (1)  while (1)
  {  {
- if (*(adc + (ADC_V2_INT_ST ​>> 2)) ^ 1) { + // End of A/D conversion 
- exynos_read_raw(0); + if (*(adc + (ADC_V2_STAT ​>> 2)) & 4) { 
- exynos_adc_isr();+ /* Read value */ 
 + if (channel == 0x0) { 
 + val0 = *(adc + (ADC_V1_DATAX >> 2)) & ADC_DATX_MASK;​ 
 + printf("ADC Channel ​: %d\n", val0); 
 + } else if (channel == 0x3
 + val3 = *(adc + (ADC_V1_DATAX >> 2)) & ADC_DATX_MASK; 
 + printf("​ADC Channel 3 : %d\n", val3); 
 +
 + 
 + if (channel == 0x0) { 
 + /* start channel 0 conversion */ 
 + exynos_read_raw(3);​ 
 +
 + else if (channel == 0x3) { 
 + // start channel 3 conversion 
 + exynos_read_raw(0);​ 
 + }
  }  }
 + channel = con2 & ADC_V2_CON2_ACH_MASK;​
  sleep(1);  sleep(1);
- printf("​%d\n",​ val); 
  }  }
 + 
  return 0;  return 0;
 } }
-void exynos_adc_isr() + 
-+
- /* Read value */ +
- val = *(adc + (ADC_V1_DATAX >> 2)) & ADC_DATX_MASK;​ +
- /* clear irq */ +
- *(adc + (ADC_V2_INT_ST >> 2)) |= 1; +
-+
 void exynos_read_raw(unsigned char channel) void exynos_read_raw(unsigned char channel)
 { {
  con2 = *(adc + (ADC_V2_CON2 >> 2));  con2 = *(adc + (ADC_V2_CON2 >> 2));
  con2 &= ~ADC_V2_CON2_ACH_MASK;​  con2 &= ~ADC_V2_CON2_ACH_MASK;​
 + *(adc + (ADC_V2_CON2 >> 2)) &= con2;
  con2 |= ADC_V2_CON2_ACH_SEL(channel);​  con2 |= ADC_V2_CON2_ACH_SEL(channel);​
  *(adc + (ADC_V2_CON2 >> 2)) |= con2;  *(adc + (ADC_V2_CON2 >> 2)) |= con2;
 + 
  con1 = *(adc + (ADC_V2_CON1 >> 2));  con1 = *(adc + (ADC_V2_CON1 >> 2));
  *(adc +(ADC_V2_CON1 >> 2)) = con1 | ADC_CON_EN_START;​  *(adc +(ADC_V2_CON1 >> 2)) = con1 | ADC_CON_EN_START;​
 } }
 </​file>​ </​file>​
-Register Map Summary+==== Register Map Summary ​==== 
 + 
 +  * Base Address : 0x12D1_0000 
 ^Name^Offset^Description^Reset Value^ ^Name^Offset^Description^Reset Value^
 |ADC_CON1|0x0000|ADC Control register|0x0000_0002| |ADC_CON1|0x0000|ADC Control register|0x0000_0002|
Line 122: Line 134:
 |ADC_INT_STATUS|0x0014|ADC Interrupt Status register|0x0000_0000| |ADC_INT_STATUS|0x0014|ADC Interrupt Status register|0x0000_0000|
 |ADC_VERSION|0x0020|ADC Version information register|0x8000_0008| |ADC_VERSION|0x0020|ADC Version information register|0x8000_0008|
 +
 +**ADC_CON1**
 +
 +  * Base Address : 0x12D1_0000
 +  * Address = Base Address + 0x0000, Reset Value = 0x0000_0002
 +
 +^Name^Bit^Type^Description^Reset Value^
 +|RSVD|[31:​3]|R|Reserved(read as zero, do not modify)|0x0|
 +|SOFT_RESET|[2:​1]|RW|Software Reset|0x1|
 +|:::​|:::​|:::​|0x2 = Reset|:::|
 +|:::​|:::​|:::​|Other = Non-reset|:::​|
 +|STC_EN|[0]|RW|Enables ADC start conversion:​|0x0|
 +|:::​|:::​|:::​|0x0 = Disables|:::​|
 +|:::​|:::​|:::​|0x1 = Enables|:::​|
 +
 +**ADC_CON2**
 +
 +  * Base Address: 0x12D1_0000
 +  * Address = Base Address + 0x0004, Reset Value = 0x0000_0720
 +
 +^Name^Bit^Type^Description^Reset Value^
 +|RSVD|[31:​11|R|Reserved(read as zero, do not modify)|0x0|
 +|OSEL|[10]|RW|Selection of the output format|0x1|
 +|:::​|:::​|:::​|0x0 = 2's complement|:::​|
 +|:::​|:::​|:::​|0x1 = Offset binary(recommended)|:::​|
 +|ESEL|[9]|RW|Selection of the ADC output timing|0x0|
 +|:::​|:::​|:::​|0x0 = The first output data is evaluated after 40 ADC Clock|:::|
 +|:::​|:::​|:::​|0x1 = The first output data is evaluated after 20 ADC Clock (recommended).|:::​|
 +|HIGHF|[8]|RW|Selection of the ADC conversion rate|0x0|
 +|:::​|:::​|:::​|0x0 = 30 KSPS conversion rate|:::|
 +|:::​|:::​|:::​|0x1 = 600 KSPS conversion rate (recommended)|:::​|
 +|RSVD|[7]|R|Reserved (read as zero, do not modify)|0x0|
 +|C_TIME|[6:​4]|RW|Selection of the ADC conversion mode|0x2|
 +|:::​|:::​|:::​|0x0 = 1 times conversion to get the data|:::|
 +|:::​|:::​|:::​|0x1 = 2 times conversion|:::​|
 +|:::​|:::​|:::​|0x2 = 4 times conversion|:::​|
 +|:::​|:::​|:::​|0x3 = 8 times conversion|:::​|
 +|:::​|:::​|:::​|0x4 = 16 times conversion|:::​|
 +|:::​|:::​|:::​|0x5 = 32 times conversion|:::​|
 +|:::​|:::​|:::​|0x6 = 64 times conversion|:::​|
 +|:::​|:::​|:::​|NOTE:​ ADC_DAT register is updated on an average with a sum after 1, 2, 4, 8, 16, 32 or 64 times conversion.|:::​|
 +|ACH_SEL|[3:​0]|RW|Analog input channel selection|0x0|
 +|:::​|:::​|:::​|0x0 = Channel 0|:::|
 +|:::​|:::​|:::​|0x1 = Channel 1|:::|
 +|:::​|:::​|:::​|0x2 = Channel 2|:::|
 +|:::​|:::​|:::​|0x3 = Channel 3|:::|
 +|:::​|:::​|:::​|0x4 = Channel 4|:::|
 +|:::​|:::​|:::​|0x5 = Channel 5|:::|
 +|:::​|:::​|:::​|0x6 = Channel 6|:::|
 +|:::​|:::​|:::​|0x7 = Channel 7|:::|
 +|:::​|:::​|:::​|0x8 = Channel 8|:::|
 +|:::​|:::​|:::​|0x9 = Channel 9|:::|
 +|:::​|:::​|:::​|0xA to 0xF = Reserved|:::​|
 +
 +**ADC_STATUS**
 +
 +  * Base Address: 0x12D1_0000
 +  * Address = Base Address + 0x00048, Reset Value = 0x0000_0000
 +
 +^Name^Bit^Type^Description^Reset Value^
 +|RSVD|[31:​3]|R|Reserved (read as zero, do not modify)|0x0|
 +|FLAG|[2]|R|End of conversion flag|-|
 +|:::​|:::​|:::​|0x0 = A/D conversion in process|:::​|
 +|:::​|:::​|:::​|0x1 = End of A/D conversion|:::​|
 +|RSVD|[1:​0]|R|Reserved (read as zero, do not modify)|0x0|
 +
 +**ADC_DAT**
 +
 +  * Base Address: 0x12D1_0000
 +  * Address = Base Address + 0x000C, Reset Value = 0x0000_0000
 +
 +^Name^Bit^Type^Description^Reset Value^
 +|RSVD|[31:​12]|R|Reserved (read as zero, do not modify)|0x0|
 +|ADCDAT|[11:​0]|R|ADC conversion data value (0x000 to 0xFFF)|-|
 +
 +**ADC_INT_EN**
 +
 +  * Base Address: 0x12D1_0000
 +  * Address = Base Address + 0x0010, Reset Value = 0x0000_0000
 +
 +^Name^Bit^Type^Description^Reset Value^
 +|RSVD|[31:​1]|R|Reserved (read as zero, do not modify)|0x0|
 +|INT_EN|[0]|RW|0x0 = Disables interrupt|0x0|
 +|:::​|:::​|:::​|0x1 = Enables interrupt|:::​|
 +
 +**ADC_INT_STATUS**
 +
 +  * Base Address: 0x12D1_0000
 +  * Address = Base Address + 0x0014, Reset Value = 0x0000_0000
 +
 +^Name^Bit^Type^Description^Reset Value^
 +|RSVD|[31:​1]|R|Reserved (read as zero, do not modify)|0x0|
 +|INT_STATUS|[0]|RW|When Read|0x0|
 +|:::​|:::​|:::​|0x0 = Interrupt is not generated|:::​|
 +|:::​|:::​|:::​|0x1 = Interrupt is generated|:::​|
 +|:::​|:::​|:::​|When Write|:::|
 +|:::​|:::​|:::​|0x0 = No action|:::|
 +|:::​|:::​|:::​|0x1 = This bit is cleared|:::​|
 +
 +
 +**ADC_VERSION**
 +
 +  * Base Address: 0x12D1_0000
 +  * Address = Base Address + 0x0020, Reset Value = 0x8000_0008
 +
 +^Name^Bit^Type^Description^Reset Value^
 +|ADC_VERSION_INFO|[31:​0]|R|ADC Version Information|0x8000_0008|
en/xu3_hardware_adc.1453346402.txt.gz · Last modified: 2016/01/21 11:50 by john1117
CC Attribution-Share Alike 3.0 Unported
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0