GPIO操作之C语言篇
来源:互联网 发布:什么软件制作照片好 编辑:程序博客网 时间:2024/05/21 10:12
1:主要内容
在嵌入式开发中,一般使用汇编语言做一些芯片初始化工作,当对程序效率要求很高时,也有时会使用汇编语言,但汇编语言相对较难阅读和理解。因此,我们希望我们以后的实验在初始化完芯片相关功能后使用C语言进行编程,方便大家阅读及理解。这一篇的内容主要是讲解使用C语言来控制LED灯闪烁。
2:相关要点
1,在通用PC机上写程序都有一个叫做main的函数,是程序的总入口。在嵌入式开发时,怎么从汇编语言跳转到C语言?在跳转之前需要设置哪些东西?
2:,在ARM体系中,汇编和C语言之间相互调用时参数如何传递?
关于上面的两个疑问,我不在这里详细分析。我给出参考资料,大家自行参考,思索。
针对问题1: ucos在s3c2410上运行过程整体剖析之基础知识-c语言和堆栈
针对问题2:参见资料 ATPCS.pdf
3:实验源码
initsystem.s
@******************************************************************************@ 文件名 :initsystem.s@ 功 能:初始化系统并copy代码@ @ 作者 :张连聘@ 创建时间:2014-06-22@******************************************************************************.text.global _start@声明常量.equ DATA_DST,0x40000000 @目的地址.equ DATA_SRC,0x80000000 @源地址@引入外部标号.extern main.extern start_copy_addr_start: LDR PC, ResetAddr ResetAddr: .word ResetInitResetInit:LDR R0,=DATA_DST @RO 指向目的地址LDR R1,=start_copy_addr @R1 指向源地址MOV R10,#128 @复制的个数为128*8*4=4KCopyLoop: <span style="white-space:pre"></span>LDMIA R1!,{R2-R9}@从R1指定的内存地址处装载数据到R2--R9中STMIA R0!,{R2-R9}@把R2--R9的数据复制到R0指定的内存中SUBS R10,R10,#1BNE CopyLoopLDR SP,=0X40000000+1024*64 @设置堆栈指针,LPC2220内部有64KRAM,设置SP指针指向最高地址LDR PC,=main @调用C语言的main函数HaltLoop:B HaltLoop.end
main.c
/******************************************************************************* 文件名 :main.c* 功 能:利用P2.28控制led灯闪烁* * 作者 :张连聘* 创建时间:2014-06-25*******************************************************************************///定义一些控制寄存器地址#define IO2DIR (*(volatile unsigned long *)0xE0028028) //IO2输入、输出配置寄存器#define IO2SET (*(volatile unsigned long *)0xE0028024) //IO2输出1控制寄存器#define IO2CLR (*(volatile unsigned long *)0xE002802C) //IO2输出0控制寄存器#define LEDCON (1<<28) void Delay(int ms);void main(void){IO2DIR = LEDCON; //配置P2.28为输出口while (1){IO2SET = LEDCON; //点亮LED灯Delay(6666);IO2CLR = LEDCON; //熄灭LED灯Delay(6666);}}/******************************************************************************* 名 称:Delay* 功 能:软件延时* 入口参数:ms * 出口参数:无******************************************************************************/void Delay(int ms){int i,j;for(i=0;i<10;i++)for(j=0;j<ms;j++);}
led_control.lds
/** led_control 的链接脚本。***/ MEMORY{ rom (rx) : ORIGIN = 0x80000000, LENGTH = 2M ram (!rx) : ORIGIN = 0x40000000, LENGTH = 2M}ENTRY(_start)SECTIONS{. = 0x80000000 ;.init : {initsystem.o(.text)start_copy_addr = . ;} >rom. = 0x40000000 ;.main :AT (ADDR(.init)+SIZEOF(.init)){main.o(.text)} >ram}
makefile
control_led.bin:main.c initsystem.sarm-linux-gcc -g -c -o main.o main.carm-linux-gcc -g -c -o initsystem.o initsystem.sarm-linux-ld -Tled_control.lds -nostdlib -g main.o initsystem.o -o control_led_elfarm-linux-objcopy -O binary -S control_led_elf control_led.binclean:rm -f control_led.bin control_led_elf *.o
4:源码重点分析
我们在main.c里定义了一个main函数,那我们在汇编代码里怎么引用呐?
.extern main 声明在另一个文件中定义了main函数。然后LDR PC,=main 跳转到main函数。这里说明一下,之所以不能使用BL指令跳转,是因为启动代码执行的地址在0X80000000 ,而启动代码将main函数代码copy到0X40000000。Bl的跳转范围没有这么大。还有,这个main函数完全可以更改为其他函数,只是一个普通的函数名称。
LDR SP,=0X40000000+1024*64 使用这条指令,是设置SP堆栈指针的位置。这里讲堆栈指针设置在了LPC2220这款芯片的内部RAM的最顶端。默认的ARM处理器是递减堆栈。
5:总结
由上面的实验可见,PC机编程时的main函数只是一个普通的函数名称,只不过他们底层设置好了,调用main函数,所以我们一般说普通PC机程序总入口是main函数。其实,在main函数之前已经做了很多工作。
0 0
- GPIO操作之C语言篇
- 树莓派瞎玩~6~控制GPIO之C语言
- 树莓派GPIO控制--C语言篇
- ARM处理器学习之--GPIO操作篇
- C语言之文件操作
- C语言之文件操作
- C语言之文件操作
- C语言之文件操作
- c语言之文件操作
- C语言之文件操作
- C语言之指针操作
- c语言之操作符
- 联发科Linkit 7688 (二)GPIO基本操作与C语言编程
- 嵌入式C语言之屏幕操作之菜单篇
- C语言之单链表操作之查找
- C语言之单链表操作之插入
- C语言嵌入式系统编程修炼之屏幕操作篇
- C语言嵌入式系统编程修炼之键盘操作篇
- 在windows下关联py文件到IDLE直接打开并可调试的方法
- 杭电 1042 N! 大数相乘
- mysql mac下解决MySQL中文乱码的问题
- struts2 问题 The content of element type "package" must match "(result-types?,interceptors?,
- 成员变量与属性存取器(Accessor)命名原则
- GPIO操作之C语言篇
- eclipse 更改Eclipse下Tomcat的部署目录
- 我们做不到一刀劈死它,但可以先切断它的一根脚趾头
- NYOJ-91阶乘之和
- STL之for_each, find_if,adjacent_find,count_if的使用
- struts2 设置文件编码的3种方式
- 腾讯2013校园实习生招聘笔试题,附答案
- oracle liunx5配置本地yum
- 机房收费系统重构(三)—工厂+反射+DAL