裸机系列代码地址:链接:http://pan.baidu.com/s/1pLHOd0v 密码:4x5s
S3C2440的CMOS模数转换器可以接收8个通道的模拟信号输入,并将它们转换成10位的二进制数据
S3C2440的触摸屏接口向外提供4个控制引脚(XP,XM,YP,YM)与触摸屏的直接相连。S3C2440的ADC和触摸屏机构图如下所示下面是一个触摸屏的实例程序
Makefile 文件
objs:= head.o init.o main.o irq.o
adcts.bin: $(objs)
arm-linux-ld -Tadc_ts.lds -o adcts_elf $^
arm-linux-objcopy -O binary -S adcts_elf $@
arm-linux-objdump -D -m arm adcts_elf > adcts.dis
%.o:%.c
arm-linux-gcc -Wall -O2 -c -o $@ $<
%.o:%.s
arm-linux-gcc -Wall -O2 -c -o $@ $<
clean:
rm -f adcts_elf adcts.dis adcts.bin *.o
链接文件
SECTIONS {
. = 0x30000000;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata)}
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
head.S
.text
.global _start
_start:
b reset
HandleUndef:
b HandleUndef
HandlerSWI:
b HandlerSWI
HandlePrefetchAbort:
b HandlePrefetchAbort
HandleDataAbort:
b HandleDataAbort
HandleNotUsed:
b HandleNotUsed
b HandleIRQ /*中断向量表的位置必须固定,即 b HandleIRQ运行位置必须在0x18处*/
HandleFIQ:
b HandleFIQ
reset:
ldr sp,=4096 /*设置C函数使用的栈*/
bl disable_watch_dog
msr cpsr_c,#0xd2 /*进入中断模式*/
ldr sp,=3072 /*设置中断模式栈指针*/
msr cpsr_c,#0xd3 /*进入系统模式*/
ldr sp,=4096 /*设置系统模式栈指针*/
msr cpsr_c,#0x5f /*开IRQ中断,这之后程序可以响应中断*/
bl init_clock /*设置系统时钟,使得uart使用PCLK为50MHZ*/
bl memsetup /*初始化存储控制器使得SDRAM可用*/
bl copy_steppingstone_to_sdram /*将代码复制到SDRAM中*/
ldr pc,=on_sdram /*地址相关代码,从这里开始程序在SDRAM中运行*/
on_sdram:
ldr sp,=0x34000000 /*设置代码在SDRAM中运行时的栈*/
bl init_uart0 /*初始化串口0*/
bl main
bl halt_loop
halt_loop:
b halt_loop
HandleIRQ:
sub lr,lr,#4
stmdb sp!,{r0-r12,lr}
ldr lr,=int_return
ldr pc,=EINT_Handle
int_return:
ldmia sp!,{r0-r12,pc}^
init.c
#include "s3c2440.h"
void disable_watch_dog(void)
{
WTCON = 0x53000000;
}
/*注意这里必须用这种方式,用数组循环赋值的方式不可取*/
void memsetup(void)
{
volatile unsigned long *p = (volatile unsigned long *)0x48000000;
/* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
* 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
* SDRAM之前就可以在steppingstone中运行
*/
/* 存储控制器13个寄存器的值 */
p[0] = 0x22011110; //BWSCON
p[1] = 0x00000700; //BANKCON0
p[2] = 0x00000700; //BANKCON1
p[3] = 0x00000700; //BANKCON2
p[4] = 0x00000700; //BANKCON3
p[5] = 0x00000700; //BANKCON4
p[6] = 0x00000700; //BANKCON5
p[7] = 0x00018005; //BANKCON6
p[8] = 0x00018005; //BANKCON7
/* REFRESH,
* HCLK=12MHz: 0x008C07A3,
* HCLK=100MHz: 0x008C04F4
*/
p[9] = 0x008C04F4;
p[10] = 0x000000B1; //BANKSIZE
p[11] = 0x00000030; //MRSRB6
p[12] = 0x00000030; //MRSRB7
}
void copy_steppingstone_to_sdram(void)
{
unsigned int *pdest = (unsigned int *)0x30000000;
unsigned int *psrc = (unsigned int *)0x00000000;
while(psrc<(unsigned int *)4096)
{
*pdest = *psrc;
pdest++;
psrc++;
}
}
void init_clock(void)
{
#define MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
CLKDIVN = 0x03;
__asm__(
"mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
"orr r1, r1, #0xc0000000\n" /* 设置为“asynchronous bus mode” */
"mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
);
MPLLCON = MPLL_200MHZ;
}
void init_uart0(void)
{
GPHCON = 0xa0; /*GPH2,GPH3用作TXD0,RXD0*/
GPHUP = 0x0c; /*GPH2,GPH3内部上拉*/
#define UART_PCLK 50000000
#define baurd 115200
#define UART_BRD ((UART_PCLK/(baurd*16)) -1 )
ULCON0 = 0x03; /*数据位数为8,一个停止位,无奇偶校验*/
UCON0 = 0x05; /*查询方式,UART时钟源为PCLK*/
UFCON0 = 0x00; /*不使用FIFO*/
UMCON0 = 0x00; /*不使用流控*/
UBRDIV0 = UART_BRD; /*波特率为115200*/
}
irq.c
#include "s3c2440.h"
#define TXD0READY (1<<2)
#define RXD0READY (1)
#define ADC_START (1 << 0)
#define PRESCALE_EN (1 << 14)
#define PRSCVL(x) ((x) << 6)
void putcc(char c)
{
while( !(UTRSTAT0 & TXD0READY));
UTXH0 = c;
}
unsigned char getcc(void)
{
while(!(UTRSTAT0 & 1));
return URXH0;
}
void putstring(char *p)
{
while(*p != '\0')
{
putcc(*p);
p++;
}
}
static void isr_tc(void)
{
if(ADCDAT0 & 0x8000)
{
putstring("stylus up\n\r");
ADCTSC = 0xd3; /*进入等待中断模式,检测触电按下*/
}
else
{
putstring("stylus down\n\r");
ADCTSC = 0x0c; /*进入自动X/Y连续转换模式*/
ADCCON |= ADC_START; /*开启ADC转换*/
}
/*清除中断*/
SUBSRCPND |= BIT_SUB_TC;
SRCPND |= BIT_ADC;
INTPND |= BIT_ADC;
}
static void isr_adc(void)
{
int x,y;
x = (int)(ADCDAT0 & 0x3ff);
y = (int)(ADCDAT1 & 0x3ff);
char ptx[4]={'\0','\0','\0','\0'};
char pty[4]={'\0','\0','\0','\0'};
ptx[0]=x/100+'0';
ptx[1]=(x%100)/10+'0';
ptx[2]=x%10+'0';
pty[0]=y/100+'0';
pty[1]=(y%100)/10+'0';
pty[2]=y%10+'0';
putstring(ptx);
putstring("\n\r");
putstring(pty);
putstring("\n\r");
ADCTSC = 0x1d3;; /*进入等待中断模式,检测触电松开*/
/*清除中断*/
SUBSRCPND |= BIT_SUB_ADC;
SRCPND |= BIT_ADC;
INTPND |= BIT_ADC;
}
void EINT_Handle(void)
{
if(SUBSRCPND & BIT_SUB_TC) /*如果是TC中断,则进入TC中断的处理函数*/
isr_tc();
if(SUBSRCPND & BIT_SUB_ADC) /*如果是ADC中断,则进入ADC中断的处理函数*/
isr_adc();
}
void Test_Ts(void)
{
INTMSK &= ~BIT_ADC; // 开启ADC总中断
INTSUBMSK &= ~(BIT_SUB_TC); // 开启INT_TC中断,即触摸屏被按下或松开时产生中断
INTSUBMSK &= ~(BIT_SUB_ADC); // 开启INT_ADC中断,即A/D转换结束时产生中断
INTMOD &= ~BIT_ADC;
// 使能预分频功能,设置A/D转换器的时钟 = PCLK/(49+1)
ADCCON = PRESCALE_EN | PRSCVL(49);
/* 采样延时时间 = (1/3.6864M)*50000 = 13.56ms
* 即按下触摸屏后,再过13.56ms才采样
*/
ADCDLY = 50000;
ADCTSC = 0xd3; /* 进入"等待中断模式",等待触摸屏被按下 */
}
main.c
#include "s3c2440.h"
extern void Test_Ts(void);
extern void putstring(char *);
int main()
{
Test_Ts();
while(1);
return 0;
}