简体   繁体   English

整洁/紧凑的 C 代码,用于在微控制器上使用多个 GPIO 端口

[英]Neat/compact C code for working with multiple GPIO ports on a microcontroller

I'm writing a program where I need to control many output pins on my Atmega4809.我正在编写一个程序,我需要在我的 Atmega4809 上控制许多 output 引脚。 How can I work with these without having to write duplicate code (using loops and arrays for example)?我如何在不必编写重复代码的情况下使用这些代码(例如使用循环和 arrays)?

Instead of doing this...而不是这样做......

PORTA.OUT |= (1 << PIN2);
PORTB.OUT |= (1 << PIN4);
PORTC.OUT |= (1 << PIN1);
PORTD.OUT |= (1 << PIN3);

.. I want to do something like this ..我想做这样的事情

for (int i = 0; i < 4; i++) {
    myPorts[i].OUT |= (1 << myPins[i];
}

I tried to #define all the ports and pins, and putting them in arrays like this: (for context the output pins are connected to rows and columns of an LED_matrix)我试图#define所有端口和引脚,并将它们放在 arrays 中,如下所示:(对于上下文,output 引脚连接到 LED_matrix 的行和列)

#define COL0_PORT PORTF
#define COL1_PORT PORTD
#define COL2_PORT PORTA
#define COL3_PORT PORTB

PORT_t col_ports[] = {COL0_PORT, COL1_PORT, COL2_PORT, COL3_PORT};

When building, I get "initializer element is not constant".构建时,我得到“初始化器元素不是常量”。

Assuming that variables like PORTA have type PORT_t , then you can store pointers to them in an array using this syntax:假设PORTA等变量的类型为PORT_t ,那么您可以使用以下语法将指向它们的指针存储在数组中:

PORT_t * col_ports[] = { &PORTA, &PORTA, &PORTF, &PORTB };

You might try putting the const keyword right before col_ports as well;您也可以尝试将const关键字放在col_ports之前; that might move the array to flash, thus saving you some RAM space.这可能会将数组移动到 flash,从而为您节省一些 RAM 空间。

Assuming 8 bit MCU with 16 bit register map, then your ports will be defined in a register map along the lines of this:假设 8 位 MCU 具有 16 位寄存器 map,那么您的端口将在寄存器 map 中定义,如下所示:

#define PORTA (*(volatile uint8_t*)0x1234u)

Why is explained here: How to access a hardware register from firmware?为什么在这里解释: How to access a hardware register from firmware?

You will want an array of volatile uint8_t* pointers: volatile uint8_t* col_ports[] .您将需要一个volatile uint8_t*指针数组: volatile uint8_t* col_ports[] However, you most likely also want this array to be allocated in flash not RAM, therefore add const after the * , to make the array itself read-only:但是,您很可能还希望将此数组分配到 flash 而不是 RAM,因此在*之后添加const以使数组本身成为只读的:

volatile uint8_t* const col_ports[] =
{
  &PORTA,
  &PORTB,
  &PORTC
};

There might also be various memory mapping hiccups related to the old AVR Harvard architecture, so you might have to add PROGMEM after the const , or similar compiler-specific non-standard keywords.可能还存在与旧 AVR Harvard 架构相关的各种 memory 映射问题,因此您可能必须在const或类似的特定于编译器的非标准关键字之后添加PROGMEM

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM