单片机寄存器访问的两种方法
mouser 2021-02-18

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

1、采用标准C的强制类型转换和指针来实现

采用标准C的强制转换和指针的概念来实现访问MCU的寄存器,例如:
#define DDRB (*(volatile unsigned char *)0x25)

分析如下:

A:(unsigned char *)0x25中的0x25只是个值,前面加(unsigned char *)表示0x25是个地址,而且这个地址所存储的数据的数据类型是unsigned char,意思就是说读/写这个地址时,要写进unsigned char的值,读出也是unsigned char的值。

(*(volatile unsigned char *)0x25)是一个固定的指针,是不可变的,而不是指针变量。再在前面加"*",即*(volatile unsigned char *)0x25则变成了变量(普通的unsigned char变量,不是指针变量),如果是#define i (*(volatile unsigned char *)0x25),则与unsigned char i是一样的,只不过前面i的地址是固定的。

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

这样读/写以0x25为地址的SRAM单元,直接书写DDRB即可,即DDRB为变量,只不过变量的地址固定为0x25。例如:

DDRB = 0xff;
这样比直接采用指针变量的方法直观和方便的多,例如:
unsigned char *p, i;
p = 0x25;
i = *p; //把地址为0x25单元中的数据读出送入i变量
*p = 0; //向地址为0x25的单元中写入0

总结一下,就是(*(volatile unsigned char *)0x25)可以看作是一个普通变量,这个变量哟固定的地址,指向0x25。而0x25只是个常量,不是指针,更不是变量。

2、对C编译器进行语法扩充

对C编译器进行语法扩充。例如MCS51系列KeilC中扩充sfr关键字,举例如下:
sfr P0 = 0x80;
这样操作0x80单元直接写P0即可。

下面对AVR的歌C编译器对访问MCU寄存器的方法进行简介。

A:采用标准C的强制类型转换和指针来实现访问MCU的寄存器,每一个C编译器都支持,原因很简单,这是标准C。

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

SFR_B(DDRB, 0x28)
CodeVisionAVR中:
sfrb DDRB = 0x28

这样,PORTB=0xff;等同于(*(volatile unsigned char *)0x05) = 0xff;而0x25正好是寄存器PORTB在器件ATmega48/88/168中的地址。

GCCAVR每个AVR器件在头文件不采用直接定义特殊功能寄存器宏,例如在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))
实质上与直接的强制类型转换和指针定义是一样的。

另外,GCCAVR中宏_BV(bit)是操作I/O寄存器是频繁用到的,avr-libc建议使用这一宏进行寄存器的位操作,他在文件sfr_defs.h中定义如下:
#define _BV(bit) (1

以下是他的使用示例;

DDRB = _BV(PB0) | _BV(PB1); //器件头文件中已经定义PB0代表0,PB1代表1
他等同于“DDRB=0x03;”,这样写的目的是为了提供程序的可读性。不要担心它会生成比“DDRB=0x03;”更大的代码,编译器会处理这种事情,最终会输出与“DDRB=0x03;”同样的结果。

本文转载自:
转载地址:
声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有,如涉及侵权,请联系小编进行处理。

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
热门推荐
  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
  • 让LED 小灯按500毫秒闪烁起来

    推广一种全新的c51单片机编程技巧,特别适合少儿及c语言基础较差的电子爱好者做编程启蒙教学,培养小孩对编程的兴趣。当然也适合我们这种没有c语言基础的老年朋友玩转c51单片机。      如果,想看到更多的类似文章,请打开公众号点击“关注”。就会收到后续的

    02-08
  • 什么是“时序”?LCD1602时序参数表解析

    所谓“时序”从字面意义上来理解,一是“时间问题”,二是“顺序问题”。 先说“顺序问题”,这个相对简单一些。我们在学 UART 串口通信的时候,先 1 位起始位,再 8 位数据位,最后 1 位停止位,这个先后顺序不能错。我们在学 1602 液晶的时候,比如写指令,

    02-20
  • 如何在STM32中配置PWM死区时间

    什么是死区时间? PWM是脉冲宽度调制,在电力电子中,最常用的就是整流和逆变。这就需要用到整流桥和逆变桥。 对三相电来说,就需要三个桥臂。以两电平为例,每个桥臂上有两个电力电子器件,比如IGBT。大致如下图所示; 这两个IGBT不能同时导通,否则就会出现

    02-22
  • 单片机程序防破解的一些建议

    公司或者个人辛辛苦苦开发的程序,肯定谁都不想被人轻易破解并利用,下面为大家分享单片机破解,以及防止破解的。 0 1 单片机解密是什么? 单片机解密又叫做单片机破解、芯片解密、IC解密等,但是这严格说来这几种称呼都不科学,但已经成了习惯叫法,我们把CP

    01-19
  • 在STM32中选用怎样选择I/O模式?

    STM32的GPIO介绍 STM32引脚说明 GPIO是通用输入/输出端口的简称,是STM32可控制的引脚。GPIO的引脚与外部硬件设备连接,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 STM32F103ZET6芯片为144脚芯片,包括7个通用目的的输入/输出口(GPIO)组

    01-19
  • RT-Thread遵循的许可协议,以及如何提交了一个完整的BSP?

    RT-Thread今天的快速发展和所取得成绩,离不开所有开发者的持续贡献和社区小伙伴的竭力支持。 一、前言 今年6月,我在一款智能混合型的FPGA芯片上,完成了RT-Thread的移植,并向RT-Thread提交了一个完整的BSP,后续又根据审查意见进行了一些完善,最近(11.18

    2020-12-01
  • 为什么有些CPU的主频更低,但运算效率却更高呢?

    为什么有些CPU的主频更低,但运算效率却更高呢? 比如:51单片机30M主频,STM32单片机20M主频,执行相同一段代码可能主频更低的STM32所花的时间更短。 这里就牵涉到CPU流水线的问题,本文围绕CPU流水线描述相关内容。 一、早期CPU流水线 1.流水线来源 流水线

    2020-10-19
  • 究竟是什么让很多单片机的工作电压是5V?

    5V来自于TTL电平,5呢为True,0即为False,之后用了压降更低的PN节,衍生出了3.3这个电平。 12V和24V来自于汽车电瓶,早年乘用车又12V和24V两个系统,现在一般小型车12V,商用车24V,再究其由来应该是铅酸电池。 所以3v3和5v一般出现在信号电路或者单片机等vc

    2020-10-19
  • 没想到,CRC校验原来这么简单

    由于公众号申请的时间比较晚,所以没有留言互动功能,最近公众号上线了读者讨论功能,和留言差不多,对本篇文章有什么感想的都可以到文章末尾留言评论。 目录 前言 CRC算法简介 CRC计算 CRC校验 CRC计算的C语言实现 CRC计算工具 总结 前言 最近的工作中,要实

    2020-11-09
  • 解决串口传输“阻塞”问题的方案

    本文在探讨传统数据收发不足之后,介绍如何使用带FIFO的串口来减少接收中断次数,通过一种自定义通讯协议格式,给出帧打包方法;之后介绍一种特殊的串口数据发送方法,可在避免使用串口发送中断的情况下,提高系统的响应速度。 1.简介 串口由于使用简单,价格

    2020-09-17
  • 嵌入式 Linux 的一切,看这一篇就够了!

    嵌入式Linux是什么 嵌入式Linux跟桌面Linux一样,是一个操作系统。从单片机走过来的童鞋往往习惯于直接控制寄存器,事必躬亲,从零开始实现想要的功能。而在嵌入式Linux的世界里,我们首先要抛弃这个思想,应把它作为最后没办法的办法。 就像我们想要在window

    2020-09-11
  • 单片机高阻态与P0口上拉电阻讲解

    51单片机的时候对P0口必须加上上拉电阻,否则P0就是高阻态,对这个问题可能感到疑惑,为什么是高阻态?加上拉电阻?今天针对这一概念进行简单讲解。 在一个系统中或在一个整体中,我们往往定义了一些参考点,就像我们常常说的海平面,在单片中也是如此,我们

    2020-09-01
下载排行榜
更多
广告