A. keil51中如何用c语言定义寄存器的地址并给地址赋值
KeilC51中定义寄存器变量的方法如下:
1、特殊功能寄存器的定义:
sfr和sfr16,比如:
sfr P1=0x90;
sfr16 T2=0xcc;
2、普通寄存器变量定义:
使用DBYTE和XBYTE来实现,比如
unsigned char temp=XBYTE[0x1000];//这是访问外部地址的语句,也可以是外部IO口地址
unsigned char temp=DBYTE[0x40];//这是将内部寄存器40H定义为变量temp
B. C语言中有哪些存储类型
c语言中的存储类型有auto, extern, register, static 这四种,存储类型说明了该变量要在进程的哪一个段中分配内存空间,可以为变量分配内存存储空间的有数据区、BBS区、栈区、堆区。
1. auto存储类型
auto只能用来标识局部变量的存储类型,对于局部变量,auto是默认的存储类型,不需要显示的指定。因此,auto标识的变量存储在栈区中。
2. extern存储类型
extern用来声明在当前文件中引用在当前项目中的其它文件中定义的全局变量。如果全局变量未被初始化,那么将被存在BBS区中,且在编译时,自动将其值赋值为0,如果已经被初始化,那么就被存在数据区中。全局变量,不管是否被初始化,其生命周期都是整个程序运行过程中,为了节省内存空间,在当前文件中使用extern来声明其它文件中定义的全局变量时,就不会再为其分配内存空间。
3. register存储类型
声明为register的变量在由内存调入到CPU寄存器后,则常驻在CPU的寄存器中,因此访问register变量将在很大程度上提高效率,因为省去了变量由内存调入到寄存器过程中的好几个指令周期。
4. static存储类型
被声明为静态类型的变量,无论是全局的还是局部的,都存储在数据区中,其生命周期为整个程序,如果是静态局部变量,其作用域为一对{}内,如果是静态全局变量,其作用域为当前文件。静态变量如果没有被初始化,则自动初始化为0。静态变量只能够初始化一次。
C. 单片机的实质,就是利用c语言来对 寄存器的操作
c语言也好,汇编语言也好,也只不过是一种编程语言罢了,真正的应用是通过用户编写的程序来控制单片机完成各种工作,也就是各种操作,来实现单片机对各种设备的控制工作。因此,你说的“对寄存器的操作”只是一些基本的操作而已,或者是一些基本的控制方式而已,而真正的控制对象是外部配置的设备,比如简单的设备有:数码管用来显示的设备,液晶屏也是显示的设备,按键或者叫键盘,是输入设备,以及各种传感器等,根据需要控制的设备种类太多了。
D. C语言调用汇编程序时,使用哪些寄存器来传递参数
C语言与汇编语言混合编程应遵守的规则
ARM编程中使用的C语言是标准C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境与ARM的硬件紧密相关。
在使用C语言时,要用到和汇编语言的混合编程。若汇编代码较为简洁,则可使用直接内嵌汇编的方法;否则要将汇编程序以文件的形式加入到项目中,按照ATPCS(ARM/Thumb过程调用标准,ARM/Thumb Procere Call Standard)的规定与C程序相互调用与访问。
在C程序和ARM汇编程序之间相互调用时必须遵守ATPCS规则。ATPCS规定了一些子程序间调用的基本规则,哪寄存器的使用规则,堆栈的使用规则和参数的传递规则等。
1)寄存器的使用规则
子程序之间通过寄存器r0~r3来传递参数,当参数个数多于4个时,使用堆栈来传递参数。此时r0~r3可记作A1~A4。
在子程序中,使用寄存器r4~r11保存局部变量。因此当进行子程序调用时要注意对这些寄存器的保存和恢复。此时r4~r11可记作V1~V8。
寄存器r12用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP。
寄存器r13用作堆栈指针,记作SP。寄存器r14称为链接寄存器,记作LR。该寄存器用于保存子程序的返回地址。
寄存器r15称为程序计数器,记作PC。
2)堆栈的使用规则
ATPCS规定堆栈采用满递减类型(FD,Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。
3)参数的传递规则
整数参数的前4个使用r0~r3传递,其他参数使用堆栈传递;浮点参数使用编号最小且能够满足需要的一组连续的FP寄存器传递参数。
子程序的返回结果为一个32位整数时,通过r0返回;返回结果为一个64位整数时,通过r0和r1返回;依此类推。结果为浮点数时,通过浮点运算部件的寄存器F0、D0或者S0返回。
2、汇编程序调用C程序的方法
汇编程序的书写要遵循ATPCS规则,以保证程序调用时参数正确传递。在汇编程序中调用C程序的方法为:首先在汇编程序中使用IMPORT伪指令事先声明将要调用的C语言函数;然后通过BL指令来调用C函数。
例如在一个C源文件中定义了如下求和函数:
int add(int x,int y){
return(x+y);
}
调用add()函数的汇编程序结构如下:
IMPORT add ;声明要调用的C函数
……
MOV r0,1
MOV r1,2
BL add ;调用C函数add
……
当进行函数调用时,使用r0和r1实现参数传递,返回结果由r0带回。函数调用结束后,r0的值变成3。
3、C程序调用汇编程序的方法
C程序调用汇编程序时,汇编程序的书写也要遵循ATPCS规则,以保证程序调用时参数正确传递。在C程序中调用汇编子程序的方法为:首先在汇编程序中使用EXPORT伪指令声明被调用的子程序,表示该子程序将在其他文件中被调用;然后在C程序中使用extern关键字声明要调用的汇编子程序为外部函数。
例如在一个汇编源文件中定义了如下求和函数:
EXPORT add ;声明add子程序将被外部函数调用
……
add ;求和子程序add
ADD r0,r0,r1
MOV pc,lr
……
在一个C程序的main()函数中对add汇编子程序进行了调用:
extern int add (int x,int y); //声明add为外部函数
void main(){
int a=1,b=2,c;
c=add(a,b); //调用add子程序
……
}
当main()函数调用add汇编子程序时,变量a、b的值会给了r0和r1,返回结果由r0带回,并赋值给变量c。函数调用结束后,变量c的值变成3。
4、C程序中内嵌汇编语句
在C语言中内嵌汇编语句可以实现一些高级语言不能实现或者不容易实现的功能。对于时间紧迫的功能也可以通过在C语言中内嵌汇编语句来实现。内嵌的汇编器支持大部分ARM指令和Thumb指令,但是不支持诸如直接修改PC实现跳转的底层功能,也不能直接引用C语言中的变量。
嵌入式汇编语句在形式上独立定义的函数体,其语法格式为:
__asm
{
指令[;指令]
……
[指令]
}
其中“__asm”为内嵌汇编语句的关键字,需要特别注意的是前面有两个下划线。指令之间用分号分隔,如果一条指令占据多行,除最后一行外都要使用连字符“\”。
5、基于ARM的C语言与汇编语言混合编程举例
下面给出了一个向串口不断发送0x55的例子:
该工程的启动代码使用汇编语言编写,向串口发送数据使用C语言实现,下面是启动代码的整体框架:
……
IMPORT Main
AREA Init,CODE,READONLY;
ENTRY
……
BL Main ;跳转到Main()函数处的C/C++程序
……
END ;标识汇编程序结束
下面是使用C语言编写的主函数:
#include "..\inc\config.h" //将有关硬件定义的头文件包含进来
unsigned char data; //定义全局变量
void main(void){
Target_Init(); //对目标板的硬件初始化
Delay(10); //延时
data=0x55; //给全局变量赋值
while(1) {
Uart_Printf("%x",data); //向串口送数
Delay(10);
}
}
E. 请教C51单片机,C语言编程,怎样把一个四位数存入(读取)外部数据存储器请举例说明。
//外部绝对地址定义,具体地址根据你所需存在哪个地址单元而定
#define uchar unsigned char
#define uint unsigned int
uchar xdata XRAM _at_ 0xFF00[4];//指定外部存储地址
uchar DATA1[4]; //你先把你的四位数每位单独分离出来存到这个4成员数组
void main(void)
{
uchar i;
for(i=0;i<4;i++)
{
XRAM[i]=DATA1[i]
}
}
F. AVR单片机怎么用C语言将通用寄存器的值赋给外部变量
这个涉及到 C语言中的嵌入式汇编代码相关:
asm(
“汇编语句”
:输出寄存器
:输入寄存器
:会被修改的寄存器
);
范例:
// 取fs 段寄存器的值(选择符)。
34 #define _fs() ({ \
35 register unsigned short __res; \
36 __asm__("mov %%fs,%%ax":"=a" (__res):); \
37 __res;})
注:关于嵌入汇编详细格式参考GNU gcc手册中[5]第4章的内容(Extensions to the C Language Family)或见参考文献[20](Using Inline Assembly with gcc), 范例摘自 LInux0.12完全释注;
G. C语言如何对外部寄存器赋值
外部寄存器? 你是说单片机的寄存器么? 如果是用c语言写单片机的代码的话,直接找到那个寄存器的名称,例如LPC2388的引脚功能选择寄存器PINSEL4,给它赋值,就直接用:
PINSEL4=0x00000000;
就行了,或者如果你不知道寄存器的名字,知道地址也行,例如你的寄存器位于地址0x02000000处,你要赋值的话,就直接用:
unsigned int *p;
p=0x02000000;
*p=0x12345678;//赋值
H. c语言单片机寄存器是怎么操作的
c语言对单片机寄存器的操作就是读/写,也很简单的,就是直接赋值。用大写字母表示寄存器,如
TMOD=0x20;//给寄存器赋值
x=SBUF; //读寄存器
I. 用C语言怎样访问CPU的寄存器
恐怕只能内嵌汇编了。
但是不建议在C语言的程序中直接访问寄存器。很容易导致程序出错。一般 内嵌单条语句可以使用asm("");如:asm("nop");
有些MCU支持asm("");内嵌复合语句。
有些不支持。
R8C/2C 好像就不支持,所以需要
#pragma asm
.
.
#pragma endasm
初学,仅供参考。