`
mmdev
  • 浏览: 12845768 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

基于S3C2440的ARM9基础程序设计及分析

 
阅读更多

基于S3C2440的ARM9基础程序设计及分析
-------JustDo
最近学习了ARM9基础程序的设计,记录下所学心得,希望对初学者提供一些帮助。学习ARM程序要注意方法,先去芯片手册的相应模块部分的结构原理框图,搞清楚所使用的模块的基本原理,然后根据框图搞清楚需要设置哪些对应的寄存器,再根据时序图搞明白相应寄存器应该怎样设置,再接着理清楚你所写程序的大概流程,最后就可以动手写程序了。
如果把流程理清楚了,你的程序基本上已经成功一半了。
我使用的是S3C2440 ARM芯片,如有疑问或者遗漏之处,请联系:qq,843308498。

源码下载地址http://download.csdn.net/source/3149713
一 LED流水灯程序
流程:
1,设置端口控制寄存器将LED对应端口设为输出模式 (GPxCON)。
2,向端口对应的数据寄存器发送数据(GPxDAT)。
实现:
//这段宏定义了使对应LED亮应该送的数据
#define LED1_ON ~(1<<5)
#define LED2_ON ~(1<<6)
#define LED3_ON ~ (1<<7)
#define LED4_ON ~(1<<8)

#define LED1_OFF (1<<5)
#define LED2_OFF (1<<6)
#define LED3_OFF (1<<7)
#define LED4_OFF (1<<8)

//LED初始化函数,设置GPBCON为输出端口,并往端口送数据,使所有LED处于灭的状态
void LEDInit()
{
rGPBCON |= (1<<10) | (1<<12) | (1<<14) | (1<<16);
rGPBDAT |= (LED1_OFF | LED2_OFF |LED3_OFF | LED4_OFF);
}

//LED轮流闪亮函数,先点亮对应LED,然后延时,再关闭
void LEDRun()
{
rGPBDAT &= LED1_ON;
delay(1000);
rGPBDAT |= LED1_OFF;
rGPBDAT &= LED2_ON;
delay(1000);
rGPBDAT |= LED2_OFF;
rGPBDAT &= LED3_ON;
delay(1000);
rGPBDAT |= LED3_OFF;
rGPBDAT &= LED4_ON;
delay(1000);
rGPBDAT |= LED4_OFF;
}
二 按键中断程序
流程:
中断处理流程
1 中断控制器汇集各类外设发出的中断信号,然后告诉CPU
2 CPU保存当前程序的运行环境,然后调用中断服务程序来处理中断
3 在ISR中通过读取中断控制寄存器,外设相关的寄存器来识别是哪个中断,并进行相应的处理
4 清楚中断:通过读写相关的中断控制寄存器和外设相关寄存器来实现
5 最好恢复被中断程序的环境,继续执行
按键中断程序流程:
初始化
1 设置按键对应的端口为中断(GPxCON)
2 设置中断程序入口
3 清外部中断挂起寄存器EINITPEND和挂起寄存器INTPND,SRCPND,防止原有干扰
4 设置电平触发方式(EXTINITn)
5 关闭外部中断ENTMASK和INTMASK对中断的屏蔽
中断程序
6清挂起寄存器INTPND,SRCPND,防止反复响应该中断
7 通过判断rEINITPEND相应的位来确定是哪一个按键产生的中断,然后执行相应的程序,并清除rEINITPEND相应的位,防止反复的响应

程序:
static void __irq KeyHander();//声明中断处理函数
//按键初始化函数
void KeyInit()
{
MMU_Init();

rGPGCON |= (1<<1 | 1<<7 | 1<<11 | 1<<13 );//设置GPGCON相应端口为中断

pISR_EINT8_23 = (U32)KeyHander;//设置中断程序入口

rEINTPEND |= (1<<8 | 1<<11 | 1<<13 | 1<<14); //清外部中断挂起寄存器,防止干扰
ClearPending(BIT_EINT8_23);

rEINTMASK &= ~(1<<8 | 1<<11 | 1<<13 | 1<<14); //打开外部中断屏蔽器
//rEXTINIT1为设置中断触发方式寄存器,因为其默认是低电平触发,所以不需要设置
EnableIrq(BIT_EINT8_23);//使能中断,其实是打开MASK
}

//按键响应函数
void KeyHander()
{
ClearPending(BIT_EINT8_23);//清中断挂起寄存器包括SRCPND INTPND
if(rEINTPEND & 1<<8)//通过外部中断挂起寄存器判断是哪个按键请求中断
{
rEINTPEND |= 1<<8;//清外部中断挂起寄存器,防止反复中断
LightLed(1);
}
if(rEINTPEND & 1<<11)
{
rEINTPEND |= 1<<11;
LightLed(2);
}
if(rEINTPEND & 1<<13)
{
rEINTPEND |= 1<<13;
LightLed(3);
}
if(rEINTPEND & 1<<14)
{
rEINTPEND |= 1<<14;
LightLed(4);
}
}
三 定时器中断程序
CPU时钟设置流程
1 设置MPLLCON寄存器设置FCLK
2 设置CLKDIVN寄存器设置FCLK:HCLK:PCLK的值
时钟设置流程
初始化
1 设置分频值TCFG0 TCFG1
2 设置定时器计数值 TCNTB0
3 设置中断程序入口,清挂起寄存器和关闭MASK屏蔽
4 更新TCTNB0和TCMTB0的值 TCCON
5 将TCCON清0,否则就会cpu就会一直在更新
启动定时器
6 启动定时器,TCCON
中断函数
清挂起寄存器,执行响应代码

void SetSysClk()//FCLK=405MHZ FCLK:HCLK:PCLK=1:4:8
{
rMPLLCON = 0;
rMPLLCON |= (0x3f<<12 | 2<<4 | 2<<0);//设置FCLK的值
rCLKDIVN |= (1<<2 | 1<<0);//设置FCLK:HCLK:PCLK的比值
//LOCKTIME不需要设置,如没设置,系统将自动选择LOCKTIME
}

void Timer0Init()//PCLK=50MHZ
{
rTCFG0 = 49;
rTCFG1 |= 2; //CLK=62500HZ
//TCFG0 TCFG1设置定时器预分频值和分配值 然后得出定时器0频率:FCLK/(49+1)/16
rTCNTB0 = 62500;
//TCNTB0设置定时器的计数寄存器

ClearPending(BIT_TIMER0);//清除计数器0中断挂起寄存器
pISR_TIMER0 = (U32)Timer0Handle;
EnableIrq(BIT_TIMER0);//打开MASK对定时器0的屏蔽

rTCON |=(1<<1); //更新TCNTB0 和 TCMTB0的值
rTCON =0; //将TCON的值清0,注这一步很重要,如没有,定时器将一直更新TCNTB0和TCMTB0的值导致无法启动
rTCON |= (1<<3 | 1<<0);//启动定时器0,并设置为自动装载

}

static void __irq Timer0Handle()
{
ClearPending(BIT_TIMER0);//清除TIMER0中断挂起寄存器,防止其反复相应
LedRun();
}
四,串口发送程序
流程:
初始化
1 设置相应的GPIO端口为串口输出端口
2 设置串口发生数据格式ULCONn
3 设置接收和发生方式 ULCONn
4 设置波特率rUBRDIVn
发送数据
5 等待发送缓冲区为空 rUTRSTATn
6 向发生数据寄存器写数据 UTXHn
程序:
void UartInit(int num, int buad)
{
int i;
switch(num)
{
case 0:
rGPHCON |= (1<<5 | 1<<7);//设置GPH端口为串口
rULCON0 = 0x03;//设置数据格式为8位数据
rUCON0 = (1<<0 | 1<<2); //设置接收和发送为查询模式
rUBRDIV0 = ((int)PCLK/(16*buad) - 1);//设置波特率
break;
case 1:
rGPHCON |= (1<<9 | 1<<11);
rUBRDIV1 = ((int)PCLK/(16*buad) - 1);
rULCON1 = 0x03;
rUCON1 = (1<<0 | 1<<2);
break;
case 2:
rGPHCON |= (1<<13| 1<<15);
rUBRDIV2 = ((int)PCLK/(16*buad) - 1);
rULCON2 = 0x03;
rUCON2 = (1<<0 | 1<<2);
break;
default:
break;
}

for( i=0; i != 100; ++i);//延时,使设置生效
}

void UartPrintf(char *fmt, ...)
{
va_list ap;
char string[256];

//将不定参数格式化成字符串string
va_start(ap, fmt);
vsprintf(string, fmt, ap);
UartSendString(string);
va_end(ap);
}

void UartSendString(char *str)
{
while(*str)
Uart_SendByte(*str++);
}

void UartSendByte(char byte)
{
switch(whichUart)
{
case 0:
while( ! (rUTRSTAT0 & 0x02));//等待发生区为空
WrUTXH0(byte);
break;

case 1:
while( ! (rUTRSTAT1 & 0x02));
WrUTXH1(byte);
break;

case 2:
while( ! (rUTRSTAT2 & 0x02));
WrUTXH2(byte);
break;

default:
break;
}
}
五,ADC转换程序
流程
初始化
1 设置转换通道和转换频率ADCCONn
2 清相应的中断挂起寄存器,设置中断入口程序,取消MASK屏蔽
启动
3 设置ADCCONn相应的位启动转换
中断服务程序
4通过SUBSRCPND判断是不是普通的ADC转换
5 清SUBSRCPND相应的位
6 读取转换值 ADCDATn
程序
void ADCInit()
{
int channel = 0, preScaler = 50000000/ADCFRE - 1;
rADCCON = (channel<<3) | (preScaler<<6) | (1<<14);//设置ADC通道和预分频值
Delay(100);

pISR_ADC = (U32)ADCHandle;//设置中断向量表
ClearPending(BIT_ADC);//清挂起寄存器
rSUBSRCPND &= (1<<10);//清子中断挂起寄存器
EnableIrq(BIT_ADC);//使能ADC中断,实际是关闭INTMSK对ADC的屏蔽
rINTSUBMSK &= (0<<10);//关闭子中断对ADC_S的屏蔽

rADCCON |= 1;//开始转换
}

static void __irq ADCHandle()
{
int ADCValue;

ClearPending(BIT_ADC);

if(rSUBSRCPND & (1<<10))//判断是不是有ADC普通转换产生的中断
{
rSUBSRCPND &= (1<<10);
ADCValue = (rADCDAT0 & 0x3FF);//读取转换值

Uart_Printf("/n ADC convert value is %d/n", ADCValue);
rADCCON |= 1;//开始转换
}
}
六,触摸屏程序
流程:
初始化
1 设置采样延时和分频值ADCDLY ADCCON
2 中断相关设置
3 设置触摸屏AD转换为等待中断模式 ADCTSC
中断服务函数
4清相关挂起寄存器
5设置转换模式,一般为连续x,y转换
6 启动转换
7 转换完成后读取x y坐标ADCDAT0 ADCDAT1
8 设置触摸屏AD转换为等待中断模式,设置等待弹起中断ADCTSC
9 弹起中断发生后,设置触摸屏转换为等待中断模式,等待下一次触笔按下rADCTSC
程序
void TouchPendInit()
{
ADCInit();
rADCTSC = 0xd3;//设置为等待中断模式
rSUBSRCPND |= (1<<9);//清ADC_TC挂起寄存器
rINTSUBMSK &= ~(1<<9);//ADC_TC屏蔽
}
void ADCInit()
{
int channel = 0, preScaler = 50000000/ADCFRE - 1;

rADCDLY=50000; //设置触摸屏转换延时,这个延时需要设置,否则数值不对
//rADCCON = (channel<<3) | (preScaler<<6) | (1<<14);//设置ADC通道和预分频值
rADCCON=(1<<14) | (preScaler<<6);
Delay(100);

pISR_ADC = (U32)ADCHandle;//设置中断向量表
ClearPending(BIT_ADC);//清挂起寄存器
rSUBSRCPND |= (1<<10);//清子中断挂起寄存器
EnableIrq(BIT_ADC);//使能ADC中断,实际是关闭INTMSK对ADC的屏蔽
rINTSUBMSK &= ~(1<<10);//关闭子中断对ADC_S的屏蔽*/
}

static void __irq ADCHandle()
{
int xADCValue, yADCValue;

ClearPending(BIT_ADC);

if(rSUBSRCPND & (1<<9))
{
rSUBSRCPND |= (1<<9);
rADCTSC |= (1<<2);//设置转换模式,X,Y连续自动转换
rADCCON |= 1;//开始转换
}
if(rSUBSRCPND & (1<<10))//判断是不是有ADC普通转换产生的中断
{
rSUBSRCPND |= (1<<10);
xADCValue = (rADCDAT0 & 0x3FF);//读取转换值
yADCValue = (rADCDAT1 & 0x3FF);
Uart_Printf("/n x=%d, y=%d/n", xADCValue, yADCValue);
rADCTSC = 0xd3;//设置为等待中断模式
rADCTSC |= (1<<8);//检测弹起中断

//等待弹起
while(1)
{
if(rSUBSRCPND & (1<<9))
{
rSUBSRCPND |= (1<<9);
rADCTSC = 0xd3;
break;
}
}
}

}

七,LCD程序
流程:
初始化
1 端口初始化,设置相应的端口为LCD端口
2 显示模式初始化,设置帧同步信号,行同步信号,屏幕大小,像素显示模式等等
3 帧缓冲初始化,设置帧缓冲的起始地址,中止地址,虚拟屏宽等等
开始输出
4 启动输出
5 往帧缓冲写入要显示的图像数据
程序:

#define LCD_WIDTH 240
#define LCD_HEIGHT 320
#define LCD_PIXCLOCK 4

#define LCD_RIGHT_MARGIN 39
#define LCD_LEFT_MARGIN 16

#define LCD_HSYNC_LEN 5

#define LCD_UPPER_MARGIN 1
#define LCD_LOWER_MARGIN 5
#define LCD_VSYNC_LEN 1

static unsigned short lcdbuffer[LCD_WIDTH][LCD_HEIGHT];//定义显存
void LCDPortInit()
{
rGPCCON = 0xaaaa00a8;//设置GPC端口为VCLK,VLINE,VFRAME VD输出
rGPCUP = 0xffff;
rGPDCON = 0xaaaaaaaa;//设置GPD端口为VD输出
rGPDUP = 0xffff;//禁止上拉

}

void LCDInit()
{
U32 bufferaddr =(U32)lcdbuffer;
LCDPortInit();
rLCDCON1 = (LCD_PIXCLOCK<<8) | (3<<5) | (0xC<<1);//设置VCLK时钟,显示模式为TFT,像格式素模式为16位
rLCDCON2 = (LCD_UPPER_MARGIN<<24) | ((LCD_HEIGHT-1)<<14) | (LCD_LOWER_MARGIN<<6) | (LCD_VSYNC_LEN<<0);//设置帧同步信号发生后无效的时钟,LCD高度,下一帧同步信号发生前的无效时钟,行同步信号的秒冲宽度
rLCDCON3 = (LCD_LEFT_MARGIN<<19) | ((LCD_WIDTH-1)<<8) | (LCD_RIGHT_MARGIN<<0);//设置行同步信号发生后无效的时钟,LCD宽度,下一个同步行同步信号发生前的无效时钟宽度
rLCDCON4 = (LCD_HSYNC_LEN<<0);//设置行同步信号时钟脉冲宽度
rLCDCON5 = (1<<11);//设置像素格式为5:6::5
rLCDSADDR1 = ((bufferaddr>>22)<<21) | (((bufferaddr>>1)&0x1fffff)<<0);//设置显存的起始地址
rLCDSADDR2 = ((bufferaddr + LCD_WIDTH*LCD_WIDTH*2)>>1)&0x1ffff;//设置显存的末端地址
rLCDSADDR3 = LCD_WIDTH; //设置虚拟屏幕宽度即为实际宽度

rLCDCON1 |= 1; //开始输出
}

void LCDDisplay()
{

LCDSubDisplay((0x1f<<11) | (0x00<<5) | (0x00)); //red
delay(100000);
LCDSubDisplay((0x00<<11) | (0x3f<<5) | (0x00)); //green
delay(100000);
LCDSubDisplay((0x00<<11) | (0x00<<5) | (0x1f)); //blue
delay(100000);


}

void LCDSubDisplay(U16 c)
{
unsigned int x ,y ;

for( x=0; x<LCD_WIDTH; ++x)
for( y=0; y<LCD_HEIGHT; ++y)
lcdbuffer[x][y] = c;
}

分享到:
评论

相关推荐

    基于S3C2440的ARM9基础程序设计及分析.pdf

    基于S3C2440的ARM9基础程序设计及分析.pdf ,希望给予初学者一点帮助

    s3c2440驱动设计和应用程序综合设计

    1.基于s3c2440的led驱动设计、驱动调用的应用程序设计; 2.基于s3c2440的按键驱动设计、驱动调用应用程序设计; 3.基于s3c2440的中断驱动设计、驱动调用应用程序设计; 4.基于s3c2440的中断poll驱动设计、驱动调用...

    S3C2440 LCD程序

    S3C2440下开发的LCD显示程序,能显示非为16、24两种显示位。

    基于S3C2440 ARM的信号采集与传输硬件系统的研究与设计

    在当前数字信息技术和网络技术高速...基于微处理器53C2440的嵌入式数据采集平台,具有体积小!功耗低!功 能强大的优势,而且随着芯片价格的降低,成本也可以控制在一个比较小的范 围,所以在工业测量领域具有较为广阔的前景

    基于S3C2440的WindML图形驱动设计_董英英

    通过对微控制器ARM9 S3C2440 和嵌入式实时操作系统VxWorks中的多媒体组件WindML体系结构进行研究, 给出了WindML下设计S3C2440 LCD驱动程序和基于I2C总线的键盘控制芯片ZLG7290设计键盘驱动程序的方法, 完成了基于S3C...

    基于S3C2440和嵌入式Linux的扩展串口设计

    本文档介绍了在基于S3C2440嵌入式开发板中利用TL16C554A芯片来扩展串口的方案,并给出了硬件原理图和部分程序。详细阐述了S3C2440芯片与TL16C554芯片之间的接口设计和扩展串口驱动程序的移植。

    嵌入式linux arm9 S3C2440实验项目指导书-迅通程式嵌入式培训中心

    基于ARM9 S3C2440的MINI2440开发板,深圳迅通程式嵌入式培训中心开发的精选20个基于嵌入式linux平台的ARM开发板经典实验项目,每个实验项目包括详细的实验原理、目的和步骤;主要内容涵盖嵌入式Linux平台开发环境...

    基于DM9000AE的S3C2440嵌入式系统的以太网接口设计

    本文介绍了一个基于三星ARM9芯片S3C2440嵌入式系统的以太网接口电路设计方案,采用了工业级以太网控制器DM9000AE成功实现了嵌入式系统网络数据交换。论文在重点阐述了网络接口电路基础之上,对Windows CE系统控制...

    基于S3C2440和嵌入式Linux操作系统的矿用车载定位装置的设计

    提出了一种应用于露天矿开采中的车载GPS定位系统,该系统采用了模块化的设计思想,硬件以ARM微处理器为核心,还扩展了LCD显示、触摸屏操作模块等。软件以Linux操作系统为平台,为GPS模块和LCD模块开发了驱动程序,介绍了...

    基于S3C2440的WindML图形驱动设计

    通过对微控制器ARM9S3C2440和嵌入式实时操作系统VxWorsk中的多媒体组件WindML体系结构进行研究,给出了WindML下设计S3C2440LCD驱动程序和基于I2C总线的键盘控制芯片ZLG7290设计键盘驱动程序的方法,完成了基于S3C...

    基于s3c2440硬件平台的五子棋游戏

    根据触摸屏和LCD的两点画线,我决定在此基础上进一步增加内容,想到了比较适合此类平台的五子棋游戏。 要实现这一个目标,...于是在以前的画线程序基础上,我开始了五子棋游戏的设计。 附件中含有所有代码和实验报告

    三星公司ARM7处理器S3C44B0的BIOS源程序-就是Bootloader

    三星公司ARM7处理器S3C44B0的BIOS源程序-就是Bootloade,经过编译,已经测试可以在班上运行。

    ARM开发--S3C4510B

    通过对本章的阅读,具有一定系统设计知识的读者应该可以掌握基于S3C4510B的系统设计,同时由于ARM体系结构的一致性和系统外围电路的通用性,本章所描述的设计方法也同样适合于其他ARM芯片。 第六章:详细介绍基于S3C...

    基于s3C2440的叶面积测量仪的设计.pdf

    以三星公司的ARM9微处理器s3C2440为硬件核心,以嵌入式Windows CE为操作系统,应用图像处理法,结合大容量的SDRAM及NAND FLASH,CMOS摄像头和带触摸功能的LED等,设计了叶面积仪的硬件系统和软件系统,并对主要部分...

    嵌入式系统/ARM技术中的基于S3C2440的nRF2401驱动设计

    针对ARM9 芯片S3C2440 的特点设计了对nFR24E1 的接口电路和驱动程序。对于在狭小空间中,有设备之间的数据共享要求的系统是一种有效解决途径。  2.4GHz 无线设备的使用,免去了系统之间连线的烦恼。一方面可以降低...

    基于ARM7TDMI内核的S3C44B0异常处理分析

    介绍了ARM7TDMI的7种工作模式及各种工作模式下处理器的基本功能、适用的条件以及在...详细分析了复位、快速中断和普通中断的编程要点以及在嵌入式程序设计中的作用,并结合S3C44B0示例程序分析了CPU对异常处理的方法。

    基于ARM的排队叫号系统源程序及课程设计报告

    基于ARM的排队叫号系统源程序及课程设计报告

    基于ARM9的嵌入式Linux网络视频监控系统的研究与实现.caj

    文中首先简述了ARM处理器的相关知识,介绍了S3C2440mini开发板,Linux操作系统、嵌入式Linux操作系统及底层知识,嵌入式Linux开发平台搭建及交叉编译环境的建立,其次阐述了Boot Loader及原理,Linux内核编译,根文件系统...

    ARM应用系统开发详解——基于S3C4510B的系统设计(第二版)

    以 Samsung公司的一款基于以太网系统的 ARM处理器-S3C4510B 为核心,详细讲解系统 的设计、调试,以及相关的软件设计和嵌入式操作系统的移植、应用程序的开发、设备驱 动程序的开发过程。通过阅读本书,可以使具备...

    通信与网络中的基于DM9000AE的S3C2440嵌入式系统的以太网接口设计

    摘要:本文介绍了一个基于三星ARM9芯片S3C2440嵌入式系统的以太网接口电路设计方案,采用了工业级以太网控制器DM9000AE成功实现了嵌入式系统网络数据交换。论文在重点阐述了网络接口电路基础之上,对Windows CE系统...

Global site tag (gtag.js) - Google Analytics