ARM1
ARM1
ARM1
ARM has introduced many processors. Each set or groups of processors are having different
core and different Features. Development of the ARM Architecture is started with 26 bit
processors and nowadays it reaches up to 64 bit. We cannot classify general development of
ARM products on any particular fact, there is only one way to understand ARM based
products is on its Architectural version profile.
The classical ARM series refers to processors starting from ARM7 to ARM11. This is the
series which gives market boost to ARM because of its core features like Data Tightly
Coupled
memory,
cache,
MMU,
MPU,
etc.
Typical
examples
of
this
series
In this Cortex architecture, we port different embedded OS and design embedded system by
OS system programming. The core feature of this profile is Highest performance at low
power, Trust Zone and Jazelle-RCT for a safe and extensible system. Practical development
platform of this types of profile is Friendly ARM, Raspberry Pi, etc.
This is Cortex architecture which mostly used for real time purpose where application abort is
critical situation contain core features like Protected memory (MPU), Low latency and
predictability real-time needs.
This profile is specially dedicated for microcontroller purpose only. The core feature of this
profile is like Lowest gate count entry point, Deterministic and predictable behaviour a key
priority, deeply embedded use. Typical example of this kind of profile architecture is
Hercules TMS470M, STM32F429, etc.
PROCESSOR MODES
All these modes indicate its special work and execute under certain condition with its own
stack and a different subset of registers. Modes other than User mode are collectively known
as privileged modes. Your program or application generally runs under User mode. Privileged
modes are used to service interrupts or exceptions, or to access protected resources.
There are some CPU based registers present in the ARM7 CPU
1. CSPR- current program status register
T Bit (Bit 5)
Indicates
saturation
has
occurred
Introduced in Architecture 4T
if
bit
controls
load/store
endianness
SUB r0,r1,#5
r0 = r1 5
ADD r2,r3,r3,LSL #2
r2 = r3 + (r3 * 4)
ADDEQ r5,r5,r6
IF EQ condition true r5 = r5 + r6
B
<Label
>
STRNEB r2,[r3,r4]
STMFD sp!,{r4-r8,lr}
Optimized for code density from C code (~65% of ARM code size)
Thumb is not a regular instruction set because that targeted at compiler generation,
not hand coding.
An application code compiled in Thumb is 30% smaller on average than the same
code compiled in ARM and normally 30% faster when using narrow 16-bit memory
systems.
Adds 32-bit instructions to implement almost all of the ARM ISA functionality
In ARM architecture, pipe-lining is possible because of its RISC feature in which all
instruction size is same so we can take advantage of pipe-lining. As you can see on above
figure when ADD instruction is executing we fetched and start decoding next instruction
SUB and at the same time we fetched the ORR instruction. So in the time of single
instruction execution, we performing 3 instruction. Therefore, this is called three stage pipelining.
EXCEPTION HANDLING
or watch-point
has
been
hit.
Communication with the EmbeddedICE logic from the external world is provided
via the test access port or TAP, controller and a standard IEEE 1149.1 JTAG connection. The
advantage of on-chip debug solutions is the ability to rapidly debug software, especially
when the software resides in ROM or Flash.
AMBA Bus
The Advanced Micro-controller Bus Architecture on-chip bus is freely available from
ARM and offers an established, open specification that serves as a framework for SoC
designs.
Reference www.arm.com
The design of the AMBA bus specification is focused on low power consumption and high
performance. A typical AMBA-based SoC consists of an advanced high-performance system
bus(AHB), and an advanced low power peripheral bus(APB). As seen in above pic
On the performance critical side of the bus is the ARM core, Memory Controller, Test
Interface Controller (TIC), the LCD Controller, on-chip IP, custom logic, and
specialized functions.
On the low power side of the bus is the Smart Card interface, audio codec, UART,
PWM, Timers, GPIO, etc.
This is an excellent example of how the AHB and APB buses work in conjunction to
provide a complete system solution.
These bus protocols are independent of the ARM processor and generalized for SoC
application. The AMBA test methodology provides a mechanism to give an external tester
access to the on-chip AMBA bus. This enables the tester to take control of the bus and check
each component separately.
MMU
The Memory Management Unit works with the cache memory system to control accesses to
and from external memory. The MMU also controls the translation of Virtual Addresses to
physical addresses and access permission checks for the instruction and data ports of
Processors. An MMU mitigates the problem of fragmentation of memory too.
MPU
A separate Memory Protection Unit feature has been introduced in ARM by Cortex-M3 cores
which provide a way to control memory access rights to applications. This prevents a bug
within a process from affecting other processes, or the operating system itself, and instead
results in a segmentation fault or storage violation exception, generally causing termination
of the process. In ARM core, separate registers are provided by which you can configure
certain portion of memory and its access rights.
ARM7 is balance between new Cortex series and old start up. it is neither too old
technology nor latest
ARM7 family is excellent for beginners as per my opinion, because it gives real depth
idea about hardware and software implementation & integration by using appropriate IDE.
Features of LPC2148
LPC2148 is the widely used IC from ARM-7 family. It is manufactured by Philips (NXP) and
it is pre-loaded with many inbuilt peripherals making it more efficient and a reliable option
for the beginners as well as high end application developer.
Embedded ICE RT and Embedded Trace interfaces offer real-time debugging with the
on-chip Real Monitor software and high speed tracing of instruction execution.
USB 2.0 Full Speed compliant Device Controller with 2 KB of endpoint RAM. In
addition, the LPC2146/8 provides 8 kB of on-chip RAM accessible to USB by DMA.
One or two (LPC2141/2 vs. LPC2144/6/8) 10-bit A/D converters provide a total of
6/14analog inputs, with conversion times as low as 2.44 us per channel.
Single 10-bit D/A converter provides variable analog output.
Two 32-bit timers/external event counters (with four capture and four compare
channels each), PWM unit (six outputs) and watchdog.
Low power real-time clock with independent power and dedicated 32 kHz clock
input.
Multiple serial interfaces including two UARTs (16C550), two Fast I2C-bus(400
kbps), SPI and SSP with buffering and variable data length capabilities.
Processor wake-up from Power-down mode via external interrupt, USB, Brown-Out
Detect (BOD) or Real-Time Clock (RTC).
Single power supply chip with Power-On Reset (POR) and BOD circuits: CPU
operating
ARM IDENTIFICATION
ARM 7 MODES
1.
2.
SYSTEM PERIPHERALS
MEMORY MAP
Despite the internal buses, the LPC2000 has a complete linear map. The general
map is as below:
The on-chip flash is fixed at 0X00000000 upwards with the user RAM fixed at 0X40000000
upwards. The LPC2000 is a pre-programmed at manufacture with a FLASH bootloader and
the ARM real monitor debug program. These programs are placed in the region
0X7FFFFFFF-0X80000000. The region between 0X80000000 and 0XE0000000 is reserved
for external memory. Currently the LPC2000 can be used to address external memory via
four chip-selects each with 16mb page.
The user peripherals are located on the VPB are all mapped onto the region between
0XE0000000 and 0XE2000000 and each peripheral is located at a 16k memory page. The
vectored interrupt unit is located on top of the address range at 0XFFFFF000.
If the user tries to access a memory region outside the defines memory region then an abort
exception is generated by the controller.
REGISTER PROGRAMMING
Within the PLL it has two constants which must be programmed in order to
determine the clock for the CPU and AHB. This is called the CCLK. The first
constant is the straight forward multiplier of the external oscillator The output
frequency of the PLL is given by
CCLK = M X Osc (frequency of the crystal)
The Feedback path is a current controlled oscillator must operate in the range of
152MHz - 320 MHz. The second constant acts as a programmable divider which
ensures that the CCO is kept in specification. The operating frequency of the CCO
is defined as
FCCO = CCLK x 2 x P
The values are written into SFR's are not transferred to the PLL until the feed
sequence is written into the PLL feed register. Once updated the PLLCON and
PLLCFG registered must be written with the sequences 0X000000AA followed by
0X00000055 these values are written on consecutive cycles. To set up the PLL
values must be written to the P and M of the PLLCFG registers. Then using
PLLCON registers the PLL is enabled. There is a finite startup time before the PLL
is stable enough to start the CCLK source. The status of the PLL can be
monitored by reading the LOCK bit of the PLLSTATUS register. Once the LOCK bit
is set the PLL can be used to maintain the main clock source.
An interrupt can be generated in the PLL when the PLL locks so as to carry out
other tasks while the PLL starts. Once the PLL is locked
as a stable clock
source it can replace the external oscillator as a source of CCLK this is done via
the PLLC and PLLCON bit.
Care should be taken for the values stored in the PLLCONFG register. The P and
M bits should never be 0. The value of M is 5 bit long so the value of P is not on
an even nibble boundary. If a simple mistake is done while setting up the PLL the
chip will enter a power down mode and is disconnected. A wake up mode does
not exist in the PLL so the same start up sequence must be followed each time
the chip enters a power down mode.
User Peripherals:
General Purpose I/O:
On reset the pin connect block configures all the peripherals to be general IO
pins. The GPIO pins are controlled by 4 registers.
IOPIN - gives the value stored of the registers
IOSET - sets the pin to accept values
IOCLR: clears the values of the registers
IODIR: defines the direction of the pin allows each pin to be configured as wither
input (0) or output (1).
#include<lpc21xx.h>
#define
#define
#define
#define
void
void
void
void
LCD (0xff<<16)
RS (1<<13)
RW (1<<14)
EN (1<<15)
int main()
{
PINSEL0=0X00000000;
IO0DIR=0XFFFFFFFF;
lcd_ini();
while(1)
{
lcd_ini();
lcd_display(' ');
lcd_display('W');
delay_fv(1000,400);
lcd_display('E');
delay_fv(1000,400);
lcd_display('L');
delay_fv(1000,400);
lcd_display('C');
delay_fv(1000,400);
lcd_display('O');
delay_fv(1000,400);
lcd_display('M');
delay_fv(1000,400);
lcd_display('E');
delay_fv(1000,400);
lcd_display(' ');
delay_fv(1000,400);
lcd_display('T');
delay_fv(1000,400);
lcd_display('O');
delay_fv(1000,400);
cmd(0x0c0);
lcd_display('F');
delay_fv(1000,400);
lcd_display('I');
delay_fv(1000,400);
lcd_display('R');
delay_fv(1000,400);
lcd_display('M');
delay_fv(1000,400);
lcd_display('C');
delay_fv(1000,400);
lcd_display('O');
delay_fv(1000,400);
lcd_display('D');
delay_fv(1000,400);
lcd_display('E');
delay_fv(1000,400);
lcd_display('S');
delay_fv(1000,400);
lcd_display('.');
delay_fv(1000,400);
lcd_display('C');
delay_fv(1000,400);
lcd_display('O');
delay_fv(1000,400);
lcd_display('M');
delay_fv(1000,400);
}
}
void delay_fv(unsigned int x,int y)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<y;j++);
}
void lcd_display(unsigned int x)
{
IO0CLR|=(RS|RW|EN|LCD);
IO0SET|=(x<<16);
IO0SET|=RS;
IO0CLR|=RW;
IO0SET|=EN;
delay_fv(100,10);
IO0CLR|=EN;
delay_fv(10,10);
}
void cmd(unsigned char m)
{
IO0CLR|=(RS|RW|EN|LCD);
IO0SET|=(m<<16);
IO0CLR|=RS;
IO0CLR|=RW;
IO0SET|=EN;
delay_fv(100,100);
IO0CLR|=EN;
delay_fv(100,10);
}
void lcd_ini()
{
cmd(0X38);
cmd(0X0e);
cmd(0X06);
cmd(0X01);
cmd(0X80);
}
#include<lpc21xx.h>
void delay(void);
void receive(void);
void transmit(void);
char c;
void lcd(unsigned char a,int b);
int main(void)
{
PINSEL0|=(1<<0)|(1<<2); //Selecting pin functions
PINSEL2=0;
IODIR1=0x03ff0000;
//Setting Directions for LCD
lcd(0x38,0);
lcd(0x0f,0);
U0LCR=(1<<7);
//Making DLAB bit as '1'
U0DLL=0x21;
//Baud Rate Value
U0LCR=0x03;
//DLAB as 0 and word length
selection
delay();
transmit();
while(1)
{
receive();
//Infinite receive loop
}
}
void delay(void)
//Software Delay
{
unsigned int i;
for(i=0;i<=3000;i++);
}
void lcd(unsigned char a,int b)
//LCD subroutine
{
IOSET1=a<<16;
IOSET1=b<<24;
IOSET1=1<<25;
delay();
IOCLR1=1<<25;
IOCLR1=b<<24;
IOCLR1=a<<16;
}
void receive(void)
//Receive subroutine
{
while(!(U0LSR&(1<<0)));
//Status check
c=U0RBR;
lcd(c,1);
}
void transmit(void)
//Transmit subroutine for "SND"
{
U0THR='S';
while(!(U0LSR&(1<<5))); //Status check
U0THR='N';
while(!(U0LSR&(1<<5)));
U0THR='D';
while(!(U0LSR&(1<<5)));
}
#include<lpc21xx.h>
# define PRESCALAR 60000
void pll();
void timer0_ini();
void delay(unsigned long int ms);
int main()
{
PINSEL0=0x00000000; // select gpio pin
IO0DIR=0XFFFFFFFF; // make gpio as output pin
pll();
// calling pll function
timer0_ini();
// calling timer function
while(1)
{
IO0SET=0XFFFFFFFF; // led on
delay(0x000000fF); // delay using timer 0
IO0CLR=0XFFFFFFFF; // led off
delay(0x000000fF); // delay using timer 0
}
return 0;
}
void pll()
{
//PLL IS CONFIGURED TO GET 60HZ pCLK
PLLCFG=0X24;
// SET PSEL=2 AND MSEL=5
PLLCON=0X01;
//PLL IS ACTIVE BUT NOT YET CONNECT
PLLFEED=0XAA;
//FEED SEQUENCE
PLLFEED=0X55;
//FEED SEQUENCE
while((PLLSTAT & 0X400)==0); //WAIT FOR FEED SEQUENCE TO BE
INSERTED
PLLCON=0X03;
VPBDIV=0X00;
PLLFEED=0XAA;
PLLFEED=0X55;
}
void timer0_ini()
{
T0TCR=0X0; // to stop timer
T0PR=PRESCALAR-1; //load the timer value
T0TCR=0X02;
//reset timer
}
void delay(unsigned long int ms)
{
T0TC=0x00000000; // t0 reset timer counting
T0TCR=0X02; // reset the timer
T0TCR=0X01; // start timer
while(T0TC<=ms); // check the condition
T0TCR=0X00; // stop timer
}
SQUARE WAVE
#include<lpc21xx.h>
# define PRESCALAR 60000
void pll();
void timer0_ini();
void delay(unsigned long int ms);
int main()
{
PINSEL0=0x00000000; // select gpio pin
IO0DIR=0XFFFFFFFF; // make gpio as output pin
pll();
// calling pll function
timer0_ini();
// calling timer function
while(1)
{
IO0SET=0X01; // high level
delay(0x0000000F); // delay using timer 0
IO0CLR=0X01; // low level
delay(0x0000000F); // delay using timer
0
}
return 0;
}
void pll()
{
//PLL IS CONFIGURED TO GET 60HZ pCLK
PLLCFG=0X24;
// SET PSEL=2 AND MSEL=5
PLLCON=0X01;
//PLL IS ACTIVE BUT NOT YET CONNECT
PLLFEED=0XAA;
//FEED SEQUENCE
PLLFEED=0X55;
//FEED SEQUENCE
while((PLLSTAT & 0X400)==0); //WAIT FOR FEED SEQUENCE TO BE
INSERTED
PLLCON=0X03;
VPBDIV=0X00;
PLLFEED=0XAA;
PLLFEED=0X55;
CONNECTRD
}
void timer0_ini()
{
T0TCR=0X0; // to stop timer
T0PR=PRESCALAR-1; //load the timer value
T0TCR=0X02;
//reset timer
}
void delay(unsigned long int ms)
{
T0TC=0x00000000; // t0 reset timer counting
T0TCR=0X02; // reset the timer
T0TCR=0X01; // start timer
while(T0TC<=ms); // check the condition
T0TCR=0X00; // stop timer
}
}
void lcd(unsigned char data,int rs_status)
{
IOSET0=(data<<0);
IOSET0=(rs_status<<8);
IOSET0=(1<<9);
delay();
IOCLR0=(1<<9);
IOCLR0=(rs_status<<8);
IOCLR0=(data<<0);
}
void delay(void)
{
unsigned int j;
for(j=0;j<=10000;j++);
}
www.firmcodes.com
DEVELOPED BY:- FIRMWARE DEVELOPER
WHAT PROGRAM DO:- Program Of Multiplex 8 Seven Segment Using
Max7221 And Controlled With ARM(LPC21XX) Using SPI Protocol
******************************************************/
#include<lpc21xx.h>
unsigned char spi_rec;
void spi_ini();
void spi_tr1(unsigned int x);
char spi_re();
void spi_tr(unsigned char cmd,unsigned char data);
void spi_str(unsigned char *str);
int ar[10]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f };
int ar1[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
void pll();
void delay_ms(unsigned int x);
int main()
{
int i,a,b,c,d,e,f,g,h;
a=b=c=d=e=f=g=h=0;
PINSEL0=0X00000000;
IO0DIR=0XFFFFFFFF;
pll();
spi_ini();
spi_tr(0x0a,0xf);
spi_tr(0x0b,0xf);
for(i=0;i<9;i++)
{
spi_tr(ar1[i],ar[0]);
delay_ms(100);
}
spi_tr(0x0c,0x01);
while(1)
{
spi_tr(ar1[7],ar[a]);
spi_tr(ar1[6],ar[b]);
spi_tr(ar1[5],ar[c]);
spi_tr(ar1[4],ar[d]);
spi_tr(ar1[3],ar[e]);
spi_tr(ar1[2],ar[f]);
spi_tr(ar1[1],ar[g]);
spi_tr(ar1[0],ar[h]);
a++;
if(a==10)
{
a=0;
b++;
}
if(b==10)
{
a=b=0;
c++;
}
if(c==10)
{
a=b=c=0;
d++;
}
if(d==10)
{
a=b=c=d=0;
e++;
}
if(e==10)
{
a=b=c=d=e=0;
f++;
}
if(f==10)
{
a=b=c=d=e=f=0;
g++;
}
if(g==10)
{
a=b=c=d=e=f=g=0;
h++;
}
if(h==10)
{
a=b=c=d=e=f=g=h=0;
}
delay_ms(3000);
}
}
void pll()
{
/*PLL IS CONFIGURED TO GET 60HZ pCLK*/
PLLCFG=0X24;
// SET PSEL=2 AND MSEL=5
PLLCON=0X01;
//PLL IS ACTIVE BUT NOT YET
CONNECT
PLLFEED=0XAA;
//FEED SEQUENCE
PLLFEED=0X55;
//FEED SEQUENCE
while((PLLSTAT & 0X400)==0); //WAIT FOR FEED SEQUENCE
TO BE INSERTED
PLLCON=0X03;
VPBDIV=0X00;
PLLFEED=0XAA;
PLLFEED=0X55;
CONNECTRD
}
void spi_ini()
{
PINSEL0 |=0x1500;
/* P0.4, P0.5, P0.6, P0.7 are set as SCK,
MISO, MOSI and GPIO */
//IODIR0 |= 0X80;
/* SSEL is output */
//IOSET0 |=0X80;
/* set SSEL to high */
S0SPCCR=8;
/* SPI clock
prescale register minimum value is 8. */
S0SPCR=0x0030;
/* Device select as
master, Set data to 8-bit, CPOL = 0, CPHA = 0*/
}
void spi_tr1(unsigned int x)
{
S0SPDR =x;
while ( !(S0SPSR & 0x80) );
trabsfer complete */
}
char spi_re()
{
while ( !(S0SPSR & 0x80) );
trabsfer complete */
spi_rec= S0SPDR;
return spi_rec;
}
#include<lpc21xx.h>
#define
#define
#define
#define
LCD (0xff<<16)
RS (1<<13)
RW (1<<14)
EN (1<<15)
lcd_ini();
init_rtc();
lcd_str("CLOCK:- 24");
cmd(0xc0);
lcd_str("00:00:00");
while(1)
{
if(flag)
{
flag=0;
lcd_pos(2,0);
lcd_display(HOUR/10 + '0');
lcd_display(HOUR%10 + '0');
lcd_display(':') ;
lcd_display(MIN/10 + '0');
lcd_display(MIN%10 + '0');
lcd_display(':') ;
lcd_display(SEC/10 + '0');
lcd_display(SEC%10 + '0');
}
}
}
void delay_fv(unsigned int x,int y)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<y;j++);
}
void lcd_display(unsigned int x)
{
IO0CLR|=(RS|RW|EN|LCD);
IO0SET|=(x<<16);
IO0SET|=RS;
IO0CLR|=RW;
IO0SET|=EN;
delay_fv(100,10);
IO0CLR|=EN;
delay_fv(10,10);
}
void cmd(unsigned char m)
{
IO0CLR|=(RS|RW|EN|LCD);
IO0SET|=(m<<16);
IO0CLR|=RS;
IO0CLR|=RW;
IO0SET|=EN;
delay_fv(100,250);
IO0CLR|=EN;
delay_fv(10,10);
}
INTERRUPTS ON ARM7:
PINSEL2=0X00000000;
mode
mode
IO0DIR=0X0fFFFFFF;
// direction of port0.0 to port0.31 worked
as output mode
IO1DIR=0XFFFFFFFF;
// direction of port1.0 to port1.31 worked
as output mode
lcd_ini();
// lcd initilization function
interrupt_ini();
// interrupt intilization function
while(1)
{
IO1SET|=(ar[count]<<16);
delay_fv(1000,1000);
IO1CLR|=(ar[count]<<16);
count++;
if(count==10)
count=0;
}
return 0;
}
void interrupt_0()__irq // interrupt 0
{
EXTINT=0X01;
IO0SET|=(0XFF<<16);
delay_fv(500,1000);
IO0CLR|=(0XFF<<16);
delay_fv(500,1000);
}
void interrupt_1()__irq // interrupt 1
{
EXTINT=0X02;
cmd(0x01);
lcd_str("WELCOME TO");
cmd(0xc0);
lcd_str("FIRMCODES.COM");
delay_fv(1000,1000);
}
void interrupt_ini()
{
/* intialize interrupt 0*/
PINSEL0|=0x0c;
VICVectAddr0=(unsigned)interrupt_0;
VICVectCntl0=0x20|14;
VICIntEnable=1<<14;
// delay_fv(1000,100);
/* intialize interrupt 1*/
PINSEL0|=0xc0;
VICVectAddr1=(unsigned)interrupt_1;
VICVectCntl1=0x20|15;
VICIntEnable=1<<15;
}
DELAY.H HEADER FILE
***********************************************************************/
void delay_ff()
{
unsigned int b,v;
for(b=0;b<600;b++)
for(v=0;v<100;v++);
}
void delay_pf(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<153;j++);
}
void delay_fv(unsigned int x,int y)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<y;j++);
}
void delay_ms(int count)
{
int j=0,i=0;
for(j=0;j<count;j++)
{
/* At 60Mhz, the below loop introduces
delay of 10 us */
for(i=0;i<35;i++);
}
}
LCD4BIT.H HEADER FILE
*********************************************************************/
#define LCD (0xf<<11)
#define RS (1<<8)
#define RW (1<<9)
#define EN (1<<10)
void lcd_display(unsigned char x)
{
unsigned int temp;
delay_ms(1000);
IO0CLR|=(RS|RW|EN|LCD);
temp=(x>>4)&0x0f;
//delay_ms(10);
IO0SET|=RS;
IO0CLR|=RW;
IO0SET|=EN;
IO0CLR|=LCD;
IO0SET|=(temp<<11);
delay_ms(100);
IO0CLR|=EN;
delay_fv(10,10);
IO0CLR|=(RS|RW|EN|LCD);
temp=x&0x0f;
//delay_ms(1000);
IO0SET|=RS;
IO0CLR|=RW;
IO0SET|=EN;
IO0CLR|=LCD;
IO0SET|=(temp<<11);
delay_ms(100);
IO0CLR|=EN;
delay_ms(100);
}
void cmd(unsigned char x)
{
unsigned int temp;
delay_ms(100);
temp=(x>>4)&0x0f;
IO0CLR|=(RS|RW|EN);
IO0CLR|=RS;
IO0CLR|=RW;
IO0SET|=EN;
IO0CLR|=LCD;
IO0SET|=(temp<<11);
delay_ms(100);
IO0CLR|=EN;
delay_fv(100,10);
IO0CLR|=(RS|RW|EN);
temp=x&0x0f;
IO0SET|=(temp<<11);
IO0CLR|=RS;
IO0CLR|=RW;
IO0SET|=EN;
IO0CLR|=LCD;
IO0SET|=(temp<<11);
delay_ms(100);
IO0CLR|=EN;
delay_fv(100,100);
}
void lcd_ini()
{
PINSEL0|=(0XFF<<8);
IO0DIR|=(0XF<<8);
cmd(0X02);
cmd(0X28);
// cmd(0X02);
cmd(0x0e);
cmd(0X06);
cmd(0X01);
cmd(0X80);
}