0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言访问MCU寄存器的方式有哪些?

GReq_mcu168 来源:未知 作者:胡薇 2018-08-30 15:42 次阅读

1.对C编译器进行语法扩充

对C编译器进行语法扩充。例如MCS51系列单片机的C-51语法中扩充了sfr关键字,举例如下:

sfr P0 = 0x80;

这样操作0x80单元直接写P0即可。

又如Atmel的AVR系列单片机,其ICCAVR和GCCAVR编译器都没有定义新的数据类型,只能采用标准C的强制类型转换和指针来实现访问MCU寄存器。而IAR和CodeVisionAVR编译器对ANSI C进行了扩充,定义了新的数据类型,使C语言可以直接访问MCU的有关寄存器,例如在IAR中可以使用:

SFR_B(DDRB, 0x28);

CodeVisionAVR中可以使用:

sfrb DDRB = 0x28;

2.使用标准C的强制类型转换和指针来实现

采用标准C的强制转换和指针的概念来实现访问MCU的寄存器,例如:

#define DDRB (*(volatile unsigned char *)0x25)

分析如下:

1.(unsigned char *)0x25中的0x25只是个值,前面加(unsigned char *)表示把这个值强制类型转换为unsigned char型的指针。再在前面加”*”,即*(volatile unsigned char *)0x25表示对这个指针解引用,相当于(unsigned char *)0x25是一个指针p,而这个宏定义为#define DDRB *p。

这样当读/写以0x25为地址的寄存器时,直接书写DDRB即可,即写:DDRB = 0xff;

相当于:

unsigned char *p, i; p = 0x25; i = *p; //把地址为0x25单元中的数据读出送入i变量*p = 0xff; //向地址为0x25的单元中写入0xff

这样经过一层宏定义的封装就变得直观和方便的多了。

2.关键字volatile确保本指令不会以为C编译器的优化而被省略,且要求每次直接读值。例如使用while(*(unsigned char *)0x25)时,有时系统可能不能真正去读0x25的值,而是用第一次读出的值,如果这样,这个循环可能就是个死循环。用了volatile则要求每次都去读0x25的实际值。

GCCAVR工具链中就使用了这样的方式,例如在iomx8.h文件中一个定义如下:#define PORTB _SFR_IO8(0x25)

而在sfr_defs.h中可以找到如下两个宏定义:

#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr)+0x20)#define _MMIO_BYTE(mem_addr) (*(volatile unit8_t *)(mem_addr))

实质上与直接的强制类型转换和指针定义是一样的。

3.使用结构体实现

使用指针的方式来访问特殊功能寄存器的优势在于完全符合标准的ANSI-C,而无需扩展语法,形成“方言”,拥有更好的兼容性和可移植性。

这种方式适合简单的应用程序,而当系统用到多个同种外设时,就需要为每一个这种外设定义寄存器,这样就会使程序的维护变得非常困难。而且,由于每次寄存器操作都会有对应的常量存储在程序Flash里,为每个寄存器定义单独的指针还会增加程序代码

为了简化程序代码,可以将寄存器组定义为结构体,而将外设当做指向这个结构体的指针。例如:

typedef struct { volatile unsigned long DATA; //0x00 volatile unsigned long RSR; //0x04 unsigned long RESERVED0[4]; //0x08-0x14 volatile unsigned long FLAG; //0x18 ... }UART_TypeDef;#define Uart0 ((UART_Type *)0x40003000)#define Uart1 ((UART_Type *)0x40004000)#define Uart2 ((UART_Type *)0x40005000)int getkey(UART_TypeDef * uartptr) { while((uartptr->FLAG & 0x40) == 0); //无数据,等待 return uartptr->DATA; // 读取字符}int main(void) { unsigned long data; data = getkey(Uart0); }

在这种设定下,同一个外设寄存器的结构体可以被多个外设实体共用,这样也使得程序维护变得容易。另外,由于立即数存储的减少,编译出的程序代码也会变小。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    17123

    浏览量

    350992
  • 寄存器
    +关注

    关注

    31

    文章

    5336

    浏览量

    120230
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136692

原文标题:C语言访问MCU寄存器的三种方式

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言环境下访问特殊功能寄存器sfr的经验

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法
    的头像 发表于 11-10 09:46 9388次阅读
    在<b class='flag-5'>C</b><b class='flag-5'>语言</b>环境下<b class='flag-5'>访问</b>特殊功能<b class='flag-5'>寄存器</b>sfr的经验

    C语言访问MCU寄存器的两种方式

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。1采用标准
    发表于 03-01 10:17

    两种方式实现C语言访问MCU寄存器

    来源 网络单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。 1、采用标准
    发表于 04-19 14:45

    如何实现C语言访问MCU寄存器?掌握这两种方式就够了!

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。1采用标准
    发表于 07-13 14:51

    如何实现C语言访问MCU寄存器?掌握这两种方式就够了!

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。1、采用标准
    发表于 03-08 09:42

    C语言访问MCU寄存器方式

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。
    发表于 02-02 07:48

    如何实现C语言访问MCU寄存器

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。
    发表于 03-08 06:33

    C语言访问MCU寄存器的方法

    C语言访问MCU寄存器问题由来://下面这行代码的意思是直接操作0X020C4068这个
    发表于 11-01 08:03

    C语言是如何访问MCU寄存器

    C语言访问MCU寄存器的三种方式MCU中的特殊功能
    发表于 11-03 08:42

    C语言访问MCU寄存器用两种方式实现

    ICCAVR和GCCAVR没有定义新的数据类型,只能采用标准C的强制类型转换和指针来实现访问MCU寄存器。而IAR和CodeVisionAVR编译
    的头像 发表于 03-12 11:20 6699次阅读

    C语言访问MCU寄存器的两种方式

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。
    发表于 04-11 06:01 10次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>访问</b><b class='flag-5'>MCU</b><b class='flag-5'>寄存器</b>的两种<b class='flag-5'>方式</b>

    C语言访问MCU寄存器

    C语言访问MCU寄存器问题由来://下面这行代码的意思是直接操作0X020C4068这个
    发表于 10-25 13:21 3次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>访问</b><b class='flag-5'>MCU</b><b class='flag-5'>寄存器</b>

    C语言访问MCU寄存器的三种方式

    C语言访问MCU寄存器的三种方式 MCU中的特殊功
    发表于 10-28 17:21 11次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>访问</b><b class='flag-5'>MCU</b><b class='flag-5'>寄存器</b>的三种<b class='flag-5'>方式</b>

    如何实现C语言访问MCU寄存器?掌握这两种方式就够了!

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来两种方法。1、采用标准
    发表于 11-21 19:21 14次下载
    如何实现<b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>访问</b><b class='flag-5'>MCU</b><b class='flag-5'>寄存器</b>?掌握这两种<b class='flag-5'>方式</b>就够了!

    C语言寄存器操作

    C语言寄存器操作
    发表于 01-13 12:56 6次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>:<b class='flag-5'>寄存器</b>操作