精华内容
下载资源
问答
  • ARM寄存器C操作探讨

    千次阅读 2012-02-21 16:52:12
    乍从51过渡到ARM,很多人往往一时不能适应ARM的开发方式,其中一个困扰就是寄存器的访问,... 近期到手ARM11架构的S3C6410片子,寄存器可谓繁多,正好拿它开刀,给大家来个现场解牛,下面是S3C6410的GPIO配置的相关寄

          乍从51过渡到ARM,很多人往往一时不能适应ARM的开发方式,其中一个困扰就是寄存器的访问,尤其是从屈指可数的51族寄存器一下子转到ARM纷繁复杂的寄存器,可能顿时会有种无从下手的感觉。面对这么多的寄存器,我们该怎么对其访问比较方便、科学和规范呢?

          近期到手ARM11架构的S3C6410片子,寄存器可谓繁多,正好拿它开刀,给大家来个现场解牛,下面是S3C6410的GPIO配置的相关寄存器一瞥(冰山一角啊,呵呵):

             

              如图,观察这些寄存器的地址是连续的,这点很重要,与我们将要讨论的第二种操作方式息息相关。通常我们有两种常用的寄存器的操作方式。

          第一种方式:宏定义。

          #define GPACON  (*(volatile U32 *) (0x7F008000))

          #define GPADAT  (*(volatile U32 *) (0x7F008004))

          #define GPAPUD  (*(volatile U32 *) (0x7F008008))

          ......

          解析:

          1、将地址强制类型转换为指向U32数据类型(即寄存器)的指针;

          2、再加“*”,表示引用指向该地址处存放的数据。

          第二种方式:结构体。

          #include <iostream>

            using namespace std;

          int regs_value[]={0,1,2,3,4,5,6,7,8,9};

          struct GPIO_REGS{
          int GPACON;
          int GPADAT;
          int GPAPUD;
          int GPACONSLP;
          int GPAPUDSLP;
          int GPBCON;
          int GPBDAT;
          int GPBPUD;
          int GPBCONSLP;
          int GPBPUDSLP;
          //......
          };

         #define GPIO_BASE (regs_value)
         #define GPIO ((volatile GPIO_REGS *) GPIO_BASE)

         void main()
         {
             cout<<GPIO->GPACON<<endl;
             cout<<GPIO->GPADAT<<endl;
             cout<<GPIO->GPAPUD<<endl;
             //......
          }

          上面的代码是我在VC6.0环境下模拟ARM第二种寄存器操作方式时写的,由于数组中元素的地址是连续的,所以这里采用一个数组的方式来模拟ARM的寄存器。下面为运行的结果,以证实确实正确的访问到了想要访问的目标寄存器。

            

            从图可以看到确实得到了正确的访问,上面的模拟程序很小大家可自行分析体会ARM的这种操作寄存器的方法。

         总结:

           对于这两种方法,第一种比较简洁,但第二种可能会更加方便(尤其是一大片地址连续的寄存器),个人意见比较推荐使用第二种方法。

           以上,希望对刚由单片机开发转向ARM开发的朋友有所帮助。


    欢迎大家扫描下方二维码关注我的个人微信公众号,一起交流学习,谢谢。


    展开全文
  • 1 寄存器地址的定义:#define UART_BASE_ADRS (0x10000000) /* 串口的基地址 */#define UART_RHR *(volatile unsigned char *)(UART_BASE_ADRS + 0) /* 数据接受寄存器 */#define UART_THR *(volatile unsigned char...

    1 寄存器地址的定义:

    #define UART_BASE_ADRS (0x10000000)     /* 串口的基地址 */

    #define UART_RHR *(volatile unsigned char *)(UART_BASE_ADRS + 0)  /* 数据接受寄存器 */

    #define UART_THR *(volatile unsigned char *)(UART_BASE_ADRS + 0)  /* 数据发送寄存器 */

    2 寄存器读写操作:

    UART_THR = ch; /* 发送数据 */

    ch = UART_RHR; /* 接收数据 */

    也可采用定义带参数宏实现

    #define WRITE_REG(addr, ch) *(volatile unsigned char *)(addr) = ch

    #define READ_REG(addr, ch) ch = *(volatile unsigned char *)(addr)

    3 对寄存器相应位的操作方法:

    定义寄存器

    #define UART_LCR *(volatile unsigned char *)(UART_BASE_ADRS + 3)  /* 线控制寄存器 */

    定义寄存器相应位的值

    #define CHAR_LEN_5 0x00

    #define CHAR_LEN_6 0x01

    #define CHAR_LEN_7 0x02

    #define CHAR_LEN_8 0x03    /* 8 data bit */

    #define LCR_STB  0x04 /* Stop bit control */

    #define ONE_STOP 0x00 /* One stop bit! */

    #define LCR_PEN  0x08 /* Parity Enable */

    #define PARITY_NONE 0x00

    #define LCR_EPS  0x10 /* Even Parity Select */

    #define LCR_SP  0x20 /* Force Parity */

    #define LCR_SBRK 0x40 /* Start Break */

    #define LCR_DLAB 0x80 /* Divisor Latch Access Bit */

    定义寄存器相应位的值另一种方法

    #define CHAR_LEN_5 0<<0

    #define CHAR_LEN_6 1<<0

    #define CHAR_LEN_7 1<<1

    #define CHAR_LEN_8 (1<<0)|(1<<1)    /* 8 data bit */

    #define LCR_STB  1<<2 /* Stop bit control */

    #define ONE_STOP 0<<2 /* One stop bit! */

    #define LCR_PEN  1<<3 /* Parity Enable */

    #define PARITY_NONE 0<<3

    #define LCR_EPS  1<<4 /* Even Parity Select */

    #define LCR_SP  1<<5 /* Force Parity */

    #define LCR_SBRK 1<<6 /* Start Break */

    #define LCR_DLAB 1<<7 /* Divisor Latch Access Bit */

    对寄存器操作只需对相应位或赋值

    UART_LCR = CHAR_LEN_8 | ONE_STOP | PARITY_NONE;    /* 设置 8位数据位,1位停止位,无校验位 */

    4 对寄存器某一位置位与清零

    对某一寄存器第7位置位

    XX_CRTL |= 1<<7;

    XX_CRTL &= ~(1<<7);

    UART_LCR |= LCR_DLAB;           /* 时钟分频器锁存使能 */

    UART_LCR &= ~(LCR_DLAB);        /* 禁止时钟分频器锁存 */

    5 判断寄存器某一位是否置位或为0的方法

    #define UART_LSR *(volatile unsigned char *)(UART_BASE_ADRS + 5)  /* 线状态寄存器 */

    #define LSR_DR  1<<0 /* Data Ready */

    当UART_LSR的第0位为1时结束循环

    while (!(UART_LSR & LSR_DR)) /* 等待数据接收完 */

    展开全文
  • } 您可以确保C变量始终使用驻留在寄存器中以实现快速访问,并且不会被其他生成的代码覆盖。 (Handy,ebx是通常的x86调用约定下的被调用者,所以即使它被调用其他函数编译没有-ffixed- *,它应该被恢复)。 另一方面...

    -ffixed-reg

    Treat the register named reg as a fixed register; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some other fixed role).

    这可以用更简单的方式复制理查德的答案,

    int main() {

    register int i asm("ebx");

    return i + 1;

    }

    虽然这是没有意义,因为你不知道ebx寄存器是什么。

    如果你把这两个,用gcc -ffixed-ebx编译,

    #include

    register int counter asm("ebx");

    void check(int n) {

    if (!(n % 2 && n % 3 && n % 5)) counter++;

    }

    int main() {

    int i;

    counter = 0;

    for (i = 1; i <= 100; i++) check(i);

    printf("%d Hamming numbers between 1 and 100\n", counter);

    return 0;

    }

    您可以确保C变量始终使用驻留在寄存器中以实现快速访问,并且不会被其他生成的代码覆盖。 (Handy,ebx是通常的x86调用约定下的被调用者,所以即使它被调用其他函数编译没有-ffixed- *,它应该被恢复)。

    另一方面,这肯定是不可移植的,通常也不是一个性能优势,因为你限制了编译器的自由。

    展开全文
  • 通过这段时间的工作和学习,我感觉在嵌入式硬件编程中,大多数情况下都是对相应硬件的功能寄存器进行设置和操作。一, 寄存器的设置和操作特性1,一个寄存器的每个位有其不同的意义,进行不同的设置会使硬件产生不同...

    通过这段时间的工作和学习,我感觉在嵌入式硬件编程中,大多数情况下都是对相应硬件的功能寄存器进行设置和操作。

    一, 寄存器的设置和操作特性

    1,一个寄存器的每个位有其不同的意义,进行不同的设置会使硬件产生不同的效果和功能;

    2,有些情况下需要对一个寄存器进行连续的不同的甚至完全相反的设置;

    3,有些情况下需要对一个寄存器中的某一位或一位进行连续的不同的甚至完全相反的设置,而其余的位要保持不变;

    4,有时,对一个寄存器进行设置时,对其不同的位进行先后顺序不同的设置,即对其各个位有先后设置的顺序的要求,使硬件产生的结果也不同;

    5,有时,对于一个寄存器要求必须一次赋值,若对其某些位赋值先后顺序不同,便达不到预期的效果和功能。

    二,寄存器的赋值操作方法

    为说明方便,定义如下3个8位的寄存器:

    #define   REG     0xFFFFFF10

    1,对单个的位进行赋值

    (1)    将寄存器REG的第5位置“1”

    REG |= (1 << 5);

    (2)    将寄存器REG的第5位清零

    REG &= ~(1 << 5);

    (3)    将寄存器REG的第3、5位置“1”

    REG |= (1 << 5) | (1 << 3);

    (4)    将寄存器REG的第3、5位清零

    REG &= ~( (1 << 5) | (1 << 3) );

    2,直接赋值

    (1)将寄存器REG的0、1、2、3、5、7位置“1”

    REG = 0x5F;

    (即给寄存器REG1赋值为1010 1111,这种方法多在初始化中使用)

    (2)分别将寄存器REG的1、3、5、7位置“1”,0、2位置“0”

    uint32 temp;

    tmep = REG;

    temp &= ~0x01;

    temp |= (1 << 1);

    temp &= ~(1 << 2);

    temp |= (1 << 3);

    temp |= (1 << 5);

    temp |= (1 << 7);

    REG = temp;

    展开全文
  • C语言寄存器变量

    千次阅读 2019-01-06 11:21:21
    寄存器存在于CPU内部,运算速度非常快, 因为内存中的数据必须载入寄存器才能计算。如果直接定义一个变量为寄存器变量,则少了载入等过程自然会快。对于频繁使用的变量可以把它放在寄存器中来提速度。 对于VC编译器...
  • c语言寄存器变量

    2016-08-10 13:46:00
    寄存器存在于CPU内部,运算速度非常快, 因为内存中的数据必须载入寄存器才能计算。如果直接定义一个变量为寄存器变量,则少了载入等过程自然会快。对于频繁使用的变量可以把它放在寄存器中来提速度。  对于VC...
  • C语言寄存器变量register

    万次阅读 2015-04-17 15:25:11
    用register声明的变量是寄存器变量,是存放在CPU的寄存器里的。而我们平时声明的变量是存放在内存中的。虽说内存的速度已经很快... 学过C的都应该知道每一个变量在内存中都占有一定的的空间,来存放数据。但是在寄存器
  • 寄存器

    2019-05-16 18:21:01
    通用寄存器(R0) 用于传送和暂存数据,也可参与算术逻辑运算,并保存运算结果。 程序计数器(PC/IP) PC寄存器中的内容,是下一条要取的指令的16位存储单元地址,在程序执行的过程中,PC中的值会自动加一。 ...
  • C语言访问MCU寄存器

    2020-03-23 08:51:21
    C语言访问MCU寄存器 问题由来: //下面这行代码的意思是直接操作0X020C4068这个寄存器 //具体寄存器的作用是通过手册得到的 #define CCM_CCGR0 *((volatile unsigned int*)0X020C4068) //假设寄存器为32位 //要设置...
  • 移位寄存器移位寄存器移位寄存器移位寄存器移位寄存器移位寄存器移位寄存器移位寄存器移位寄存器移位寄存器移位寄存器
  • 单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来有两种方法。
  • 寄存器C语言复习MDK寄存器地址名称映射分析 C语言复习 位操作 define宏定义 #define 标识符 字符串 标识符位宏定义宏名 字符串可以是常数、表达式、格式串 ifdef条件编译 #ifdef #endif extern变量申明 提示...
  • Turbo C下的寄存器变量

    2020-08-03 05:38:38
    在Turbo C下有种变量叫寄存器变量。使用寄存器的好处是可以提高程序的运行速度!因为减少了寻址时间。
  • c语言常见寄存器操作

    千次阅读 2019-04-24 18:40:55
    1 寄存器地址的定义: #define UART_BASE_ADRS (0x10000000) /* 串口的基地址 */ #define UART_RHR *(volatile unsigned char *)(UART_BASE_ADRS + 0) /* 数据接受寄存器 */ #define UART_THR *(volatile ...
  • C语言寄存器变量

    2020-01-05 00:27:48
    文章目录1、寄存器变量2、寄存器变量速度测试 ...因此,C语言\C++语言还定义了一种变量,不是保存在内存上,而是直接存储在CPU中的寄存器中,这种变量称为寄存器变量。 register int i=100; C编译程序会自动...
  • S3C2440寄存器合集

    2012-03-23 21:39:25
    S3C2440寄存器合集
  • 单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来有两种方法。
  • 使用C语言操作DSP的寄存器,嵌入式培训机构的内部资料,对学习嵌入式刚入门的同学帮助很大。.
  • 32单片机C语言相关知识以及寄存器地址名称映射分析

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 334,750
精华内容 133,900
关键字:

寄存器c