本文主要探讨210的ADC相关知识。
ADC
ADC:模数转换(模拟信号转数字信号)
量程:模拟电压信号范围(210为0~3.3V)
精度:若10二进制位来表示精度(210为10位或12位),量程为0~3.3V,则精度为3.3V/2^10=0.0032265V
转换速率(MSPS):每秒转多少M数字值,210为 1 MSPS
通道数:模拟信号输入的路数,210共10ADC通道(AIN[0]~AIN[9]),同时可做10路AD转换,通道引脚为模拟引脚
ADC寄存器
TSADCCON0 ADC的配置
TSDATX0,TSDATY0转出的AD值
CLRINTADC0清中断
ADCMUX选择AD通道
demo:
测试ADC的值变化状况(转动螺丝)
start.S
#define WTCON 0xE2700000
#define SVC_STACK 0xd0037d80
#define SOFT_SW 0xE010E81C
.global _start
_start:
//set soft switcher,mean set XEINT[0] as PS_HOLD_OUT_EN,set output high level
ldr r0, =SOFT_SW
ldr r1, [r0]
orr r1, r1, #0x300
orr r1, r1, #0x01
str r1, [r0]
//close WatchDog
ldr r0,=WTCON
ldr r1,=0x0
str r1,[r0]
//init SVC stack
ldr sp,=SVC_STACK
//init icache
mrc p15,0,r0,c1,c0,0
bic r0,r0,#(1<<12) //close icache
orr r0,r0,#(1<<12) //open icache
mcr p15,0,r0,c1,c0,0
//use func
bl main
b .
main.c
#include "uart_printf.h"
#include "adc.h"
#include "stdio.h"
int main()
{
//init uart
init_uart();
printf("init uart\r\n");
//init adc
printf("init adc\r\n");
init_adc();
//read adc
printf("read adc data\r\n");
read_adc_data();
return 0;
}
uart_printf.h
void init_uart();
uart_printf.c
#define GPA0CON 0xE0200000
#define ULCON0 0xE2900000
#define UCON0 0xE2900004
#define UFCON0 0xE2900008
#define UMCON0 0xE290000C
#define UTRSTAT0 0xE2900010
#define UTXH0 0xE2900020
#define URXH0 0xE2900024
#define UBRDIV0 0xE2900028
#define UDIVSLOT0 0xE290002C
#define rGPA0CON (*(volatile unsigned int *)GPA0CON)
#define rULCON0 (*(volatile unsigned int *)ULCON0)
#define rUCON0 (*(volatile unsigned int *)UCON0)
#define rUFCON0 (*(volatile unsigned int *)UFCON0)
#define rUMCON0 (*(volatile unsigned int *)UMCON0)
#define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0)
#define rUTXH0 (*(volatile unsigned int *)UTXH0)
#define rURXH0 (*(volatile unsigned int *)URXH0)
#define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
#define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
//init uart
void init_uart()
{
//set gpio as uart(rx,tx)
rGPA0CON &= ~(0xff);
rGPA0CON |= ((1<<2)|(1<<5));
//set uart base configure(mode)
rULCON0 = 0x3;
rUCON0 = 0x5;
rUMCON0 = 0;
rUFCON0 = 0;
//set uart baud
//DIV_VAL = (PCLK / (bps x 16))-1
//(66000000 /(115200 * 16)) -1 = 34.8
rUBRDIV0 = 34;
//set uart baud calibration
//0.8 * 16 = 13,check 210 table
rUDIVSLOT0 = 0xdfdd;
}
//send data
void putc(char data)
{
while (!(rUTRSTAT0 & (1<<1)));
rUTXH0 = data;
}
//receive data
char getc()
{
while (!(rUTRSTAT0 & (1<<0)));
return (rURXH0 & 0xff);
}
adc.h
void init_adc();
void read_adc_data();
adc.c
#include "stdio.h"
#define TSADCCON0 0xE1700000
#define TSDATX0 0xE170000C
#define TSDATY0 0xE1700010
#define ADCMUX 0xE170001C
#define rTSADCCON0 (*(volatile unsigned int *)TSADCCON0)
#define rTSDATX0 (*(volatile unsigned int *)TSDATX0)
#define rTSDATY0 (*(volatile unsigned int *)TSDATY0)
#define rADCMUX (*(volatile unsigned int *)ADCMUX)
static void dealy_time()
{
volatile unsigned int num = 900000;
while(num--);
}
void init_adc()
{
//set adc is 10 bit
rTSADCCON0 |= (1<<16);
//set adc enable prescaler
rTSADCCON0 |= (1<<14);
//set adc prescaler value,value = 66 / (65 + 1) = 1Mhz
rTSADCCON0 &= ~(0xff<<6);
rTSADCCON0 |= (65<<6);
//set adc mode(normal)
rTSADCCON0 &= ~(1<<2);
//close when start adc is read only
rTSADCCON0 &= ~(1<<1);
//select adc channel 0
rADCMUX &= ~(0xf);
}
void read_adc_data()
{
volatile unsigned int x_value = 0;
volatile unsigned int y_value = 0;
while(1)
{
//start adc
rTSADCCON0 |= (1<<0);
//judge adc adc covert status(end or ing)
while(!(rTSADCCON0 & (1<<15)));
//read adc data
x_value = rTSDATX0;
y_value = rTSDATY0;
printf("read adc data : x : %d y : %d\r\n",(x_value & 0xfff),(y_value & 0xfff));
dealy_time();
}
}
link.lds
SECTIONS
{
. = 0xd0020010;
.text :
{
start.o
* (.text)
}
.data :
{
* (.data)
}
bss_start = .;
.bss :
{
* (.bss)
}
}
Makefile
CC = arm-linux-gcc
LD = arm-linux-ld
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump
INCDIR := $(shell pwd)
#预处理器的flag,flag就是编译器可选的选项
CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include
#C编译器的flag
CFLAGS := -Wall -O2 -fno-builtin
export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
objs := start.o uart_printf.o main.o adc.o
objs += lib/libc.a
led.bin:$(objs)
$(LD) -Tlink.lds -o adc.elf $^
$(OBJCOPY) -O binary adc.elf adc.bin
$(OBJDUMP) -D adc.elf > adc.dis
gcc mkv210.c -o mkv210
./mkv210 adc.bin sd.bin
lib/libc.a:
cd lib; make; cd ..
%.o:%.S
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
%.o:%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
clean:
rm *.o *.elf *.bin *.dis mkv210 -f
cd lib; make clean; cd ..
文件示例:
结果示例: