AVR1000XMEGA的C语言代码编写入门

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

8-bit 8位
Microcontrollers 微处理器
Application Note 应用注释
AVR1000: Getting Started Writing C-code for XMEGA
AVR1000 : XMEGA的C语言代码编写入门
Features
特点:
•Naming conventions
命名约定
- Register names
寄存器名
- Bit names
位名
•C-code names
C-代码名
- Bit and group masks
位与组掩码
- Group configuration masks
组配置掩码
•Methods for accessing registers
访问寄存器的方法
•Methods for writing reusable module functions
可多次使用模块功能的写入方法
1 Introduction
引言
Short development times and high quality requirements on electronic products has made high-level programming languages a requirement. The main reason is that High level languages make it easier to maintain and reuse code due to better portability and readability.
由于电子产品的开发时间短,质量要求高,因此需要高层次的编程语言。

最主要的原因是,高级语言具有更好的可移植性和可读性,使其更易于维护和重复使用代码。

The choice of programming language alone does not ensure high readability and reusability; good coding style does. Therefore the XMEGA™ peripherals, header files and drivers are designed with this in mind.
编程语言的选择本身并非是能确保具有较高的可读性和可重复使用性的唯一条件,还必须有良好的编码风格。

因此XMEGA ™的外围设备,头文件和驱动程序的设计都是基于这方面考虑的。

The most widely used high-level language for AVR®microcontrollers is C, and this application note therefore focuses on C programming. To support most of the AVR C compilers that are available, the code examples are as far as possible written in ANSI C. A few examples are specific to IAR Embedded Workbench®, but the ideas and methods can be used for other compilers with minor changes. IAR specific examples are clearly marked.
AVR ®微控制器使用的最广泛的高级语言就是 C 语言,因此本应用注释的重点是 C 语言编程。

为了支持大多数可用的 AVR C 语言编译器,我们尽可能把代码示例编写在 ANSI C 语言的规中。

有些例子是 IAR Embedded Workbench®专用的,但其思路和方法可用于与其他变化不大的编译器。

IAR 专用的示例都有清晰的标示。

2 XMEGA Modules
XMEGA 模块
An AVR XMEGA is composed of several building blocks: An AVR CPU core, SRAM, Flash, EEPROM and a number of peripheral modules. These building blocks are called “module types”. An XMEGA can have one or more instances of a given module type. All instances of a module type have the same features and functions.
一个 AVR XMEGA 由数个结构块组成:一个AVR CPU 芯片,一个 SRAM,一个闪存,一个 EEPROM 以及若干外设模块。

这些结构块被称为“模块类型”。

XMEGA可以有一个或多个给定模块类型的实例。

一个模块类型的所有实例都具有相同的特性和功能。

Some module types can be a subset of other module types. These inherit a subset of the features (and registers) of the super type, all inherited features are fully compatible. This applies to e.g. timers and IO ports. The subset of a module type can for a timer mean that it has fewer compare and capture channels than a full timer module. Similarly, an IO port may have less than eight pins.
有些模块类型可以是其他模块类型的子集。

这些(模块类型)继承了特大模块类型的某个子集的特征(和寄存器),其继承的所有特征都完全兼容。

这适用于比如计时器和IO端口。

用于计时器的模块类型的子集可能意味着它所能得到的比较和捕获通道比完整的计时器模块的要少。

同样,一个 IO 端口的管脚可能不足八个。

A module type can be a “USART”, while the module instance is e.g. “USARTC0”, where the “C0” suffix indicates the instance is “USART number 0 on port C”. For simplicity, a module instance will be referred to as a module throughout this document, unless there is a need to differentiate.
一个模块类型可以是“USART”的,如果这个模块实例比如是“USARTC0”,其中的“C0”后缀表示这个实例是“端口 C 上的 USART 编号为 0”。

为了简单起见,一个模块实例将被称为这整个文件中的一个模块,除非是有必要另作区分。

Each module has a number of registers that contain control or status bits. All modules of a given type contain the same set (or subset) of registers, and all these registers contain the same set (or subset) of control and status bits.
每个模块都有若干寄存器,这些寄存器都包含控制位或状态位。

一个给定类型的所有模块都包含相同的寄存器集合(或子集),并且所有这些寄存器包含相同的控制位和状态位的集合(或子集)。

Figure 2-1. Module types, instances, registers and bits.
图2-1. 模块类型,实例,寄存器和位
Each module has a fixed base address in the IO memory map and all registers contained in the module have fixed offset addresses relative to the module base address. This way each register will not only have an absolute address in the IO memory space, but also a relative address defined by its offset. The register offset addresses are equal for all instances of a module type, simplifying the task of writing drivers that can be used for all modules of a specific type.
在 IO 存图里,每个模块都有一个固定的基础地址,并且该模块中的所有寄存器都有固定的偏移地址(这是相对于模块的基地址而言)。

如此这样,每个寄存器不仅会在 IO 存空间有一个绝对地址,而且还有一个根据其偏移量定义的相对地址。

一个模块类型的所有实例中的寄存器偏移地址都是平等的,这样就简化了编写能够适用于某个特定类型的所有模块的驱动程序的任务。

2.1 Register Naming Convention
2.1. 寄存器命名约定
Register are roughly speaking divided into control, status and data registers and the naming of registers reflect this. A general-purpose control register of the module is named CTRL. If multiple general-purpose control registers exists in a module they have a suffix character. In this case the control registers would be named CTRLA, CTRLB, CTRLC and so on. This also applies to STATUS registers.
大致说来,寄存器有控制寄存器、状态寄存器和数据寄存器之分,这从寄存器的命名就可看出。

模块的一个通用的控制寄存器被命名为CTRL。

如果在一个模块中存在多个通用控制寄存器,他们都有一个后缀字符。

在这种情况下,
控制寄存器将被命名为CTRLA 、 CTRLB 、 CTRLC等。

这方法也适用于状态寄存器。

For registers that have a specific function the name reflects this functionality. For example, a control register that controls the interrupt level of a module is named INTCTRL.
对于具有特定功能的的寄存器,它们的命名会反映其功能性。

例如,一个控制寄存器,控制一个模块的中断级别,它就被命名为 INTCTRL 。

Since the AVR data bus width is 8 bit, larger registers are implemented using several 8-bit registers. For a 16-bit register, the high and low bytes are accessed by appending “H” and “L” respectively to the register name. For example, the 16-bit Timer/Counter count register is named CNT. The two bytes are named CNTL and CNTH.
由于 AVR 的数据总线宽度为 8 位,较大的寄存器得使用几个 8 位寄存器才能生效。

对于一个16位寄存器,要访问其高8位元组和低8位元组,得在这个寄存器的命名上分别附加“H”和“L”。

例如,16位计时器/计数器的计数寄存器被命名为CNT ,其两个8位元组就被命名为 CNTL和 CNTH 。

For a register larger than 16 bit, the bytes are numbered from the least significant byte. For example, the 32-bit ADC calibration register is named CAL. The four bytes are named CAL0, CAL1, CAL2 and CAL3 (from least to most significant byte).
对于大于16位的寄存器,其8位元组的编号是从最低有效的8位元组开始。

例如,32位的 ADC 校准寄存器被命名为CAL,其四个8位元组(从最低到最高有效8位元组)就被分别命名为 CAL0 , CAL1 , CAL2 和 CAL3 。

Most C compilers offer automatic handling of access to multi-byte registers. In that case the name CNT, without “H” or “L” suffix, could be used to perform a 16-bit access to the Timer/Counter count register. This is also the case for 32-bit registers.
大多数 C 语言编译器都提供了自动处理多8位元组寄存器的访问。

在这种情况下, CNT 的命名没有加“ H”或“ L”后缀的,可以用来执行16位的计时器/计数器的计数寄存器的访问。

这方法也同样使用于32位寄存器。

2.2 Bit Naming Convention
2.2 位命名约定
Register bits can have an individual function or be part of a bit group that have a joint function: An individual bit could be a bit that enables a module, e.g. the USART ENABLE bit. A bit group can consist of two of more bits that jointly select a specific configuration of the module that they belong to. A bit group offers up
to 2n selections, where n is the number of bits in the bit group. The two bits that control the USART Receive
Complete interrupt level, RXINTLVL[1:0], is an example of a bit group. These two bits offer the following selections:
寄存器位可以有一个单独的函数,或是一个位组的一部分,有一个共同的功能:一个单独的位可以是启用一个模块的位,如 USART ENABLE 位。

一个位组可以由两个或两个以上的位组成,这些位共同选择了它们所属的模块的特殊配置。

一个位组提供多达 2n 个选项,其中的 n 是位组中位的数量。

这两个位控制的 USART 接收结束中断级别,RXINTLVL [1:0 ] ,是一个位组的一个例子。

这两个位提供以下选项:
Table 2-1. RXINTLVL bits and corresponding interrupt level selection.
表 2-1. RXINTLVL 位和相应的中断级别选项
Bits that are part of a group will always have a number suffix. Bits that are not part of a bit group will never have a number suffix. A Timer/Counter control register D has two bit groups, EVACT and EVSEL. The bits in these groups have a number suffix, while the EVDLY bit, which is not part of a bit group has no number suffix.
作为一个组的一部分的位,将始终有一个数字后缀。

不是一个位组的一部分的位,永远不会有一个数字后缀。

计时器/计数器控制寄存器 D 有两个位组: EVACT 和 EVSEL 。

在这些组中的位都有一个数字后缀,而 EVDLY 位不是一个位组的一部分,因此它没有数字后缀。

Table 2-2. Bits groups and bit names for bits in Timer/Counter Control register D – CTRLD.
表 2-2. 适用于计时器/计数器控制寄存器 D - CTRLD 中的位的位组和位名称
3 Writing C-code for XMEGA
编写 XMEGA 的 C 语言代码
The following sections focus on how to write C-code for the XMEGA. The examples show how to make the code highly readable and portable between different XMEGA devices. The examples can also be used as a guideline to write code that is easy to verify and maintain.
以下各节重点放在如何编写 XMEGA 的 C 语言代码。

示例显示了如何使代码具有很强的可读性,并能在不同的XMEGA 器件之间移植。

这些例子也可以作为指导编写代码的准则,使其易于验证和维护。

XMEGA modules are located in dedicated and continuous blocks in the memory space and can be seen as encapsulated units. This reflects on the way that the modules are accessed when coding C: modules are encapsulated using C structs, in which all module registers are contained. Figure 3-1 shows an illustration of this. XMEGA的模块位于存空间的专用的连续的块区域中,我们可以把这些模块看作是被封装的单元。

这反映了编写 C 语言代码时访问模块的路径:模块是用 C 语言结构封装的,其中包容了所有的模块寄存器。

图3-1给出了这个图解。

Note that some registers have no direct module association. These are not encapsulated in structs, as the
struct is used to associate registers with a module.
请注意,某些寄存器没有直接的模块相联,这些寄存器都不是封装在结构里的,因为该结构是用来使寄存器与某个模块相关联的。

For larger code projects the module structs provide advantages, not only to readability, but also because the compilers can reuse the module drivers and thereby make the code very compact. This is described in more details later.
模块结构为较大的代码项目提供的优势不仅具有可读性,而且还因为编译器可以重复使用模块驱动程序,从而使代码非常紧凑。

这在后面会作更详细的描述。

This document introduces a naming convention and register access methods that are different from what AVR programming veterans are used to, but one should be aware that the “classic” way to access registers is still supported by the header files. This also applies on the bit level.
本文档介绍的命名约定和寄存器访问的方法,不同于 AVR 编程老手过去常用的方法,但是有一点应该知道:访问寄存器的“经典”方法仍然是要得到头文件的支持。

这方法也同样适用于对位级别的访问。

Figure 3-1. Modules placed in dedicated blocks in IO memory space.
图3-1 .放置在 IO 存空间里的专用块区的模块。

3.1 XMEGA Header Files
3.1 XMEGA的头文件
A dedicated header file is available for each XMEGA device. If the target device is specified in the project settings (assuming that one uses the IDE for IAR EWAVR), the IAR compiler will automatically include the correct header file if the device file is included as shown in Code Listing 3-1.
为每个XMEGA的设备提供一个专用的头文件,如果目标设备是在项目设置中指定的(假设一个目标设备将 IDE 用于IAR EWAVR ),又如果该设备文件是包含在如代码列表3-1中所示的文件,那么 IAR 编译器将自动包含这个正确的头文件。

Code Listing 3-1. IAR header file inclusion.
代码列表3-1 . IAR的头文件包含
The advantage is that if the target device changes, there is no need to change the source files, only the project settings.
它的优点是,如果目标设备变了,没有必要修改源文件,唯有以项目设置的为准。

3.2 Modules Registers
3.2. 模块寄存器
The IO map is laid out so that all registers for a given peripheral module are placed in one continuous memory block. Registers belonging to different modules are not mixed. This makes it possible to organize all peripheral modules in C structs, where the address of the struct defines the base address, of the module. All registers belonging to a module are elements in the module struct.
IO 地图的设计是使一个给定的外设模块的所有的寄存器都放置在一个连续的存块,属于不同模块的寄存器不得混合。

这使得IO 地图可以将所有外设模块组织到 C 语言结构中,其结构的地址定义模块的基础地址,同属于一个模块的所有的寄存器都是这个模块结构中的成员。

An example is the Programmable Multi-level Interrupt Controller (PMIC) module. The struct declaration for this module is shown in Code Listing 3-2 and an example of its use in Code Listing 3-3. Note that the example in Code Listing 3-3 assumes that there is an instance of the PMIC_t type named PMIC. This is covered later in this document.
一个例子是可编程的多级中断控制器( PMIC )模块。

申报此模块的结构由代码列表 3-2 给出,其用途的例子由代码列表 3-3 给出。

请注意,在代码列表 3-3 中的例子是假设有一个 PMIC_t 类型的实例被命名为PMIC。

这在本文档后面还有提及。

Code Listing 3-2. Module struct declaration.
代码列表 3-2. 模块结构的申报
Code Listing 3-3. Module struct usage.
代码列表 3-3. 模块结构的用途
3.2.1 Multi-word Registers in Module Structs
3.2.1. 模块结构中的多词寄存器
Some registers are used in conjunction with other registers to represent 16 or 32 bit values. As example one could look at the ADC struct declaration shown in Code Listing 3-4.
将一些寄存器与其他寄存器一起用来代表16位或32位的值。

我们可以举一个例子,看看 ADC 结构申报的一个寄存器,见代码列表3-4:
Code Listing 3-4. ADC struct declaration.
代码列表3-4. ADC 结构申报
In Code Listing 3-4, the ADC channel result registers CH0RES, CH1RES, CH2RES, CH3RES and the compare register, CMP, are 16-bit values. These are declared using the WORDREGISTER macro shown in Code Listing 3-5. The calibration register, CAL, is a 32-bit value, declared using the DWORDREGISTER shown in Code Listing 3-6.
在代码列表3-4中, ADC通道的结果寄存器CH0RES , CH1RES , CH2RES , CH3RES和比较寄存器CMP都是16位值。

这些寄存器都是用在代码列表 3-5 中所示的 WORDREGISTER 宏申报的。

校准寄存器CAL,是一个32位值的,它是用在代码列表3-6中所示的 DWORDREGISTER 宏来申报的。

Code Listing 3-5. WORDREGISTER Macro.
代码列表 3-5. WORDREGISTER 宏
Code Listing 3-6. DWORDREGISTER Macro.
代码列表3-6. DWORDREGISTER 宏
As seen, the WORDREGISTER macro uses “H” and “L” suffix for the high and low bytes respectively. The DWORDREGISTER uses number suffix to indicate the byte order. Both the 16-bit and 32-bit registers can be accessed in 16-bit/32-bit mode, by using the register name without suffix as shown in Code Listing 3-7.
如我们所看到的, WORDREGISTER宏使用后缀“H”和“L” 分别作为高8位元组和低8位元组, DWORDREGISTER 使用数字后缀来表示8位元组的顺序。

在16/32位模式中,都可以使用不带后缀的寄存器名访问16位和32位寄存器,见代码列表3-7。

Code Listing 3-7. Accessing registers of varying size.
代码清单3-7 。

访问不同大小的寄存器。

Code Listing 3-7 shows how the single byte register CTRLA is read, how the two CH0RES[H:L] registers are read using a 16-bit operation, and how the four CAL[3:0] registers are read in a 32-bit operation. C compilers handle multi-byte registers automatically. Note however that in some cases it may be required to read and write multi-byte registers in one atomic operation to avoid corruption. In this case, interrupts must be disabled during the multi-byte access to make sure that an interrupt service routine does not interfere with the multi-byte access. AVR1306 includes examples on how atomic access of registers is done for the XMEGA Timer/Counter modules.
代码列表3-7演示了如何读取单个8位元组寄存器CTRLA,如何使用一个16位的操作来读取两个 CH0RES [ H:L] 寄存器,以及如何在32位的操作中读取四个 CAL [3:0] 寄存器。

C 语言编译器会自动处理多个8位元组的寄存器。

但是请注意,在某些情况下可能要求在一个原子操作中读写多个8位元组的寄存器,以避免讹误。

假如这样的话,在多个8位元组的访问期间必须禁止中断,以确保一个中断服务例程不妨碍多个8位元组的访问。

AVR1306中有些例子是关于寄存器是如何对XMEGA的计时器/计数器模块进行原子访问的。

3.3 Module Addresses
3.3 模块访问
Definitions of all peripheral modules are found in the device header files available for the XMEGA. The address for the modules is specified in ANSI C to make it compatible with most available C compilers. Code Listing 3-8 shows how ADC 0 on port A is defined.
在适用于XMEGA设备的头文件中找到所有外设模块的定义。

这些模块的地址在ANSI C 语言标准中作了明确的规定,使其与大多数可用的 C 语言编译器兼容。

代码列表 3-8 显示了端口 A 上的 ADC 0 是如何定义的。

Code Listing 3-8. Peripheral module definition.
代码列表 3-8. 外设模块的定义
Code Listing 3-8 shows how the module instance definition uses a dereferenced pointer to the absolute address in the memory, coinciding with the module instance base address. The module pointers are pre-defined in the XMEGA header files, it is therefore not necessary to add these definitions in the source code
代码列表3-8显示模块实例定义如何使用一个被解除引用的指针指向存中的绝对地址,正好与模块实例的基础地址重合。

模块指针是在 XMEGA 的头文件中预先定义的,因此没有必要在源代码中添加这些定义。

3.4 Bit Masks and Bit Group Masks
3.4 位掩码和位组掩码
Register bits can be manipulated using pre-defined masks, or alternatively bit positions. Bit positions are
not recommended for most tasks. The pre-defined bit masks are either related to individual bits, called a bit mask or a bit group, called a bit group mask, or group mask for short.
寄存器的位可以使用预先定义的掩码,或另一个位的位置,进行操作,但大多数任务中并不推荐使用位位置。

预先定义的位掩码可以与独立的位有关,称之为位掩码;或与一个位组有关,称之为位组掩码,或简称组掩码。

A bit mask is used both when setting and clearing individual bits. A bit group mask is mainly used when clearing multiple bits in a bit group. Setting multiple bit that are part of a bit group is covered in section 3.5. 一个位掩码是在设置和清除独立的位时使用,一个位组掩码主要是用在清除一个位组中的复合位时使用。

在3.5节中,介绍了复合位(作为一个位组的一部分)的设置。

3.4.1 Bit Mask
3.4.1 位掩码
Consider a Timer Counter Control Register D, CTRLD. The bit groups, bit names, bit positions and bit masks of this register can be seen in Table 3-1.
细心观察一个计时器计数器控制寄存器D,CTRLD,在表3-1中我们可以看到该寄存器的位组、位名称、位位置以及
位掩码。

Table 3-1. Bit groups, bit names, bit positions and bit masks for bits in Timer Counter Control register D – CTRLD.
表3-1. 计时器计数器控制寄存器D-CTRLD里的位的位组、位名称、位位置以及位掩码
Since the names of bits need to be unique for the compiler to handle them, all bits are prefixed with the module type it belongs to. In many cases, the module type name is abbreviated. For all bit defines related to the Timer/Counter modules, the bit names are prefixed by “TC_”.
由于位的名称相对于处理它们的编译器而言必须是唯一的,所有的位都是用其所属的模块类型作前缀。

在许多情况下,模块类型名称是缩写的。

对于所有与计时器/计数器模块有关的位的定义,其位名称的前缀是“ TC_ ”
To differentiate between bit masks and bit positions, a suffix is also appended. For a bit mask, the suffix is “_bm”. The name of the bit mask for the EVDLY bit is thus TC_EVDLY_bm. Code Listing 3-9 shows the typical usage of a bit mask. The EVDLY bit in the CTRLD register of Timer/Counter D0 is set, leaving all the other bits in the register unchanged.
要区分位掩码和位的位置,还得附加一个后缀。

对于一个位掩码,其后缀是“ _bm ” 。

因此 EVDLY位的位掩码的名称是 TC_EVDLY_bm 。

代码列表 3-9 显示了一个位掩码的典型用法。

将EVDLY位在计时器/计数器 D0的 CTRLD 寄存器中作了设置,让该寄存器的所有其它的位保持不变。

Code Listing 3-9. Bit mask usage.
代码列表 3-9. 位掩码的用法
3.4.2 Bit Group Masks
3.4.2 . 位组掩码
Many functions are controlled by a group of bits. Timer Counter CTRLD register the EVACT[2:0] and the EVSEL[3:0] bits are grouped bits. The value of the bits in a group selects a specific configuration.
许多功能是受一组位来控制的,计时器计数器CTRLD寄存器里的EVACT [2:0]位和EVSEL [3:0]位是被分组的位,一组的位值选择一个特定的配置。

When changing bits in a bit group it is often required to clear the bit group before assigning a new value. To put it in another way: It is not enough to set the bits that should be set, it is also required to clear the bits that should be cleared. To make this easy a bit group mask is defined. The group mask uses same name as the bits in the bit group and is suffixed “_gm”.
当改变一个位组的位时,通常要求先清除该位组后方可分配一个新的值。

换句话说:由于不够设置应设置的位,所以还需要清除应清除的位。

为了简单起见,我们对一个位组掩码进行定义,该组掩码采用的名称与该位组中的位名相同,并且加后缀“ _gm ” 。

Code Listing 3-10 shows how the group mask relates to the bit masks. In reality, the group mask values are pre-calculated in the header files, so the compiler does not need to calculate the same constant over and over again.
代码列表3-10显示了如何使组掩码与位掩码有联系。

实际上,组掩码值是在头文件中预先计算的,所以编译器并不需要一遍又一遍地对相同的常量再作计算。

Code Listing 3-10. Group mask and bit mask relation.
代码列表3-10. 组掩码与位掩码的关联
The bit group mask is primarily intended to clear the old configuration of a bit group before writing a new value. Code Listing 3-11 shows how this can be done. The code will clear the EVACT bit group in the CTRLD register of Timer/Counter D0. This construct is not very useful in itself. The group mask will typically be used in conjunction with a group configuration mask, which is covered in section 3.5.
首先,位组掩码是要在写入一个新值之前先将一个位组的老的配置清除掉,代码列表3-11显示了如何可以做到这一点。

代码将清除掉在计时器/计数器D0 的 CTRLD 寄存器里的 EVACT 位组。

这种构造本身并不是很实用的。

组掩码通常会与一个组配置掩码一起使用,这在3.5节中会涉及到。

Code Listing 3-11. Group mask usage.
代码列表3-11. 组掩码用途
3.5 Bit group Configuration Masks
3.5. 位组配置掩码
It is often required to consult the datasheet to investigate what bit pattern needs to be used when setting a bit group to a desired configuration. This also applies when reading or debugging code. To increase the readability and to minimize the likeliness of setting bits in bit groups incorrectly, a number of group configuration masks are made available. Each group configuration mask selects a configuration for a specific group mask.
当你想把一个位组设置成某种理想配置状态时,通常要查阅数据表,研究需要使用什么样的位图。

在阅读代码或调试代码时,这种方法也同样适用。

为了提高可读性,并尽量减少不正确的设置位组的位的可能性,有许多组配置掩码可用,每个组配置掩码为一个特定组掩码选择一个配置。

The name of a group configuration mask is a concatenation of the module type, the bit group name, a description of the configuration and a suffix, “_gc”, indicating that this is a group conf iguration. See Figure 3-2 for an example.
一组配置掩码的名称是一连串的模块类型、位组名、配置的说明以及后缀“ _GC ” ,表明这是一个组配置。

请参见图3-2的一个例子。

Figure 3-2. Group configuration name composition (using USART receive complete interrupt level bits as example).
见图3-2. 组配置名的构成(用USART接收完成中断级位作为实例)
Inspecting the group configuration Figure 3-2, one can see that it is used to select a configuration for the RXCINTLVL bits in a USART module. This specific group configuration selects a high (HI) interrupt level. 通过仔细查看组配置图3-2 ,我们可以发现这是用来为一个USART模块中的 RXCINTLVL 位选择一个配置的。

这个特定组的配置选择的是高(HI)中断级别。

The bit group for the Receive Complete Interrupt Level consists of two bits, RXINTLVL[1:0]. Table 3-2 shows the available group configurations for this bit group.
接收完成中断级的位组由两个位 RXINTLVL [1:0] 组成。

表3-2显示了此位组的可用的组配置。

The configuration names are “OFF”, “LO”, “MED” and “HI”. These names make it very easy to write and maintain code, as it requires very little effort to understand what configuration the specific configuration mask selects.
配置名称是“OFF”,“LO” ,“MED”,“HI” 。

这些名称使得编写和维护代码变得很容易,因为这样你无需太费力就能知道特定配置掩码选择什么样的配置。

Table 3-2. RXINTLVL bits and corresponding interrupt level of module interrupt.
表3-2. RXINTLVL 位与相关模块中断的中断级别
To change a bit group to a new configuration, the bit group configuration is typically used in conjunction with the bit group mask, to ensure that the old configuration is erased first. Code Listing 3-12 shows how the group mask and a configuration mask can be used to reconfigure the USART C0 Receive Complete Interrupt level to medium level.
要改变一个位组到一个新的配置,位组配置通常结合位组掩码使用,以确保首先擦除了旧的配置。

代码列表3-12显示了如何使用组掩码和一个配置掩码来将USART C0接收完成中断优先级重新配置成中等级别。

Code Listing 3-12. Changing a bit group configuration.
代码列表3-12. 改变一个位组配置
Note that though it may be tempting to split the code in Code Listing 3-12 into two separate code lines, one that clear the bit group and one that sets the new value, this is not recommended. Since the INTCTRL register is defined as volatile, two separate code lines will trigger reading and writing the INTCTRL register twice instead of once. In addition to making the code inefficient, this can put the peripheral in an unintended state.
请注意,尽管这里可能是引诱你将代码列表3-12中的代码分裂成两个不同的代码行,其中一行是用来清除该位组,另一行是用来设定新的值,但是我们不建议这样做。

由于INTCTRL寄存器被定义为volatile(可变的),因此,两个不同的代码行会触发读写这个INTCTRL寄存器两次而不是一次。

此外,还会使此代码效率低下,这样有可能将外围设备置于非预期的状态中。

The use of group masks to clear bits is not always required. Code Listing 3-13 shows how all interrupt levels of USARTC0 can be configured at the same time. Receive Complete, Transmit Complete and USART Data Register Empty interrupt levels are set to MEDIUM, OFF and LOW interrupt levels respectively.
并不总是需要用组掩码清除位的,代码列表3-13显示USARTC0的所有中断级别是如何可以在同一时间进行配置的。

接收完成、发送完成以及USART数据寄存器空中断级别分别被设置为MEDIUM(中等)、OFF(关闭)以及 LOW(低)的中断优先级。

Code Listing 3-13. Setting all configurations in a register at the same time.
代码列表3-13. 对一个寄存器里的所有配置在同一时间进行设置
3.5.1 Enumeration of Group Configuration masks
3.5.1 组配置掩码的枚举
Unlike bit masks and group masks, the bit group configuration masks are defined using C enumerators. One enumerator is defined for each bit group. The enumerator for the USART RXCINTLVL bit group is shown in Code Listing 3-14.
不同的位掩码和组掩码,其位组配置掩码是用 C 语言枚举符定义的,为每个位组定义一个枚举符。

代码列表3-14 给出了用于 USART RXCINTLVL 位组的枚举符。

Code Listing 3-14. USART RXCINTLVL enumerator
代码列表3-14. USART RXCINTLVL的枚举符
As seen in Code Listing 3-14, the name of the enumerator is a concatenation of the module type (USART), the bit group (RXCINTLVL) and a suffix (_t) that indicates that this is a data type.
代码列表3-14中可以看出,枚举符的名字是一连串的(USART)模块类型,位组(RXCINTLVL)和后缀(_t),表明这是一种数据类型。

Each of the enumerator constants behaves much like a normal constant when used on its own. However, using an enumerator has the advantage that it creates a new data type. USART_RXCINTLVL_t can be used as a type name, just like an int or char. An enumerator constant can be used directly as integer, but assigning an integer to an enumerator type will trigger a compiler warning. This can be used to the programmers advantage. Imagine a function that sets the receive complete interrupt level for a USART module. If the function accepts the interrupt level as an integer type (e.g. unsigned char), any legal or illegal value can be passed to the function. If the function instead accepts a parameter of type USART_RXCINTLVL_t, only the four pre-defined constants in the USART_RXCINTLVL_t enumerator can be passed to the function. Passing anything else will result in a compiler warning.
每个枚举符的常量单独使用时,其表现很像是一个普通的常数。

然而,使用枚举符的优点在于创建一个新的数据类型。

USART_RXCINTLVL_t 就像是一个int或char 那样,可以作为一个类型名使用。

一个枚举符常数完全可以作为整数使用,但是把一个整数赋给一个枚举符类型,将会触发一个编译器警告。

这可能是习惯了程序员的优势的缘故。

试想一个函数设置一个USART模块接收完成中断级别,如果此函数接受中断级别为整数类型(如无符号的字符),那么任何合法的或非法的值都可以传递给此函数;如果此函数改为接受USART_RXCINTLVL_t类型的参数,那么可以传递给此函数的就只有4个预先在USART_RXCINTLVL_t枚举符中定义的常量。

除此而外,给此函数传递任何其它参数都将会导致编译器警告。

Notice that the constants in Code Listing 3-14 are shifted to the actual bit position. This means that the enumerator contstants are the actual values that shall be written to the register. No additional shifting is needed.
请注意,在代码列表3-14中的常量被转移到当前的位位置,这意味着枚举符常量就是应写入该寄存器的当前值,无需额外的转移。

3.6 Functions Calls and Module Drivers
3.6 函数调用与模块驱动程序
When writing drivers for module types that have multiple instances, the fact that all instances have the same register memory map, can be utilized to make the driver reusable for all instances of the module type. If the driver takes a pointer argument, pointing to the relevant module instance, the driver can be used for all modules of this type. When considering portability this represents a great advantage.。

相关文档
最新文档