ADC Acquisition Application
This chapter describes the GK7206 ADC (analog-to-digital converter) acquisition application example — sample_lsadc. The application demonstrates reading ADC channel data through the /dev/lsadc device node, and supports two working modes: single-step scan and continuous scan.
The application source code is located in the SDK directory sample/lsadc/. It is a simple hardware peripheral access example that shows how to interact with a hardware driver through the Linux character device interface.
1 Application Overview
1.1 Features
- Dual scan modes: supports single-step scan and continuous scan working modes
- Multi-channel selection: supports selecting different ADC input channels
- Interactive operation: select the mode and channel via the command line
- Real-time data display: prints the acquired ADC values in real time
- Low memory footprint: minimal memory usage with no complex dependencies
1.2 Technical Specifications
| Parameter | Value |
|---|---|
Device node | /dev/lsadc |
Scan modes | single-step scan, continuous scan |
Sampling interval | 1 second (adjustable) |
Acquisition count | 20 (default) |
Memory footprint | Minimal |
Kernel module | requires xm_lsadc.ko |
1.3 Directory Structure
sample/lsadc/
├── Makefile # Build script
└── sample_lsadc.c # Main program2 Build and Deployment
2.1 Prerequisites
Before building this application, make sure the following preparations have been completed:
- SDK environment is set up: follow SDK Compilation to set up the cross-compilation toolchain and SDK configuration
- Kernel module is loaded: the
xm_lsadc.komodule must be loaded
2.2 Build the Application
# Enter the sample directory
cd <SDK_PATH>/sample
# lsadc is not in the top-level objects; build it separately
make -C lsadc clean && make -C lsadcTips
The lsadc sample is not in the objects list of the top-level Makefile and must be built separately.
2.3 Deploy to the Board
# Transfer to the development board via SCP
scp sample/lsadc/sample_lsadc root@<board IP>:/tmp/
# Or download via TFTP
tftp -g -r sample_lsadc <board IP>Info
Since this application is very small, it can run directly from /tmp.
2.4 Run the Application
# Add execute permission
chmod +x /tmp/sample_lsadc
# Load the kernel module (required on first run)
insmod /opt/ko/xm_lsadc.ko
# Run the application (interactive)
./sample_lsadc2.5 Expected Output
Startup screen
=============== LSADC TEST ===============
0:single step scan mode
1:continuous scan mode
please select the mode:Single-step scan mode (select mode 0)
After selecting the channel:
please select the channel:
0
get value:1234,chn[0]
get value:1235,chn[0]
get value:1233,chn[0]
get value:1236,chn[0]
get value:1234,chn[0]
get value:1237,chn[0]
get value:1232,chn[0]
get value:1238,chn[0]
get value:1235,chn[0]
get value:1239,chn[0]
get value:1233,chn[0]
get value:1236,chn[0]
get value:1234,chn[0]
get value:1237,chn[0]
get value:1232,chn[0]
get value:1238,chn[0]
get value:1235,chn[0]
get value:1239,chn[0]
get value:1233,chn[0]
get value:1236,chn[0]Expected behavior:
- Prints
get value:<ADC value>,chn[<channel>]20 times in a loop - Prints once per second (
usleep(1000*1000)) - ADC value range: 0~4095 (12-bit ADC)
- The ADC value varies with the input voltage
- Exits automatically after 20 readings
Continuous scan mode (select mode 1)
After selecting the channel:
please select the channel:
0
get value:1234,chn[0]
get value:1235,chn[0]
get value:1233,chn[0]
get value:1236,chn[0]
get value:1234,chn[0]
get value:1237,chn[0]
get value:1232,chn[0]
get value:1238,chn[0]
get value:1235,chn[0]
get value:1239,chn[0]
get value:1233,chn[0]
get value:1236,chn[0]
get value:1234,chn[0]
get value:1237,chn[0]
get value:1232,chn[0]
get value:1238,chn[0]
get value:1235,chn[0]
get value:1239,chn[0]
get value:1233,chn[0]
get value:1236,chn[0]Expected behavior:
- Prints
get value:<ADC value>,chn[<channel>]20 times in a loop - Prints once per second
- The ADC value varies with the input voltage
- Exits automatically after 20 readings
How to exit
- Automatic exit: exits automatically after 20 acquisitions
- Manual exit: press
Ctrl+Cto force exit
Error cases
fail to open file:/dev/lsadcCause: the xm_lsadc.ko kernel module is not loaded Solution: insmod /opt/ko/xm_lsadc.ko
adc model select error.Cause: invalid mode argument Solution: make sure to enter 0 or 1
2.5 Interactive Operation
Single-step scan mode
please select the mode: 0
please select the channel: 0
get value:1234,chn[0]
get value:1235,chn[0]
...Continuous scan mode
please select the mode: 1
please select the channel: 0
get value:1234,chn[0]
get value:1235,chn[0]
...3 Internal Execution Logic in Detail
3.1 Application Architecture
This application uses a simple interactive architecture:
int main(void)
{
int mode, chn;
// Show the menu
printf("=============== LSADC TEST ===============\n");
printf("0:single step scan mode\n");
printf("1:continuous scan mode\n");
printf("please select the mode:\n");
// Read user input
scanf("%d", &mode);
// Select the scan mode based on the mode value
switch(mode) {
case 0:
printf("please select the channel:\n");
scanf("%d", &chn);
sample_lsadc_single_step_scan_mode(mode, chn);
break;
case 1:
printf("please select the channel:\n");
scanf("%d", &chn);
sample_lsadc_continuous_scan_mode(mode, chn);
break;
default:
printf("invalid mode\n");
break;
}
return 0;
}3.2 Single-Step Scan Mode
Each acquisition in single-step scan mode requires the full start → read → stop sequence:
xmedia_s32 sample_lsadc_single_step_scan_mode(lsadc_scan_mode mode, xmedia_s32 chn)
{
int i, value;
int fd = open(DEV_FILE, O_RDWR); // Open /dev/lsadc
if (fd < 0) {
fprintf(stderr, "fail to open file:%s\n", DEV_FILE);
return -1;
}
// Select the scan mode
if(ioctl(fd, LSADC_IOC_MODEL_SEL, &mode) < 0) {
fprintf(stderr, "adc model select error.\n");
goto exit;
}
// Enable the channel
if(ioctl(fd, LSADC_IOC_CHN_ENABLE, &chn) < 0) {
fprintf(stderr, "enable chn %d error.\n", chn);
goto exit;
}
// Acquire 20 samples in a loop
for(i = 0; i < 20; i++) {
// Start the ADC
if(ioctl(fd, LSADC_IOC_START) < 0) {
fprintf(stderr, "start lsadc error.\n");
goto exit;
}
// Read the channel value
value = ioctl(fd, LSADC_IOC_GET_CHNVAL, &chn);
printf("get value:%d,chn[%d]\n", value, chn);
usleep(1000 * 1000); // Wait 1 second
// Stop the ADC
if(ioctl(fd, LSADC_IOC_STOP) < 0) {
fprintf(stderr, "stop lsadc error.\n");
}
}
exit:
// Clean up
if(ioctl(fd, LSADC_IOC_STOP) < 0) {
fprintf(stderr, "stop lsadc error.\n");
}
if(ioctl(fd, LSADC_IOC_CHN_DISABLE, &chn) < 0) {
fprintf(stderr, "disable chn %d error.\n", chn);
}
close(fd);
return 0;
}3.3 Continuous Scan Mode
Continuous scan mode starts the ADC only once, then keeps reading data:
xmedia_s32 sample_lsadc_continuous_scan_mode(lsadc_scan_mode mode, xmedia_s32 chn)
{
int i, value;
int fd = open(DEV_FILE, O_RDWR);
if (fd < 0) {
fprintf(stderr, "fail to open file:%s\n", DEV_FILE);
return -1;
}
// Select the scan mode
if(ioctl(fd, LSADC_IOC_MODEL_SEL, &mode) < 0) {
fprintf(stderr, "adc model select error.\n");
goto exit;
}
// Enable the channel
if(ioctl(fd, LSADC_IOC_CHN_ENABLE, &chn) < 0) {
fprintf(stderr, "enable chn %d error.\n", chn);
goto exit;
}
// Start the ADC (started only once)
if(ioctl(fd, LSADC_IOC_START) < 0) {
fprintf(stderr, "start lsadc error.\n");
goto exit;
}
// Read data in a loop
for(i = 0; i < 20; i++) {
value = ioctl(fd, LSADC_IOC_GET_CHNVAL, &chn);
printf("get value:%d,chn[%d]\n", value, chn);
usleep(1000 * 1000); // Wait 1 second
}
exit:
// Clean up
if(ioctl(fd, LSADC_IOC_STOP) < 0) {
fprintf(stderr, "stop lsadc error.\n");
}
if(ioctl(fd, LSADC_IOC_CHN_DISABLE, &chn) < 0) {
fprintf(stderr, "disable chn %d error.\n", chn);
}
close(fd);
return 0;
}3.4 IOCTL Commands
The application uses the following IOCTL commands to interact with the driver:
| Command | Function | Argument |
|---|---|---|
LSADC_IOC_MODEL_SEL | Select scan mode | 0=single-step, 1=continuous |
LSADC_IOC_CHN_ENABLE | Enable channel | Channel number |
LSADC_IOC_CHN_DISABLE | Disable channel | Channel number |
LSADC_IOC_START | Start the ADC | None |
LSADC_IOC_STOP | Stop the ADC | None |
LSADC_IOC_GET_CHNVAL | Get channel value | Channel number |
3.5 Meaning of the ADC Value
The value returned by the ADC is an integer, typically in the range 0~4095 (12-bit ADC). The value is proportional to the input voltage:
voltage = (ADC value / 4095) × reference voltageFor example, with a 3.3 V reference voltage and an ADC value of 2048, the input voltage is approximately:
voltage = (2048 / 4095) × 3.3V ≈ 1.65V4 Key Programming Points
4.1 Device Node Operations
The standard operating pattern for a Linux character device:
// Open the device
int fd = open("/dev/lsadc", O_RDWR);
// IOCTL control
ioctl(fd, LSADC_IOC_MODEL_SEL, &mode);
// Close the device
close(fd);4.2 Error Handling
Check the return value of every IOCTL call:
if(ioctl(fd, LSADC_IOC_START) < 0) {
fprintf(stderr, "start lsadc error.\n");
goto exit; // Jump to the cleanup code
}4.3 Resource Cleanup
Use goto for unified resource cleanup:
exit:
// Disable the channel
if(ioctl(fd, LSADC_IOC_CHN_DISABLE, &chn) < 0) {
fprintf(stderr, "disable chn %d error.\n", chn);
}
// Close the device
close(fd);
return 0;
}5 Troubleshooting
| Problem | Possible cause | Solution |
|---|---|---|
fail to open file:/dev/lsadc | Device node does not exist | Check whether xm_lsadc.ko is loaded |
adc model select error | Invalid mode argument | Check that mode is 0 or 1 |
enable chn X error | Invalid channel number | Check that the channel number is in a valid range |
| ADC value always 0 | Input not connected or voltage too low | Check the hardware connection |
| ADC value always 4095 | Input voltage too high or above the reference | Check the input voltage range |
