ldr r13,=0x1000

本文深入解析了在C语言编程中,如何使用ldrr13指令配合立即数实现堆栈指针初始化,以及其在跑马灯应用中的实际作用。重点介绍了C语言基于栈的特性,以及如何通过修改地址范围来优化程序运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



对于ldr r13,=0x1000的解释
有“=”号表示ldr是一个伪指令。
ldr r13,=0x1000 //表示把立即数0x1000送入r13,0x1000=4KB代表bootloader结束处

r13是stack pointer,因为后面要跳到LedMain,这个function是用c写的,所以必须要事先分配stack,否则c程序没法运行。给r13赋值就是分配stack,对跑马灯来说只要是可用内存就行,并不在乎具体地址在哪。

其实只要记住一条,C是基于栈的语言,没有栈是无法运行的,而且栈是从高地址处向低地址处的,所以是从0x1000~0x0。

(将0x1000改成sdram的地址 0x30000000~0x34000000也行,只是不要覆盖到RO Base的地址)
/**********************按键实验*********************************/ // 公司名称 :保定飞凌嵌入式技术有限公司 // 描 述 :蜂鸣器 // 版 权 :保定飞凌嵌入式技术有限公司 // 网 址 :www.witech.com.cn /***************************************************************/ /* 本实验接口说明 GPB0 ------ 蜂鸣器控制口 */ void Delay(unsigned int); /*------------------------地址声明-----------------------------*/ #define GPBCON (*(volatile unsigned *)0x56000010) #define GPBDAT (*(volatile unsigned *)0x56000014) #define GPBUP (*(volatile unsigned *)0x56000018) /*------------------------------------------------------------- 函数名称: BellMain 功能描述: 入口程序 初始化后,进入按键扫描死循环 传 参: 无 返 回 值: int 0 -------------------------------------------------------------*/ int BellMain() { GPBUP &= 0XFFFFFFFE; //上拉使能GPB0 GPBCON &= 0XFFFFFFC; //GPB0设为输出 GPBCON |= 0X0000001; while(1) { GPBDAT &= 0xfe; //不能用!(非) Delay(40); GPBDAT |=0x1; //用与或方式,不影响其他位 Delay(40); } return(0); } /*------------------------------------------------------------/ 函数名称: Delay 功能描述: 延时函数 延时count毫秒 传 参: int count 返 回 值: 无 -------------------------------------------------------------*/ void Delay(unsigned int x ) { unsigned int i,j,k; for(i=0;i<=x;i++) for(j=0;j<=0xff;j++) for(k=0;k<=0xff;k++); } AREA |DATA|,CODE,READONLY ENTRY ldr r13,=0x1000 IMPORT BellMain b BellMain END1. BellMain ()函数中的两条语句rGPBCON &= 0xFFFFFFC; rGPBCON |= 0x0000001;的具体作用是什么? //上拉电阻使能GPB0 2. GPB0端口的上拉电阻有没有使能?判断依据是什么? 3. 语句rGPBDAT &= 0xFE; rGPBDAT |= 0x1; 的作用是什么?
06-08
/按键实验***********/ // 公司名称 :保定飞凌嵌入式技术有限公司 // 描 述 :按键控制蜂鸣器 // 版 权 :保定飞凌嵌入式技术有限公司 // 网 址 :www.witech.com.cn /***************************************************************/ /* 本实验接口说明 GPB5 ------ LED0 GPB6 ------ LED1 GPB8 ------ LED2 GPB10 ------ LED3 */ /------------------------地址声明---------------------------/ #define GPBCON (*(volatile unsigned )0x56000010) #define GPBDAT ((volatile unsigned )0x56000014) #define GPBUP ((volatile unsigned *)0x56000018) #define uchar unsigned char #define uint unsigned int /-----------------------定义全局变量------------------------/ /-----------------------函数声明----------------------------/ void Delay(int x); /------------------------------------------------------------/ 函数名称: Delay 功能描述: 延时函数 传 参: int x 返 回 值: 无 -------------------------------------------------------------/ void Delay(int x) { int k, j; while(x) { for (k=0;k<=0xff;k++) for(j=0;j<=0xff;j++); x--; } } /------------------------------------------------------------- 函数名称: ledMain 功能描述: 入口程序 初始化后,进入跑马灯死循环 传 参: 无 返 回 值: int 0 -------------------------------------------------------------/ int ledMain(void) { GPBCON = 0x1dd7fc; // GPB5,GPB6,GPB8,GPB10设置为输出 GPBDAT = ((1<<5)|(1<<6)|(1<<8)|(1<<10)); //使LED全灭 GPBDAT&=0xffe; //关闭蜂鸣器 GPBUP = 0x00; while (1) // 死循环 { GPBDAT = ~(1<<5); //LED0亮 Delay(500); GPBDAT = ~(1<<6); //LED1亮 Delay(500); GPBDAT = ~(1<<8); //LED2亮 Delay(500); GPBDAT = ~(1<<10); //LED3亮 Delay(500); } return 0; } ; init.s AREA |DATA|,CODE,READONLY ENTRY ldr r13, =0x1000 ;设置堆栈栈顶指针 IMPORT ledMain b ledMain END 预定义语句#define rGPBCON (*(volatile unsigned )0x56000010)中,关键字volatile的作用是什么?unsigned * 的作用的是什么? 第一个的作用是什么?rGPBCON代表的是什么特殊功能寄存器?其功能是什么? volatile 不稳定的,易变的,告诉编译器不要对volatile 修饰的变量或存储单元进行优化,其值随时可变,每次都直接访问存储单元。 unsigned * 的作用是强制类型转换,把0x56000010的本来的整数类型强制转换成无符号指针类型 第一个*的作用在地址0x56000010上,是指针运算符,访问地址为0x56000010的特殊功能寄存器 GPBCON是 GPIO的B端口的配置寄存器,为每一个GPIO B组的引脚定义功能(用2位定义一个引脚的功能) 00 - 输入 01-输出 10-定义具体硬件模块引脚功能 11 - 保留 把十六进制数0x1dd7fc转换成二进制,配置管脚GPB5的功能是什么?是GPBCON的哪些位段以及什么数值决定的? 语句rGPBDAT = ((1<<5)|(1<<6)|(1<<8)|(1<<10)); 执行后,GPB5、GPB6、GPB8、GPB10分别输出高电平还是低电平? 高电平, 对应的LED灯亮还是灭? 都处于熄灭状态(初始状态) 语句rGPBDAT = ~(1<<8); 执行后,GPB5、GPB6、GPB8、GPB10分别输出高电平还是低电平?对应的LED灯亮还是灭? GPB5、GPB6、GPB10输出高电平,对应的LED灯熄灭;GPB8输出低电平,对应的LED灯点亮 /按键实验***********/ // 公司名称 :保定飞凌嵌入式技术有限公司 // 描 述 :蜂鸣器 // 版 权 :保定飞凌嵌入式技术有限公司 // 网 址 :www.witech.com.cn /***************************************************************/ /* 本实验接口说明 GPB0 ------ 蜂鸣器控制口 */ void Delay(unsigned int); /------------------------地址声明-----------------------------/ #define GPBCON (*(volatile unsigned )0x56000010) #define GPBDAT ((volatile unsigned )0x56000014) #define GPBUP ((volatile unsigned *)0x56000018) /------------------------------------------------------------- 函数名称: BellMain 功能描述: 入口程序 初始化后,进入按键扫描死循环 传 参: 无 返 回 值: int 0 -------------------------------------------------------------/ int BellMain() { GPBUP &= 0XFFFFFFFE; //上拉使能GPB0 GPBCON &= 0XFFFFFFC; //GPB0设为输出 GPBCON |= 0X0000001; while(1) { GPBDAT &= 0xfe; //不能用!(非) Delay(40); GPBDAT |=0x1; //用与或方式,不影响其他位 Delay(40); } return(0); } /------------------------------------------------------------/ 函数名称: Delay 功能描述: 延时函数 延时count毫秒 传 参: int count 返 回 值: 无 -------------------------------------------------------------/ void Delay(unsigned int x ) { unsigned int i,j,k; for(i=0;i<=x;i++) for(j=0;j<=0xff;j++) for(k=0;k<=0xff;k++); } AREA |DATA|,CODE,READONLY ENTRY ldr r13,=0x1000 IMPORT BellMain b BellMain END1. BellMain ()函数中的两条语句rGPBCON &= 0xFFFFFFC; rGPBCON |= 0x0000001;的具体作用是什么? //上拉电阻使能GPB0 2. GPB0端口的上拉电阻有没有使能?判断依据是什么? 3. 语句rGPBDAT &= 0xFE; rGPBDAT |= 0x1; 的作用是什么? 写出实验小结
最新发布
06-09
/**********************按键实验*********************************/ // 公司名称 :保定飞凌嵌入式技术有限公司 // 描 述 :按键控制蜂鸣器 // 版 权 :保定飞凌嵌入式技术有限公司 // 网 址 :www.witech.com.cn /***************************************************************/ /* 本实验接口说明 */ #include "2440addr.h" /*-----------------------函数声明----------------------------*/ extern void Uart_Printf(char *fmt,...); void Wr24C02(U32 slvAddr,U32 addr,U8 data); void Rd24C02(U32 slvAddr,U32 addr,U8 *data); void Run_IicPoll(void); void IicPoll(void) ; void Delay(int x) ; static U8 iicData[IICBUFSIZE]; static volatile int iicDataCount; static volatile int iicStatus; static volatile int iicMode; static int iicPt; /*------------------------------------------------------------/ 函数名称: iicMain 功能描述: 入口函数 传 参: int count 返 回 值: 无 -------------------------------------------------------------*/ void iicMain(void) { unsigned int i,j; static U8 data[256]; Uart_Printf("IIC Test(Polling) using AT24C02\n"); //设置GPE15->IICSDA 和 GPE14->IICSCL rGPEUP |= 0xc000; //关断上拉 rGPECON &= ~0xf0000000; rGPECON |= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL //使能ACK, 预分频 IICCLK=PCLK/16, 使能中断, 发送时钟 Tx clock=IICCLK/16 rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); rIICADD = 0x10; //2440 从地址 = [7:1] rIICSTAT = 0x10; //IIC总线数据输出使能(Rx/Tx) Uart_Printf("Write test data into AT24C02\n"); //写入一个page的数据,page的大小是256byte, //page 的起始地址是0xa0,写入的数据是:0、1、2、...255。0xa0是AT24C02的页地址。 //AT24C02的页地址是0x00/0x20/0x40/0x60/0x80/0xa0/0xc0/0xe0。 for(i=0;i<256;i++) Wr24C02(0xa0,(U8)i,i); //U32 slvAddr,U32 addr,U8 data for(i=0;i<256;i++) //初始化data数组的值为0。 data[i] = 0; Uart_Printf("Read test data from AT24C02\n"); for(i=0;i<256;i++) //读24C02的0xa0地址中数据到data数组中。 Rd24C02(0xa1,(U8)i,&(data[i])); for(i=0;i<16;i++) //输出data数组接收数据的值 { for (j=0;j<16;j++) Uart_Printf("%2x ",data[i*16+j]); Uart_Printf("\n"); } Uart_Printf("OK! Write data is same to Read data!\n"); while(1); } /*------------------------------------------------------------/ 函数名称: Wr24C02 功能描述: 写24c02 传 参: U32 slvAddr,U32 addr,U8 data 返 回 值: 无 -------------------------------------------------------------*/ void Wr24C02(U32 slvAddr,U32 addr,U8 data) { iicMode = WRDATA; iicPt = 0; iicData[0] = (U8)addr; iicData[1] = data; iicDataCount = 2; //8-bit data shift register for IIC-bus Tx/Rx operation. rIICDS = slvAddr; //0xa0 //Master Tx mode, Start(Write), IIC-bus data output enable //Bus arbitration sucessful, Address as slave status flag Cleared, //Address zero status flag cleared, Last received bit is 0 rIICSTAT = 0xf0; //Clearing the pending bit isn't needed because the pending bit has been cleared. while(iicDataCount!=-1) Run_IicPoll(); iicMode = POLLACK; while(1) { rIICDS = slvAddr; iicStatus = 0x100; //To check if _iicStatus is changed rIICSTAT = 0xf0; //Master Tx, Start, Output Enable, Sucessful, Cleared, Cleared, 0 rIICCON = 0xe0;//0xaf; //Resumes IIC operation. //hzh while(iicStatus==0x100) Run_IicPoll(); if(!(iicStatus & 0x1)) break; //When ACK is received } rIICSTAT = 0xd0; //Master Tx condition, Stop(Write), Output Enable rIICCON = 0xe0;//0xaf; //Resumes IIC operation. //hzh Delay(1); //Wait until stop condtion is in effect. } /*------------------------------------------------------------/ 函数名称: Rd24C02 功能描述: 读24c02 传 参: U32 slvAddr,U32 addr,U8 *data 返 回 值: 无 -------------------------------------------------------------*/ void Rd24C02(U32 slvAddr,U32 addr,U8 *data) { iicMode = SETRDADDR; iicPt = 0; iicData[0] = (U8)addr; iicDataCount = 1; rIICDS = slvAddr; rIICSTAT = 0xf0; //MasTx,Start //Clearing the pending bit isn't needed because the pending bit has been cleared. while(iicDataCount!=-1) Run_IicPoll(); iicMode = RDDATA; iicPt = 0; iicDataCount = 1; rIICDS = slvAddr; rIICSTAT = 0xb0; //主接收开始 rIICCON = 0xe0; //Resumes IIC operation. while(iicDataCount!=-1) Run_IicPoll(); *data = iicData[1]; } /*------------------------------------------------------------/ 函数名称: Run_IicPoll 功能描述: 传 参: 无 返 回 值: 无 -------------------------------------------------------------*/ void Run_IicPoll(void) { if(rIICCON & 0x10) //Tx/Rx Interrupt Enable IicPoll(); } /*------------------------------------------------------------/ 函数名称: IicPoll 功能描述: 传 参: 无 返 回 值: 无 -------------------------------------------------------------*/ void IicPoll(void) { U32 iicSt,i; iicSt = rIICSTAT; if(iicSt & 0x8){}; //When bus arbitration is failed. 总线仲裁失败 if(iicSt & 0x4){}; //When a slave address is matched with IICADD if(iicSt & 0x2){}; //When a slave address is 0000000b if(iicSt & 0x1){}; //When ACK isn't received switch(iicMode) { case POLLACK: iicStatus = iicSt; break; case RDDATA: if((iicDataCount--)==0) { iicData[iicPt++] = rIICDS; rIICSTAT = 0x90; //Stop MasRx condition rIICCON = 0xe0; //Resumes IIC operation. Delay(1); //Wait until stop condtion is in effect. //Too long time... //The pending bit will not be set after issuing stop condition. break; } iicData[iicPt++] = rIICDS; //The last data has to be read with no ack. if((iicDataCount)==0) rIICCON = 0x60;//0x2f; //Resumes IIC operation with NOACK. else rIICCON = 0xe0;//0xaf; //Resumes IIC operation with ACK break; case WRDATA: if((iicDataCount--)==0) { rIICSTAT = 0xd0; //stop MasTx condition rIICCON = 0xe0;//0xaf; //resumes IIC operation. Delay(1); //wait until stop condtion is in effect. //The pending bit will not be set after issuing stop condition. break; } rIICDS = iicData[iicPt++]; //_iicData[0] has dummy. for(i=0;i<10;i++); //for setup time until rising edge of IICSCL rIICCON = 0xe0;//0xaf; //resumes IIC operation. break; case SETRDADDR: if((iicDataCount--)==0) break; //IIC operation is stopped because of IICCON[4] rIICDS = iicData[iicPt++]; for(i=0;i<10;i++); //for setup time until rising edge of IICSCL rIICCON = 0xe0;//0xaf; //resumes IIC operation. break; default: break; } } /*------------------------------------------------------------/ 函数名称: Delay 功能描述: 延时函数 传 参: int x 返 回 值: 无 -------------------------------------------------------------*/ void Delay(int x) { int k, j; while(x) { for (k=0;k<=0xff;k++) for(j=0;j<=0xff;j++); x--; } } #include <stdarg.h> #include "2440addr.h" void Uart_Init(int baud) { int i; rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable //UART0 rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits // [10] [9] [8] [7] [6] [5] [4] [3:2] [1:0] // Clock Sel, Tx Int, Rx Int, Rx Time Out, Rx err, Loop-back, Send break, Transmit Mode, Receive Mode // 0 1 0 , 0 1 0 0 , 01 01 // PCLK Level Pulse Disable Generate Normal Normal Interrupt or Polling rUCON0 = 0x805; // Control register rUBRDIV0=( (int)(50000000/16./baud+0.5) -1 ); //Baud rate divisior register 0 //UART1 for(i=0;i<100;i++); } //===================================================================== void Uart_SendByte(int data) { if(data=='\n') { while(!(rUTRSTAT0 & 0x2)); // Delay(1); //because the slow response of hyper_terminal WrUTXH0('\r'); } while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty. // Delay(1); WrUTXH0(data); } //==================================================================== void Uart_SendString(char *pt) { while(*pt) Uart_SendByte(*pt++); } //===================================================================== //If you don't use vsprintf(), the code size is reduced very much. void Uart_Printf(char *fmt,...) { va_list ap; char str[255]; va_start(ap,fmt); vsprintf(str,fmt,ap); Uart_SendString(str); va_end(ap); } AREA |DATA|,CODE,READONLY ENTRY ldr r13,=0x1000 IMPORT iicMain b iicMain END 1. 通过UART0发送一个字符的数据(INT8U data)的发送语句是什么?该语句能得到执行的条件是什么?把该条件写成C语言语句。 2. 准备把要接收的字符放在INT8U类型的变量reData中,则接收一个字符的语句是什么?接收到字符的条件是什么?把该条件写成C语言语句。 3. 预定义语句 #define rUTXH0 (*(volatile unsigned *) 0x50000020)中,关键字volatile的作用是什么?unsigned * 的作用的是什么?第一个*的作用是什么? rUTXH0代表的是什么特殊功能寄存器?其功能是什么? 4. 以下两条语句的具体作用是什么? ULCON0 &=0xFFFFFF00; ULCON0 |=0x03; 5. 若PCLK为50MHz,UART0使用的波特率是115200pbs,则给rUBRDIV0 赋的值是多少? 6. S3C2410A的IIC总线有哪两条信号线?这两条信号线的作用分别是什么?为使用这两条信号线,对IIC接口的管脚该做如何设置?IIC是如何发出开始信号和停止信号的?
06-08
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值